comparison 3rdparty/drivers/ide/ccide.asm @ 89:2727056db0d3

Updated to Curtis Boyle's latest IDE driver, works with L1 and L2
author boisy
date Thu, 27 Jun 2002 18:10:41 +0000 (2002-06-27)
parents 8b423669e5d2
children 16dc49e3a104
comparison
equal deleted inserted replaced
88:93d2c224fa1f 89:2727056db0d3
1 * NOTE: Currently, will return RAW error #'s from drive (see ATA bit flags
2 * in error register). After driver finalized, switch back to OS9 error
3 * codes.
4 * NOTE 2: drvrbusy checks are done even before hardware access, because
5 * some variables are shared in the driver memory, and if a 2nd request
6 * comes in in the middle of it, the vars might be changed at a dangerous
7 * time. Note if you have two IDE controllers: since they get separate driver
8 * memory from each other, that both controllers CAN be active at the same
9 * time.
10 * BIG NOTE ON OLDER ATA-1 DRIVES!!!
11 * SOME DRIVES (MY MINISCRIBE 8051A INCLUDED) HAVE A TRANSLATION MODE THAT
12 * _IS_BUILT_INTO_THE_IDE_ROM_ITSELF! THE BAD PART IS, THE "IDENTIFY DRIVE"
13 * COMMAND _DOES_NOT_ TAKE THIS INTO CONSIDERATION, BUT RETURNS THE "NATIVE"
14 * DRIVE SPECS FOR CYLINDERS, HEADS & SECTORS PER TRACK. TO GET THE FULL
15 * CAPACITY OF THE DRIVE, WITHOUT ERRORS, YOU _MUST_ SET YOUR DEVICE
16 * DESCRIPTOR BASED ON THE HARDWARE _TRANSLATED_ SETTINGS, _NOT_ THE _NATIVE_
17 * SETTINGS (DESCRIBED IN THE IDENTIFY DRIVE COMMAND)! AS A REAL WORLD
18 * EXAMPLE, ON MY MINISCRIBE 8051A:
19 * Drives "Native" mode (as well as the Identify Drive command) returns:
20 * 745 cylinders, 4 heads & 28 sectors/cylinder.
21 * HOWEVER, the "Translation" mode (which is checked off on the sticker on
22 * the drive itself from the manufacturer), says:
23 * Translated: 5 heads, 17 sectors. At this point, you will have to figure
24 * out the # of cylinders, by computing the # of sectors TOTAL for the
25 * drive in it's native mode (745*4*28 in the above example, or 83,440
26 * sectors), and then dividing that value by (# of sectors/track * # of
27 * heads) in the translation mode, and rounding down. In the above case,
28 * 83,440/(5*17)=981.647, so use 981 (which in hex is $03d5).
29 * Therefore, the proper device descriptor for this drive is:
30 * cyl=3d5 sid=5 sct=22 t0s=22 (Actually, t0s is ignored by CCIDE)
31 * The sct=22 is because the value is hexidecimal (it means 34 sectors/
32 * track), and is double the 17 I mentioned above because OS9 sectors are
33 * half the size of IDE sectors (256 bytes vs. 512 bytes). If this drive
34 * had been shipped in "Native" mode, it would use the following:
35 * cyl=2E9 sid=4 sct=38 t0s=38, which is what the IDENTIFY DRIVE command
36 * reports.
37 * You can verify the highest cylinder # by setting the OFS in the descriptor
38 * to what you think is the highest cylinder # (total # of cylinders-1 ...
39 * remember that CHS cylinder numbers start at 0!), and then try to read
40 * enough sectors to cover the whole track. If you go one past that value,
41 * you should start getting errors if you have the right cylinder count.
42 * This is kind of a dumb system, but I assume it had something to do with
43 * IBM PC BIOS in the early days of IDE.
44 *A LITTLE LATER, WHEN THE DRIVER IS STABLE, MAY WANT TO ADD ANOTHER BIT FLAG
45 * TO DRIVEFLG, SET UP BY A FIRST TIME READ: 8 BIT ACCEPTED. THEN, USE THE 8
46 * BIT TRANSFER MODE IF POSSIBLE (LIKE I DID WITH LBA). THIS SHOULD ALLOW
47 * MUCH FASTER SECTOR ACCESS ON A NITROS9 SYSTEM, AND IT WOULD BE INTERESTING
48 * TO SEE HOW MANY DRIVES ACCEPT THAT MODE (SUPPOSED TO RETURN AN 'ABORTED'
49 * FLAG IF IT DOES NOT).
50 * NOTE: RBF WILL ASSIGN NEW DEVICE MEM (,U PTR) TO _EACH_ CONTROLLER ON IT'S
51 * OWN, BASED ON THE BASE ADDRESS FROM THE DEVICE DESCRIPTOR. THEREFORE,
52 * CCIDE SHOULD BE SET UP FOR _2_ DRIVES MAX (PER CONTROLLER), AND LET RBF
53 * TAKE CARE OF MULTIPLE CONTROLLERS.
54 * The exception to this is when using partitions; since they will have a
55 * separate descriptor for each partition, they will need a separate drive
56 * table entry. Each table entry is $26 (38) bytes each, so it is not a lot.
57 * Should make the device table fill up the rest of a 256 byte page (with
58 * all other variables allocated), since OS9 will force System RAM pages to
59 * even multiples of 256 anyways. Once full 8k block caching is implemented,
60 * some of the two 256 byte sector buffers currently in system RAM could be
61 * reused for more drive table entries as well. With current system RAM
62 * requirements in driver, this would allow 5 device table entries without
63 * taking any more system RAM then it is already. These can be shared in
64 * whatever combination you need for your (up to) 2 physical drives.
65 * ALSO, RBF CALLS THE INIT ROUTINE ONLY ONCE PER _DRIVER_, NOT DRIVE!
1 ******************************************************************** 66 ********************************************************************
67 * DO NOT FORGET TO SET H6309 FLAG IN DEFSFILE APPROPRIATELY FOR 6809 VS.
68 * 6309 CODE WHEN ASSEMBLING!!
2 * CCIDE - IDE device driver for CoCo 69 * CCIDE - IDE device driver for CoCo
3 * 70 *
4 * $Id$ 71 * $Id$
5 * 72 *
6 * Driver originally from Jim Hathaway, originally 8-bit only 73 * Driver originally from Jim Hathaway, originally 8-bit only
7 * Converted to 16 bit by Alan DeKok 74 * Converted to 16 bit by Alan DeKok
8 * Disassembled (OK, so I didn't have the source version at first!) 75 * Disassembled (OK, so I didn't have the source version at first!)
9 * by Eddie Kuns, ATA specs followed carefully and sector buffering 76 * by Eddie Kuns, ATA specs followed carefully and sector buffering
10 * on writes handled more carefully 77 * on writes handled more carefully
11 * 78 * This driver uses 16-bit transfers *only*
12 * This driver uses 16-bit transfers *only* 79 * Check with Glenside - can we switch to 16 bit only, so there is less to
80 * maintain? With the cacheing stuff, the speed is fairly decent, although
81 * some 6309 optomizations are still possible (cache copies, drive table
82 * copies, hardware divide for CHS translation, etc.)
13 * 83 *
14 * Ed. Comments Who YY/MM/DD 84 * Ed. Comments Who YY/MM/DD
15 * ------------------------------------------------------------------ 85 * ------------------------------------------------------------------
16 * 5 Source as distributed by Glenside 99/05/02 86 * 5 Source as distributed by Glenside 99/05/02
17 * Added comments from 8 bit driver BGP 99/05/07 87 * Added comments from 8 bit driver BGP 99/05/07
18 * 6 Driver now gets address from descriptor, made BGP 99/05/10 88 * 6 Driver now gets address from descriptor, made BGP 99/05/10
19 * minor optimizations, added symbols 89 * minor optimizations, added symbols
20 90 * 7 Change to use real 16 bits LCB 99/09/06
21 * Maximum number of drives to support 91 * partitions (both LBA & CHS) to 99/10/31
22 NUMDRIVE equ 4 92 * better error reporting
23 93 * slightly optomized read
94 * Half sector & LSN0 caches for current drive
95 * Auto-sense/run LBA & CHS modes
96 * Full CHS calculations (up to 4096 cylinders)
97 * for ATA-1 old drive compatibility
98 * 8 Attempted to add support for removable media LCB 00/05/27
99 * commands (Door Lock/Unlock, Acknowledge Media to 00/??/??
100 * Change)
101 * Attempt 'generic' ATA command system call
102 * Constants - change if needed
103 * NUMDRIVE is LOGICAL drives (partitions), NOT physical drives-use 5,11,etc
104 * 5=768 byte data area, 11=1024 byte data area
105 NUMDRIVE equ 11 Max. # of device descriptors per controller address
106 MAXWAIT equ 60*5 Max. # clock ticks to give up on read/write (5 sec)
107 HDSclPwr equ 2048 Set to 2048 as start ^2 cylinder (CHS translate)
108
109 * New definitions in Device Descriptor
110 PartOfs equ $26 2 byte partition offset
111
112 * Definitions for DD.DNS
113 PhysDriv equ %00000001 Physical drive # (0=Master, 1=Slave)
114 ForceCHS equ %00000010 Force driver to use CHS mode
115
116 * New GetStat/SetStat calls:
117 * SS.DrInf call shares call # with SS.ScInf from NitrOS9 WindInt (info)
118 SS.DrInf equ $8f Drive info call (see routine for parms)
119 * Subcall #'s fro SS.DrInf (Y register on entry)
120 ATAIdent equ 0 ATA (handles ATAPI & plain ATA)
121
122 * IDE & ATAPI Commands (ATAPI stuff not implemented yet, and LBA is mandatory)
123 ReadRtry equ $20 Read sector with retry
124 WritRtry equ $30 Write sector with retry
125 Diagnost equ $90 Execute drive diagnostic
126 Identify equ $EC Identify drive command
127 DoorLock equ $DE Lock drive
128 DoorUnLk equ $DF Unlock (eject) drive
129 AckMdChg equ $DB Acknowledge media change
130
131 PIIdent equ $A1 Identify ATAPI drive command
132
133 * IDE Status Register
134 Busy equ %10000000 Drive busy (1=busy)
135 DrvReady equ %01000000 Drive ready (1=ready to accept command)
136 WriteFlt equ %00100000 Drive Write Fault (1=Write fault?)
137 SeekDone equ %00010000 Seek Complete (1=Seek complete)
138 DataReq equ %00001000 Data Request (1=drive ready for read/write data)
139 CorrData equ %00000100 Corrected Data (1=correctable data error was done)
140 Index equ %00000010 1=1 disk revolution completed
141 ErrorFnd equ %00000001 1=Error detected - see error register
142
143 * IDE hardware offsets
144 DataReg equ 0 Data (1st 8 bits, non-latched)
145 Error equ 1 Error # when read
146 Features equ 1 Features when write
147 SectCnt equ 2 Sector count
148 SectNum equ 3 Sector #
149 CylLow equ 4 Low byte of cylinder
150 CylHigh equ 5 High byte of cylinder
151 DevHead equ 6 Device/Head
152 Status equ 7 Status when read
153 Command equ 7 Command when write
154 Latch equ 8 Latch (2nd 8 bits of 16 bit word)
155
156 * Special flags (Mini extra drive table - 1 byte per drive) - starts at
157 * DriveFlg,u
158 * These are set by inquiring the drive, NOT from the descriptor
159 * Should add a GETSTAT to allow user to access these for any drive
160 Unused equ %10000000 Entry is un-initialized
161 DrvMode equ %00000001 0=CHS mode, 1=LBA mode
162 ATAPI equ %00000010 0=Device is ATA,1=Device is ATAPI
163 Remove equ %00000100 0=Fixed Drive, 1=Removable media
164 ReadOnly equ %00001000 0=Read & write allowed, 1=Read only (CD-ROM)
165 * Could also use to write-protect hard drive
24 nam CCIDE 166 nam CCIDE
25 ttl IDE device driver for CoCo 167 ttl IDE device driver for CoCo
26 168
27 ifp1 169 ifp1
28 use defsfile 170 use defsfile
29 use rbfdefs
30 endc 171 endc
31 172
32 tylg set Drivr+Objct 173 tylg set Drivr+Objct
33 atrv set ReEnt+rev 174 atrv set ReEnt+rev
34 rev set $01 175 rev set $01
35 edition equ 6 176 edition equ 8
36 177
37 mod eom,name,tylg,atrv,start,size 178 mod eom,name,tylg,atrv,start,size
179
180 * NOTE: OS9 WILL ALWAYS ASSIGN DRIVER MEM SPACE ON AN EVEN 256 BYTE PAGE,
181 * SO TAKE ADVANTAGE OF "EXTRA" SPACE!
38 182
39 org 0 183 org 0
40 rmb DRVBEG+(DRVMEM*NUMDRIVE) 184 rmb DRVBEG+(DRVMEM*NUMDRIVE)
41 * Start of driver-specific statics 185 * Start of driver-specific statics
186 SlpCntr rmb 2 # ticks left before we give up on a read/write
187 PhysDrv rmb 1 Physical drive # (for quick lookup)
188 DriveFlg rmb NUMDRIVE 1 byte per drive (bit flags)
42 OS9LSN rmb 3 LSN of current OS-9 256-byte sector 189 OS9LSN rmb 3 LSN of current OS-9 256-byte sector
43 Counter rmb 1 190 * IDE spec can handle 28 bits (4 bits of 4th byte) for LBA mode. Since OS9
191 * can't get that high anyways, we only work with 3, and then use the offset
192 * partition value to bump it up beyond the 4 GB mark.
193 OS9PSN rmb 3 PSN of current OS9 sector (512 byte)
194 DrivMask rmb 1 Drive # (0 or 1) for IDE (in proper bit position)
44 idecmd rmb 1 1 byte IDE command code 195 idecmd rmb 1 1 byte IDE command code
45 rmb 20 196 identcmd rmb 1 1 byte IDE Identify drive code
197
198 * Following flag is because the IDE interface can NOT access a 2nd drive
199 * while the 1st drive is completing a read or write. Because of shared
200 * device memory variables, this flag is set even on cached entries.
201 drvrbusy rmb 1 Driver busy flag (0=not busy)
202
203 * Following for CHS mode drives only!
204 Head rmb 1 Head # (s/b base 0)
205 Cylinder rmb 2 Cylinder #
206 CHSSect rmb 1 CHS mode sector #
207 CHSSPT rmb 2 CHS mode sectors/track
208
209 * Buffer/cache variables
210 LSN0Flag rmb 1 $FF=Not LSN0, $00=LSN0
211 Sect0Drv rmb 1 Drive # of LSN0 currently buffered ($FF=none)
212 Sect0Ofs rmb 2 Offset value for current LSN0 buffered drive
213 TempHalf rmb 3 Temp spot to hold other half calculation
214 HalfDrv rmb 1 Drive # of HalfBuff buffered ($FF=none)
215 HalfOfs rmb 2 Offset value for drive for current cached sector
216 HalfSct rmb 3 OS9 sector # of half sector not asked for
217 TempOfs rmb 2 Temporary copy of partition offset
218
219 * NOTE: When 8k block buffering is added, move both of these to that block.
220 * Of course, if removable media, re-read LSN0 physically every time. At that
221 * time, we should make tables here instead (32 entries per drive up to the
222 * maximum # of drives) of LSN #'s buffered (3 bytes/entry).
223 Sect0 rmb 256 Buffer for LSN0
224 HalfBuff rmb 256 Buffer for other half of 512 byte phys. sector
46 size equ . 225 size equ .
47 226
48 fcb $FF mode byte 227 fcb $FF mode byte
49 228
50 name fcs /CCIDE/ module name 229 name fcs /CCIDE/ module name
51 fcb edition module edition 230 fcb edition module edition
52 231
232 * INIT - appears to only be called on 1ST try on ANY IDE device IF link counts
233 * are 0.
234 * Y = address of path descriptor (but
235 * U = address of driver memory (ie, of V.PAGE)
236 * Inits the drive table, and the DriveFlg table
237 Init ldd #$8000+NUMDRIVE Flag that special drive flags are all unused
238 leax DriveFlg,u
239 DrvFlgLp sta ,x+
240 decb
241 bne DrvFlgLp
242 GoInit leax DRVBEG,u Point to start of drive tables
243 ldd #$FF00+NUMDRIVE
244 stb V.NDRV,u Max # of drives
245 sta Sect0Drv,u Flag that no LSN0 is buffered
246 sta HalfDrv,u Flag that we have no half sector buffered
247 NextDrv sta DD.TOT,x Set Total # of sectors to illegal value
248 sta V.TRAK,x Non 0, so 1st seek can read Track 0
249 leax DRVMEM,x Point to next drive
250 decb Dec # of drives left
251 bne NextDrv Still more, init them too
252 clrb No error & return
253 rts
254
255 * Do drive diagnostic (use CHS mode) - Do not worry about ATAPI at this point
256 * Entry: U=driver mem ptr
257 * Y=path descriptor
258 * B=Identify command
259 * Exit: CC clear - drive ready to send info
260 * CC set - error from drive, B contains raw error register
261 * TRASHES X - does timeout (CHECK - WILL SOME DRIVES TAKE TOO LONG?)
262 * This is called by INIT, and should also be called by a GETSTAT at some
263 * point.
264 Ident pshs y Save path descriptor
265 stb identcmd,u Save which Ident we are doing
266 ldy V.PORT,u Get IDE controller address
267 DoIdent lda DrivMask,u Get drive # requested
268 ora #%10100000 Mask in head 0 & CHS mode
269 std DevHead,y Send drive/head to controller, and IDENTIFY
270 * Note, if person booting from ROM, drive may not have spun up yet. See if
271 * we can check some sort of status or error flag that indicates drive is
272 * still firing up, if this is a problem.
273 ldx #$a000 Arbitrary amount of time to give up
274 WaitIdnt lda Status,y Get Status register
275 bmi NoErr Busy, drop counter
276 bita #ErrorFnd Error?
277 beq NoErr No, continue
278 ldb Error,y Get error code
279 bra BadIdent
280
281 NoErr cmpa #DrvReady+SeekDone+DataReq Drive ready to send Identify data?
282 beq GotIdent Yep, exit out
283 leax -1,x Drop timer
284 bne WaitIdnt Keep trying
285 ldb #E$NotRdy Timed out, device not ready error
286 BadIdent coma Flag error
287 puls y,pc Restore path descriptor & return
288
289 GotIdent clrb No error
290 puls y,pc Restore path descriptor & return
291
292 * Send Identify drive command (ATA or ATAPI - see identcmd,u), update DriveFlg
293 * table
294 * PLEASE NOTE: The 2 identify commands are mutually exclusive; it will fail
295 * with an 'Aborted' error if the wrong Identify is used.
296 * UNLIKE A NORMAL READ OF A SECTOR, THE INFORMATION CONTAINED IN THE IDENTIFY
297 * DRIVE COMMAND IS ALL IN INTEL ORDER WORD (16 BITS)
298 * Entry: Y=Ptr to path descriptor
299 * U=Ptr to driver memory
300 * X IS DESTROYED!
301 * Exit: CC=0 if DriveFlg properly updated
302 * & A=DriveFlg value from update entry in table
303 * CC=1, B=error if Identify Drive failed
304 * DriveFlg,u - the proper flags for the specified controller/drive are
305 * updated
306 * Sect0 contains 1st 256 bytes, HalfBuff contains 2nd half
307 IdentDrv lbsr WaitDrv Wait for IDE to be ready
308 ldb #Identify
309 bsr Ident Send identify drive command to controller
310 bcc DoInfo Worked, Do info
311 bitb #%00000100 Error, Aborted Flag set?
312 beq ExitIdnt No, exit with other error
313 ldb #PIIdent Try ATAPI identify
314 bsr Ident
315 bcs ExitIdnt That didn't work either, abort
316 DoInfo leax Sect0,u Point to buffer
317 * NOTE: INIT routine only gets called when the DRIVER is Initing...not every
318 * device. Hence, READ/WRITE must check the DriveFlg settings and make sure
319 * the hi bit is clear for the drive it is using, to indicate that it HAS
320 * been set properly from an Identify Drive command.
321 * Read in 1st 256 bytes of Identify Drive buffer, parse out info we need
322 * for our special flag table
323 lbsr Read256 Generic 256 byte copy from IDE routine
324 ldb #$FF Since we made it this far, flag that HalfBuff
325 stb HalfDrv,u & Sect0Drv are now bogus
326 stb Sect0Drv,u
327 clra Set current flags to all off
328 leax Sect0,u Point to start of buffer again
329 ldb ,x Get general config low byte
330 andb #%10000000 Removable cartridge bit set?
331 beq CheckLBA No, check LBA mode
332 ora #Remove Set removable media flag
333 CheckLBA ldb 99,x Get LBA mode byte
334 andb #%00000010 LBA allowed on this drive?
335 beq ChkATAPI No
336 ora #DrvMode Yes, set LBA flag
337 ChkATAPI ldb identcmd,u Get Identify drive command type
338 cmpb #PIIdent ATAPI?
339 bne SetFlg No, set drive flags
340 ora #ATAPI Set ATAPI flag
341 SetFlg ldb PD.DNS,y Get special settings flags
342 bitb #ForceCHS Force CHS mode on?
343 beq LeavAlon No
344 anda #^DrvMode Yes, force to CHS mode
345 LeavAlon ldb PD.DRV,y Get Logical drive #
346 leax DriveFlg,u Point to drive flags table
347 sta b,x Save flags
348 pshs a Save for exit
349 leax HalfBuff,u Point to 2nd buffer
350 lbsr Read256 Identify info part 2
351 lbsr WaitOK Make sure drive finished command
352 puls a Restore flags byte
353 ExitIdnt rts No error, return
354
355 * Entry: U=driver memory ptr
356 * Y=path descriptor ptr
357 GetStat ldx PD.RGS,y Get ptr to callers register stack
358 lda R$B,x Get function code
359 cmpa #SS.DrInf Drive info command?
360 bne NextGet No, try next
361 ldd R$Y,x Get sub-function type
362 beq GoodFunc
363 comb Only sub-functions 0 allowed for IDE
364 ifeq Level-2
365 ldb #E$IllArg
366 else
367 ldb #167
368 endc
369 ExitGet rts
370
371 GoodFunc pshs x,y,u Preserve regs
372 bsr IdentDrv Get either ATA or ATAPI Identify info
373 bcc GotInfo Something wrong, return
374 puls x,y,u,pc Restore regs, return with error
375
376 GotInfo leay Sect0,u Point to start of 512 byte buffer
377 ldx #256 # of two byte entries in buffer
378 SwapLoop ldd ,y Swap all words to Motorola order
379 exg a,b
380 std ,y++
381 leax -1,x
382 bne SwapLoop
383 leay Sect0,u Point to start of buffer again
384 ldx 114,y Get Current Capacity, swap to Motorola
385 ldd 116,y
386 stx 116,y
387 std 114,y
388 ldx 120,y Get LBA sector count, swap to Motorola
389 ldd 122,y
390 stx 122,y
391 std 120,y
392 ifeq Level-2
393 lda <D.SysTsk Get system task #
394 ldx <D.Proc Get user task ptr
395 ldb P$Task,x Get user's task #
396 leax Sect0,u Point to source buffer
397 ldu ,s Get ptr to PD.RGS
398 ldu R$X,u Get Destination ptr
399 ldy #512 Move 512 bytes to caller
400 os9 F$Move
401 else
402 endc
403 puls x,y,u Restore regs to normal
404 bcc SetUserR No error, set exit registers for caller
405 rts
406
407 SetUserR ldd #512 # of bytes returned=512 (Callers Y)
408 std R$Y,x
409 clrb Device type=ATA
410 lda identcmd,u Get which Identify Drive command worked
411 cmpa #PIIdent ATAPI?
412 bne SaveType No, save ATA as type
413 incb
414 SaveType lda PD.DRV,y Get logical drive #
415 leay DriveFlg,u Point to drive flag table
416 lda a,y Get drive flags
417 std R$D,x Save drive flags & device type
418 clrb
419 rts
420
421 NextGet comb
422 ldb #E$UnkSvc
423 rts
424
425 SetStat clrb
426 rts
427
53 start lbra Init 428 start lbra Init
54 lbra FRead 429 lbra Read
55 lbra FWrite 430 lbra FWrite
56 lbra GetStat 431 lbra GetStat
57 lbra SetStat 432 lbra SetStat
58 lbra Term 433 clrb Term routine (does nothing)
59 * 434 rts
60 * INIT 435
61 * 436 NotBsy lda #$FF
62 * Y = address of path descriptor 437 sta drvrbusy,u
63 * U = address of device memory (ie, of V.PAGE) 438 rts
64 * 439
65 Init ldx #$1500 delay loop value 440 * Checks if driver is busy, retries & possibly sleeps if it is.
66 ldy V.PORT,u 441 * Set's driver to busy again when done.
67 RdyIni1 tst 7,y Wait for drive ready 442 * A reg is destroyed, all others are preserved
68 bpl GoInit 443 ChekBusy lda #64 # of fast retries for driver
69 leax -1,x 444 BsyTst tst drvrbusy,u Is current driver/controller already in use?
70 bne RdyIni1 445 beq NotBsy No, continue
71 lbeq ENotRdy Timed out ... give up on drive 446 deca
72 447 bne BsyTst Try up to 64 times
73 GoInit ldd #$AF20 Drive is ready -- initialize 448 pshs x Otherwise, sleep a tick & try again
74 * For IDE command $91, DrvHd reg = 101xhhhh binary 449 ldx #1
75 sta 6,y $10 heads (x=0-master/1-slave; hhhh=#heads) 450 os9 F$Sleep
76 stb 2,y $20 sectors/track 451 puls x
77 lda #$91 452 bra ChekBusy
78 sta 7,y Give drive the Init Drive Parameters IDE command 453
79 RdyIni2 tst 7,y 454 * Save OS9 LSN & Physical PSN (not including any partition offset)
80 bmi RdyIni2 Wait *forever* until drive is ready 455 * Also saves sector # of other half that is buffered
81 456 * Will have to add check later for ATAPI stuff, up to 2048 bytes/sector
82 * Initialize drive table (only first is inited here) 457 * for CD ROM
83 leax DRVBEG,u 458 * Entry: U=ptr to driver mem
84 lda #1 459 * B:X=OS9 LSN
85 sta V.NDRV,u 460 * Exit: B:X=OS9 LSN
86 lda #$FF 461 * OS9PSN updated (512 byte Physical sector # that IDE needs)
87 sta DD.TOT+2,x 462 * TempHalf updated to cached LSN # (Use HalfDrv to figure out if legit
88 sta V.TRAK,x 463 * or not)
89 464 * TempOfs updated to current partition offset
90 GetStat 465 * Zero flag set if LSN0 was requested (also saved at LSN0Flag,u)
91 SetStat 466 * PhysDrv set to physical drive #
92 Term clrb 467 SavLSN pshs b,x Save work copy of LSN
93 rts 468 lda PD.DNS,y Make copy of physical drive #
94 469 anda #PhysDriv
95 SavLSN stb OS9LSN,u Save OS-9 LSN 470 sta PhysDrv,u
96 stx OS9LSN+1,u 471 clra Flag: LSN0
97 rts 472 stb OS9LSN,u Save OS-9 LSN
98 * 473 beq dox Could be LSN0
474 inca Not LSN0
475 dox stx OS9LSN+1,u
476 beq doPSN Is LSN0
477 inca Not LSN0
478 doPSN sta LSN0Flag,u Save LSN0 flag (0=Yes, anything else, no)
479 stb OS9PSN,u Save OS-9 PSN
480 stx OS9PSN+1,u
481 lsr OS9PSN,u Divide LSN by 2 for PSN (512 bytes/sector)
482 ror OS9PSN+1,u
483 ror OS9PSN+2,u
484 bcc Even Even sector requested, half will be odd (+1)
485 * Subtract 1 from current LSN
486 ldd 1,s
487 subd #1
488 std 1,s
489 ldb ,s
490 sbcb #0
491 bra SaveExit
492
493 * Add 1 to current LSN
494 Even ldd 1,s
495 addd #1
496 std 1,s
497 ldb ,s
498 adcb #0
499 SaveExit ldx 1,s
500 stb TempHalf,u Save buffered sector #
501 stx TempHalf+1,u
502 leas 3,s Eat temp stack
503 ldx PD.DEV,y Get ptr to device table entry
504 ldx V$DESC,x Get device descriptor ptr
505 ldx PartOfs,x Get partition offset value
506 stx TempOfs,u Save copy of it
507 ldb OS9LSN,u Restore LSN
508 ldx OS9LSN+1,u
509 lda LSN0Flag,u Set CC bits for LSN0 compare
510 rts
511
99 * READ 512 * READ
100 * 513 * Entry: Y = address of path descriptor
514 * U = address of device memory (ie, of V.PAGE)
515 * B = MSB of OS-9 disk LSN
516 * X = LSB of OS-9 disk LSN
517 * Eventually change LSN stuff to use a bit from descriptor as to whether
518 * buffered LSN0 or not. (After that, add in for general 8k block buffering
519 * or not).
520 * Later, add check for DriveFlg that sees if device has removable media. If
521 * not, and caching for each logical drive is done, keep PERMANENT copy of
522 * LSN0 at all times, and just copy it when requested (WRITE will update copy
523 * if new LSN0 is written).
524 * MAKE SURE WRITE ROUTINE UPDATES CACHING STUFF CORRECTLY!
525 Read lbsr ChekBusy Wait for driver to be unbusy
526 bsr SavLSN Save LSN/PSN, PartOfs & HalfSect info
527 bne NotLSN0 Not LSN0, skip ahead
528 * Theoretically, following REM'ed out lines will handle removable media:
529 * lda DriveFlg,u Get drive flag settings
530 * bita #Remove Removable media?
531 * bne NotLSN0 Yes, LSN0 may change from disk swap
532
533 * LSN0 - 1st see if buffered
534 lda PhysDrv,u Get requested physical drive #
535 cmpa Sect0Drv,u Same drive in LSN0 cache?
536 bne PhysRead No, go physically read off of drive
537 ldx TempOfs,u Get copy of partition offset
538 cmpx Sect0Ofs,u Same as cached LSN0 offset?
539 bne PhysRead No, physically read the sector
540 * LSN0 buffered goes here - later add check against DriveFlg with removable
541 * media bit - if non-removable, copy from cache, otherwise to physical read
542 leax Sect0,u Point to LSN0 cache
543 bra CopyBuff Copy to caller's PD.BUF, exit from there
544
545 * Not LSN0 - see if normal sector is currently cached.
546 * Entry: B:X=LSN
547 NotLSN0 cmpb HalfSct,u Same as cached sector?
548 bne PhysRead
549 cmpx HalfSct+1,u Same as cached sector?
550 bne PhysRead
551 lda PhysDrv,u Same drive as cached?
552 cmpa HalfDrv,u
553 bne PhysRead No, need physical read of sector
554 ldd TempOfs,u Get current request's Partition offset
555 cmpd HalfOfs,u Same as cached?
556 bne PhysRead No, physical read of sector
557 * Non-LSN0 sector is cached - if removable drive, force physical read unless
558 * we somehow monitor disk swaps (some media require Eject commands)
559 leax HalfBuff,u Point to cached sector
560 * Copy sector from cache buffer to caller's buffer
561 * Entry: X=Ptr to cache buffer (either Sect0, or HalfBuff)
562 CopyBuff clrb 256 counter
563 ldy PD.BUF,y Point to caller's buffer
564 CpyLoop lda ,x+ Copy it
565 sta ,y+
566 decb
567 bne CpyLoop
568 clr drvrbusy,u Flag driver not busy
569 rts
570
571 * Not buffered in any way - physical read required - update cache tags AFTER
572 * read, or flag with $FF if failed.
573 * Entry: Y=Ptr to path descriptor
574 * U=Driver mem
575 PhysRead lbsr InitRead Tell IDE to read sector
576 bcc DoRead No error, do read
577 FlagBad lda #$FF If IDE can't even initiate read, flag both
578 sta Sect0Drv,u LSN0 and HalfBuff as bad
579 sta HalfDrv,u
580 lbra RprtErr
581
582 * Entry: Y=path dsc. ptr
583 * U=Driver mem ptr
584 DoRead lda OS9LSN+2,u Get LSB of OS9 sector #
585 lsra Shift 1/2 512 sector flag out
586 bcs DoOdd Odd sector, buffer even one 1st
587 ldx PD.BUF,y Get pointer to caller's buffer
588 bsr Read256 Copy 1st half of HD sector there
589 leax HalfBuff,u Point to cache buffer
590 bsr Read256 Copy 2nd half of HD sector there
591 bra FinRead Finish the Read command on IDE
592
593 * Copy to cache 1st (Odd sector # request)
594 DoOdd leax HalfBuff,u Point to cache buffer
595 bsr Read256 1st half goes there
596 ldx PD.BUF,y Get pointer to caller's buffer
597 bsr Read256 2nd half goes there
598 FinRead lbsr WaitOK Wait for drive to complete command
599 bcc DoneRead No error, exit
600 lbra RprtErr Exit with error
601
602 * Update HalfSct vars to whatever is in TempHalf
603 GoodCach ldd TempHalf,u Copy Buffered LSN to HalfSct
604 std HalfSct,u
605 lda TempHalf+2,u
606 sta HalfSct+2,u
607 ldd TempOfs,u Get partition offset
608 std HalfOfs,u Save it
609 lda PhysDrv,u Copy drive # to HalfDrv
610 sta HalfDrv,u
611 rts
612
613 * Entry: Read command complete on IDE.
614 * Y=ptr to path descriptor
615 * U=ptr to driver mem
616 DoneRead bsr GoodCach Update HalfSct stuff with Temp stuff
617 ldb LSN0Flag,u Was this LSN0?
618 bne GoodExit No, leave
619 * LSN0 just physically read - update drive table
620 * CHANGE EVENTUALLY TO CHECK IF NON-REMOVABLE MEDIA; IF IT IS, DON'T BOTHER
621 * WITH THESE CHECKS!
622 sta Sect0Drv,u Save which drive LSN0 is buffered
623 ldd TempOfs,u Restore partition offset again
624 std Sect0Ofs,u Save for LSN0
625 leax Sect0,u Point to LSN0 buffer
626 clrb 256 counter
627 pshs y Save path dsc. ptr
628 ldy PD.BUF,y Point to caller's buffer
629 LSN0Loop lda ,y+ Copy LSN0 from callers buffer to LSN0 cache
630 sta ,x+
631 decb
632 bne LSN0Loop
633 puls y Restore path dsc. ptr
634 leax Sect0,u Point to LSN0 cache again
635 CopyTbl1 lbsr CpyDrvTb Copy LSN0 stuff to drive table
636 GoodExit clr drvrbusy,u No error & return
637 rts
638
639 * Initiate the 512 byte READ sequence
640 * Entry: U=Driver mem ptr
641 * Y=Path dsc. ptr (?)
642 * Exit: CC=0 if no error
643 * CC=1 if error
644 * B=Error code
645 InitRead ldb #ReadRtry Read sector (with retry) IDE command
646 lbra SetIDE Send to IDE, return from there (w or w/o err)
647
648 * Copy 256 bytes of data from IDE controller (after READ, etc.)
649 * Entry: X=ptr to 256 byte destination buffer
650 * U=ptr to driver memory
651 * Exit: 256 bytes copied
652 * B is destroyed, A=0
653 * Y is preserved
654 Read256 lda #$20 # of loops (of 8 bytes)
655 pshs y,a Save y & counter
656 ldy V.PORT,u Get ptr to IDE controller for this drive
657 ReadLp lda ,y Get 16 bits of data, and save in buffer, 8
658 ldb Latch,y times
659 std ,x
660 lda ,y
661 ldb Latch,y
662 std 2,x
663 lda ,y
664 ldb Latch,y
665 std 4,x
666 lda ,y
667 ldb Latch,y
668 std 6,x
669 leax 8,x Bump ptr up
670 dec ,s Done all bytes?
671 bne ReadLp No, keep going
672 puls a,y,pc Restore Y & return
673
674 * WRITE - Can use cache data, or preread sector
101 * Y = address of path descriptor 675 * Y = address of path descriptor
102 * U = address of device memory (ie, of V.PAGE) 676 * U = address of device memory (ie, of V.PAGE)
103 * B = MSB of OS-9 disk LSN 677 * B = MSB of OS-9 disk LSN
104 * X = LSB of OS-9 disk LSN 678 * X = LSB of OS-9 disk LSN
105 * 679 * 1st , see if other half is buffered in HalfBuff
106 FRead bsr SavLSN 680 FWrite lbsr ChekBusy Wait for driver to be unbusy
107 ldb #$20 681 lbsr SavLSN Save LSN info, set LSN0Flag for later
108 lbsr SetIDE 682 ldb TempHalf,u Get OS9 LSN of 'other half' of 512 byte sector
109 bcs Ret 683 cmpb HalfSct,u Same MSB of buffered sector #?
110 ldx PD.BUF,y 684 bne ChkLSN1 No, check if LSN1
111 lda #$20 685 ldx TempHalf+1,u LSW of 'other half'
112 sta Counter,u 686 cmpx HalfSct+1,u Same as LSW of buffered sector #?
113 pshs y 687 bne ChkLsn1 No, check if LSN1
114 ldy V.PORT,u 688 ldd HalfOfs,u Same partition as buffered sector's drive?
115 ReadLp lda ,y 689 cmpd TempOfs,u
116 ldb ,y 690 bne ChkLsn1 No, check if LSN1
117 std ,x++ 691 lda PhysDrv,u Same physical drive as buffered sector's drive?
118 lda ,y 692 cmpa HalfDrv,u Same as buffered sector's drive?
119 ldb ,y 693 bne ChkLsn1 No, check is LSN1
120 std ,x++ 694 * Buffered sector IS the other half of current write sector...no preread nec-
121 lda ,y 695 * essary.
122 ldb ,y 696 lbsr InitWrit Send Write command to IDE, setup mode, etc.
123 std ,x++ 697 bcc GoodWrit No problems, continue with Write
124 lda ,y 698 lbra FlagBad Flag caches as bad, exit with error
125 ldb ,y 699
126 std ,x++ 700 * See if request is for LSN1, in which case we may have LSN0 buffered
127 dec Counter,u 701 ChkLSN1 ldb OS9LSN,u Get MSB of sector to write
128 bne ReadLp 702 bne PreRead Not 0, need physical preread
129 puls y 703 ldx OS9LSN+1,u Get LSW of sector to write
130 704 cmpx #1 LSN=1?
131 ldx OS9LSN+1,u Is this LSN 0? 705 bne PreRead Not LSN1, need to preread sector
132 bne NotLSN0 706 lda PhysDrv,u Get physical drive #
133 ldb OS9LSN,u 707 cmpa Sect0Drv,u Same as buffered LSN0?
134 bne NotLSN0 708 bne PreRead No, need physical preread
135 ldx PD.BUF,y 709 ldd TempOfs,u Get partition offset of requested sector
136 710 cmpd Sect0Ofs,u Same as buffered?
137 pshs y Yes, it is LSN 0 711 bne PreRead
138 lda #DD.SIZ Copy useful information to our LSN 0 buffer 712 * We have LSN0 buffered for an LSN1 write
713 lbsr InitWrit Send Write to IDE
714 bcc ContWrt1 Successful, continue
715 lbra RprtErr
716
717 ContWrt1 leax Sect0,u Point to buffered Sector 0
718 bsr Write256 Write to IDE
719 ldx PD.BUF,y Get ptr to caller's LSN1 buffer
720 bsr Write256 Write to IDE
721 bra FinWrite Complete the write command
722
723 * Nothing buffered, pre-read sector in so we have other half to write.
724 * Note that OS9PSN is already set to the correct physical sector.
725 PreRead lbsr InitRead Send Read command to IDE
726 bcc GotPreRd No problem, continue
727 lbra FlagBad Flag caches as bad; exit with error
728
729 GotPreRd lda OS9LSN+2,u Get least sig. byte of LSN to write
730 lsra Odd or even sector?
731 bcc ReadOdd Even write sector requested
732 * Odd write requested
733 leax HalfBuff,u Point to 1/2 sector cache
734 lbsr Read256 Read it in
735 bsr Eat256 Bleed off other half (not needed)
736 bra FinPre
737
738 * Even sector to write - buffer odd one
739 ReadOdd bsr Eat256 Bleed 1st half
740 leax HalfBuff,u Read in 2nd half
741 lbsr Read256
742 FinPre lbsr WaitOK Get OK from controller
743 bcc DonePre Good, continue
744 BadExit lbra RprtErr Error, exit with it
745
746 DonePre lbsr GoodCach Update HalfSct stuff only
747 lbsr InitWrit Initialize Write command
748 bcs BadExit
749 * Now, onto the write
750 GoodWrit ldb OS9LSN+2,u Get least sig. byte of LSN
751 lsrb Odd or even sector to write?
752 bcs BuffWOdd Write fully buffered Odd
753 * We are writing even portion, odd is in cache
754 ldx PD.BUF,y Get ptr to caller's 256 byte buffer
755 bsr Write256 Write to IDE
756 leax HalfBuff,u Point to cached sector
757 bsr Write256 Write to IDE
758 bra FinWrite
759
760 BuffWOdd leax HalfBuff,u Point to cached sector
761 bsr Write256 Write to IDE
762 ldx PD.BUF,y Point to caller's 256 byte buffer
763 bsr Write256 Write to IDE
764 FinWrite lbsr WaitOK Wait for IDE to be done command
765 bcc DoneWrit No error, done writing
766 lbra RprtErr Error, exit with it
767
768 * Write 256 bytes from ,x to IDE
769 * Entry: X=ptr to 256 buffer to write
770 * U=driver mem ptr
771 * Exit: 256 bytes written
772 * B is destroyed, A=0
773 * X=end of buffer+1
774 * Y is preserved
775 Write256 lda #$20 # of 8 byte loops
776 pshs y,a Save Y & loop counter
777 ldy V.PORT,u Get IDE base address
778 WritLp ldd ,x Copy 256 bytes from buffer to IDE
779 stb Latch,y
780 sta ,y
781 ldd 2,x
782 stb Latch,y
783 sta ,y
784 ldd 4,x
785 stb Latch,y
786 sta ,y
787 ldd 6,x
788 stb Latch,y
789 sta ,y
790 leax 8,x
791 dec ,s
792 bne WritLp
793 puls a,y,pc Restore regs & return
794
795 * Eat 256 bytes from IDE (hopefully, triggering latch will skip having to
796 * read even bytes)
797 * Entry: U=driver memory ptr
798 * Y=Path descriptor ptr
799 * Exit: 256 bytes bled off of sector buffer on IDE
800 * All regs preserved
801 Eat256 pshs d,x Save regs
802 ldb #$20 32 loops
803 ldx V.PORT,u Get pointer to IDE
804 EatLp lda ,x Read seems to be a pre-trigger
805 lda ,x Eat each 16 bit trigger byte
806 lda ,x
807 lda ,x
808 decb
809 bne EatLp
810 puls d,x,pc Restore regs & return
811
812 * Write command to IDE completed successfully
813 * Update cache (copy PD.BUF to Cache if even sector, so a sequential
814 * write will have the 1st half cached, or leave current cache alone if
815 * odd). Also, check if LSN0. If it is, copy to LSN0 cache, updating
816 * vars, and copy drive table info
817 DoneWrit ldb LSN0Flag,u Was it sector 0?
818 beq WritLSN0 Yes, special processing for that
819 ldb OS9LSN+2,u Get LSB of sector #
820 lsrb Odd/Even?
821 bcc CpyCache Even, copy to Cache
822 * Odd sector written, leave cache as is
823 clr drvrbusy,u Exit without error
824 rts
825
826 * Copy PD.BUF sector to HalfBuff cache, update cache tags
827 CpyCache lda PhysDrv,u Set cache vars for PD.BUF sector
828 sta HalfDrv,u
829 ldd TempOfs,u
830 std HalfOfs,u
831 ldd OS9LSN,u
832 std HalfSct,u
833 lda OS9LSN+2,u
834 sta HalfSct+2,u
835 leax HalfBuff,u Point to 1/2 sector cache
836 CachBuff clrb
837 ldy PD.BUF,y Get ptr to callers buffer
838 CachLp lda ,y+ Copy even sector to cache (in case of sequential
839 sta ,x+ writes)
840 decb
841 bne CachLp
842 clr drvrbusy,u
843 rts
844
845 * We wrote LSN0 - 1st, update LSN0 cache tags, then copy PD.BUF to Sect0,
846 * then update drive table entry.
847 * Entry: U=drive mem ptr
848 * Y=path dsc. ptr
849 WritLSN0 lda PhysDrv,u Copy cache tag stuff for Sect0 cache
850 sta Sect0Drv,u
851 ldd TempOfs,u
852 std Sect0Ofs,u
853 leax Sect0,u Point to LSN0 cache
854 bsr CachBuff Copy from PD.BUF to Sect0 buff
855 leax Sect0,u Point to LSN0 cache again
856 clr drvrbusy,u
857 lbra CpyDrvTb Copy info to drive table, exit from there
858
859 * Initialize Write sequence to IDE
860 * Entry: U=driver mem ptr
861 * Y=Ptr to path descriptor
862 * Exits back to calling routine. CC=0 if command ready on controller
863 * CC=1, B=Raw IDE error code if command failed
864 InitWrit ldb #WritRtry IDE Write w/ Retry command
865 bra SetIDE Send to IDE, return from there w or w/o error
866
867 * After read or write, check drive status
868 * Exit: CC=0, command ok, CC=1, Error from IDE (B=Raw error code)
869 * X=Ptr to hardware address
870 WaitOK ldx V.PORT,u Get status register
871 WaitLp tst Status,x Still busy, wait till unbusy
872 bmi WaitLp
873 lda #ErrorFnd Check Error flag
874 bita Status,x Error from controller?
875 bne RprtErr Yes, go get error
876 clrb No, exit without error
877 rts
878
879 * Entry: B=Error code from IDE
880 RprtErr lsrb
881 bcc ChkTk0
882 SctrExit ldb #E$Sect Bad sector # for Addres Mark Not Found
883 bra ExitErr
884
885 ChkTk0 lsrb
886 bcc ChkMdChg
887 SeekExit ldb #E$Seek Seek error for Track 0 not found
888 bra ExitErr
889
890 ChkMdChg lsrb
891 bcc ChkAbrt
892 MdChExit ldb #E$DIDC Media changed error
893 bra ExitErr
894
895 ChkAbrt lsrb
896 bcc ChkIdnf
897 ldb #E$UnkSvc Unknown service error for aborted command
898 bra ExitErr
899
900 ChkIdnf lsrb
901 bcs SctrExit Sector error for ID not found
902 lsrb
903 bcs MdChExit Media changed error for Media Change
904 lsrb
905 bcc ChkBBK
906 ldb #E$CRC CRC Error for Uncorrectable data
907 bra ExitErr
908
909 ChkBBK lsrb
910 bcs ReadExit Read error for Bad Block Detected
911 * Error flag set, but no error condition
912 lbra ENotRdy Assume drive not ready
913
914 ReadExit ldb #E$Read
915 ExitErr clr drvrbusy,u Flag driver not busy
916 coma Set carry & exit
917 rts
918
919 BadUnit ldb #E$Unit
920 bra ExitErr
921
922 CmdErr ldb Error,x Get Error register
923 bra RprtErr
924
925 * Send IDE command (read or write)
926 * Entry: B = IDE command code
927 * Y = address of path descriptor
928 * U = address of device memory (ie, of V.PAGE)
929 * trashes D and X
930 * Exit: CC=0 if command exited with data ready on controller
931 * CC=1, B=error if problem.
932 SetIDE stb idecmd,u Save copy of IDE command
933 ldb PD.DRV,y Get logical drive #
934 cmpb #NUMDRIVE Within range?
935 bhs BadUnit No, exit with error
936 leax DriveFlg,u Point to special drive flags table
937 lda b,x Get flags for our drive
938 bpl TblReady Properly initialized, figure out mode
939 lbsr IdentDrv NOT Initialized, get mode info
940 bcs CmdErr Error doing IDENTIFY DRIVE command, exit
941 TblReady anda #DrvMode Just need CHS/LBA mode for now
942 bne DoLBA LBA mode, go do
943 * Do CHS mode
944 ldd PD.SCT,y Get # of OS9 (256) sectors/track
945 lsra Convert to 512 byte sectors/track
946 rorb
947 std CHSSPT,u Save for Calc routine
948 ldx PD.DTB,y Get pointer to device table
949 lbsr CalcCHS Go calculate cyl/head/sector stuff
950 bcs CmdErr Error calculating, exit
951 lbsr WaitDrv Go wait for the drive (preserves y)
952 bcs CmdErr Error waiting for drive, exit
953 * Do sector #, then Drive/Head, then Cyl, then sector count, then command
954 pshs y Save path descriptor ptr
955 ldy V.PORT,u Get IDE hardware address
956 lda CHSSect,u Get IDE sector #
957 sta SectNum,y Save to controller
958 lda Head,u Get IDE head #
959 ora #%10100000 Set CHS mode
960 ora DrivMask,u Merge drive #
961 sta DevHead,y Save to controller
962 ldd Cylinder,u Get 16 bit cylinder # (4095 max)
963 addd TempOfs,u Add partition offset cylinder
964 bcs SeekErr If it overflowed, SEEK error
965 sta CylHigh,y Save to controller
966 stb CylLow,y
967 bra SendCmd Send sector count & IDE command
968
969 * Do LBA mode IDE command here
970 DoLBA bsr WaitDrv Wait for controller to be ready
971 pshs y Save path descriptor ptr
972 ldy V.PORT,u Get IDE hardware address
973 * Copy LBA sector # to controller, including device/head (LBA 24-27)
974 ldd OS9PSN+1,u Get bits 0-15 of PSN
975 stb SectNum,y Save bits 0-7
976 sta CylLow,y Save bit 8-15
977 clra
978 ldb OS9PSN,u D=PSN bits 16-23 (24 & up set to 0 for OS9)
979 addd TempOfs,u Add partition offset cylinder
980 cmpa #$0f Overflow past LBA bits?
981 bhi SeekErr Yes, SEEK error
982 stb CylHigh,y Save bits 16-23
983 ora #%11100000 Set LBA mode
984 ora DrivMask,u Merge drive #
985 sta DevHead,y Save to controller
986 * Send sector count (1) & command to controller, get results
987 SendCmd ldx #MAXWAIT Get # 1/60th sec. ticks to wait on drive
988 stx SlpCntr,u Save it for sleep routine (if needed)
989 ldd #$0140 Sector count to 1, fast retry to 64 tries
990 sta SectCnt,y Send to controller
991 lda idecmd,u Get command to send
992 sta Command,y Send to controller
993 CmdLp lda Status,y Get status of drive command
994 bmi CmdLp IDE still busy, no other bits are valid
995 bita #ErrorFnd Not busy anymore, is there an error?
996 bne TransErr Yes, figure out what (don't forget to PULS Y!)
997 bita #DataReq Is data ready for us yet?
998 bne CmdDone Yes, exit
999 decb Dec counter
1000 bne CmdLp Keep trying
1001 ldx SlpCntr,u Get sleep tick counter
1002 leax -1,x Drop it by one
1003 beq NoWay Done count, give up with device not ready error
1004 stx SlpCntr,u Save new sleep counter
1005 ldx #1 Fast retry didn't work, sleep a tick
1006 os9 F$Sleep
1007 ldb #$40 64 fast retries again
1008 bra CmdLp Try again
1009
1010 SeekErr lbsr SeekExit Seek error & exit
1011 puls y,pc
1012
1013 NoWay puls y
1014 bra ENotRdy
1015
1016 TransErr lbsr CmdErr Get error code
1017 puls y,pc Exit with it, restore path dsc. ptr
1018
1019 CmdDone clrb Command complete, return with no error
1020 puls y,pc Restore path dsc. ptr
1021
1022 * Wait for IDE controller to be ready
1023 * Entry: Y=path dsc. ptr
1024 * U=driver mem ptr
1025 * Exit: CC=0 - controller ready for command
1026 * CC=1 - Error message in B
1027 * DrivMask,u - contains drive # bit ready for IDE masking
1028 * PRESERVES X&Y
1029 WaitDrv pshs x,y Preserve regs
1030 ldx #$A000 (1/2 to 1/3 second busy check)
1031 lda PD.DNS,y Get physical drive #
1032 anda #PhysDriv No bad drive # possible
1033 lsla Move drive # into proper bit for Drive/head
1034 lsla
1035 lsla
1036 lsla
1037 sta DrivMask,u Save drive mask for IDE
1038 ldy V.PORT,u Get controller address for drive selected
1039 RdyIni1 tst Status,y IDE busy?
1040 bpl IDEReady No, return
1041 leax -1,x Dec counter
1042 bne RdyIni1 Try again
1043 puls x,y Restore regs
1044 ENotRdy clr drvrbusy,u
1045 comb Tried too long; give up with error
1046 ldb #E$NotRdy
1047 rts
1048
1049 IDEReady puls x,y Restore regs
1050 clrb IDE ready, return
1051 rts
1052
1053 * Copy LSN0 stuff into drive table
1054 * Entry: X=ptr to 256 byte buffer containing LSN0 Sector.
1055 * Exit: X,D is destroyed
1056 CpyDrvTb pshs y Save path desc. ptr
1057 ldb PD.DRV,y Get LOGICAL drive #
1058 lda #DRVMEM Copy useful information to our LSN 0 buffer
1059 mul Point to proper entry in drive table
139 leay DRVBEG,u 1060 leay DRVBEG,u
1061 leay d,y
1062 lda #DD.SIZ
140 LSN0Cp ldb ,x+ 1063 LSN0Cp ldb ,x+
141 stb ,y+ 1064 stb ,y+
142 deca 1065 deca
143 bne LSN0Cp 1066 bne LSN0Cp
144 puls y Done with LSN 0 stuff 1067 puls y,pc Restore path desc. ptr & return
145 1068
146 NotLSN0 bsr WaitOK Wait for drive to complete command 1069 * Notes: PhysSN is the physical sector number to send to the controller,
147 bcc Ret 1070 * not the LSN...so it must be translated from the LSN (for IDE, divide by
148 lbra ReadErr 1071 * 2, unless using ATAPI CDROM, in which case divide by 8).
149 Ret rts 1072 * Note that the head returned from this routine is base 0, so that the
150 1073 * lowest head # returned would be 0 (for the first head). This matches
151 * 1074 * the IDE spec (which can also only go up to 16 heads).
152 * WRITE 1075 * The cylinder returned is also base 0, same as IDE.
153 * 1076 * The sector returned is base 0, but IDE needs base 1.
154 * Y = address of path descriptor 1077 * Vars used from elsewhere - OS9PSN,u - Physical (IDE 512) sector #
155 * U = address of device memory (ie, of V.PAGE) 1078 * - Head,u - IDE head #
156 * B = MSB of OS-9 disk LSN 1079 * - Cylinder,u - IDE Cylinder #
157 * X = LSB of OS-9 disk LSN 1080 * - CHSSect,u - IDE sector (512) #
158 * 1081 * - CHSSPT,u - IDE (512 byte) sctrs/track)
159 FWrite lbsr SavLSN Save LSN info 1082
160 * 1083 * LSN division routine variable definitions: all on temp stack
161 * *** HACK *** Read the 2 sectors into our buffer first 1084 org 0
162 * 1085 S.SclPwr rmb 2 scale power
163 ldb #$30 IDE Read w/ Retry command 1086 S.SclAmt rmb 3 scale amount
164 lbsr SetIDE Setup IDE command registers 1087 S.Cyl rmb 2 cylinder number
165 bcs ReadDone 1088 S.PSN rmb 3 physical sector number (work copy)
166 pshs y 1089 S.Head rmb 1 head number
167 ldx PD.BUF,y 1090 S.Frame equ . size of stack frame
168 lda #$20 1091
169 sta Counter,u 1092 * Entry: U=ptr to driver data area
170 ldy V.PORT,u 1093 * Y=Ptr to path descriptor
171 HackLp ldd ,x++ 1094 * X=Ptr to current drives' entry in drive table (DD.TOT, etc.)
172 sta ,y 1095 * OS9PSN,u- Three byte Physical (512 byte) sector #)
173 stb ,y 1096 * Exit: U=ptr to driver data area
174 ldd ,x++ 1097 * Y=ptr to path descriptor
175 sta ,y 1098 * X=Drive table ptr
176 stb ,y 1099 * Head,u=Head # in CHS mode
177 ldd ,x++ 1100 * Cylinder,u=Cylinder # in CHS mode
178 sta ,y 1101 * CHSSect,u=Sector # in CHS mode
179 stb ,y 1102 * CC=0, no error, above 3 vars. are legit
180 ldd ,x++ 1103 * CC=1, error, error return in B
181 sta ,y 1104 CalcCHS leas -S.Frame,s make room for LSN division variables
182 stb ,y 1105 ldb OS9PSN,u
183 dec Counter,u 1106 stb S.PSN,s initialize PSN MSB
184 bne HackLp 1107 ldd OS9PSN+1,u
185 puls y 1108 std S.PSN+1,s initialize PSN LSBs
186 bsr WaitOK Wait for drive to finish command 1109 ldd #$0000
187 bcc ReadDone 1110 sta S.Head,s initialize head number
188 lbsr WriteErr 1111 std S.Cyl,s initialize cylinder number
189 ReadDone rts 1112 ldd S.PSN+1,s get PSN LSBs
190 * 1113 subd CHSSPT,u less sectors/track
191 * After read or write, check drive status 1114 bhs NotTrk0
192 * Return value = CC, true=error, false=OK 1115 tst S.PSN,s PSN MSB = 0?
193 * 1116 beq DivDone yes, sector in track 0, go save info
194 WaitOK ldy V.PORT,u Is DRQ still true? Just one check necessary 1117 dec S.PSN,s PSN MSB less 1
195 tst 7,y If it is, sector isn't fully transferred 1118 NotTrk0 std S.PSN+1,s save remaining PSN LSBs
196 bmi WaitOK 1119 inc S.Head,s set to next head (1)
197 lda #$01 Wait *forever* for drive ready 1120 inc V.TRAK+1,x mark track as non-0 for SetUpWD
198 bita 7,y 1121 ldb CHSSPT+1,u get IDE sectors per track
199 bne CmdErr 1122 lda PD.SID,y Get # of disk heads
200 clrb Nope -- clear CC 1123 deca less track 0
201 rts 1124 mul calculate sectors remaining in cylinder 0
202 CmdErr comb Yep -- set CC 1125 std S.SclPwr,s save it temporarily
203 rts 1126 ldd S.PSN+1,s get remaining PSN LSBs
204 1127 subd S.SclPwr,s less sectors remaining in cylinder 0
205 * 1128 bhs NotCyl0
206 * Setup IDE read or write operation 1129 tst S.PSN,s remaining PSN MSB = 0?
207 * 1130 beq CalcHead sector in cylinder 0, go get head number
208 * B = IDE command code 1131 dec S.PSN,s remaining PSN MSB less 1
209 * 1132 NotCyl0 std S.PSN+1,s save remaining PSN LSBs
210 * trashes D and X 1133 inc S.Cyl+1,s set cylinder to 1
211 * 1134 clr S.Head,s reset head number to 0
212 SetIDE stb idecmd,u 1135 lda PD.SID,y get disk sides
213 pshs y 1136 ldb CHSSPT+1,u get sectors per track
214 ldx #$A000 1137 NrmlDiv clr S.SclAmt+2,s initialize scale amount LSB
215 CmdLp1 ldy V.PORT,u 1138 lsla HD prescale = heads x 8
216 tst 7,y 1139 lsla This is the max we can do with a 16 head
217 bpl SetRdy Should go to ChkDRDY ????? 1140 lsla drive, using 8 bit MUL.
218 leax -1,x 1141 mul calculate scale amount MSBs
219 bne CmdLp1 1142 std S.SclAmt,s save scale amount MSBs
220 puls y 1143 ldd #HDSclPwr Set hard drive scale power
221 bra ENotRdy 1144 std S.SclPwr,s save scale power
222 1145 DivLoop lda S.PSN,s get remaining PSN MSB
223 SetRdy ldy V.PORT,u Drive is ready -- calculate HCS from LSN 1146 cmpa S.SclAmt,s remaining PSN > scale amount?
224 lda OS9LSN+2,u Sector first 1147 blo DivLoop1 no, go set up next scale amount & power
225 anda #$1F 1148 bhi DivLoop2 yes, go do subtraction
226 adda #$01 1149 ldd S.PSN+1,s get remaining PSN LSBs
227 sta 3,y Store calculated sector number 1150 subd S.SclAmt+1,s remaining PSN >= scale amount?
228 ldd OS9LSN+1,u Drive number next 1151 blo DivLoop1 no, go set up next scale amount & power
229 rolb 1152 std S.PSN+1,s save remaining PSN LSBs
230 rola 1153 bra DivLoop3
231 rolb 1154
232 rola 1155 DivLoop2 ldd S.PSN+1,s get remaining PSN LSBs
233 rolb 1156 subd S.SclAmt+1,s less scale amount LSBs
234 rola 1157 std S.PSN+1,s save remaining PSN LSBs
235 anda #$0F 1158 DivLoop3 lda S.PSN,s get remaining PSN MSB
236 ora #$A0 1159 sbca S.SclAmt,s less scale amount MSB and borrow (if any)
237 sta 6,y Store calculated drive number 1160 sta S.PSN,s save remaining PSN MSB
238 ldd OS9LSN,u Last, the cylinder number (2-bytes) 1161 ldd S.Cyl,s get cylinder number
239 rora 1162 addd S.SclPwr,s add scale power
240 rorb 1163 std S.Cyl,s save cylinder number
241 anda #$7F 1164 DivLoop1 lsr S.SclAmt,s * divide scale amount by two
242 sta 5,y Store calculated CylHi 1165 ror S.SclAmt+1,s
243 stb 4,y Store calculated CylLo 1166 ror S.SclAmt+2,s
244 lda #$01 1167 lsr S.SclPwr,s * divide scale power by two
245 sta 2,y Sector count = 1 1168 ror S.SclPwr+1,s
246 ldb idecmd,u 1169 bcc DivLoop
247 stb 7,y Lastly, push the command to the drive 1170 CalcHead ldd S.PSN+1,s get remaining PSN LSBs
248 ldb #$40 1171 NextHead subd CHSSPT,u less sectors per track (head)
249 lda #$08 Wait for Drive ready 1172 blo DivDone underflow, go save info
250 CmdLp2 bita 7,y 1173 std S.PSN+1,s save remaining PSN LSBs
251 bne CmdDone 1174 inc S.Head,s increment head number
252 decb 1175 bra NextHead
253 bne CmdLp2 1176
254 ldx #$0001 If we time out, sleep 1 tick, then loop *forever* 1177 DivDone ldd S.Cyl,s get cylinder number
255 os9 F$Sleep 1178 cmpd PD.CYL,y cylinder number OK?
256 CmdLp3 bita 7,y 1179 bhs LSNErrSF no, go return error
257 beq CmdLp3 1180 std Cylinder,u
258 CmdDone puls y 1181 lda S.PSN+2,s get sector number (remaining PSN LSB)
259 clrb All right, drive ready -- return 1182 inca IDE needs base 1
260 rts 1183 sta CHSSect,u
261 1184 ldb S.Head,s get head number
262 ENotRdy comb 1185 stb Head,u
263 ldb #E$NotRdy 1186 leas S.Frame,s restore stack pointer
264 rts 1187 clrb
265 WriteErr comb 1188 rts
266 ldb #E$Write 1189
267 rts 1190 LSNErrSF leas S.Frame,s restore stack pointer
268 ReadErr comb 1191 LSNErr comb
269 ldb #E$Read 1192 ldb #E$Sect Exit with Bad sector # error
270 rts 1193 rts
271 1194
272 emod 1195 emod
273 eom equ * 1196 eom equ *
274 end 1197 end