2590
|
1 *******************************************************************
|
|
2 * llide - Low-level IDE driver
|
|
3 *
|
|
4 * $Id$
|
|
5 *
|
|
6 * This low level driver works with both ATA and ATAPI devices.
|
|
7 *
|
|
8 * The type of device (ATA or ATAPI) is automatically detected
|
|
9 * by the 'IOSetup' routine. Additionally, an ATA device is
|
|
10 * further detected as either an LBA or CHS device.
|
|
11 *
|
|
12 * Since only two physical drives are allowed (master/slave),
|
|
13 * there is a two entry "per drive static storage" that indicates
|
|
14 * if a drive has been initialized, its type (ATAPI or ATA, LBA or
|
|
15 * CHS), and if ATA, its geometry.
|
|
16 *
|
|
17 * Edt/Rev YYYY/MM/DD Modified by
|
|
18 * Comment
|
|
19 * ------------------------------------------------------------------
|
|
20 * 1 2004/04/08 Boisy G. Pitre
|
|
21 * Created.
|
|
22 *
|
|
23 * 2 2005/07/23 Christopher R. Hawks
|
|
24 * Fixes for persnickity ATAPI CDROMs.
|
|
25 *
|
|
26 * 3 2005/08/21 Christopher R. Hawks
|
|
27 * More fixes.
|
|
28 *
|
|
29 * 4 2005/12/13 Boisy G. Pitre
|
|
30 * Moved SS.VarSect code into RBSuper for performance
|
|
31
|
|
32 NAM llide
|
|
33 TTL Low-level IDE driver
|
|
34
|
|
35 IFP1
|
|
36 USE defsfile
|
|
37 USE rbsuper.d
|
|
38 USE ide.d
|
|
39 ENDC
|
|
40
|
|
41 tylg SET Sbrtn+Objct
|
|
42 atrv SET ReEnt+rev
|
|
43 rev SET 4
|
|
44
|
|
45
|
|
46 RW12 SET 0 Use READ12/WRITE12 ATAPI commands (1 = yes)
|
|
47 WAITTIME SET 10 BUSY wait time (in approximate seconds)
|
|
48
|
|
49 *
|
|
50 * Status Register Flip/Mask Values
|
|
51 *
|
|
52 NBUSYDRDY EQU (BusyBit|DrdyBit)*256+(DrdyBit)
|
|
53 NBUSY EQU (BusyBit)*256+$00
|
|
54 NBUSYDRQ EQU (BusyBit|DrqBit)*256+(DrqBit)
|
|
55 NBUSYNDRQ EQU (BusyBit|DrqBit)*256+$00
|
|
56
|
|
57 MOD eom,name,tylg,atrv,start,0
|
|
58
|
|
59 IFNE RW12
|
|
60 READCODE EQU A$READ2
|
|
61 WRITCODE EQU A$WRITE2
|
|
62 ELSE
|
|
63 READCODE EQU A$READ
|
|
64 WRITCODE EQU A$WRITE
|
|
65 ENDC
|
|
66
|
|
67 NumRetries EQU 8
|
|
68
|
|
69 * Low-level driver static memory area
|
|
70 ORG V.LLMem
|
|
71 * Master static storage
|
|
72 V.Master RMB 1 status byte (ATAPI or ATA (CHS or LBA))
|
|
73 RMB 2 Cylinders (CHS) or Bits 31-16 of LBA
|
|
74 RMB 1 Sides (CHS) or Bits 15-8 of LBA
|
|
75 RMB 2 Sectors (CHS) or Bits 7-0 of LBA
|
|
76 * Slave drive static storage
|
|
77 V.Slave RMB 1
|
|
78 RMB 2
|
|
79 RMB 1
|
|
80 RMB 2
|
|
81 * ATAPI Command Packet
|
|
82 V.ATAPICmd RMB 18
|
|
83 V.SnsData EQU V.ATAPICmd Sense Data is shared with ATAPI command block
|
|
84 * The following values are for device 0 and 1 respectively:
|
|
85 * Bit 0 = device inited (0 = false, 1 = true)
|
|
86 * Bit 1 = device type (0 = ATA, 1 = ATAPI)
|
|
87 * Bit 2 = device mode (0 = CHS, 1 = LBA)
|
|
88 V.CurStat RMB 1
|
|
89 V.Retries RMB 1
|
|
90 V.WhichDv RMB 1 contains devhead selection (made by IOSetup)
|
|
91 V.PhySct RMB 3 local copy of physical sector passed (V.PhySct)
|
|
92 V.SctCnt RMB 1 local copy of physical sector passed (V.SectCnt)
|
|
93 V.Sectors RMB 1 number of sectors (harvested directly from drive query)
|
|
94 V.CurDTbl RMB 2
|
|
95 V.ATAVct RMB 2
|
|
96
|
|
97
|
|
98 name FCS /llide/
|
|
99
|
|
100 start bra ll_init
|
|
101 nop
|
|
102 lbra ll_read
|
|
103 lbra ll_write
|
|
104 lbra ll_getstat
|
|
105 lbra ll_setstat
|
|
106
|
|
107 * ll_init - Low level init routine
|
|
108 *
|
|
109 * Entry:
|
|
110 * Y = address of device descriptor
|
|
111 * U = address of low level device memory area
|
|
112 *
|
|
113 * Exit:
|
|
114 * CC = carry set on error
|
|
115 * B = error code
|
|
116 *
|
|
117 * Note: This routine is called ONCE: for the first device
|
|
118 * IT IS NOT CALLED PER DEVICE!
|
|
119 *
|
|
120 ll_init
|
|
121 * clrb
|
|
122 * rts
|
|
123
|
|
124
|
|
125 * ll_term - Low level term routine
|
|
126 *
|
|
127 * Entry:
|
|
128 * Y = address of device descriptor
|
|
129 * U = address of device memory area
|
|
130 *
|
|
131 * Exit:
|
|
132 * CC = carry set on error
|
|
133 * B = error code
|
|
134 *
|
|
135 * Note: This routine is called ONCE: for the last device
|
|
136 * IT IS NOT CALLED PER DEVICE!
|
|
137 *
|
|
138 ll_term
|
|
139 clrb
|
|
140 rts
|
|
141
|
|
142
|
|
143 * Entry: Y = address of per-drive static storage
|
|
144 ATADSize
|
|
145 pshs y,x,b make room for space on stack (and save id byte)
|
|
146 * Determine if we are dealing with LBA or CHS
|
|
147 bitb #$04 LBA?
|
|
148 bne lba@
|
|
149 * Here we pull CHS values
|
|
150 chs@
|
|
151 ldd 1,y get cylinders
|
|
152 std 1,s
|
|
153 lda 3,y get sides
|
|
154 sta ,s save sides on stack (B)
|
|
155 ldd 4,y get sectors
|
|
156 std 3,s save sectors/track on stack (Y)
|
|
157 bra m@
|
|
158 * Here we pull LBA values at words 60-61
|
|
159 lba@
|
|
160 clr ,s clear flag indicating LBA mdoe (B)
|
|
161 ldd 3,y get bits 15-0
|
|
162 std 3,s save bits 15-0 on stack (Y)
|
|
163 ldd 1,y get bits 31-16
|
|
164 std 1,s save bits 31-16 (X)
|
|
165 m@ lda #$02 512 bytes/sector
|
|
166 ex@ puls b,x,y,pc
|
|
167
|
|
168
|
|
169 * SSDSize - Get a disk medium's size
|
|
170 *
|
|
171 * GetStat Call SS.DSize:
|
|
172 *
|
|
173 * Entry: B = SS.DSize
|
|
174 * Exit: Carry = 1; error with code in B
|
|
175 * Carry = 0:
|
|
176 * IF B = 0
|
|
177 * A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048)
|
|
178 * X = Number of Sectors (bits 31-16)
|
|
179 * Y = Number of Sectors (Bits 15-0)
|
|
180 * IF B != 0
|
|
181 * A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048)
|
|
182 * X = Number of Logical Cylinders
|
|
183 * B = Number of Logical Sides
|
|
184 * Y = Number of Logical Sectors/Track
|
|
185 *
|
|
186 SSDSize pshs u,y
|
|
187 bsr DSize
|
|
188 bcs ex@
|
|
189 ldu ,s get path desc in U
|
|
190 ldu PD.RGS,u
|
|
191 std R$D,u
|
|
192 stx R$X,u
|
|
193 sty R$Y,u
|
|
194 clrb
|
|
195 ex@ puls y,u,pc
|
|
196
|
|
197 DSize lbsr IOSetup
|
|
198 bcs ex@
|
|
199 * Determine if this device is ATAPI or ATA
|
|
200 bitb #$02 ATAPI?
|
|
201 lbeq ATADSize no, it's ATA
|
|
202 * Note - for ATAPI version of SS.DSize, we use the obsolete
|
|
203 * READ CAPACITY call because it works on CD-ROMs, as opposed to
|
|
204 * READ FORMAT CAPACITIES.
|
|
205 ATAPIDSize
|
|
206 lbsr ATAPIPreSend prepare packet
|
|
207 * Populate packet buffer with STOP code and Eject
|
|
208 * ldd #$230C ATAPI READ FORMAT CAPACITIES Code
|
|
209 lda #$25 ATAPI READ CAPACITY Code
|
|
210 sta V.ATAPICmd,u write it
|
|
211 * stb V.ATAPICmd+8,u and allocation length
|
|
212 * Send to data port
|
|
213 bsr ATAPISend send command
|
|
214 bcs ex@
|
|
215 * Read 8 bytes of format capacity data
|
|
216 * ldb #6
|
|
217 ldb #4
|
|
218 pshs b
|
|
219 leay V.SnsData,u
|
|
220 read@ lda DataReg,x
|
|
221 ldb Latch,x
|
|
222 std ,y++
|
|
223 dec ,s
|
|
224 bne read@
|
|
225 puls b
|
|
226 ldx V.SnsData+0,u
|
|
227 ldy V.SnsData+2,u
|
|
228 leay 1,y
|
|
229 bcc b@
|
|
230 leax 1,x
|
|
231 b@ lda V.SnsData+6,u
|
|
232 clrb
|
|
233 ex@ rts
|
|
234
|
|
235 * ldy PD.RGS,y
|
|
236 * ldd V.SnsData+0,u get bits 31-16
|
|
237 * std R$X,y
|
|
238 * ldd V.SnsData+2,u get bits 15-0
|
|
239 * addd #$0001 add 1
|
|
240 * std R$Y,y
|
|
241 * bcc b@
|
|
242 * ldd R$X,y
|
|
243 * addd #$0001
|
|
244 * std R$X,y
|
|
245 *b@ lda V.SnsData+6,u get bits 15-8 of block size
|
|
246 * sta R$A,y
|
|
247 * clr R$B,y signal that this is LBA mode
|
|
248 * clrb
|
|
249 *ex@ rts
|
|
250
|
|
251
|
|
252 * ll_getstat - Low level GetStat routine
|
|
253 *
|
|
254 * Entry:
|
|
255 * Y = address of path descriptor
|
|
256 * U = address of device memory area
|
|
257 *
|
|
258 * Exit:
|
|
259 * CC = carry set on error
|
|
260 * B = error code
|
|
261 *
|
|
262 ll_getstat
|
|
263 ldx PD.RGS,y
|
|
264 lda R$B,x
|
|
265 cmpa #SS.DSize
|
|
266 beq SSDSize
|
|
267 ldb #E$UnkSvc
|
|
268 coma
|
|
269 ex1 rts
|
|
270
|
|
271
|
|
272 * StopUnit - Park a drive
|
|
273 *
|
|
274 * ATA Devices: This is a No-Op.
|
|
275 * ATAPI Devices: A STOP UNIT command is issued to the device.
|
|
276 * (ejects media on ATAPI removable devices)
|
|
277 StopUnit lbsr IOSetup
|
|
278 bcs ex1
|
|
279 * Determine if this device is ATAPI or ATA
|
|
280 bitb #$02 ATAPI?
|
|
281 beq ex1 no, ignore...
|
|
282 lbsr ATAPIPreSend prepare packet
|
|
283 * Populate packet buffer with STOP code and Eject
|
|
284 ok@ ldd #A$STOP*256+$02 ATAPI STOP Code and Eject byte
|
|
285 sta V.ATAPICmd,u write it and RSV to zero
|
|
286 stb V.ATAPICmd+4,u
|
|
287 * Send to data port
|
|
288 bra ATAPISend send command
|
|
289
|
|
290
|
|
291 * ll_setstat - Low level SetStat routine
|
|
292 *
|
|
293 * Entry:
|
|
294 * Y = address of path descriptor
|
|
295 * U = address of device memory area
|
|
296 *
|
|
297 * Exit:
|
|
298 * CC = carry set on error
|
|
299 * B = error code
|
|
300 *
|
|
301 ll_setstat
|
|
302 ldx PD.RGS,y
|
|
303 lda R$B,x
|
|
304 cmpa #SS.SQD
|
|
305 beq StopUnit
|
|
306 IFNE 0
|
|
307 cmpa #SS.DCmd
|
|
308 bne n@
|
|
309 pshs x save pointer to caller registers
|
|
310 bsr DCmd call DCmd
|
|
311 puls x get pointer to caller registers
|
|
312 sta R$A,x save status byte in A
|
|
313 ENDC
|
|
314 n@ clrb
|
|
315 ssex rts
|
|
316
|
|
317
|
|
318 IFNE 0
|
|
319 BadType comb
|
|
320 ldb #E$BTyp
|
|
321 rts
|
|
322
|
|
323 * Entry:
|
|
324 * X = caller regs
|
|
325 * Y = path descriptor
|
|
326 *
|
|
327 * R$B = SS.DCmd
|
|
328 * R$X = Transfer buffer
|
|
329 * R$Y = ATAPI command packet
|
|
330 DCmd
|
|
331 pshs y
|
|
332 os9 F$ID get the user ID of the calling process
|
|
333 cmpy #$0000 is it 0 (superuser)?
|
|
334 puls y
|
|
335 bne noperms no, don't allow the call
|
|
336 lbsr IOSetup
|
|
337 ** SS.DCmd only works with ATAPI devices.
|
|
338 bitb #$02 ATAPI?
|
|
339 beq BadType branch if not
|
|
340 ldy R$X,x get caller's transfer buffer
|
|
341 sty V.UTxBuf,u save off in mem for later
|
|
342 ldx R$Y,x get ptr to caller's command buffer
|
|
343 IFGT Level-1
|
|
344 ldy D.Proc get current process ptr
|
|
345 lda P$Task,y get task # for current process
|
|
346 ldb D.SysTsk get system task #
|
|
347 ldy #ATAPIPkLn max size of ATAPI command
|
|
348 pshs u save on stack
|
|
349 leau V.ATAPICmd,u point to ATAPI command buffer in our statics
|
|
350 os9 F$Move copy from caller to temporary task
|
|
351 puls u
|
|
352 bcs ex error copying, exit
|
|
353 ELSE
|
|
354 ldb #ATAPIPkLn
|
|
355 leay V.ATAPICmd,u
|
|
356 cl@ lda ,x+
|
|
357 sta ,y+
|
|
358 decb
|
|
359 bne cl@
|
|
360 ENDC
|
|
361 ldy V.PORT-UOFFSET,u get hw address (because we overwrite Y earlier)
|
|
362 * inc V.OS9Err,u we want real errors returned
|
|
363 inc V.CchDirty,u and make cache dirty
|
|
364 * leax retry@,pcr
|
|
365 * stx V.RetryVct,u
|
|
366 retry@ lbsr ATAPISend
|
|
367 bcs ex
|
|
368 IFGT Level-1
|
|
369 ldx D.Proc get current process ptr
|
|
370 ldb P$Task,x get task # for current process
|
|
371 ENDC
|
|
372 ldx V.UTxBuf,u
|
|
373
|
|
374 msgloop@ lbsr Wait4REQ wait for REQ to be asserted
|
|
375 bita #CMD command phase?
|
|
376 lbne PostXfr yes, return
|
|
377 io@ bita #INOUT data coming in or going out?
|
|
378 bne in@ branch if coming in...
|
|
379 IFGT Level-1
|
|
380 os9 F$LDABX
|
|
381 leax 1,x
|
|
382 ELSE
|
|
383 lda ,x+
|
|
384 ENDC
|
|
385 sta SCSIDATA,y
|
|
386 bra msgloop@
|
|
387 in@ lda SCSIDATA,y
|
|
388 IFGT Level-1
|
|
389 os9 F$STABX
|
|
390 leax 1,x
|
|
391 ELSE
|
|
392 sta ,x+
|
|
393 ENDC
|
|
394 bra msgloop@
|
|
395 ENDC
|
|
396
|
|
397 * ATAPISend - Sends the command packet to the device
|
|
398 *
|
|
399 * Entry: X = HW address
|
|
400 * V.WhichDv = DevHead device selection value
|
|
401 * Exit: Carry = 1; error code in B
|
|
402 * Carry = 0; command successfully sent
|
|
403 ATAPISend
|
|
404 * First, select the device and wait for /BUSY
|
|
405 lda V.WhichDv,u
|
|
406 sta DevHead,x select device
|
|
407 * ATAPI says we wait for !BUSY
|
|
408 ldd #NBUSYDRDY wait for NBUSY and DEVREADY too - CRH
|
|
409 lbsr StatusWait wait for proper condition
|
|
410 bcs timeout branch if error
|
|
411 lda #NumRetries get retry count
|
|
412 sta V.Retries,u and save
|
|
413 retry@
|
|
414 clr Features,x clear feature byte
|
|
415 clr SectCnt,x clear TAG field
|
|
416 ldd #$FFFF maximum read in PIO mode
|
|
417 std CylLow,x
|
|
418 lda #$A0 ATAPI PACKET CODE
|
|
419 sta Command,x write it to device
|
|
420 * Check for error
|
|
421 ldd #NBUSYDRQ /BUSY and DRQ
|
|
422 lbsr StatusWait wait for proper condition
|
|
423 bcs ex@ branch if error
|
|
424 * Send to data port
|
|
425 lda #6 packet size / 2
|
|
426 pshs a,y
|
|
427 leay V.ATAPICmd,u
|
|
428 l@ ldd ,y++
|
|
429 stb Latch,x
|
|
430 sta DataReg,x
|
|
431 dec ,s
|
|
432 bne l@
|
|
433 puls a,y
|
|
434 * Added by CRH - Some drives require that we wait for much more than
|
|
435 * 400ns. Hence this code forces a slow-down and checks the status
|
|
436 * to see if things are ok.
|
|
437 clrb
|
|
438 slow@ decb CRH wait for much more than 400ns
|
|
439 bne slow@
|
|
440 lda Status,x CRH Sometimes error on first try
|
|
441 lsra
|
|
442 bcc ok@
|
|
443 dec V.Retries,u
|
|
444 bne retry@
|
|
445 * As per ATA/ATAPI-6 spec (T13/1410D Revision 3A), page 161, we wait for /BUSY
|
|
446 * and DRQ after sending a command
|
|
447 * That IS NOT the case when sending START/STOP unit commands, so we don't check
|
|
448 * for DRQ.
|
|
449 ok@ ldd #NBUSY /BUSY
|
|
450 lbsr StatusWait wait for proper condition
|
|
451 bcs ex@ branch if error
|
|
452 lda #A$STOP CRH see above
|
|
453 cmpa V.ATAPICmd,u
|
|
454 beq nodata@
|
|
455 ldd #NBUSYDRQ /BUSY and DRQ
|
|
456 lbsr StatusWait wait for proper condition
|
|
457 bcs ex@ branch if error
|
|
458 nodata@ lsra shift in CHECK CONDITION bit
|
|
459 bcc ex@ branch if ok
|
|
460 * Note: if the device returns error, DRQ won't be set...
|
|
461 err@ lbsr HandleSenseKey go check sense key
|
|
462 bcs ex@
|
|
463 ret@ dec V.Retries,u else retry until terminal
|
|
464 bne retry@ continue retrying
|
|
465 timeout comb set carry
|
|
466 ldb #E$DevBsy+4 SHOULD BE AN E$TimeOut ERROR!
|
|
467 ex@ rts
|
|
468
|
|
469 * Prepare the ATAPI Packet
|
|
470 ATAPIPreSend
|
|
471 pshs x
|
|
472 * Clear 12 byte packet.
|
|
473 leax V.ATAPICmd,u
|
|
474 ldb #12
|
|
475 c@ clr ,x+
|
|
476 decb
|
|
477 bne c@
|
|
478 ex@ puls x,pc
|
|
479
|
|
480
|
|
481 ** ATAPI REQUEST SENSE Command
|
|
482 ** Should only be called for ATAPI devices
|
|
483 *ReqSense
|
|
484 * bsr ATAPIPreSend prepare packet
|
|
485 ** Populate packet buffer with REQUEST SENSE
|
|
486 * ldd #$0312 ATAPI REQUEST SENSE Code and allocation length byte
|
|
487 * sta V.ATAPICmd,u
|
|
488 * stb V.ATAPICmd+4,u
|
|
489 ** Send to data port
|
|
490 * lbsr ATAPISend send command
|
|
491 * lda Status,x get status code
|
|
492 * lsra shift in CHECK CONDITION bit
|
|
493 * bcs ex@ branch if ok
|
|
494 ** Read 18 bytes of sense data
|
|
495 * ldb #$12
|
|
496 * pshs y,b
|
|
497 * leay V.SnsData,u
|
|
498 *read@ lda DataReg,x
|
|
499 * ldb Latch,x
|
|
500 * std ,y++
|
|
501 * dec ,s
|
|
502 * bne read@
|
|
503 * puls b,y,pc
|
|
504 *ex@ rts
|
|
505
|
|
506
|
|
507 * IOSetup - Sets up the device for I/O
|
|
508 *
|
|
509 * The device is selected (master or slave), then the device is
|
|
510 * checked for previous initialization.
|
|
511 *
|
|
512 * If the device has not been initialized, it is queried for its
|
|
513 * mode (ATAPI/ATA, LBA or CHS) and size. That information is
|
|
514 * saved in the driver's static storage for later use by other
|
|
515 * routines.
|
|
516 *
|
|
517 * Entry: Y = path descriptor pointer
|
|
518 * U = static memory pointer
|
|
519 * Exit: B = status byte for device
|
|
520 * X = HW address
|
|
521 * Y = pointer to current device table
|
|
522 IOSetup ldx V.PORT-UOFFSET,u get hw address
|
|
523 lda PD.DNS,y get device ID bit
|
|
524 lsra shift device ID into carry
|
|
525 bcs slave@
|
|
526 lda #%10100000 master byte
|
|
527 leay V.Master,u
|
|
528 bra t@
|
|
529 slave@ lda #%10110000 slave byte
|
|
530 leay V.Slave,u else point to slave status byte
|
|
531 t@ sty V.CurDTbl,u
|
|
532 sta V.WhichDv,u save for later
|
|
533 * Select the device -- on power-up, the status register is usually 0
|
|
534 sta DevHead,x select device
|
|
535 * According to page 320 of the ATA/ATAPI-6 document, we must wait for BOTH
|
|
536 * BUSY and DRQ to be clear before proceeding. (HI2: Device_Select State)
|
|
537 ldd #NBUSYNDRQ /BUSY and /DRQ
|
|
538 lbsr StatusWait wait for proper condition
|
|
539 lbcs ex@ branch if error
|
|
540 * Determine if this device has already been initialized
|
|
541 tst ,y test device's stat byte
|
|
542 lbne initdone if not zero, init already done
|
|
543 * Here we must initialize the device by IDENTIFYING it.
|
|
544 * First, try sending the ATA IDENTIFY DRIVE code
|
|
545 lda #$EC ATA identify command
|
|
546 sta Command,x write it
|
|
547 ldd #NBUSY /BUSY
|
|
548 lbsr StatusWait wait for proper condition
|
|
549 lbcs ex@ branch if error
|
|
550 * Check if there's an error
|
|
551 lsra shift error bit into carry
|
|
552 bcc ATAIdent if no error, then probably ATA
|
|
553 * If here, we got an error sending $EC, so try ATAPI's $A1
|
|
554 lda #$A1
|
|
555 sta Command,x
|
|
556 clrb
|
|
557 slow@ decb CRH wait for much more than 400ns
|
|
558 bne slow@
|
|
559 ldd #NBUSY
|
|
560 lbsr StatusWait wait for proper condition
|
|
561 bcs ex@ branch if error
|
|
562 lsra shift error bit into carry
|
|
563 bcs timeout if not error, we're ok
|
|
564 ldd #NBUSYDRQ
|
|
565 lbsr StatusWait wait for proper condition
|
|
566 lbcs ex@ branch if error
|
|
567 * Here, we have identified an ATAPI device.
|
|
568 ATAPIIdent
|
|
569 ldb #$03 ATAPI
|
|
570 stb ,y
|
|
571 * We flush the ATAPI data but don't reference it
|
|
572 dread@ ldb DataReg,x CRH flush ALL bytes
|
|
573 * ldb Latch,x but save time by not reading latch
|
|
574 lda Status,x
|
|
575 anda #8
|
|
576 bne dread@
|
|
577 bra initdone
|
|
578 * ATAIdent - process an ATA device
|
|
579 * This routine is called by IOSetup when it deduces that the device
|
|
580 * being queried is an ATA device. This device is called ONCE -- the
|
|
581 * first time the device is accessed.
|
|
582 * This routine will set up our per-drive static storage to indicate that
|
|
583 * it is an ATA device. It will also determine if it is an LBA or CHS mode
|
|
584 * device, and save the appropriate CHS or LBA sector values.
|
|
585 ATAIdent
|
|
586 ldd #NBUSYDRDY /BUSY and DRDY
|
|
587 lbsr StatusWait wait for proper condition
|
|
588 bcs ex@ branch if error
|
|
589 * Harvest C/H/S and LBA sector values.
|
|
590 ldb DataReg,x ignore bytes 0-1
|
|
591 ldb DataReg,x bytes 2-3 = no. of cylinders
|
|
592 lda Latch,x
|
|
593 std 1,y save cylinders in our private static area
|
|
594 ldb DataReg,x ignore bytes 4-5
|
|
595 ldb DataReg,x bytes 6-7 = no. of heads
|
|
596 lda Latch,x
|
|
597 stb 3,y save sides on stack (B)
|
|
598 ldb DataReg,x ignore bytes 8-9
|
|
599 ldb DataReg,x ignore bytes 10-11
|
|
600 ldb DataReg,x bytes 12-13 = no. of sectors/track
|
|
601 lda Latch,x
|
|
602 std 4,y save sectors/track on stack (Y)
|
|
603 * Throw away the next 42 (7-48) words
|
|
604 ldb #43
|
|
605 l@ tst DataReg,x
|
|
606 lda Latch,x
|
|
607 decb
|
|
608 bne l@
|
|
609 * A holds byte with LBA bit
|
|
610 incb B was 0, now 1
|
|
611 anda #%00000010 LBA allowed on this drive?
|
|
612 beq nope@
|
|
613 orb #$04 set LBA mode
|
|
614 stb ,y save updated status byte
|
|
615 * Since we're LBA mode, get the number of LBA sectors in words 60-61
|
|
616 ldb #10 skip to the LBA sectors (words 60-61)
|
|
617 more@ tst DataReg,x simply read the data register like this...
|
|
618 decb
|
|
619 bne more@
|
|
620 ldb DataReg,x get word 60
|
|
621 lda Latch,x
|
|
622 std 3,y
|
|
623 ldb DataReg,x and 61
|
|
624 lda Latch,x
|
|
625 std 1,y
|
|
626 lda #256-61 how many words we have left
|
|
627 bra left@ go on.
|
|
628 nope@ stb ,y save updated status byte
|
|
629 * Read remaining 256-50 words
|
|
630 lda #256-50
|
|
631 left@ ldb DataReg,x
|
|
632 deca
|
|
633 bne left@
|
|
634 initdone ldb ,y get status byte of drive
|
|
635 clra clear carry
|
|
636 ex@ rts
|
|
637
|
|
638
|
|
639 * ATAPI Write Routine -- Independent of ATA Read
|
|
640 ATAPIWrite
|
|
641 lbsr ATAPIPreSend prepare packet
|
|
642 * Populate packet buffer with WRITE code and sector information
|
|
643 again@ ldb V.PhySct,u get bits 23-16 of sector
|
|
644 stb V.ATAPICmd+3,u
|
|
645 ldd V.PhySct+1,u get bits 15-0 of sector
|
|
646 std V.ATAPICmd+4,u
|
|
647 ldd #WRITCODE*256+$01 ATAPI WRITE Code and transfer length
|
|
648 sta V.ATAPICmd,u write it
|
|
649 IFNE RW12
|
|
650 stb V.ATAPICmd+9,u write to byte 9
|
|
651 ELSE
|
|
652 stb V.ATAPICmd+8,u write to byte 8
|
|
653 ENDC
|
|
654 * Send to data port
|
|
655 lbsr ATAPISend send command
|
|
656 bcs ex@
|
|
657 * Shift data from device
|
|
658 o@ pshs d
|
|
659 lda V.Log2Phys,u
|
|
660 sta 1,s set up our logical sector counter
|
|
661 inc@ clr ,s set up our byte counter
|
|
662 wr@ ldd ,y++
|
|
663 stb Latch,x
|
|
664 sta DataReg,x
|
|
665 inc ,s
|
|
666 bpl wr@
|
|
667 dec 1,s
|
|
668 bne inc@
|
|
669 puls d
|
|
670 * Increment physical sector
|
|
671 inc V.PhySct+2,u
|
|
672 bcc go@
|
|
673 inc V.PhySct+1,u
|
|
674 bcc go@
|
|
675 inc V.PhySct,u
|
|
676 go@ dec V.SctCnt,u decrement # of hw sectors to read
|
|
677 bne again@ if not zero, do it again
|
|
678 ldd #NBUSY /BUSY
|
|
679 lbsr StatusWait wait for proper condition
|
|
680 bcs ex@ branch if error
|
|
681 lsra error bit set?
|
|
682 bcc ex@ yep...
|
|
683 bsr HandleSenseKey
|
|
684 ex@ puls x,pc
|
|
685
|
|
686
|
|
687
|
|
688 * ATAPI Read Routine -- Independent of ATA Read
|
|
689 ATAPIRead
|
|
690 ldy V.CchPSpot,u get pointer to spot in cache to put sector
|
|
691 lbsr ATAPIPreSend do command packet setup stuff
|
|
692 * Populate packet buffer with READ code and sector information
|
|
693 again@ ldb V.PhySct,u get,u bits 23-16 of sector
|
|
694 stb V.ATAPICmd+3,u
|
|
695 ldd V.PhySct+1,u get bits 15-0 of sector
|
|
696 std V.ATAPICmd+4,u
|
|
697 ldd #READCODE*256+$01 ATAPI Read Code and transfer length
|
|
698 sta V.ATAPICmd,u write it and RSV to zero
|
|
699 IFNE RW12
|
|
700 stb V.ATAPICmd+9,u write to byte 9
|
|
701 ELSE
|
|
702 stb V.ATAPICmd+8,u write to byte 8
|
|
703 ENDC
|
|
704 * Send to data port
|
|
705 lbsr ATAPISend send command
|
|
706 bcs ex@
|
|
707 * Shift data from device
|
|
708 o@ pshs d
|
|
709 lda V.Log2Phys,u
|
|
710 sta 1,s set up our logical sector counter
|
|
711 inc@ clr ,s set up our byte counter
|
|
712 read@ lda DataReg,x
|
|
713 ldb Latch,x
|
|
714 std ,y++
|
|
715 inc ,s
|
|
716 bpl read@
|
|
717 dec 1,s
|
|
718 bne inc@
|
|
719 puls d
|
|
720 * Increment physical sector
|
|
721 inc V.PhySct+2,u
|
|
722 bcc go@
|
|
723 inc V.PhySct+1,u
|
|
724 bcc go@
|
|
725 inc V.PhySct,u
|
|
726 go@ dec V.SctCnt,u decrement # of hw sectors to read
|
|
727 bne again@ if not zero, do it again
|
|
728 ldd #NBUSY /BUSY
|
|
729 lbsr StatusWait wait for proper condition
|
|
730 bcs ex@ branch if error
|
|
731 lsra error bit set?
|
|
732 bcc ex@ nope...
|
|
733 bsr HandleSenseKey
|
|
734 ex@ puls x,pc
|
|
735
|
|
736
|
|
737 * Handle ATAPI Sense Key
|
|
738 * If the resulting error in the look-up table is zero,
|
|
739 * we return with carry clear
|
|
740 * Returns: B = 0 (carry clear, no error)
|
|
741 * B != 1 (carry set, error)
|
|
742 HandleSenseKey
|
|
743 pshs x,a
|
|
744 ldb ErrorReg,x get error register value
|
|
745 lsrb shift sense key into place
|
|
746 lsrb
|
|
747 lsrb
|
|
748 lsrb
|
|
749 leax SenseMap,pcr point to Sense Key Map
|
|
750 clra clear carry
|
|
751 ldb b,x get appropriate error
|
|
752 beq ok@ if error is zero, return ok
|
|
753 coma set carry
|
|
754 ok@ puls a,x,pc
|
|
755
|
|
756 * ll_read - Low level read routine
|
|
757 *
|
|
758 * Entry:
|
|
759 * Registers:
|
|
760 * Y = address of path descriptor
|
|
761 * U = address of device memory area
|
|
762 * Static Variables of interest:
|
|
763 * V.PhySct = starting physical sector to read from
|
|
764 * V.SectCnt = number of physical sectors to read
|
|
765 * V.SectSize = physical sector size (0=256,1=512,2=1024,3=2048)
|
|
766 * V.CchPSpot = address where physical sector(s) will go
|
|
767 *
|
|
768 * Exit:
|
|
769 * All registers may be modified
|
|
770 * Static variables may NOT be modified
|
|
771 ll_read
|
|
772 pshs x make some space on the stack
|
|
773 lbsr IOSetup initialize the device
|
|
774 lbcs ex@
|
|
775 * Copy V.PhySct and V.SectCnt to our local copy
|
|
776 * since we cannot modify them.
|
|
777 lda V.PhysSect,u
|
|
778 ldy V.PhysSect+1,u
|
|
779 sta V.PhySct,u
|
|
780 sty V.PhySct+1,u
|
|
781 lda V.SectCnt,u
|
|
782 sta V.SctCnt,u
|
|
783 bitb #$02 ATAPI device?
|
|
784 lbne ATAPIRead yes, go do it
|
|
785 * ATA Read Routine
|
|
786 ATARead
|
|
787 * stb V.CurStat,u save status of current drive
|
|
788 bitb #$04 LBA drive?
|
|
789 bne lba@ branch if so
|
|
790 leay DoCHS,pcr else point Y to CHS routine
|
|
791 bra skip@
|
|
792 lba@ leay DoLBA,pcr
|
|
793 skip@ sty V.ATAVct,u save pointer
|
|
794 ldy V.CchPSpot,u get pointer to spot in cache to put sector
|
|
795 loop@
|
|
796 ldd #NBUSY /BUSY
|
|
797 bsr StatusWait wait for proper condition
|
|
798 bcs ex@ branch if error
|
|
799 jsr [V.ATAVct,u] do proper ATA preparation
|
|
800 bcs ex@ branch if error
|
|
801 cont@ lda #$01
|
|
802 sta SectCnt,x store it
|
|
803 lda #S$READ
|
|
804 sta Command,x
|
|
805 ldd #NBUSY /BUSY
|
|
806 bsr StatusWait wait for proper condition
|
|
807 bcs ex@ branch if error
|
|
808 lsra error bit set?
|
|
809 bcc w@ branch if not
|
|
810 lbsr ATAError
|
|
811 bra ex@
|
|
812 w@ ldd #NBUSYDRQ /BUSY and DRQ
|
|
813 bsr StatusWait wait for proper condition
|
|
814 bcs ex@ branch if error
|
|
815 lda V.Log2Phys,u
|
|
816 sta 1,s set up our logical sector counter
|
|
817 inc@ clr ,s set up our byte counter
|
|
818 read@ lda DataReg,x
|
|
819 ldb Latch,x
|
|
820 std ,y++
|
|
821 inc ,s
|
|
822 bpl read@
|
|
823 dec 1,s
|
|
824 bne inc@
|
|
825 * Increment physical sector
|
|
826 inc V.PhySct+2,u
|
|
827 bcc go@
|
|
828 inc V.PhySct+1,u
|
|
829 bcc go@
|
|
830 inc V.PhySct,u
|
|
831 go@ dec V.SctCnt,u decrement # of hw sectors to read
|
|
832 bne loop@ if not zero, do it again
|
|
833 clrb
|
|
834 ex@ puls x,pc
|
|
835
|
|
836
|
|
837 *
|
|
838 * Convert LSN to LBA values
|
|
839 *
|
|
840 * Entry: V.PhySct = bits 23-0 of LSN
|
|
841 * X = ptr to hardware
|
|
842 *
|
|
843 * Exit: CHS values placed directly in HW
|
|
844 *
|
|
845 DoLBA lda V.WhichDv,u get devhead value populated by IOSetup (CHS mode)
|
|
846 ora #%01000000 OR in LBA bit
|
|
847 sta DevHead,x
|
|
848 ldd #NBUSYNDRQ /BUSY and /DRQ
|
|
849 bsr StatusWait
|
|
850 bcs ex@
|
|
851 ldb V.PhySct,u get bits 23-16 of sector
|
|
852 stb CylHigh,x store it
|
|
853 ldd V.PhySct+1,u get bits 15-0 of sector
|
|
854 stb SectNum,x store it
|
|
855 sta CylLow,x
|
|
856 ex@ rts
|
|
857
|
|
858
|
|
859 * Wait for a set of conditions in the status register to be TRUE
|
|
860 * This yields a delay of about 4 seconds.
|
|
861 *
|
|
862 * Entry: X = HW address
|
|
863 * A = flip (if bit set, that bit is tested)
|
|
864 * B = mask (result must match this byte)
|
|
865 * Exit: A = status
|
|
866 StatusWait
|
|
867 pshs y,b,a
|
|
868 IFEQ Level-1
|
|
869 ldb #WAITTIME/2
|
|
870 ldy #$0000
|
|
871 ELSE
|
|
872 ldb #WAITTIME
|
|
873 ldy #$0000
|
|
874 ENDC
|
|
875 l@ lda Status,x
|
|
876 anda ,s apply flip
|
|
877 cmpa 1,s compare to mask
|
|
878 bne dec@ branch if not equal (not what we want)
|
|
879 clrb clear carry
|
|
880 bra ok@
|
|
881 dec@ leay -1,y count down
|
|
882 bne l@
|
|
883 decb decrement bits 23-16
|
|
884 bpl l@ if >=0, keep going
|
|
885 err@ comb set carry
|
|
886 ldb #E$DevBsy
|
|
887 ok@ leas 2,s
|
|
888 lda Status,x get status again
|
|
889 puls y,pc
|
|
890
|
|
891 * Wait for 1 tick (1/60 second)
|
|
892 *Delay1Tk
|
|
893 * pshs x
|
|
894 * IFGT Level-1
|
|
895 * ldx D.Proc get proc descriptor
|
|
896 * cmpx D.SysPrc system?
|
|
897 * beq hw@ yep, system cannot sleep
|
|
898 * ENDC
|
|
899 * ldx D.AProcQ get active proc queue
|
|
900 * beq hw@ if empty, do hard wait
|
|
901 * ldx #1
|
|
902 * os9 F$Sleep give up worst case: 1 tick (1/60 second)
|
|
903 * puls x,pc return to caller
|
|
904 ** In case we can't sleep... do a hard 1/60 second delay
|
|
905 *hw@
|
|
906 * IFEQ Level-1
|
|
907 * ldx #$E52E/2 (5) (4)
|
|
908 * ELSE
|
|
909 * ldx #$E52E (5) (4)
|
|
910 * ENDC
|
|
911 *w@ leax -1,x (4+) (4+)
|
|
912 * bne w@ (3) (3)
|
|
913 * puls x,pc return to caller
|
|
914 *
|
|
915
|
|
916
|
|
917 * ll_write - Low level write routine
|
|
918 *
|
|
919 * Entry:
|
|
920 * Registers:
|
|
921 * Y = address of path descriptor
|
|
922 * U = address of device memory area
|
|
923 * Static Variables of interest:
|
|
924 * V.PhySct = starting physical sector to write to
|
|
925 * V.SectCnt = number of physical sectors to write
|
|
926 * V.SectSize = physical sector size (0=256,1=512,2=1024,3=2048)
|
|
927 * V.CchPSpot = address of data to write to device
|
|
928 *
|
|
929 * Exit:
|
|
930 * All registers may be modified
|
|
931 * Static variables may NOT be modified
|
|
932 ll_write
|
|
933 pshs x make some space on the stack
|
|
934 lbsr IOSetup initialize the device
|
|
935 lbcs ex@
|
|
936 * Copy V.PhySct to our local copy
|
|
937 lda V.PhysSect,u
|
|
938 ldy V.PhysSect+1,u
|
|
939 sta V.PhySct,u
|
|
940 sty V.PhySct+1,u
|
|
941 lda V.SectCnt,u
|
|
942 sta V.SctCnt,u
|
|
943 *
|
|
944 ldy V.CchPSpot,u get pointer to spot in cache where physical sector is
|
|
945 bitb #$02 ATAPI device?
|
|
946 lbne ATAPIWrite yes, go do it
|
|
947 * ATA Write Routine
|
|
948 ATAWrite stb V.CurStat,u save status of current drive
|
|
949 loop@
|
|
950 ldd #NBUSY /BUSY
|
|
951 bsr StatusWait wait for proper condition
|
|
952 bcs ex@ branch if ok
|
|
953 * Check for LBA mode
|
|
954 ldb V.CurStat,u get status of current drive
|
|
955 bitb #$04 LBA bit set?
|
|
956 bne lba@ branch if so
|
|
957 * Here, we use CHS
|
|
958 bsr DoCHS
|
|
959 bcs ex@
|
|
960 bra cont@
|
|
961 lba@ lbsr DoLBA
|
|
962 cont@ lda #$01
|
|
963 sta SectCnt,x store it
|
|
964 lda #S$WRITE
|
|
965 sta Command,x
|
|
966 ldd #NBUSY /BUSY
|
|
967 bsr StatusWait wait for proper condition
|
|
968 bcs ex@ branch if ok
|
|
969 lsra error bit set?
|
|
970 bcc g@ branch if not
|
|
971 lbsr ATAError
|
|
972 bra ex@
|
|
973 g@ ldd #NBUSYDRQ /BUSY and DRQ
|
|
974 lbsr StatusWait wait for proper condition
|
|
975 bcs ex@ branch if ok
|
|
976 again@ lda V.Log2Phys,u
|
|
977 sta 1,s set up our sector counter
|
|
978 inc@ clr ,s set up our byte counter
|
|
979 wr@ ldd ,y++
|
|
980 stb Latch,x
|
|
981 sta DataReg,x
|
|
982 inc ,s
|
|
983 bpl wr@
|
|
984 dec 1,s
|
|
985 bne inc@
|
|
986 * Increment physical sector
|
|
987 inc V.PhySct+2,u
|
|
988 bcc go@
|
|
989 inc V.PhySct+1,u
|
|
990 bcc go@
|
|
991 inc V.PhySct,u
|
|
992 go@
|
|
993 dec V.SctCnt,u decrement # of hw sectors to read
|
|
994 bne loop@ if not zero, do it again
|
|
995 clrb
|
|
996 ex@ puls x,pc
|
|
997
|
|
998 *
|
|
999 * Convert LSN to C/H/S values and write to IDE hardware
|
|
1000 *
|
|
1001 * Entry: V.PhySct = bits 23-0 of LSN
|
|
1002 * X = ptr to hardware
|
|
1003 *
|
|
1004 * Exit: CHS values placed directly in HW
|
|
1005 *
|
|
1006 DoCHS
|
|
1007 * Select device
|
|
1008 lda V.WhichDv,u get devhead value made by IOSetup (already CHS)
|
|
1009 sta DevHead,x
|
|
1010 ldd #NBUSYNDRQ /BUSY and /DRQ
|
|
1011 lbsr StatusWait wait for proper condition
|
|
1012 bcc start@ branch if ok
|
|
1013 rts
|
|
1014 * Start computation
|
|
1015 start@ pshs y save original Y
|
|
1016 ldy V.CurDTbl,u
|
|
1017 lda 3,y get device's head
|
|
1018 ldb 5,y and sector
|
|
1019 stb V.Sectors,u
|
|
1020 mul multiply H*S
|
|
1021 beq ZeroProd if zero, error out
|
|
1022 pshs d save product of H*S
|
|
1023 ldd V.PhySct+1,u get bits 15-0 of LSN
|
|
1024 ldy #-1 start Y at -1
|
|
1025 inc V.PhySct,u increment physical sector
|
|
1026 * Here we are doing physLSN/(H*S) to get cylinder for physLSN
|
|
1027 a@ leay 1,y increment count to compensate
|
|
1028 subd ,s subtract (H*S) from physLSN
|
|
1029 bhs a@ if D>=0 then continue
|
|
1030 dec V.PhySct,u decrement phys sector bits 23-16
|
|
1031 bne a@ if not zero, continue divide
|
|
1032 addd ,s++ add in (H*S) to make non-negative
|
|
1033 pshs d D now holds cylinder, save on stack
|
|
1034 tfr y,d Y now holds cylinder value
|
|
1035 exg a,b swap
|
|
1036 std CylLow,x store computed cylinder in HW
|
|
1037 puls d restore saved cylinder
|
|
1038 * Now we will compute the sector/head value
|
|
1039 ldy #-1
|
|
1040 b@ leay 1,y
|
|
1041 subb V.Sectors,u
|
|
1042 sbca #0
|
|
1043 bcc b@
|
|
1044 addb V.Sectors,u
|
|
1045 incb add 1 to B, which is sector
|
|
1046 stb SectNum,x store computed sector in HW
|
|
1047 tfr y,d
|
|
1048 orb DevHead,x OR in with value written earlier
|
|
1049 stb DevHead,x
|
|
1050 clrb
|
|
1051 puls y,pc
|
|
1052 ZeroProd ldb #E$Sect
|
|
1053 coma
|
|
1054 puls y,pc
|
|
1055
|
|
1056 * ATAError - Checks the ATA error register and maps
|
|
1057 * to a NitrOS-9 error message.
|
|
1058 *
|
|
1059 * Called if the error bit in the status register is set.
|
|
1060 ATAError
|
|
1061 lda ErrorReg,x
|
|
1062 ldb #7
|
|
1063 l@ lsra
|
|
1064 bcs LookUp
|
|
1065 decb
|
|
1066 bne l@
|
|
1067 LookUp leax Errs,pcr
|
|
1068 x@ ldb b,x
|
|
1069 coma
|
|
1070 rts
|
|
1071
|
|
1072 * This is the ATAPI Sense Key -> NitrOS-9 Error Table
|
|
1073 * The Sense Key Table is on page 50 of the ATAPI Removable
|
|
1074 * Rewritable Specification, Revision 1.3 Proposed.
|
|
1075 * If an error number is zero, then no error is returned.
|
|
1076 SenseMap FCB 0 sense key 0 (NO SENSE)
|
|
1077 FCB 0 sense key 1 (RECOVERED ERROR)
|
|
1078 FCB E$NotRdy sense key 2 (NOT READY)
|
|
1079 FCB E$Sect sense key 3 (MEDIUM ERROR)
|
|
1080 FCB E$Unit sense key 4 (HARDWARE ERROR)
|
|
1081 FCB E$IllArg sense key 5 (ILLEGAL REQUEST)
|
|
1082 FCB 0 sense key 6 (UNIT ATTENTION)
|
|
1083 FCB E$WP sense key 7 (DATA PROTECT)
|
|
1084 FCB 0 sense key 8 (BLANK CHECK)
|
|
1085 FCB 0 sense key 9 (VENDOR SPECIFIC)
|
|
1086 FCB 0 sense key A (RESERVED)
|
|
1087 FCB 1 sense key B (ABORTED COMMAND)
|
|
1088 FCB 0 sense key C (RESERVED)
|
|
1089 FCB 0 sense key D (VOLUME OVERFLOW)
|
|
1090 FCB 0 sense key E (MISCOMPARE)
|
|
1091 FCB 0 sense key F (RESERVED)
|
|
1092
|
|
1093 * ERROR REG Bit 0 1 2 3 4 5 6 7
|
|
1094 Errs FCB E$Unit,E$CRC,E$UnkSvc,E$Sect,E$UnkSvc,E$DIDC,E$Seek,E$Sect
|
|
1095
|
|
1096 EMOD
|
|
1097 eom EQU *
|
|
1098 END
|