#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/memory.h"
#include "exec/interrupts.h"
#include "exec/ports.h"
#include "exec/libraries.h"
#include "exec/io.h"
#include "exec/tasks.h"
#include "exec/execbase.h"
#include "exec/devices.h"
#include "devices/trackdisk.h"

#define TD_READ CMD_READ
#define BLOCKSIZE TD_SECTOR

SHORT error;
struct MsgPort *diskport;
struct IOExtTD *diskreq;
BYTE diskbuffer[BLOCKSIZE];
BYTE *diskdata;
SHORT testval;

extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();

ULONG diskChangeCount;

ReadCylSec(cyl,sec,hd)
SHORT cyl,sec,hd;
{
   LONG offset;

   diskreq->iotd_Req.io_Length=BLOCKSIZE;
   diskreq->iotd_Req.io_Data=(APTR)diskbuffer;
      /*show where to put data when read*/
   diskreq->iotd_Req.io_Command=ETD_READ;
      /*check for diskchange before reading*/
   diskreq->iotd_Count=diskChangeCount;

/* convert from cylinder, head, sector to byte-offset value to get
* right one (as dos and everyone else sees it)....*/

/*driver reads one cylinder at a time (head does not move for
* 22 sequential sector reads, or better-put, head doesn't move for
* 2 sequential full track reads.)
*/

   offset=TD_SECTOR*(sec+NUMSECS*hd+NUMSECS*NUMHEADS*cyl);
   diskreq->iotd_Req.io_Offset=offset;
   DoIO(diskreq);
   return(0);
}

MotorOn()
{
/* Turn on disk motor ... old motor state is returned in io_Actual*/

   diskreq->iotd_Req.io_Length=1;
      /* this says motor is to be turned on */
   diskreq->iotd_Req.io_Command=TD_MOTOR;
      /* do something with the motor */
   DoIO(diskreq);
   printf("\nOld motor state was:%ld",diskreq->iotd_Req.io_Actual);
   printf("\nio_Error value was: %ld",diskreq->iotd_Req.io_Error);
   return(0);
}

MotorOff()
{
   printf("\n\nNow turn it off");
   diskreq->iotd_Req.io_Length=0;
      /*says that motor is to be turned off*/
   diskreq->iotd_Req.io_Command=TD_MOTOR;
      /*do something with the motor*/
   DoIO(diskreq);
   printf("\nOld motor state was:%ld",diskreq->iotd_Req.io_Actual);
   printf("\nio_Error value was:%ld",diskreq->iotd_Req.io_Error);
   return(0);
}

SeekFullRange(howmany)
SHORT howmany;
{
int i;
for(i=0;i<howmany;i++);
   {
      diskreq->iotd_Req.io_Offset=
                           ((NUMCYLS-1)*NUMSECS*NUMHEADS-1)*512;
         /*seek to cylinder 79, head 1 */
      diskreq->iotd_Req.io_Command=TD_SEEK;
      DoIO(diskreq);
      if(diskreq->iotd_Req.io_Error!=0)
         printf("\nSeek Cykle Number %ld, Error=%ld",
				i,diskreq->iotd_Req.io_Error);
      diskreq->iotd_Req.io_Offset=0;
         /*seek to cylinder 0, head 0)*/
      diskreq->iotd_Req.io_Command=TD_SEEK;
      DoIO(diskreq);
      if(diskreq->iotd_Req.io_Error!=0)
         printf("\nSeek Cycle Number %ld, Error=%ld",
                           i,diskreq->iotd_Req.io_Error);
      printf("\ncompleted a seek");
   }
   return(0);
}

main()
{
   SHORT cylinder,head,sector;

   diskdata= &diskbuffer[0];
      /*point to first location in disk buffer*/
   diskport=CreatePort(0,0);
   if (diskport==0)exit(100); /*error in createport*/
   diskreq=(struct IOExtTD *)CreateExtIO(diskport,
                              sizeof(struct IOExtTD));
           /*make io request block for communacating
            * with the disk*/
   if(diskreq==0){DeletePort(diskport);exit(200);}

   error=OpenDevice(TD_NAME,0,diskreq,0);
      /*open the device for access, unit 0 is built in*/
   printf("/nError value returned by OpenDevice was:%ld",error);
   /*now get the disk change value*/
   diskreq->iotd_Req.io_Command=TD_CHANGENUM;
   DoIO(diskreq);
   diskChangeCount=diskreq->iotd_Req.io_Actual;
   printf("\nChange number for disk is currently %ld",diskChangeCount);

   MotorOn();
   SeekFullRange(10);
   for(cylinder=0;cylinder<80;cylinder++)    /*tracks to test*/
      {
      for(head=0;head<2;head++)  /*numbers of heads to test*/
         for(sector=0;sector<11;sector++) /*sectors to test*/
            {
            ReadCylSec(cylinder,sector,head);
            if(diskreq->iotd_Req.io_Error!=0)
               printf("\nError At Cyl=%ld, Sc=%ld, Hd=%ld, Error=%ld",
                           cylinder,sector,head,diskreq->iotd_Req.io_Error);
            }
         printf("\nCompleted reading Cylinder=%ld",cylinder);
      }
   MotorOff();
   CloseDevice(diskreq);
   printf("\n");
   DeleteExtIO(diskreq,sizeof(struct IOExtTD));
   DeletePort(diskport);
}

