Mercurial > hg > Members > kono > nitros9-code
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 |