home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
datafiles
/
text
/
c_manual
/
devices
/
trackdiskdevice
/
example4.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-27
|
31KB
|
931 lines
/***********************************************************/
/* */
/* Amiga C Encyclopedia (ACE) V3.0 Amiga C Club (ACC) */
/* ------------------------------- ------------------ */
/* */
/* Book: ACM Devices Amiga C Club */
/* Chapter: Trackdisk Device Tulevagen 22 */
/* File: Example4.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 contains a lot of small and useful */
/* functions that does almost everything you ever */
/* would like to do with the trackdisk device. The */
/* example has been written so you can easily use */
/* the functions in your own programs. */
#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
/* Buffer size (512 bytes): */
#define BUFFERSIZE TD_SECTOR
/* Disk drives: */
#define DF0 0
#define DF1 1
#define DF2 2
#define DF3 3
/* Declare our functions: */
void main();
void clean_up
(
BYTE error,
STRPTR text,
struct MsgPort *mp,
struct IOExtTD *req,
BOOL open,
BYTE *buf
);
BYTE DiskMotor
(
struct IOExtTD *extreq,
BYTE status
);
void TrackdiskError( BYTE error );
ULONG DiskChangeCount( struct IOExtTD *extreq );
BYTE ReadDisk
(
struct IOExtTD *extreq,
BYTE *buffer,
ULONG size,
ULONG counter,
WORD head,
WORD cylinder,
WORD sector
);
BYTE WriteDisk
(
struct IOExtTD *extreq,
BYTE *buffer,
ULONG size,
ULONG counter,
WORD head,
WORD cylinder,
WORD sector
);
BYTE FormatDisk
(
struct IOExtTD *extreq,
BYTE *buffer,
ULONG counter,
WORD head,
WORD cylinder
);
BYTE SeekDisk
(
struct IOExtTD *extreq,
ULONG counter,
WORD head,
WORD cylinder,
WORD sector
);
BYTE UpdateDisk
(
struct IOExtTD *extreq,
ULONG counter
);
BYTE ClearDisk
(
struct IOExtTD *extreq,
ULONG counter
);
ULONG DiskPresent( struct IOExtTD *extreq );
ULONG DiskProtected( struct IOExtTD *extreq );
ULONG DriveType( struct IOExtTD *extreq );
ULONG GetNumTracks( struct IOExtTD *extreq );
void RemoveDisk( struct IOExtTD *extreq );
/* This short main program demonstrates some of the functions. */
/* Note that we have put the request block and message port */
/* structures inside the main program rather than declare them */
/* as global structures. It should then be easier for you to */
/* use your own request blocks and names. */
void main()
{
/* Declare a pointer to our reply port: */
struct MsgPort *replymp = NULL;
/* Declare a pointer to an IOExtTD structure: */
struct IOExtTD *our_request = NULL;
/* Have we opened the Trackdisk Device? */
BOOL device_open = FALSE;
/* Error number: */
BYTE error;
/* Pointer to our memory buffer: */
BYTE *buffer = NULL;
/* Drive type: ("DRIVE3_5" or "DRIVE5_25") */
ULONG drive_type;
/* Number of tracks: */
ULONG num_tracks;
/* Get a reply port: */
replymp = (struct MsgPort *)
CreatePort( NULL, 0 );
if( !replymp )
clean_up
(
0,
"Could not create the reply port!",
replymp,
our_request,
device_open,
buffer
);
/* Create an IOExtTD structure: */
our_request = (struct IOExtTD *)
CreateExtIO( replymp, sizeof( struct IOExtTD ) );
if( !our_request )
clean_up
(
0,
"Could not create the IO!",
replymp,
our_request,
device_open,
buffer
);
/* Open the Trackdisk Device: */
error = OpenDevice( TD_NAME, DF0, our_request, 0 );
if( error )
clean_up
(
error,
"Could not open the Trackdisk Device!",
replymp,
our_request,
device_open,
buffer
);
else
device_open = TRUE;
/* Demonstrate some of the functions: */
/* Is there a disk in the drive? */
if( DiskPresent( our_request ) )
printf( "No disk in drive.\n" );
else
printf( "There is a disk in the drive.\n" );
/* Is the disk write protected? */
if( DiskProtected( our_request ) )
printf( "The disk is write protected.\n" );
else
printf( "The disk is not write protected.\n" );
/* What type of disks does it use: (3 1/2" or 5 1/4") */
drive_type = DriveType( our_request );
if( drive_type == DRIVE3_5 )
printf( "It is a 3 1/2\" drive.\n" );
else
if( drive_type == DRIVE5_25 )
printf( "It is a 5 1/4\" drive.\n" );
else
printf( "It is a very strange drive!\n" );
/* How many tracks does this drive use: */
num_tracks = GetNumTracks( our_request );
printf( "Number of tracks: %d (%d / side)\n", num_tracks, num_tracks / 2 );
/* Clean up and quit: */
clean_up
(
0,
"The End!",
replymp,
our_request,
device_open,
buffer
);
}
/* Close and return everything that has been */
/* opened and allocated before we quit: */
void clean_up
(
BYTE error,
STRPTR text,
struct MsgPort *mp,
struct IOExtTD *req,
BOOL open,
BYTE *buf
)
{
if( error )
TrackdiskError( error );
/* Free buffer: */
if( buf )
FreeMem( buf, BUFFERSIZE );
/* Close the Trackdisk Device: */
if( open )
CloseDevice( req );
/* Delete the IOExtTD structure: */
if( req )
DeleteExtIO( req, sizeof( struct IOExtTD ) );
/* Remove the replyport: */
if( mp )
DeletePort( mp);
/* 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). */
/* */
/* extreq: (struct IOExtTD *) Pointer to the request */
/* block. */
/* */
/* 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
(
struct IOExtTD *extreq,
BYTE status
)
{
/* Will the user what we will do: */
printf( "Motor will be turned: %s\n", status ? "On" : "Off" );
/* Set our request: */
extreq->iotd_Req.io_Command = TD_MOTOR; /* Turn motor on/off. */
extreq->iotd_Req.io_Length = status; /* 0 = off, 1 = on. */
/* Do our request, and return when done: */
DoIO( extreq );
/* 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", extreq->iotd_Req.io_Actual ? "On" : "Off" );
/* Return 1 if the motor was already on, 0 if not: */
return( (BYTE) extreq->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( extreq ); */
/* */
/* count: (ULONG) The disk's "change count value". */
/* */
/* extreq: (struct IOExtTD *) Pointer to the request block. */
ULONG DiskChangeCount( struct IOExtTD *extreq )
{
/* Get the disk's change count value: */
extreq->iotd_Req.io_Command = TD_CHANGENUM;
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return the answer: */
return( (ULONG) extreq->iotd_Req.io_Actual );
}
/* ReadDisk() will start to read a specified number of bytes of data, */
/* and store it in the buffer. Before you call this function you should */
/* have got the disk's current count value by using our DiskChangeCount() */
/* function. If you do not want to check if the disk has been changed, */
/* set the counter field to 0xFFFF. */
/* */
/* Synopsis: er = ReadDisk( req, buf, size, count, head, cyl, sec ); */
/* */
/* er: (BYTE) ReadDisk() returns 0 if everything was OK, else an */
/* error number is returned. Use our function TrackdiskError() */
/* to find out what went wrong. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
/* */
/* buf: (BYTE *) Pointer to a buffer in which all data will be */
/* stored. Make sure that this buffer is at least as big as */
/* the specified number of bytes that should be read (size). */
/* */
/* size: (ULONG) The number of bytes that should be read. */
/* */
/* count: (ULONG) This disk current counter value. Use our function */
/* DiskChangeCount() to get the current count value. */
/* */
/* head: (WORD) Which head should be used. [0-1] */
/* */
/* cyl: (WORD) Start at this cylinder. [0-79] */
/* */
/* sec: (WORD) Start at this sector. [0-10] */
BYTE ReadDisk
(
struct IOExtTD *extreq,
BYTE *buffer,
ULONG size,
ULONG counter,
WORD head,
WORD cylinder,
WORD sector
)
{
/* We want to read: */
extreq->iotd_Req.io_Command = ETD_READ;
/* Pointer to the buffer: */
extreq->iotd_Req.io_Data = (APTR) buffer;
/* Number of bytes that should be read: */
extreq->iotd_Req.io_Length = size;
/* Set current disk count value: (If the value has changed */
/* this request will be cancelled.) */
extreq->iotd_Count = counter;
/* 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.) */
extreq->iotd_Req.io_Offset = (LONG)
TD_SECTOR*( NUMSECS * 2 * cylinder + NUMSECS * head + sector );
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return error value: (0: OK, else ERROR) */
return( (BYTE) extreq->iotd_Req.io_Error );
}
/* WriteDisk() will start to write a specified number of bytes of data. */
/* Before you call this function you should have got the disk's current */
/* count value by using our DiskChangeCount() function. If you do not */
/* want to check if the disk has been changed, set the counter field to */
/* 0xFFFF. */
/* */
/* Synopsis: er = WriteDisk( req, buf, size, count, head, cyl, sec ); */
/* */
/* er: (BYTE) WriteDisk() returns 0 if everything was OK, else an */
/* error number is returned. Use our function TrackdiskError() */
/* to find out what went wrong. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
/* */
/* buf: (BYTE *) Pointer to a buffer from which all data will be */
/* fetched. Make sure that this buffer is at least as big as */
/* the specified number of bytes that should be written (size). */
/* */
/* size: (ULONG) The number of bytes that should be written. */
/* */
/* count: (ULONG) This disk current counter value. Use our function */
/* DiskChangeCount() to get the current count value. */
/* */
/* head: (WORD) Which head should be used. [0-1] */
/* */
/* cyl: (WORD) Start at this cylinder. [0-79] */
/* */
/* sec: (WORD) Start at this sector. [0-10] */
BYTE WriteDisk
(
struct IOExtTD *extreq,
BYTE *buffer,
ULONG size,
ULONG counter,
WORD head,
WORD cylinder,
WORD sector
)
{
/* We want to write: */
extreq->iotd_Req.io_Command = ETD_WRITE;
/* Pointer to the buffer: */
extreq->iotd_Req.io_Data = (APTR) buffer;
/* Number of bytes that should be written: */
extreq->iotd_Req.io_Length = size;
/* Set current disk count value: (If the value has changed */
/* this request will be cancelled.) */
extreq->iotd_Count = counter;
/* Start to write 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.) */
extreq->iotd_Req.io_Offset = (LONG)
TD_SECTOR*( NUMSECS * 2 * cylinder + NUMSECS * head + sector );
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return error value: (0: OK, else ERROR) */
return( (BYTE) extreq->iotd_Req.io_Error );
}
/* FormatDisk() will format a specified cylinder. */
/* */
/* Synopsis: error = FormatDisk( req, buffer, count, head, cylinder ); */
/* */
/* error: (BYTE) FormatDisk() returns 0 if everything was OK, else an */
/* error number is returned. Use our function TrackdiskError() */
/* to find out what went wrong. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
/* */
/* buffer: (BYTE *) Pointer to a buffer which contains the data that */
/* will be stored on the reformatted cylinder. Make sure that */
/* this buffer is at least one cylinder of bytes large. */
/* (NUMSECS * TD_SECTOR) */
/* */
/* count: (ULONG) This disk current counter value. Use our function */
/* DiskChangeCount() to get the current count value. */
/* */
/* head: (WORD) Which head should be used. [0-1] */
/* */
/* cylinder: (WORD) The cylinder which sould be formatted. [0-79] */
BYTE FormatDisk
(
struct IOExtTD *extreq,
BYTE *buffer,
ULONG counter,
WORD head,
WORD cylinder
)
{
/* We want to format: */
extreq->iotd_Req.io_Command = ETD_FORMAT;
/* Pointer to the buffer: */
extreq->iotd_Req.io_Data = (APTR) buffer;
/* Format one cylinder: */
extreq->iotd_Req.io_Length = NUMSECS * TD_SECTOR;
/* Set current disk count value: (If the value has changed */
/* this request will be cancelled.) */
extreq->iotd_Count = counter;
/* Start at position: */
extreq->iotd_Req.io_Offset = (LONG)
TD_SECTOR*( NUMSECS * 2 * cylinder + NUMSECS * head );
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return error value: (0: OK, else ERROR) */
return( (BYTE) extreq->iotd_Req.io_Error );
}
/* SeekDisk() will move the head to a specified position. Not extremely */
/* useful, but maybe someone needs to do it. */
/* */
/* Synopsis: er = SeekDisk( req, count, head, cyl, sec ); */
/* */
/* er: (BYTE) returns 0 if everything was OK, else an error number */
/* is returned. Use our function TrackdiskError() to find out */
/* what went wrong. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
/* */
/* count: (ULONG) This disk current counter value. Use our function */
/* DiskChangeCount() to get the current count value. */
/* */
/* head: (WORD) Which head. [0-1] */
/* */
/* cyl: (WORD) Move to cylinder. [0-79] */
/* */
/* sec: (WORD) Move to sector. [0-10] */
BYTE SeekDisk
(
struct IOExtTD *extreq,
ULONG counter,
WORD head,
WORD cylinder,
WORD sector
)
{
/* We want to position the head: */
extreq->iotd_Req.io_Command = ETD_SEEK;
/* Set current disk count value: (If the value has changed */
/* this request will be cancelled.) */
extreq->iotd_Count = counter;
/* Move to position: */
extreq->iotd_Req.io_Offset = (LONG)
TD_SECTOR*( NUMSECS * 2 * cylinder + NUMSECS * head + sector );
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return error value: (0: OK, else ERROR) */
return( (BYTE) extreq->iotd_Req.io_Error );
}
/* UpdateDisk() will update the trackdisk device's internal buffer. If */
/* there is anything left in the buffer it will be copied out onto the */
/* disk. You shuld always update the disk after you have finished */
/* writing and just before you stop the motor. */
/* */
/* Synopsis: error = UpdateDisk( req, count ); */
/* */
/* error: (BYTE) returns 0 if everything was OK, else an error */
/* number is returned. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
/* */
/* count: (ULONG) This disk current counter value. Use our function */
/* DiskChangeCount() to get the current count value. */
BYTE UpdateDisk
(
struct IOExtTD *extreq,
ULONG counter
)
{
/* We want to update the internal buffer: */
extreq->iotd_Req.io_Command = ETD_UPDATE;
/* Set current disk count value: (If the value has changed */
/* this request will be cancelled.) */
extreq->iotd_Count = counter;
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return error value: (0: OK, else ERROR) */
return( (BYTE) extreq->iotd_Req.io_Error );
}
/* ClearDisk() will clear the trackdisk device's internal buffer. It is */
/* always good to clear the internal buffer when you realize that the */
/* user has changed disks. Old data from the first disk will then not */
/* accidentally be stored on the new disk. */
/* */
/* Synopsis: error = ClearDisk( req, count ); */
/* */
/* error: (BYTE) returns 0 if everything was OK, else an error */
/* number is returned. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
/* */
/* count: (ULONG) This disk current counter value. Use our function */
/* DiskChangeCount() to get the current count value. */
BYTE ClearDisk
(
struct IOExtTD *extreq,
ULONG counter
)
{
/* We want to clear the internal buffer: */
extreq->iotd_Req.io_Command = ETD_CLEAR;
/* Set current disk count value: (If the value has changed */
/* this request will be cancelled.) */
extreq->iotd_Count = counter;
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return error value: (0: OK, else ERROR) */
return( (BYTE) extreq->iotd_Req.io_Error );
}
/* DiskPresent() will return 0 if there is a disk in the drive, */
/* else a non zero value is returned. */
/* */
/* Synopsis: disk = DiskPresent( req ); */
/* */
/* disk: (ULONG) returns 0 if there is a disk in the drive, */
/* else a non zero value is returned. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
ULONG DiskPresent( struct IOExtTD *extreq )
{
extreq->iotd_Req.io_Command = TD_CHANGESTATE;
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return 0 if there is a disk in the drive, else a non zero value: */
return( extreq->iotd_Req.io_Actual );
}
/* DiskProtected() will return 0 if the disk is not protected, */
/* else (disk is write protected) a non zero value is returned. */
/* */
/* Synopsis: protected = DiskProtected( req ); */
/* */
/* protected: (ULONG) returns 0 if the disk is not protected, */
/* else (disk is write protected) a non zero value */
/* is returned. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
ULONG DiskProtected( struct IOExtTD *extreq )
{
/* Check is the disk is protected or not: */
extreq->iotd_Req.io_Command = TD_PROTSTATUS;
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return 0 if the disk is not protected, else a non zero value: */
return( extreq->iotd_Req.io_Actual );
}
/* DriveType() will return "DRIVE3_5" if it is a normal 3 1/2" disk */
/* in the drive, or it it returns "DRIVE5_25" if it is a 5 1/4 disk. */
/* */
/* Synopsis: drive_type = DriveType( req ); */
/* */
/* drive_type: (ULONG) returns "DRIVE3_5" if it is a normal 3 1/2" */
/* disk drive, else it returns "DRIVE5_25" if it is a */
/* 5 1/4 disk drive. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
ULONG DriveType( struct IOExtTD *extreq )
{
/* Check drive type: */
extreq->iotd_Req.io_Command = TD_GETDRIVETYPE;
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return drive type: (DRIVE3_5 or DRIVE5_25) */
return( extreq->iotd_Req.io_Actual );
}
/* GetNumTracks() will return the number of tracks the drive is */
/* using. Remember that if you test it on a double sided drive the */
/* function will count the tracks on both sides. A normal 3 1/2" */
/* drive is using 160 tracks (80 tracks / head - side ). */
/* */
/* Synopsis: num_tracks = GetNumTracks( req ); */
/* */
/* num_tracks: (ULONG) returns the number of tracks the drive is */
/* using. */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
ULONG GetNumTracks( struct IOExtTD *extreq )
{
/* Get the number of tracks this drive is using: */
extreq->iotd_Req.io_Command = TD_GETNUMTRACKS;
/* Do our request, and return when completed: */
DoIO( extreq );
/* Return the number of tracks: */
return( extreq->iotd_Req.io_Actual );
}
/* RemoveDisk() makes the system beleive that the user has removed */
/* and/or changed the disks. It will cause the disk drive to increase */
/* its own internal count value. */
/* */
/* Synopsis: RemoveDisk( req ); */
/* */
/* req: (struct IOExtTD *) Pointer to the request block. */
void RemoveDisk( struct IOExtTD *extreq )
{
/* Let the system think that the user */
/* has removed and/or changed disks: */
extreq->iotd_Req.io_Command = TD_REMOVE;
/* Do our request, and return when completed: */
DoIO( extreq );
}