home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************/
- /* */
- /* Amiga C Encyclopedia (ACE) V3.0 Amiga C Club (ACC) */
- /* ------------------------------- ------------------ */
- /* */
- /* Book: ACM Devices Amiga C Club */
- /* Chapter: Trackdisk Device Tulevagen 22 */
- /* File: Example3.c 181 41 LIDINGO */
- /* Author: Anders Bjerin SWEDEN */
- /* Date: 92-04-27 */
- /* Version: 1.00 */
- /* */
- /* Copyright 1992, Anders Bjerin - Amiga C Club (ACC) */
- /* */
- /* Registered members may use this program freely in their */
- /* own commercial/noncommercial programs/articles. */
- /* */
- /***********************************************************/
-
-
-
- /* This example demonstrates how you can read data with help of the */
- /* Trackdisk Device. You give this program four arguments (drive, */
- /* head, cylinder and sector), and it will print out all data in that */
- /* sector. You only have to expand this program a little and you will */
- /* end up with a nice disk viewer. */
- /* */
- /* Use: Example3 drive (0-3) head (0-1) cylinder (0-79) sector (0-10) */
-
-
-
- #include <exec/types.h> /* Datatypes */
- #include <exec/ports.h> /* Messages */
- #include <exec/errors.h> /* IO Error */
- #include <exec/memory.h> /* Allocating memory */
- #include <devices/trackdisk.h> /* Trackdisk Device */
-
-
-
- /* Motor status: */
- #define OFF 0
- #define ON 1
-
- /* Help text: */
- #define HELP "Use: Example3 drive (0-3) head (0-1) cylinder (0-79) sector (0-10)"
-
- /* Buffer size (512 bytes): */
- #define BUFFERSIZE TD_SECTOR
-
-
-
- /* Declare a pointer to our reply port: */
- struct MsgPort *replymp;
-
- /* Declare a pointer to an IOExtTD structure: */
- struct IOExtTD *exreq;
-
- /* Have we opened the Trackdisk Device? */
- BOOL device_open = FALSE;
-
- /* Pointer to our memory buffer: */
- BYTE *buffer;
-
- /* Disk change value: */
- ULONG disk_change_count;
-
-
-
- /* Declare our functions: */
- void main();
- void clean_up( BYTE error, STRPTR text );
- BYTE DiskMotor( BYTE status );
- void TrackdiskError( BYTE error );
- ULONG DiskChangeCount( void );
- BYTE ReadDisk( WORD head, WORD cylinder, WORD sector );
- void PrintTrackdiskData( void );
-
-
-
- void main( int argc, char *argv[] )
- {
- /* Was the motor already on or not? */
- BYTE motor_was_on;
-
- /* Error number: */
- BYTE error;
-
- /* Store the four arguments in these variables: */
- int drive, head, cylinder, sector;
-
-
-
- /* Process the arguments: */
- /* If not 4 arguments + program name, error: */
- if( argc != 5 )
- clean_up( 0, HELP );
- else
- {
- /* Convert to integer: */
- drive = atoi( argv[1] );
- head = atoi( argv[2] );
- cylinder = atoi( argv[3] );
- sector = atoi( argv[4] );
-
- /* Check the values: */
- if( drive < 0 || drive > 3 || /* Drive: 0 - 3 */
- head < 0 || head > 1 || /* Head: 0 - 1 */
- cylinder < 0 || cylinder > 79 || /* Cylinder: 0 - 79 */
- sector < 0 || sector > 10 ) /* Sector: 0 - 10 */
- clean_up( 0, HELP );
- }
-
-
-
- /* Get a reply port: */
- replymp = (struct MsgPort *)
- CreatePort( NULL, 0 );
- if( !replymp )
- clean_up( 0, "Could not create the reply port!" );
-
-
-
- /* Create an IOExtTD structure: */
- exreq = (struct IOExtTD *)
- CreateExtIO( replymp, sizeof( struct IOExtTD ) );
- if( !exreq )
- clean_up( 0, "Could not create the IO!" );
-
-
-
- /* Open the Trackdisk Device: */
- error = OpenDevice( TD_NAME, drive, exreq, 0 );
- if( error )
- clean_up( error, "Could not open the Trackdisk Device!" );
- else
- device_open = TRUE;
-
-
-
- /* Allocate memory for our disk buffer: (Must be Chip Memory!) */
- buffer = (BYTE *) AllocMem( BUFFERSIZE, MEMF_CHIP | MEMF_CLEAR );
- if( !buffer )
- clean_up( 0, "Could not allocate enough memory for the buffer!" );
-
-
-
- /* Get the disk's change count value: (We can later compare */
- /* this number with the disk's cout value later on, and if */
- /* they are not equal, the disk has been removed and/or */
- /* changed!) */
- disk_change_count = DiskChangeCount();
-
-
-
- /* Turn the motor on: Well, we do not actually need to do this, */
- /* since it will automatically be turned on when we start to */
- /* read. However, it takes some micro seconds to "tune" the drive */
- /* when it is turned on so if you are going to write several */
- /* times to the drive you better keep it on. Note that once the */
- /* motor is on you must turn it off yourself! (Unless it was */
- /* already on.) */
- motor_was_on = DiskMotor( ON );
-
-
-
- /* Print some information: */
- printf( "Diskdrive: df%d:\n", drive );
- printf( "Head: %d\n", head );
- printf( "Cylinder: %d\n", cylinder );
- printf( "Sector: %d\n", sector );
-
-
-
- /* Try to read one sector: */
- if( error = ReadDisk( head, cylinder, sector ) )
- TrackdiskError( error ); /* ERROR! */
- else
- PrintTrackdiskData(); /* OK! */
-
-
-
- /* Only if the motor was off before we turned it on should */
- /* we turn it off again. If the motor was already on we */
- /* should not turn it off since that means that some other */
- /* task wants it to be on. */
- if( !motor_was_on )
- DiskMotor( OFF );
-
-
-
- /* Clean up and quit: */
- clean_up( 0, "The End!" );
- }
-
-
-
- /* Close and return everything that has been */
- /* opened and allocated before we quit: */
-
- void clean_up( BYTE error, STRPTR text )
- {
- if( error )
- TrackdiskError( error );
-
- /* Free buffer: */
- if( buffer )
- FreeMem( buffer, BUFFERSIZE );
-
- /* Close the Trackdisk Device: */
- if( device_open )
- CloseDevice( exreq );
-
- /* Delete the IOExtTD structure: */
- if( exreq )
- DeleteExtIO( exreq, sizeof( struct IOExtTD ) );
-
- /* Remove the replyport: */
- if( replymp )
- DeletePort( replymp);
-
- /* Print the message: */
- printf( "%s\n", text );
-
- /* Quit: */
- exit( 0 );
- }
-
-
-
- /* DiskMotor() will turn on/off the diskdrive's motor. */
- /* */
- /* Synopsis: oldstatus = DiskMotor( new_status ); */
- /* */
- /* oldstatus: (BYTE) DiskMotor() returns 1 if the motor */
- /* was already on, else 0 (motor was off). */
- /* */
- /* newstatus: (BYTE) Set this field to 1 (ON) if you */
- /* want to turn the motor on, else set it to */
- /* 0 (OFF) and the motor will be turned off. */
- /* Note! If you turned the motor on when the */
- /* motor was off you must turn it off before */
- /* your program terminates. However, if it */
- /* was already on you should not turn it */
- /* off. */
-
- BYTE DiskMotor( BYTE status )
- {
- /* Will the user what we will do: */
- printf( "Motor will be turned: %s\n", status ? "On" : "Off" );
-
- /* Set our request: */
- exreq->iotd_Req.io_Command = TD_MOTOR; /* Turn motor on/off. */
- exreq->iotd_Req.io_Length = status; /* 0 = off, 1 = on. */
-
- /* Do our request, and return when done: */
- DoIO( exreq );
-
- /* DoIO() will return when it has done our request, */
- /* so it will therefore not send us any message to */
- /* our reply port. If we had used SendIO() instead */
- /* (returns immediately) we would had to wait for a */
- /* message to arrive at our reply port. */
-
- /* Check if the motor was on or not before we changed it: */
- printf( "Motor was: %s\n", exreq->iotd_Req.io_Actual ? "On" : "Off" );
-
- /* Return 1 if the motor was already on, 0 if not: */
- return( (BYTE) exreq->iotd_Req.io_Actual );
- }
-
-
-
- /* TrackdiskError() will give the user some more information */
- /* about the error. */
- /* */
- /* Synopsis: TrackdiskError( error ); */
- /* */
- /* error: (BYTE) Give this function the error value, and */
- /* it will give the user some more information */
- /* about the error. */
-
- void TrackdiskError( BYTE error )
- {
- printf( "Error code: %d\n", error );
- printf( "Problem: " );
-
- /* The complete list of possible errors: */
- switch( error )
- {
- case TDERR_NotSpecified:
- printf( "Something, we do not know what, failed!\n" );
- break;
-
- case TDERR_NoSecHdr:
- printf( "Could not find a sector!\n" );
- break;
-
- case TDERR_BadSecPreamble:
- printf( "The sector is corrupted!\n" );
- break;
-
- case TDERR_BadSecID:
- printf( "Problems with identifying the sector!\n" );
- break;
-
- case TDERR_BadHdrSum:
- printf( "The header had incorrect checksum!\n" );
- break;
-
- case TDERR_BadSecSum:
- printf( "The sector had incorrect checksum!\n" );
- break;
-
- case TDERR_TooFewSecs:
- printf( "There are too few sectors!\n" );
- break;
-
- case TDERR_BadSecHdr:
- printf( "The sector's header is corrupted!\n" );
- break;
-
- case TDERR_WriteProt:
- printf( "The disk is write protected!\n" );
- break;
-
- case TDERR_DiskChanged:
- printf( "No disk present or disk changed!\n" );
- break;
-
- case TDERR_SeekError:
- printf( "Could not find track 0!\n" );
- break;
-
- case TDERR_NoMem:
- printf( "Not enough memory!\n" );
- break;
-
- case TDERR_BadUnitNum:
- printf( "Requested diskdrive does not exist!\n" );
- break;
-
- case TDERR_BadDriveType:
- printf( "The Trackdisk Device can not handle that diskdrive!\n" );
- break;
-
- case TDERR_DriveInUse:
- printf( "The requested diskdrive is already used by someone else!\n" );
- break;
-
- case TDERR_PostReset:
- printf( "Oh no! The user hit the reset buttons, we are going down!\n" );
- break;
-
-
- /* The standard device errors: */
-
- case IOERR_OPENFAIL:
- printf( "Could not open the device!\n" );
- break;
-
- case IOERR_ABORTED:
- printf( "The request was aborted!\n" );
- break;
-
- case IOERR_NOCMD:
- printf( "Not a valid command! Not supported by the trackdisk device!\n" );
- break;
-
- case IOERR_BADLENGTH:
- printf( "Bad length or value!\n" );
- break;
-
- default:
- /* Unknown error value: */
- printf( "What? Unknown error code!\n" );
- }
- }
-
-
-
- /* DiskChangeCount() returns the current disk's "count value". */
- /* If the value has changet we know that the disk has been */
- /* removed and/or changed. */
- /* */
- /* Synopsis: count = DiskChangeCount(); */
- /* */
- /* count: (ULONG) The disk's "change count value". */
-
- ULONG DiskChangeCount( void )
- {
- /* Get the disk's change count value: */
- exreq->iotd_Req.io_Command = TD_CHANGENUM;
-
- /* Do our request, and return when completed: */
- DoIO( exreq );
-
- /* Return the answer: */
- return( (ULONG) exreq->iotd_Req.io_Actual );
- }
-
-
-
- /* ReadDisk() will start to read at a specific sector, until */
- /* the diskbuffer is filled. (In this example we only read */
- /* one sector. */
- /* */
- /* Synopsis: error = ReadDisk( head, cylinder, sector ); */
- /* */
- /* error: (BYTE) ReadDisk() returns 0 if everything was */
- /* OK, else an error number is returned. Use our */
- /* function TrackdiskError() to find out what went */
- /* wrong. */
- /* */
- /* head: (WORD) Which head should be used. [0-1] */
- /* */
- /* cylinder: (WORD) Start at this cylinder. [0-79] */
- /* */
- /* sector: (WORD) Start at this sector. [0-10] */
-
- BYTE ReadDisk( WORD head, WORD cylinder, WORD sector )
- {
- /* We want to read: */
- exreq->iotd_Req.io_Command = ETD_READ;
-
- /* Pointer to our buffer: */
- exreq->iotd_Req.io_Data = (APTR) buffer;
-
- /* Read until the buffer is filled: */
- exreq->iotd_Req.io_Length = BUFFERSIZE;
-
- /* Set current disk count value: (If the value has changed */
- /* this request will be canceled.) */
- exreq->iotd_Count = disk_change_count;
-
- /* Start to read at position: (The diskdrive has 2 heads, 80 */
- /* cylinders which each consists of 11 (NUMSECS) sectors, */
- /* with 512 (TD_SECTOR) usable bytes of data each.) */
- exreq->iotd_Req.io_Offset = (LONG)
- TD_SECTOR*( NUMSECS * 2 * cylinder + NUMSECS * head + sector );
-
- /* Do our request, and return when completed: */
- DoIO( exreq );
-
- /* Return error value: (0: OK, else ERROR) */
- return( (BYTE) exreq->iotd_Req.io_Error );
- }
-
-
-
- /* PrintTrackdiskData() prints out the data which we have put */
- /* in the buffer. The left side of the screen is filled with */
- /* the data in hexadecimal form, while on the right side you */
- /* can see what it represents in ASCII codes. */
- /* */
- /* Synopsis: PrintTrackdiskData(); */
-
- void PrintTrackdiskData( void )
- {
- /* Temporary buffer pointer: */
- UBYTE *ptr;
- int x, y;
-
-
- /* Start at the beginning of the buffer: */
- ptr = buffer;
- /* Print out the whole buffer: */
- for( y = 0; y < BUFFERSIZE / 16; y++ )
- {
- /* The first 8 bytes in hexadecimal form: */
- printf( "%02X: %02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,", y,
- ptr[0], ptr[1], ptr[2], ptr[3],
- ptr[4], ptr[5], ptr[6], ptr[7] );
-
- /* The following 8 bytes in hexadecimal form: */
- printf( "%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X | ",
- ptr[8], ptr[9], ptr[10], ptr[11],
- ptr[12], ptr[13], ptr[14], ptr[15] );
-
- /* If the value is between 32 (!) and 126 (~) we print out the */
- /* character, else we print a space: */
- for( x = 0; x < 16; x++ )
- printf( "%1c", ( ptr[ x ] > 31 && ptr[ x ] < 127 ) ? ptr[ x ] : ' ' );
-
- /* Next line: */
- printf( "\n" );
-
- /* Next 16 bytes: */
- ptr += 16;
- }
- }
-
-