Mercurial > hg > Members > kono > nitros9-code
changeset 36:8b423669e5d2
Removed Boyle's IDE drivers for the time being... they don't seem to work
Replaced with edition 6
author | boisy |
---|---|
date | Mon, 15 Apr 2002 20:48:57 +0000 |
parents | 2e8c642a2e19 |
children | 1b329bae6f60 |
files | 3rdparty/drivers/ide/ccide.asm 3rdparty/drivers/ide/defsfile 3rdparty/drivers/ide/h0_ide.asm 3rdparty/drivers/ide/makefile |
diffstat | 4 files changed, 299 insertions(+), 1196 deletions(-) [+] |
line wrap: on
line diff
--- a/3rdparty/drivers/ide/ccide.asm Thu Apr 11 19:34:44 2002 +0000 +++ b/3rdparty/drivers/ide/ccide.asm Mon Apr 15 20:48:57 2002 +0000 @@ -1,1191 +1,274 @@ -* NOTE: Currently, will return RAW error #'s from drive (see ATA bit flags -* in error register). After driver finalized, switch back to OS9 error -* codes. -* NOTE 2: drvrbusy checks are done even before hardware access, because -* some variables are shared in the driver memory, and if a 2nd request -* comes in in the middle of it, the vars might be changed at a dangerous -* time. Note if you have two IDE controllers: since they get separate driver -* memory from each other, that both controllers CAN be active at the same -* time. -* BIG NOTE ON OLDER ATA-1 DRIVES!!! -* SOME DRIVES (MY MINISCRIBE 8051A INCLUDED) HAVE A TRANSLATION MODE THAT -* _IS_BUILT_INTO_THE_IDE_ROM_ITSELF! THE BAD PART IS, THE "IDENTIFY DRIVE" -* COMMAND _DOES_NOT_ TAKE THIS INTO CONSIDERATION, BUT RETURNS THE "NATIVE" -* DRIVE SPECS FOR CYLINDERS, HEADS & SECTORS PER TRACK. TO GET THE FULL -* CAPACITY OF THE DRIVE, WITHOUT ERRORS, YOU _MUST_ SET YOUR DEVICE -* DESCRIPTOR BASED ON THE HARDWARE _TRANSLATED_ SETTINGS, _NOT_ THE _NATIVE_ -* SETTINGS (DESCRIBED IN THE IDENTIFY DRIVE COMMAND)! AS A REAL WORLD -* EXAMPLE, ON MY MINISCRIBE 8051A: -* Drives "Native" mode (as well as the Identify Drive command) returns: -* 745 cylinders, 4 heads & 28 sectors/cylinder. -* HOWEVER, the "Translation" mode (which is checked off on the sticker on -* the drive itself from the manufacturer), says: -* Translated: 5 heads, 17 sectors. At this point, you will have to figure -* out the # of cylinders, by computing the # of sectors TOTAL for the -* drive in it's native mode (745*4*28 in the above example, or 83,440 -* sectors), and then dividing that value by (# of sectors/track * # of -* heads) in the translation mode, and rounding down. In the above case, -* 83,440/(5*17)=981.647, so use 981 (which in hex is $03d5). -* Therefore, the proper device descriptor for this drive is: -* cyl=3d5 sid=5 sct=22 t0s=22 (Actually, t0s is ignored by CCIDE) -* The sct=22 is because the value is hexidecimal (it means 34 sectors/ -* track), and is double the 17 I mentioned above because OS9 sectors are -* half the size of IDE sectors (256 bytes vs. 512 bytes). If this drive -* had been shipped in "Native" mode, it would use the following: -* cyl=2E9 sid=4 sct=38 t0s=38, which is what the IDENTIFY DRIVE command -* reports. -* You can verify the highest cylinder # by setting the OFS in the descriptor -* to what you think is the highest cylinder # (total # of cylinders-1 ... -* remember that CHS cylinder numbers start at 0!), and then try to read -* enough sectors to cover the whole track. If you go one past that value, -* you should start getting errors if you have the right cylinder count. -* This is kind of a dumb system, but I assume it had something to do with -* IBM PC BIOS in the early days of IDE. -*A LITTLE LATER, WHEN THE DRIVER IS STABLE, MAY WANT TO ADD ANOTHER BIT FLAG -* TO DRIVEFLG, SET UP BY A FIRST TIME READ: 8 BIT ACCEPTED. THEN, USE THE 8 -* BIT TRANSFER MODE IF POSSIBLE (LIKE I DID WITH LBA). THIS SHOULD ALLOW -* MUCH FASTER SECTOR ACCESS ON A NITROS9 SYSTEM, AND IT WOULD BE INTERESTING -* TO SEE HOW MANY DRIVES ACCEPT THAT MODE (SUPPOSED TO RETURN AN 'ABORTED' -* FLAG IF IT DOES NOT). -* NOTE: RBF WILL ASSIGN NEW DEVICE MEM (,U PTR) TO _EACH_ CONTROLLER ON IT'S -* OWN, BASED ON THE BASE ADDRESS FROM THE DEVICE DESCRIPTOR. THEREFORE, -* CCIDE SHOULD BE SET UP FOR _2_ DRIVES MAX (PER CONTROLLER), AND LET RBF -* TAKE CARE OF MULTIPLE CONTROLLERS. -* The exception to this is when using partitions; since they will have a -* separate descriptor for each partition, they will need a separate drive -* table entry. Each table entry is $26 (38) bytes each, so it is not a lot. -* Should make the device table fill up the rest of a 256 byte page (with -* all other variables allocated), since OS9 will force System RAM pages to -* even multiples of 256 anyways. Once full 8k block caching is implemented, -* some of the two 256 byte sector buffers currently in system RAM could be -* reused for more drive table entries as well. With current system RAM -* requirements in driver, this would allow 5 device table entries without -* taking any more system RAM then it is already. These can be shared in -* whatever combination you need for your (up to) 2 physical drives. -* ALSO, RBF CALLS THE INIT ROUTINE ONLY ONCE PER _DRIVER_, NOT DRIVE! -******************************************************************** -* DO NOT FORGET TO SET H6309 FLAG IN DEFSFILE APPROPRIATELY FOR 6809 VS. -* 6309 CODE WHEN ASSEMBLING!! -* CCIDE - IDE device driver for CoCo -* -* $Id$ -* -* Driver originally from Jim Hathaway, originally 8-bit only -* Converted to 16 bit by Alan DeKok -* Disassembled (OK, so I didn't have the source version at first!) -* by Eddie Kuns, ATA specs followed carefully and sector buffering -* on writes handled more carefully -* This driver uses 16-bit transfers *only* -* Check with Glenside - can we switch to 16 bit only, so there is less to -* maintain? With the cacheing stuff, the speed is fairly decent, although -* some 6309 optomizations are still possible (cache copies, drive table -* copies, hardware divide for CHS translation, etc.) -* -* Ed. Comments Who YY/MM/DD -* ------------------------------------------------------------------ -* 5 Source as distributed by Glenside 99/05/02 -* Added comments from 8 bit driver BGP 99/05/07 -* 6 Driver now gets address from descriptor, made BGP 99/05/10 -* minor optimizations, added symbols -* 7 Change to use real 16 bits LCB 99/09/06 -* partitions (both LBA & CHS) to 99/10/31 -* better error reporting -* slightly optomized read -* Half sector & LSN0 caches for current drive -* Auto-sense/run LBA & CHS modes -* Full CHS calculations (up to 4096 cylinders) -* for ATA-1 old drive compatibility -* 8 Attempted to add support for removable media LCB 00/05/27 -* commands (Door Lock/Unlock, Acknowledge Media to 00/??/?? -* Change) -* Attempt 'generic' ATA command system call -* Constants - change if needed -* NUMDRIVE is LOGICAL drives (partitions), NOT physical drives-use 5,11,etc -* 5=768 byte data area, 11=1024 byte data area -NUMDRIVE equ 11 Max. # of device descriptors per controller address -MAXWAIT equ 60*5 Max. # clock ticks to give up on read/write (5 sec) -HDSclPwr equ 2048 Set to 2048 as start ^2 cylinder (CHS translate) - -* New definitions in Device Descriptor -PartOfs equ $26 2 byte partition offset - -* Definitions for DD.DNS -PhysDriv equ %00000001 Physical drive # (0=Master, 1=Slave) -ForceCHS equ %00000010 Force driver to use CHS mode - -* New GetStat/SetStat calls: -* SS.DrInf call shares call # with SS.ScInf from NitrOS9 WindInt (info) -SS.DrInf equ $8f Drive info call (see routine for parms) -* Subcall #'s fro SS.DrInf (Y register on entry) -ATAIdent equ 0 ATA (handles ATAPI & plain ATA) - -* IDE & ATAPI Commands (ATAPI stuff not implemented yet, and LBA is mandatory) -ReadRtry equ $20 Read sector with retry -WritRtry equ $30 Write sector with retry -Diagnost equ $90 Execute drive diagnostic -Identify equ $EC Identify drive command -DoorLock equ $DE Lock drive -DoorUnLk equ $DF Unlock (eject) drive -AckMdChg equ $DB Acknowledge media change - -PIIdent equ $A1 Identify ATAPI drive command - -* IDE Status Register -Busy equ %10000000 Drive busy (1=busy) -DrvReady equ %01000000 Drive ready (1=ready to accept command) -WriteFlt equ %00100000 Drive Write Fault (1=Write fault?) -SeekDone equ %00010000 Seek Complete (1=Seek complete) -DataReq equ %00001000 Data Request (1=drive ready for read/write data) -CorrData equ %00000100 Corrected Data (1=correctable data error was done) -Index equ %00000010 1=1 disk revolution completed -ErrorFnd equ %00000001 1=Error detected - see error register - -* IDE hardware offsets -DataReg equ 0 Data (1st 8 bits, non-latched) -Error equ 1 Error # when read -Features equ 1 Features when write -SectCnt equ 2 Sector count -SectNum equ 3 Sector # -CylLow equ 4 Low byte of cylinder -CylHigh equ 5 High byte of cylinder -DevHead equ 6 Device/Head -Status equ 7 Status when read -Command equ 7 Command when write -Latch equ 8 Latch (2nd 8 bits of 16 bit word) - -* Special flags (Mini extra drive table - 1 byte per drive) - starts at -* DriveFlg,u -* These are set by inquiring the drive, NOT from the descriptor -* Should add a GETSTAT to allow user to access these for any drive -Unused equ %10000000 Entry is un-initialized -DrvMode equ %00000001 0=CHS mode, 1=LBA mode -ATAPI equ %00000010 0=Device is ATA,1=Device is ATAPI -Remove equ %00000100 0=Fixed Drive, 1=Removable media -ReadOnly equ %00001000 0=Read & write allowed, 1=Read only (CD-ROM) -* Could also use to write-protect hard drive - nam CCIDE - ttl IDE device driver for CoCo - - ifp1 - use defsfile - use rbfdefs - endc - -tylg set Drivr+Objct -atrv set ReEnt+rev -rev set $01 -edition equ 8 - - mod eom,name,tylg,atrv,start,size - -* NOTE: OS9 WILL ALWAYS ASSIGN DRIVER MEM SPACE ON AN EVEN 256 BYTE PAGE, -* SO TAKE ADVANTAGE OF "EXTRA" SPACE! - - org 0 - rmb DRVBEG+(DRVMEM*NUMDRIVE) -* Start of driver-specific statics -SlpCntr rmb 2 # ticks left before we give up on a read/write -PhysDrv rmb 1 Physical drive # (for quick lookup) -DriveFlg rmb NUMDRIVE 1 byte per drive (bit flags) -OS9LSN rmb 3 LSN of current OS-9 256-byte sector -* IDE spec can handle 28 bits (4 bits of 4th byte) for LBA mode. Since OS9 -* can't get that high anyways, we only work with 3, and then use the offset -* partition value to bump it up beyond the 4 GB mark. -OS9PSN rmb 3 PSN of current OS9 sector (512 byte) -DrivMask rmb 1 Drive # (0 or 1) for IDE (in proper bit position) -idecmd rmb 1 1 byte IDE command code -identcmd rmb 1 1 byte IDE Identify drive code - -* Following flag is because the IDE interface can NOT access a 2nd drive -* while the 1st drive is completing a read or write. Because of shared -* device memory variables, this flag is set even on cached entries. -drvrbusy rmb 1 Driver busy flag (0=not busy) - -* Following for CHS mode drives only! -Head rmb 1 Head # (s/b base 0) -Cylinder rmb 2 Cylinder # -CHSSect rmb 1 CHS mode sector # -CHSSPT rmb 2 CHS mode sectors/track - -* Buffer/cache variables -LSN0Flag rmb 1 $FF=Not LSN0, $00=LSN0 -Sect0Drv rmb 1 Drive # of LSN0 currently buffered ($FF=none) -Sect0Ofs rmb 2 Offset value for current LSN0 buffered drive -TempHalf rmb 3 Temp spot to hold other half calculation -HalfDrv rmb 1 Drive # of HalfBuff buffered ($FF=none) -HalfOfs rmb 2 Offset value for drive for current cached sector -HalfSct rmb 3 OS9 sector # of half sector not asked for -TempOfs rmb 2 Temporary copy of partition offset - -* NOTE: When 8k block buffering is added, move both of these to that block. -* Of course, if removable media, re-read LSN0 physically every time. At that -* time, we should make tables here instead (32 entries per drive up to the -* maximum # of drives) of LSN #'s buffered (3 bytes/entry). -Sect0 rmb 256 Buffer for LSN0 -HalfBuff rmb 256 Buffer for other half of 512 byte phys. sector -size equ . - - fcb $FF mode byte - -name fcs /CCIDE/ module name - fcb edition module edition - -* INIT - appears to only be called on 1ST try on ANY IDE device IF link counts -* are 0. -* Y = address of path descriptor (but -* U = address of driver memory (ie, of V.PAGE) -* Inits the drive table, and the DriveFlg table -Init ldd #$8000+NUMDRIVE Flag that special drive flags are all unused - leax DriveFlg,u -DrvFlgLp sta ,x+ - decb - bne DrvFlgLp -GoInit leax DRVBEG,u Point to start of drive tables - ldd #$FF00+NUMDRIVE - stb V.NDRV,u Max # of drives - sta Sect0Drv,u Flag that no LSN0 is buffered - sta HalfDrv,u Flag that we have no half sector buffered -NextDrv sta DD.TOT,x Set Total # of sectors to illegal value - sta V.TRAK,x Non 0, so 1st seek can read Track 0 - leax DRVMEM,x Point to next drive - decb Dec # of drives left - bne NextDrv Still more, init them too - clrb No error & return - rts - -* Do drive diagnostic (use CHS mode) - Do not worry about ATAPI at this point -* Entry: U=driver mem ptr -* Y=path descriptor -* B=Identify command -* Exit: CC clear - drive ready to send info -* CC set - error from drive, B contains raw error register -* TRASHES X - does timeout (CHECK - WILL SOME DRIVES TAKE TOO LONG?) -* This is called by INIT, and should also be called by a GETSTAT at some -* point. -Ident pshs y Save path descriptor - stb identcmd,u Save which Ident we are doing - ldy V.PORT,u Get IDE controller address -DoIdent lda DrivMask,u Get drive # requested - ora #%10100000 Mask in head 0 & CHS mode - std DevHead,y Send drive/head to controller, and IDENTIFY -* Note, if person booting from ROM, drive may not have spun up yet. See if -* we can check some sort of status or error flag that indicates drive is -* still firing up, if this is a problem. - ldx #$a000 Arbitrary amount of time to give up -WaitIdnt lda Status,y Get Status register - bmi NoErr Busy, drop counter - bita #ErrorFnd Error? - beq NoErr No, continue - ldb Error,y Get error code - bra BadIdent - -NoErr cmpa #DrvReady+SeekDone+DataReq Drive ready to send Identify data? - beq GotIdent Yep, exit out - leax -1,x Drop timer - bne WaitIdnt Keep trying - ldb #E$NotRdy Timed out, device not ready error -BadIdent coma Flag error - puls y,pc Restore path descriptor & return - -GotIdent clrb No error - puls y,pc Restore path descriptor & return - -* Send Identify drive command (ATA or ATAPI - see identcmd,u), update DriveFlg -* table -* PLEASE NOTE: The 2 identify commands are mutually exclusive; it will fail -* with an 'Aborted' error if the wrong Identify is used. -* UNLIKE A NORMAL READ OF A SECTOR, THE INFORMATION CONTAINED IN THE IDENTIFY -* DRIVE COMMAND IS ALL IN INTEL ORDER WORD (16 BITS) -* Entry: Y=Ptr to path descriptor -* U=Ptr to driver memory -* X IS DESTROYED! -* Exit: CC=0 if DriveFlg properly updated -* & A=DriveFlg value from update entry in table -* CC=1, B=error if Identify Drive failed -* DriveFlg,u - the proper flags for the specified controller/drive are -* updated -* Sect0 contains 1st 256 bytes, HalfBuff contains 2nd half -IdentDrv lbsr WaitDrv Wait for IDE to be ready - ldb #Identify - bsr Ident Send identify drive command to controller - bcc DoInfo Worked, Do info - bitb #%00000100 Error, Aborted Flag set? - beq ExitIdnt No, exit with other error - ldb #PIIdent Try ATAPI identify - bsr Ident - bcs ExitIdnt That didn't work either, abort -DoInfo leax Sect0,u Point to buffer -* NOTE: INIT routine only gets called when the DRIVER is Initing...not every -* device. Hence, READ/WRITE must check the DriveFlg settings and make sure -* the hi bit is clear for the drive it is using, to indicate that it HAS -* been set properly from an Identify Drive command. -* Read in 1st 256 bytes of Identify Drive buffer, parse out info we need -* for our special flag table - lbsr Read256 Generic 256 byte copy from IDE routine - ldb #$FF Since we made it this far, flag that HalfBuff - stb HalfDrv,u & Sect0Drv are now bogus - stb Sect0Drv,u - clra Set current flags to all off - leax Sect0,u Point to start of buffer again - ldb ,x Get general config low byte - andb #%10000000 Removable cartridge bit set? - beq CheckLBA No, check LBA mode - ora #Remove Set removable media flag -CheckLBA ldb 99,x Get LBA mode byte - andb #%00000010 LBA allowed on this drive? - beq ChkATAPI No - ora #DrvMode Yes, set LBA flag -ChkATAPI ldb identcmd,u Get Identify drive command type - cmpb #PIIdent ATAPI? - bne SetFlg No, set drive flags - ora #ATAPI Set ATAPI flag -SetFlg ldb PD.DNS,y Get special settings flags - bitb #ForceCHS Force CHS mode on? - beq LeavAlon No - anda #^DrvMode Yes, force to CHS mode -LeavAlon ldb PD.DRV,y Get Logical drive # - leax DriveFlg,u Point to drive flags table - sta b,x Save flags - pshs a Save for exit - leax HalfBuff,u Point to 2nd buffer - lbsr Read256 Identify info part 2 - lbsr WaitOK Make sure drive finished command - puls a Restore flags byte -ExitIdnt rts No error, return - -* Entry: U=driver memory ptr -* Y=path descriptor ptr -GetStat ldx PD.RGS,y Get ptr to callers register stack - lda R$B,x Get function code - cmpa #SS.DrInf Drive info command? - bne NextGet No, try next - ldd R$Y,x Get sub-function type - beq GoodFunc - comb Only sub-functions 0 allowed for IDE - ldb #E$IllArg -ExitGet rts - -GoodFunc pshs x,y,u Preserve regs - bsr IdentDrv Get either ATA or ATAPI Identify info - bcc GotInfo Something wrong, return - puls x,y,u,pc Restore regs, return with error - -GotInfo leay Sect0,u Point to start of 512 byte buffer - ldx #256 # of two byte entries in buffer -SwapLoop ldd ,y Swap all words to Motorola order - exg a,b - std ,y++ - leax -1,x - bne SwapLoop - leay Sect0,u Point to start of buffer again - ldx 114,y Get Current Capacity, swap to Motorola - ldd 116,y - stx 116,y - std 114,y - ldx 120,y Get LBA sector count, swap to Motorola - ldd 122,y - stx 122,y - std 120,y - lda <D.SysTsk Get system task # - ldx <D.Proc Get user task ptr - ldb P$Task,x Get user's task # - leax Sect0,u Point to source buffer - ldu ,s Get ptr to PD.RGS - ldu R$X,u Get Destination ptr - ldy #512 Move 512 bytes to caller - os9 F$Move - puls x,y,u Restore regs to normal - bcc SetUserR No error, set exit registers for caller - rts - -SetUserR ldd #512 # of bytes returned=512 (Callers Y) - std R$Y,x - clrb Device type=ATA - lda identcmd,u Get which Identify Drive command worked - cmpa #PIIdent ATAPI? - bne SaveType No, save ATA as type - incb -SaveType lda PD.DRV,y Get logical drive # - leay DriveFlg,u Point to drive flag table - lda a,y Get drive flags - std R$D,x Save drive flags & device type - clrb - rts - -NextGet comb - ldb #E$UnkSvc - rts - -SetStat clrb - rts - -start lbra Init - lbra Read - lbra FWrite - lbra GetStat - lbra SetStat - clrb Term routine (does nothing) - rts - -NotBsy lda #$FF - sta drvrbusy,u - rts - -* Checks if driver is busy, retries & possibly sleeps if it is. -* Set's driver to busy again when done. -* A reg is destroyed, all others are preserved -ChekBusy lda #64 # of fast retries for driver -BsyTst tst drvrbusy,u Is current driver/controller already in use? - beq NotBsy No, continue - deca - bne BsyTst Try up to 64 times - pshs x Otherwise, sleep a tick & try again - ldx #1 - os9 F$Sleep - puls x - bra ChekBusy - -* Save OS9 LSN & Physical PSN (not including any partition offset) -* Also saves sector # of other half that is buffered -* Will have to add check later for ATAPI stuff, up to 2048 bytes/sector -* for CD ROM -* Entry: U=ptr to driver mem -* B:X=OS9 LSN -* Exit: B:X=OS9 LSN -* OS9PSN updated (512 byte Physical sector # that IDE needs) -* TempHalf updated to cached LSN # (Use HalfDrv to figure out if legit -* or not) -* TempOfs updated to current partition offset -* Zero flag set if LSN0 was requested (also saved at LSN0Flag,u) -* PhysDrv set to physical drive # -SavLSN pshs b,x Save work copy of LSN - lda PD.DNS,y Make copy of physical drive # - anda #PhysDriv - sta PhysDrv,u - clra Flag: LSN0 - stb OS9LSN,u Save OS-9 LSN - beq dox Could be LSN0 - inca Not LSN0 -dox stx OS9LSN+1,u - beq doPSN Is LSN0 - inca Not LSN0 -doPSN sta LSN0Flag,u Save LSN0 flag (0=Yes, anything else, no) - stb OS9PSN,u Save OS-9 PSN - stx OS9PSN+1,u - lsr OS9PSN,u Divide LSN by 2 for PSN (512 bytes/sector) - ror OS9PSN+1,u - ror OS9PSN+2,u - bcc Even Even sector requested, half will be odd (+1) -* Subtract 1 from current LSN - ldd 1,s - subd #1 - std 1,s - ldb ,s - sbcb #0 - bra SaveExit - -* Add 1 to current LSN -Even ldd 1,s - addd #1 - std 1,s - ldb ,s - adcb #0 -SaveExit ldx 1,s - stb TempHalf,u Save buffered sector # - stx TempHalf+1,u - leas 3,s Eat temp stack - ldx PD.DEV,y Get ptr to device table entry - ldx V$DESC,x Get device descriptor ptr - ldx PartOfs,x Get partition offset value - stx TempOfs,u Save copy of it - ldb OS9LSN,u Restore LSN - ldx OS9LSN+1,u - lda LSN0Flag,u Set CC bits for LSN0 compare - rts - -* READ -* Entry: Y = address of path descriptor -* U = address of device memory (ie, of V.PAGE) -* B = MSB of OS-9 disk LSN -* X = LSB of OS-9 disk LSN -* Eventually change LSN stuff to use a bit from descriptor as to whether -* buffered LSN0 or not. (After that, add in for general 8k block buffering -* or not). -* Later, add check for DriveFlg that sees if device has removable media. If -* not, and caching for each logical drive is done, keep PERMANENT copy of -* LSN0 at all times, and just copy it when requested (WRITE will update copy -* if new LSN0 is written). -* MAKE SURE WRITE ROUTINE UPDATES CACHING STUFF CORRECTLY! -Read lbsr ChekBusy Wait for driver to be unbusy - bsr SavLSN Save LSN/PSN, PartOfs & HalfSect info - bne NotLSN0 Not LSN0, skip ahead -* Theoretically, following REM'ed out lines will handle removable media: -* lda DriveFlg,u Get drive flag settings -* bita #Remove Removable media? -* bne NotLSN0 Yes, LSN0 may change from disk swap - -* LSN0 - 1st see if buffered - lda PhysDrv,u Get requested physical drive # - cmpa Sect0Drv,u Same drive in LSN0 cache? - bne PhysRead No, go physically read off of drive - ldx TempOfs,u Get copy of partition offset - cmpx Sect0Ofs,u Same as cached LSN0 offset? - bne PhysRead No, physically read the sector -* LSN0 buffered goes here - later add check against DriveFlg with removable -* media bit - if non-removable, copy from cache, otherwise to physical read - leax Sect0,u Point to LSN0 cache - bra CopyBuff Copy to caller's PD.BUF, exit from there - -* Not LSN0 - see if normal sector is currently cached. -* Entry: B:X=LSN -NotLSN0 cmpb HalfSct,u Same as cached sector? - bne PhysRead - cmpx HalfSct+1,u Same as cached sector? - bne PhysRead - lda PhysDrv,u Same drive as cached? - cmpa HalfDrv,u - bne PhysRead No, need physical read of sector - ldd TempOfs,u Get current request's Partition offset - cmpd HalfOfs,u Same as cached? - bne PhysRead No, physical read of sector -* Non-LSN0 sector is cached - if removable drive, force physical read unless -* we somehow monitor disk swaps (some media require Eject commands) - leax HalfBuff,u Point to cached sector -* Copy sector from cache buffer to caller's buffer -* Entry: X=Ptr to cache buffer (either Sect0, or HalfBuff) -CopyBuff clrb 256 counter - ldy PD.BUF,y Point to caller's buffer -CpyLoop lda ,x+ Copy it - sta ,y+ - decb - bne CpyLoop - clr drvrbusy,u Flag driver not busy - rts - -* Not buffered in any way - physical read required - update cache tags AFTER -* read, or flag with $FF if failed. -* Entry: Y=Ptr to path descriptor -* U=Driver mem -PhysRead lbsr InitRead Tell IDE to read sector - bcc DoRead No error, do read -FlagBad lda #$FF If IDE can't even initiate read, flag both - sta Sect0Drv,u LSN0 and HalfBuff as bad - sta HalfDrv,u - lbra RprtErr - -* Entry: Y=path dsc. ptr -* U=Driver mem ptr -DoRead lda OS9LSN+2,u Get LSB of OS9 sector # - lsra Shift 1/2 512 sector flag out - bcs DoOdd Odd sector, buffer even one 1st - ldx PD.BUF,y Get pointer to caller's buffer - bsr Read256 Copy 1st half of HD sector there - leax HalfBuff,u Point to cache buffer - bsr Read256 Copy 2nd half of HD sector there - bra FinRead Finish the Read command on IDE - -* Copy to cache 1st (Odd sector # request) -DoOdd leax HalfBuff,u Point to cache buffer - bsr Read256 1st half goes there - ldx PD.BUF,y Get pointer to caller's buffer - bsr Read256 2nd half goes there -FinRead lbsr WaitOK Wait for drive to complete command - bcc DoneRead No error, exit - lbra RprtErr Exit with error - -* Update HalfSct vars to whatever is in TempHalf -GoodCach ldd TempHalf,u Copy Buffered LSN to HalfSct - std HalfSct,u - lda TempHalf+2,u - sta HalfSct+2,u - ldd TempOfs,u Get partition offset - std HalfOfs,u Save it - lda PhysDrv,u Copy drive # to HalfDrv - sta HalfDrv,u - rts - -* Entry: Read command complete on IDE. -* Y=ptr to path descriptor -* U=ptr to driver mem -DoneRead bsr GoodCach Update HalfSct stuff with Temp stuff - ldb LSN0Flag,u Was this LSN0? - bne GoodExit No, leave -* LSN0 just physically read - update drive table -* CHANGE EVENTUALLY TO CHECK IF NON-REMOVABLE MEDIA; IF IT IS, DON'T BOTHER -* WITH THESE CHECKS! - sta Sect0Drv,u Save which drive LSN0 is buffered - ldd TempOfs,u Restore partition offset again - std Sect0Ofs,u Save for LSN0 - leax Sect0,u Point to LSN0 buffer - clrb 256 counter - pshs y Save path dsc. ptr - ldy PD.BUF,y Point to caller's buffer -LSN0Loop lda ,y+ Copy LSN0 from callers buffer to LSN0 cache - sta ,x+ - decb - bne LSN0Loop - puls y Restore path dsc. ptr - leax Sect0,u Point to LSN0 cache again -CopyTbl1 lbsr CpyDrvTb Copy LSN0 stuff to drive table -GoodExit clr drvrbusy,u No error & return - rts - -* Initiate the 512 byte READ sequence -* Entry: U=Driver mem ptr -* Y=Path dsc. ptr (?) -* Exit: CC=0 if no error -* CC=1 if error -* B=Error code -InitRead ldb #ReadRtry Read sector (with retry) IDE command - lbra SetIDE Send to IDE, return from there (w or w/o err) - -* Copy 256 bytes of data from IDE controller (after READ, etc.) -* Entry: X=ptr to 256 byte destination buffer -* U=ptr to driver memory -* Exit: 256 bytes copied -* B is destroyed, A=0 -* Y is preserved -Read256 lda #$20 # of loops (of 8 bytes) - pshs y,a Save y & counter - ldy V.PORT,u Get ptr to IDE controller for this drive -ReadLp lda ,y Get 16 bits of data, and save in buffer, 8 - ldb Latch,y times - std ,x - lda ,y - ldb Latch,y - std 2,x - lda ,y - ldb Latch,y - std 4,x - lda ,y - ldb Latch,y - std 6,x - leax 8,x Bump ptr up - dec ,s Done all bytes? - bne ReadLp No, keep going - puls a,y,pc Restore Y & return - -* WRITE - Can use cache data, or preread sector -* Y = address of path descriptor -* U = address of device memory (ie, of V.PAGE) -* B = MSB of OS-9 disk LSN -* X = LSB of OS-9 disk LSN -* 1st , see if other half is buffered in HalfBuff -FWrite lbsr ChekBusy Wait for driver to be unbusy - lbsr SavLSN Save LSN info, set LSN0Flag for later - ldb TempHalf,u Get OS9 LSN of 'other half' of 512 byte sector - cmpb HalfSct,u Same MSB of buffered sector #? - bne ChkLSN1 No, check if LSN1 - ldx TempHalf+1,u LSW of 'other half' - cmpx HalfSct+1,u Same as LSW of buffered sector #? - bne ChkLsn1 No, check if LSN1 - ldd HalfOfs,u Same partition as buffered sector's drive? - cmpd TempOfs,u - bne ChkLsn1 No, check if LSN1 - lda PhysDrv,u Same physical drive as buffered sector's drive? - cmpa HalfDrv,u Same as buffered sector's drive? - bne ChkLsn1 No, check is LSN1 -* Buffered sector IS the other half of current write sector...no preread nec- -* essary. - lbsr InitWrit Send Write command to IDE, setup mode, etc. - bcc GoodWrit No problems, continue with Write - lbra FlagBad Flag caches as bad, exit with error - -* See if request is for LSN1, in which case we may have LSN0 buffered -ChkLSN1 ldb OS9LSN,u Get MSB of sector to write - bne PreRead Not 0, need physical preread - ldx OS9LSN+1,u Get LSW of sector to write - cmpx #1 LSN=1? - bne PreRead Not LSN1, need to preread sector - lda PhysDrv,u Get physical drive # - cmpa Sect0Drv,u Same as buffered LSN0? - bne PreRead No, need physical preread - ldd TempOfs,u Get partition offset of requested sector - cmpd Sect0Ofs,u Same as buffered? - bne PreRead -* We have LSN0 buffered for an LSN1 write - lbsr InitWrit Send Write to IDE - bcc ContWrt1 Successful, continue - lbra RprtErr - -ContWrt1 leax Sect0,u Point to buffered Sector 0 - bsr Write256 Write to IDE - ldx PD.BUF,y Get ptr to caller's LSN1 buffer - bsr Write256 Write to IDE - bra FinWrite Complete the write command - -* Nothing buffered, pre-read sector in so we have other half to write. -* Note that OS9PSN is already set to the correct physical sector. -PreRead lbsr InitRead Send Read command to IDE - bcc GotPreRd No problem, continue - lbra FlagBad Flag caches as bad; exit with error - -GotPreRd lda OS9LSN+2,u Get least sig. byte of LSN to write - lsra Odd or even sector? - bcc ReadOdd Even write sector requested -* Odd write requested - leax HalfBuff,u Point to 1/2 sector cache - lbsr Read256 Read it in - bsr Eat256 Bleed off other half (not needed) - bra FinPre - -* Even sector to write - buffer odd one -ReadOdd bsr Eat256 Bleed 1st half - leax HalfBuff,u Read in 2nd half - lbsr Read256 -FinPre lbsr WaitOK Get OK from controller - bcc DonePre Good, continue -BadExit lbra RprtErr Error, exit with it - -DonePre lbsr GoodCach Update HalfSct stuff only - lbsr InitWrit Initialize Write command - bcs BadExit -* Now, onto the write -GoodWrit ldb OS9LSN+2,u Get least sig. byte of LSN - lsrb Odd or even sector to write? - bcs BuffWOdd Write fully buffered Odd -* We are writing even portion, odd is in cache - ldx PD.BUF,y Get ptr to caller's 256 byte buffer - bsr Write256 Write to IDE - leax HalfBuff,u Point to cached sector - bsr Write256 Write to IDE - bra FinWrite - -BuffWOdd leax HalfBuff,u Point to cached sector - bsr Write256 Write to IDE - ldx PD.BUF,y Point to caller's 256 byte buffer - bsr Write256 Write to IDE -FinWrite lbsr WaitOK Wait for IDE to be done command - bcc DoneWrit No error, done writing - lbra RprtErr Error, exit with it - -* Write 256 bytes from ,x to IDE -* Entry: X=ptr to 256 buffer to write -* U=driver mem ptr -* Exit: 256 bytes written -* B is destroyed, A=0 -* X=end of buffer+1 -* Y is preserved -Write256 lda #$20 # of 8 byte loops - pshs y,a Save Y & loop counter - ldy V.PORT,u Get IDE base address -WritLp ldd ,x Copy 256 bytes from buffer to IDE - stb Latch,y - sta ,y - ldd 2,x - stb Latch,y - sta ,y - ldd 4,x - stb Latch,y - sta ,y - ldd 6,x - stb Latch,y - sta ,y - leax 8,x - dec ,s - bne WritLp - puls a,y,pc Restore regs & return - -* Eat 256 bytes from IDE (hopefully, triggering latch will skip having to -* read even bytes) -* Entry: U=driver memory ptr -* Y=Path descriptor ptr -* Exit: 256 bytes bled off of sector buffer on IDE -* All regs preserved -Eat256 pshs d,x Save regs - ldb #$20 32 loops - ldx V.PORT,u Get pointer to IDE -EatLp lda ,x Read seems to be a pre-trigger - lda ,x Eat each 16 bit trigger byte - lda ,x - lda ,x - decb - bne EatLp - puls d,x,pc Restore regs & return - -* Write command to IDE completed successfully -* Update cache (copy PD.BUF to Cache if even sector, so a sequential -* write will have the 1st half cached, or leave current cache alone if -* odd). Also, check if LSN0. If it is, copy to LSN0 cache, updating -* vars, and copy drive table info -DoneWrit ldb LSN0Flag,u Was it sector 0? - beq WritLSN0 Yes, special processing for that - ldb OS9LSN+2,u Get LSB of sector # - lsrb Odd/Even? - bcc CpyCache Even, copy to Cache -* Odd sector written, leave cache as is - clr drvrbusy,u Exit without error - rts - -* Copy PD.BUF sector to HalfBuff cache, update cache tags -CpyCache lda PhysDrv,u Set cache vars for PD.BUF sector - sta HalfDrv,u - ldd TempOfs,u - std HalfOfs,u - ldd OS9LSN,u - std HalfSct,u - lda OS9LSN+2,u - sta HalfSct+2,u - leax HalfBuff,u Point to 1/2 sector cache -CachBuff clrb - ldy PD.BUF,y Get ptr to callers buffer -CachLp lda ,y+ Copy even sector to cache (in case of sequential - sta ,x+ writes) - decb - bne CachLp - clr drvrbusy,u - rts - -* We wrote LSN0 - 1st, update LSN0 cache tags, then copy PD.BUF to Sect0, -* then update drive table entry. -* Entry: U=drive mem ptr -* Y=path dsc. ptr -WritLSN0 lda PhysDrv,u Copy cache tag stuff for Sect0 cache - sta Sect0Drv,u - ldd TempOfs,u - std Sect0Ofs,u - leax Sect0,u Point to LSN0 cache - bsr CachBuff Copy from PD.BUF to Sect0 buff - leax Sect0,u Point to LSN0 cache again - clr drvrbusy,u - lbra CpyDrvTb Copy info to drive table, exit from there - -* Initialize Write sequence to IDE -* Entry: U=driver mem ptr -* Y=Ptr to path descriptor -* Exits back to calling routine. CC=0 if command ready on controller -* CC=1, B=Raw IDE error code if command failed -InitWrit ldb #WritRtry IDE Write w/ Retry command - bra SetIDE Send to IDE, return from there w or w/o error - -* After read or write, check drive status -* Exit: CC=0, command ok, CC=1, Error from IDE (B=Raw error code) -* X=Ptr to hardware address -WaitOK ldx V.PORT,u Get status register -WaitLp tst Status,x Still busy, wait till unbusy - bmi WaitLp - lda #ErrorFnd Check Error flag - bita Status,x Error from controller? - bne RprtErr Yes, go get error - clrb No, exit without error - rts - -* Entry: B=Error code from IDE -RprtErr lsrb - bcc ChkTk0 -SctrExit ldb #E$Sect Bad sector # for Addres Mark Not Found - bra ExitErr - -ChkTk0 lsrb - bcc ChkMdChg -SeekExit ldb #E$Seek Seek error for Track 0 not found - bra ExitErr - -ChkMdChg lsrb - bcc ChkAbrt -MdChExit ldb #E$DIDC Media changed error - bra ExitErr - -ChkAbrt lsrb - bcc ChkIdnf - ldb #E$UnkSvc Unknown service error for aborted command - bra ExitErr - -ChkIdnf lsrb - bcs SctrExit Sector error for ID not found - lsrb - bcs MdChExit Media changed error for Media Change - lsrb - bcc ChkBBK - ldb #E$CRC CRC Error for Uncorrectable data - bra ExitErr - -ChkBBK lsrb - bcs ReadExit Read error for Bad Block Detected -* Error flag set, but no error condition - lbra ENotRdy Assume drive not ready - -ReadExit ldb #E$Read -ExitErr clr drvrbusy,u Flag driver not busy - coma Set carry & exit - rts - -BadUnit ldb #E$Unit - bra ExitErr - -CmdErr ldb Error,x Get Error register - bra RprtErr - -* Send IDE command (read or write) -* Entry: B = IDE command code -* Y = address of path descriptor -* U = address of device memory (ie, of V.PAGE) -* trashes D and X -* Exit: CC=0 if command exited with data ready on controller -* CC=1, B=error if problem. -SetIDE stb idecmd,u Save copy of IDE command - ldb PD.DRV,y Get logical drive # - cmpb #NUMDRIVE Within range? - bhs BadUnit No, exit with error - leax DriveFlg,u Point to special drive flags table - lda b,x Get flags for our drive - bpl TblReady Properly initialized, figure out mode - lbsr IdentDrv NOT Initialized, get mode info - bcs CmdErr Error doing IDENTIFY DRIVE command, exit -TblReady anda #DrvMode Just need CHS/LBA mode for now - bne DoLBA LBA mode, go do -* Do CHS mode - ldd PD.SCT,y Get # of OS9 (256) sectors/track - lsra Convert to 512 byte sectors/track - rorb - std CHSSPT,u Save for Calc routine - ldx PD.DTB,y Get pointer to device table - lbsr CalcCHS Go calculate cyl/head/sector stuff - bcs CmdErr Error calculating, exit - lbsr WaitDrv Go wait for the drive (preserves y) - bcs CmdErr Error waiting for drive, exit -* Do sector #, then Drive/Head, then Cyl, then sector count, then command - pshs y Save path descriptor ptr - ldy V.PORT,u Get IDE hardware address - lda CHSSect,u Get IDE sector # - sta SectNum,y Save to controller - lda Head,u Get IDE head # - ora #%10100000 Set CHS mode - ora DrivMask,u Merge drive # - sta DevHead,y Save to controller - ldd Cylinder,u Get 16 bit cylinder # (4095 max) - addd TempOfs,u Add partition offset cylinder - bcs SeekErr If it overflowed, SEEK error - sta CylHigh,y Save to controller - stb CylLow,y - bra SendCmd Send sector count & IDE command - -* Do LBA mode IDE command here -DoLBA bsr WaitDrv Wait for controller to be ready - pshs y Save path descriptor ptr - ldy V.PORT,u Get IDE hardware address -* Copy LBA sector # to controller, including device/head (LBA 24-27) - ldd OS9PSN+1,u Get bits 0-15 of PSN - stb SectNum,y Save bits 0-7 - sta CylLow,y Save bit 8-15 - clra - ldb OS9PSN,u D=PSN bits 16-23 (24 & up set to 0 for OS9) - addd TempOfs,u Add partition offset cylinder - cmpa #$0f Overflow past LBA bits? - bhi SeekErr Yes, SEEK error - stb CylHigh,y Save bits 16-23 - ora #%11100000 Set LBA mode - ora DrivMask,u Merge drive # - sta DevHead,y Save to controller -* Send sector count (1) & command to controller, get results -SendCmd ldx #MAXWAIT Get # 1/60th sec. ticks to wait on drive - stx SlpCntr,u Save it for sleep routine (if needed) - ldd #$0140 Sector count to 1, fast retry to 64 tries - sta SectCnt,y Send to controller - lda idecmd,u Get command to send - sta Command,y Send to controller -CmdLp lda Status,y Get status of drive command - bmi CmdLp IDE still busy, no other bits are valid - bita #ErrorFnd Not busy anymore, is there an error? - bne TransErr Yes, figure out what (don't forget to PULS Y!) - bita #DataReq Is data ready for us yet? - bne CmdDone Yes, exit - decb Dec counter - bne CmdLp Keep trying - ldx SlpCntr,u Get sleep tick counter - leax -1,x Drop it by one - beq NoWay Done count, give up with device not ready error - stx SlpCntr,u Save new sleep counter - ldx #1 Fast retry didn't work, sleep a tick - os9 F$Sleep - ldb #$40 64 fast retries again - bra CmdLp Try again - -SeekErr lbsr SeekExit Seek error & exit - puls y,pc - -NoWay puls y - bra ENotRdy - -TransErr lbsr CmdErr Get error code - puls y,pc Exit with it, restore path dsc. ptr - -CmdDone clrb Command complete, return with no error - puls y,pc Restore path dsc. ptr - -* Wait for IDE controller to be ready -* Entry: Y=path dsc. ptr -* U=driver mem ptr -* Exit: CC=0 - controller ready for command -* CC=1 - Error message in B -* DrivMask,u - contains drive # bit ready for IDE masking -* PRESERVES X&Y -WaitDrv pshs x,y Preserve regs - ldx #$A000 (1/2 to 1/3 second busy check) - lda PD.DNS,y Get physical drive # - anda #PhysDriv No bad drive # possible - lsla Move drive # into proper bit for Drive/head - lsla - lsla - lsla - sta DrivMask,u Save drive mask for IDE - ldy V.PORT,u Get controller address for drive selected -RdyIni1 tst Status,y IDE busy? - bpl IDEReady No, return - leax -1,x Dec counter - bne RdyIni1 Try again - puls x,y Restore regs -ENotRdy clr drvrbusy,u - comb Tried too long; give up with error - ldb #E$NotRdy - rts - -IDEReady puls x,y Restore regs - clrb IDE ready, return - rts - -* Copy LSN0 stuff into drive table -* Entry: X=ptr to 256 byte buffer containing LSN0 Sector. -* Exit: X,D is destroyed -CpyDrvTb pshs y Save path desc. ptr - ldb PD.DRV,y Get LOGICAL drive # - lda #DRVMEM Copy useful information to our LSN 0 buffer - mul Point to proper entry in drive table - leay DRVBEG,u - leay d,y - lda #DD.SIZ -LSN0Cp ldb ,x+ - stb ,y+ - deca - bne LSN0Cp - puls y,pc Restore path desc. ptr & return - -* Notes: PhysSN is the physical sector number to send to the controller, -* not the LSN...so it must be translated from the LSN (for IDE, divide by -* 2, unless using ATAPI CDROM, in which case divide by 8). -* Note that the head returned from this routine is base 0, so that the -* lowest head # returned would be 0 (for the first head). This matches -* the IDE spec (which can also only go up to 16 heads). -* The cylinder returned is also base 0, same as IDE. -* The sector returned is base 0, but IDE needs base 1. -* Vars used from elsewhere - OS9PSN,u - Physical (IDE 512) sector # -* - Head,u - IDE head # -* - Cylinder,u - IDE Cylinder # -* - CHSSect,u - IDE sector (512) # -* - CHSSPT,u - IDE (512 byte) sctrs/track) - -* LSN division routine variable definitions: all on temp stack - org 0 -S.SclPwr rmb 2 scale power -S.SclAmt rmb 3 scale amount -S.Cyl rmb 2 cylinder number -S.PSN rmb 3 physical sector number (work copy) -S.Head rmb 1 head number -S.Frame equ . size of stack frame - -* Entry: U=ptr to driver data area -* Y=Ptr to path descriptor -* X=Ptr to current drives' entry in drive table (DD.TOT, etc.) -* OS9PSN,u- Three byte Physical (512 byte) sector #) -* Exit: U=ptr to driver data area -* Y=ptr to path descriptor -* X=Drive table ptr -* Head,u=Head # in CHS mode -* Cylinder,u=Cylinder # in CHS mode -* CHSSect,u=Sector # in CHS mode -* CC=0, no error, above 3 vars. are legit -* CC=1, error, error return in B -CalcCHS leas -S.Frame,s make room for LSN division variables - ldb OS9PSN,u - stb S.PSN,s initialize PSN MSB - ldd OS9PSN+1,u - std S.PSN+1,s initialize PSN LSBs - ldd #$0000 - sta S.Head,s initialize head number - std S.Cyl,s initialize cylinder number - ldd S.PSN+1,s get PSN LSBs - subd CHSSPT,u less sectors/track - bhs NotTrk0 - tst S.PSN,s PSN MSB = 0? - beq DivDone yes, sector in track 0, go save info - dec S.PSN,s PSN MSB less 1 -NotTrk0 std S.PSN+1,s save remaining PSN LSBs - inc S.Head,s set to next head (1) - inc V.TRAK+1,x mark track as non-0 for SetUpWD - ldb CHSSPT+1,u get IDE sectors per track - lda PD.SID,y Get # of disk heads - deca less track 0 - mul calculate sectors remaining in cylinder 0 - std S.SclPwr,s save it temporarily - ldd S.PSN+1,s get remaining PSN LSBs - subd S.SclPwr,s less sectors remaining in cylinder 0 - bhs NotCyl0 - tst S.PSN,s remaining PSN MSB = 0? - beq CalcHead sector in cylinder 0, go get head number - dec S.PSN,s remaining PSN MSB less 1 -NotCyl0 std S.PSN+1,s save remaining PSN LSBs - inc S.Cyl+1,s set cylinder to 1 - clr S.Head,s reset head number to 0 - lda PD.SID,y get disk sides - ldb CHSSPT+1,u get sectors per track -NrmlDiv clr S.SclAmt+2,s initialize scale amount LSB - lsla HD prescale = heads x 8 - lsla This is the max we can do with a 16 head - lsla drive, using 8 bit MUL. - mul calculate scale amount MSBs - std S.SclAmt,s save scale amount MSBs - ldd #HDSclPwr Set hard drive scale power - std S.SclPwr,s save scale power -DivLoop lda S.PSN,s get remaining PSN MSB - cmpa S.SclAmt,s remaining PSN > scale amount? - blo DivLoop1 no, go set up next scale amount & power - bhi DivLoop2 yes, go do subtraction - ldd S.PSN+1,s get remaining PSN LSBs - subd S.SclAmt+1,s remaining PSN >= scale amount? - blo DivLoop1 no, go set up next scale amount & power - std S.PSN+1,s save remaining PSN LSBs - bra DivLoop3 - -DivLoop2 ldd S.PSN+1,s get remaining PSN LSBs - subd S.SclAmt+1,s less scale amount LSBs - std S.PSN+1,s save remaining PSN LSBs -DivLoop3 lda S.PSN,s get remaining PSN MSB - sbca S.SclAmt,s less scale amount MSB and borrow (if any) - sta S.PSN,s save remaining PSN MSB - ldd S.Cyl,s get cylinder number - addd S.SclPwr,s add scale power - std S.Cyl,s save cylinder number -DivLoop1 lsr S.SclAmt,s * divide scale amount by two - ror S.SclAmt+1,s - ror S.SclAmt+2,s - lsr S.SclPwr,s * divide scale power by two - ror S.SclPwr+1,s - bcc DivLoop -CalcHead ldd S.PSN+1,s get remaining PSN LSBs -NextHead subd CHSSPT,u less sectors per track (head) - blo DivDone underflow, go save info - std S.PSN+1,s save remaining PSN LSBs - inc S.Head,s increment head number - bra NextHead - -DivDone ldd S.Cyl,s get cylinder number - cmpd PD.CYL,y cylinder number OK? - bhs LSNErrSF no, go return error - std Cylinder,u - lda S.PSN+2,s get sector number (remaining PSN LSB) - inca IDE needs base 1 - sta CHSSect,u - ldb S.Head,s get head number - stb Head,u - leas S.Frame,s restore stack pointer - clrb - rts - -LSNErrSF leas S.Frame,s restore stack pointer -LSNErr comb - ldb #E$Sect Exit with Bad sector # error - rts - - emod -eom equ * - end +******************************************************************** +* CCIDE - IDE device driver for CoCo +* +* $Id$ +* +* Driver originally from Jim Hathaway, originally 8-bit only +* Converted to 16 bit by Alan DeKok +* Disassembled (OK, so I didn't have the source version at first!) +* by Eddie Kuns, ATA specs followed carefully and sector buffering +* on writes handled more carefully +* +* This driver uses 16-bit transfers *only* +* +* Ed. Comments Who YY/MM/DD +* ------------------------------------------------------------------ +* 5 Source as distributed by Glenside 99/05/02 +* Added comments from 8 bit driver BGP 99/05/07 +* 6 Driver now gets address from descriptor, made BGP 99/05/10 +* minor optimizations, added symbols + +* Maximum number of drives to support +NUMDRIVE equ 4 + + nam CCIDE + ttl IDE device driver for CoCo + + ifp1 + use defsfile + use rbfdefs + endc + +tylg set Drivr+Objct +atrv set ReEnt+rev +rev set $01 +edition equ 6 + + mod eom,name,tylg,atrv,start,size + + org 0 + rmb DRVBEG+(DRVMEM*NUMDRIVE) +* Start of driver-specific statics +OS9LSN rmb 3 LSN of current OS-9 256-byte sector +Counter rmb 1 +idecmd rmb 1 1 byte IDE command code + rmb 20 +size equ . + + fcb $FF mode byte + +name fcs /CCIDE/ module name + fcb edition module edition + +start lbra Init + lbra FRead + lbra FWrite + lbra GetStat + lbra SetStat + lbra Term +* +* INIT +* +* Y = address of path descriptor +* U = address of device memory (ie, of V.PAGE) +* +Init ldx #$1500 delay loop value + ldy V.PORT,u +RdyIni1 tst 7,y Wait for drive ready + bpl GoInit + leax -1,x + bne RdyIni1 + lbeq ENotRdy Timed out ... give up on drive + +GoInit ldd #$AF20 Drive is ready -- initialize +* For IDE command $91, DrvHd reg = 101xhhhh binary + sta 6,y $10 heads (x=0-master/1-slave; hhhh=#heads) + stb 2,y $20 sectors/track + lda #$91 + sta 7,y Give drive the Init Drive Parameters IDE command +RdyIni2 tst 7,y + bmi RdyIni2 Wait *forever* until drive is ready + +* Initialize drive table (only first is inited here) + leax DRVBEG,u + lda #1 + sta V.NDRV,u + lda #$FF + sta DD.TOT+2,x + sta V.TRAK,x + +GetStat +SetStat +Term clrb + rts + +SavLSN stb OS9LSN,u Save OS-9 LSN + stx OS9LSN+1,u + rts +* +* READ +* +* Y = address of path descriptor +* U = address of device memory (ie, of V.PAGE) +* B = MSB of OS-9 disk LSN +* X = LSB of OS-9 disk LSN +* +FRead bsr SavLSN + ldb #$20 + lbsr SetIDE + bcs Ret + ldx PD.BUF,y + lda #$20 + sta Counter,u + pshs y + ldy V.PORT,u +ReadLp lda ,y + ldb ,y + std ,x++ + lda ,y + ldb ,y + std ,x++ + lda ,y + ldb ,y + std ,x++ + lda ,y + ldb ,y + std ,x++ + dec Counter,u + bne ReadLp + puls y + + ldx OS9LSN+1,u Is this LSN 0? + bne NotLSN0 + ldb OS9LSN,u + bne NotLSN0 + ldx PD.BUF,y + + pshs y Yes, it is LSN 0 + lda #DD.SIZ Copy useful information to our LSN 0 buffer + leay DRVBEG,u +LSN0Cp ldb ,x+ + stb ,y+ + deca + bne LSN0Cp + puls y Done with LSN 0 stuff + +NotLSN0 bsr WaitOK Wait for drive to complete command + bcc Ret + lbra ReadErr +Ret rts + +* +* WRITE +* +* Y = address of path descriptor +* U = address of device memory (ie, of V.PAGE) +* B = MSB of OS-9 disk LSN +* X = LSB of OS-9 disk LSN +* +FWrite lbsr SavLSN Save LSN info +* +* *** HACK *** Read the 2 sectors into our buffer first +* + ldb #$30 IDE Read w/ Retry command + lbsr SetIDE Setup IDE command registers + bcs ReadDone + pshs y + ldx PD.BUF,y + lda #$20 + sta Counter,u + ldy V.PORT,u +HackLp ldd ,x++ + sta ,y + stb ,y + ldd ,x++ + sta ,y + stb ,y + ldd ,x++ + sta ,y + stb ,y + ldd ,x++ + sta ,y + stb ,y + dec Counter,u + bne HackLp + puls y + bsr WaitOK Wait for drive to finish command + bcc ReadDone + lbsr WriteErr +ReadDone rts +* +* After read or write, check drive status +* Return value = CC, true=error, false=OK +* +WaitOK ldy V.PORT,u Is DRQ still true? Just one check necessary + tst 7,y If it is, sector isn't fully transferred + bmi WaitOK + lda #$01 Wait *forever* for drive ready + bita 7,y + bne CmdErr + clrb Nope -- clear CC + rts +CmdErr comb Yep -- set CC + rts + +* +* Setup IDE read or write operation +* +* B = IDE command code +* +* trashes D and X +* +SetIDE stb idecmd,u + pshs y + ldx #$A000 +CmdLp1 ldy V.PORT,u + tst 7,y + bpl SetRdy Should go to ChkDRDY ????? + leax -1,x + bne CmdLp1 + puls y + bra ENotRdy + +SetRdy ldy V.PORT,u Drive is ready -- calculate HCS from LSN + lda OS9LSN+2,u Sector first + anda #$1F + adda #$01 + sta 3,y Store calculated sector number + ldd OS9LSN+1,u Drive number next + rolb + rola + rolb + rola + rolb + rola + anda #$0F + ora #$A0 + sta 6,y Store calculated drive number + ldd OS9LSN,u Last, the cylinder number (2-bytes) + rora + rorb + anda #$7F + sta 5,y Store calculated CylHi + stb 4,y Store calculated CylLo + lda #$01 + sta 2,y Sector count = 1 + ldb idecmd,u + stb 7,y Lastly, push the command to the drive + ldb #$40 + lda #$08 Wait for Drive ready +CmdLp2 bita 7,y + bne CmdDone + decb + bne CmdLp2 + ldx #$0001 If we time out, sleep 1 tick, then loop *forever* + os9 F$Sleep +CmdLp3 bita 7,y + beq CmdLp3 +CmdDone puls y + clrb All right, drive ready -- return + rts + +ENotRdy comb + ldb #E$NotRdy + rts +WriteErr comb + ldb #E$Write + rts +ReadErr comb + ldb #E$Read + rts + + emod +eom equ * + end
--- a/3rdparty/drivers/ide/defsfile Thu Apr 11 19:34:44 2002 +0000 +++ b/3rdparty/drivers/ide/defsfile Mon Apr 15 20:48:57 2002 +0000 @@ -1,3 +1,9 @@ -Level equ 2 use os9defs -* use rbfdefs +* use rbfdefs + + ifeq Level-1 + use systype.l1 + else + use systype.l2 + endc +
--- a/3rdparty/drivers/ide/h0_ide.asm Thu Apr 11 19:34:44 2002 +0000 +++ b/3rdparty/drivers/ide/h0_ide.asm Mon Apr 15 20:48:57 2002 +0000 @@ -23,7 +23,7 @@ mod eom,name,tylg,atrv,mgrnam,drvnam fcb DIR.!ISIZ.!SHARE.!PEXEC.!PWRIT.!PREAD.!EXEC.!UPDAT. mode byte - fcb $FF extended controller address + fcb HW.Page extended controller address fdb $FF70 physical controller address fcb initsize-*-1 initilization table size fcb DT.RBF device type:0=scf,1=rbf,2=pipe,3=scf
--- a/3rdparty/drivers/ide/makefile Thu Apr 11 19:34:44 2002 +0000 +++ b/3rdparty/drivers/ide/makefile Mon Apr 15 20:48:57 2002 +0000 @@ -1,12 +1,26 @@ include ../../../Makefile.rules DEPENDS = ./Makefile -DRVRS = ccide.dr -DESCS = h0_ide.dd +DRVRS = ccide_l1.dr ccide_l2.dr +DESCS = h0_ide_l1.dd h0_ide_l2.dd ALLOBJS = $(DRVRS) $(DESCS) +IDEL1FLAGS = $(AFLAGS) -aLevel=1 +IDEL2FLAGS = $(AFLAGS) -aLevel=2 all: $(ALLOBJS) $(DEPENDS) +ccide_l1.dr: ccide.asm + $(AS) $(ASOUT)$@ $< $(IDEL1FLAGS) + +ccide_l2.dr: ccide.asm + $(AS) $(ASOUT)$@ $< $(IDEL2FLAGS) + +h0_ide_l1.dd: h0_ide.asm + $(AS) $(ASOUT)$@ $< $(IDEL1FLAGS) + +h0_ide_l2.dd: h0_ide.asm + $(AS) $(ASOUT)$@ $< $(IDEL2FLAGS) + clean: $(RM) $(ALLOBJS)