home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
datafiles
/
text
/
c_manual
/
devices
/
trackdiskdevice
/
example3.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-27
|
15KB
|
492 lines
/***********************************************************/
/* */
/* 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;
}
}