/* * MyTDIO.c * * Handles a trackdisk RAW read with WORDSYNC. * I can't get the ETD_RAWREAD to work, so coded one myself. DAV */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __NO_PRAGMAS #include #define CIAF_DSKSELALL (CIAF_DSKSEL3 | CIAF_DSKSEL2\ | CIAF_DSKSEL1 | CIAF_DSKSEL0) #ifndef NUMHEADS #define NUMHEADS 2 #endif extern struct Custom custom; extern struct CIA ciaa, ciab; /* Above doesn't seem to work with Aztec, small data model, so ... */ #define CUSTOMADD ((struct Custom *)0xdff000) #define CIAAADD ((struct CIA *)0xbfe001) #define CIABADD ((struct CIA *)0xbfd000) /* * Disable/Enable interrupts at the CPU */ static APTR sysStack; static ULONG oldSR; cpuDisable() { oldSR = SetSR(0x700L,0x700L); sysStack = SuperState(); } cpuEnable() { if(sysStack) UserState(sysStack); SetSR(oldSR,0x700L); } /* make a special read request up */ MyTDIO(struct IOExtTD *tdreq) { struct Custom *pcustom = CUSTOMADD; /*&custom;*/ struct CIA *pciaa = CIAAADD; /*&ciaa;*/ struct CIA *pciab = CIABADD; /*&ciab;*/ UWORD command; ULONG actual,length,offset; APTR data; UBYTE flags; int drive,head; UWORD dsklenw; long timeout; struct IOStdReq *req = (struct IOStdReq *) tdreq; if(!(req->io_Command == ETD_RAWREAD || req->io_Command == TD_RAWREAD)) { req->io_Error = 100; return; } /* our request - local copy parameters */ command = req->io_Command; flags = req->io_Flags; actual = req->io_Actual; /* SPECIAL - expect drive unit # here */ length = req->io_Length; data = req->io_Data; offset = req->io_Offset; /* Track (not cyl) */ drive = actual; head = offset % (NUMSECS*TD_SECTOR); /* Seek to track */ req->io_Offset = offset * (NUMSECS*TD_SECTOR); req->io_Command = TD_SEEK; DoIO((struct IORequest *)req); if(req->io_Error != 0) { req->io_Error = 101; return; } /* Do raw - read magic */ cpuDisable(); pcustom->dmacon = DMAF_SETCLR | DMAF_DISK | DMAF_MASTER; /* turn OFF bits - not GCR, and no pre-comp. for now */ pcustom->adkcon = ADKF_PRECOMP0|ADKF_PRECOMP1|ADKF_MSBSYNC|ADKF_WORDSYNC; /* turn ON bits - mfm */ pcustom->adkcon = ADKF_SETCLR|ADKF_WORDSYNC|ADKF_MFMPREC|ADKF_FAST; /* turn ON wordsync if required */ if(flags & IOTDF_WORDSYNC) pcustom->adkcon = ADKF_SETCLR|ADKF_WORDSYNC; pcustom->dsksync = 0x4489; pcustom->dsklen = DSKDMAOFF; /* 0x4000 */ pcustom->dskpt = data; dsklenw = 0x8000 | ((length >> 1) & 0x3fff); pciab->ciaprb &= ~CIAF_DSKMOTOR; /* ensure motor on */ if(drive == 0) pciab->ciaprb &= ~CIAF_DSKSEL0; else if(drive == 1) pciab->ciaprb &= ~CIAF_DSKSEL1; else if(drive == 2) pciab->ciaprb &= ~CIAF_DSKSEL2; else if(drive == 3) pciab->ciaprb &= ~CIAF_DSKSEL3; if(head == 0) pciab->ciaprb &= ~CIAF_DSKSIDE; else pciab->ciaprb |= CIAF_DSKSIDE; pcustom->dsklen = dsklenw; /* first write */ timeout = 0; while(pciaa->ciapra & CIAF_DSKRDY) { /* wait for ready */ if(++timeout > 1000000L) { pcustom->dsklen = DSKDMAOFF; pciab->ciaprb |= (CIAF_DSKSELALL); cpuEnable(); req->io_Error = 102; return; /* timed out waiting for ready */ } } if(flags & IOTDF_INDEXSYNC) { timeout = pciab->ciaicr; timeout = 0; while(!(pciab->ciaicr & CIAICRF_FLG)) { /* wait for index pls */ if(++timeout > 1000000L) { pcustom->dsklen = DSKDMAOFF; pciab->ciaprb |= (CIAF_DSKSELALL); cpuEnable(); req->io_Error = 103; return; /* timed out waiting for index */ } } } pcustom->intena = INTF_SETCLR | INTF_DSKBLK; pcustom->intreq = INTF_DSKBLK; /* clear pending DMA-done */ pcustom->dsklen = dsklenw; /* second write - start DMA*/ timeout = 0; while(!(pcustom->intreqr & INTF_DSKBLK)) { /* wait for DMA done */ if(++timeout > 1000000L) { pcustom->dsklen = DSKDMAOFF; pciab->ciaprb |= (CIAF_DSKSELALL); cpuEnable(); req->io_Error = 104; return; /* timed out waiting for DMA */ } } pciab->ciaprb |= (CIAF_DSKSELALL); pcustom->dsklen = DSKDMAOFF; pcustom->intreq = INTF_DSKBLK; /* clear DMA-done */ cpuEnable(); req->io_Error = 0; return; }