2590
|
1 ********************************************************************
|
|
2 * llscsi - Low-level SCSI driver
|
|
3 *
|
|
4 * $Id$
|
|
5 *
|
|
6 * Drives tested with this driver:
|
|
7 * -------------------------------
|
|
8 * Conner DCP30200 Hard Drive - Sends out a SDTR message immediately,
|
|
9 * which confused the driver. The driver now handles the receipt
|
|
10 * of SCSI messages from the target.
|
|
11 *
|
|
12 * IBM DPES-31080 Hard Drive - Works, but seizes the bus if a
|
|
13 * device ID is referenced on the bus that doesn't exist.
|
|
14 *
|
|
15 * Sony CDU415 2X CD-ROM - Works fine.
|
|
16 *
|
|
17 * Toshiba XM-4101BME 12X CD-ROM - Works fine.
|
|
18 *
|
|
19 * NOTE: A full dsave from the Sony to the IBM was done on 300+ MB
|
|
20 * of data (RTSI RBF CD-ROM) on June 7, 2004 with no problems.
|
|
21 *
|
|
22 *
|
|
23 * Edt/Rev YYYY/MM/DD Modified by
|
|
24 * Comment
|
|
25 * ------------------------------------------------------------------
|
|
26 * 2004/04/?? Boisy G. Pitre
|
|
27 * Created.
|
|
28 *
|
|
29 * 2004/??/?? Boisy G. Pitre
|
|
30 * RELEASED WITH SUPERDRIVERS 1.0
|
|
31 *
|
|
32 * 2005/12/02 Boisy G. Pitre
|
|
33 * Now detects MESSAGE IN phase and reads in message codes (ignoring
|
|
34 * the data). The Conner DCP30200 Hard Drive sends out a SDTR message
|
|
35 * immediately, which confused the driver. The driver now handles the
|
|
36 * receipt of messages from the target.
|
|
37 *
|
|
38 * 2005/12/11 Boisy G. Pitre
|
|
39 * Added SS.SQD and SS.DCmd support.
|
|
40 *
|
|
41 * 2005/12/13 Boisy G. Pitre
|
|
42 * Moved SS.VarSect code into RBSuper for performance.
|
|
43 *
|
|
44 * 2006/03/22 Boisy G. Pitre
|
|
45 * Moved SS.VarSect code into RBSuper for performance.
|
|
46 *
|
|
47 * 2008/01/21 Boisy G. Pitre
|
|
48 * Fixed issue in DCmd where Y was not being saved when os9 F$ID was being called.
|
|
49
|
|
50 NAM llscsi
|
|
51 TTL Low-level SCSI driver
|
|
52
|
|
53 IFP1
|
|
54 USE defsfile
|
|
55 USE rbsuper.d
|
|
56 USE scsi.d
|
|
57 ENDC
|
|
58
|
|
59 tylg SET Sbrtn+Objct
|
|
60 atrv SET ReEnt+rev
|
|
61 rev SET 0
|
|
62
|
|
63
|
|
64 *
|
|
65 * SCSI Delay Constants
|
|
66 *
|
|
67 IFGT Level-1
|
|
68 BUSYDELAY EQU $FFFF
|
|
69 ELSE
|
|
70 BUSYDELAY EQU $FFFF/2
|
|
71 ENDC
|
|
72 NUMTRIES EQU 8
|
|
73
|
|
74 MOD eom,name,tylg,atrv,start,0
|
|
75
|
|
76 ORG V.LLMem
|
|
77 * Low-level driver static memory area
|
|
78 * SCSI Command Packet
|
|
79 * SCSI packet length is 14 bytes
|
|
80 V.SCSICMD RMB 1
|
|
81 V.SCSILUN RMB 1
|
|
82 V.SCSIPrm0 RMB 1
|
|
83 V.SCSIPrm1 RMB 1
|
|
84 V.SCSIPrm2 RMB 1
|
|
85 V.SCSIPrm3 RMB 1
|
|
86 V.SCSIPrm4 RMB 1
|
|
87 V.SCSIPrm5 RMB 1
|
|
88 V.SCSIPrm6 RMB 1
|
|
89 V.SCSIPrm7 RMB 1
|
|
90 RMB 4
|
|
91 SCSIPkLn EQU .-V.SCSICMD
|
|
92 V.Retries RMB 1 SCSI command retry counter
|
|
93 V.OS9Err RMB 1 (0 = return OS-9 error code, 1 = return SCSI error code)
|
|
94 V.Turbo RMB 1 turbo flag (0 = regular read, 1 = turbo read)
|
|
95 V.TfrBuf RMB 2 transfer buffer pointer
|
|
96 V.RetryVct RMB 2 retry vector
|
|
97 V.ReadVct RMB 2 normal/turbo read vectoor
|
|
98 V.WriteVct RMB 2 normal/turbo write vector
|
|
99 V.DnsByte RMB 1 copy of PD.DNS from last accessed drive
|
|
100 IFNE D4N1+HDII
|
|
101 V.MPISlot RMB 1 MPI slot
|
|
102 V.MPISave RMB 1 contents of original MPI slot
|
|
103 ENDC
|
|
104 * The Request Sense Packet and Read Capacity return data share the same space
|
|
105 ReqSnPkt EQU .
|
|
106 V.TxBuf EQU . used by DSize
|
|
107 V.R$Err RMB 2 SCSI error code return value
|
|
108 V.UTxBuf EQU .
|
|
109 V.R$Err2 RMB 10
|
|
110 V.R$AdSns RMB 1
|
|
111 ReqPkL EQU .-ReqSnPkt length of packet
|
|
112 RMB 3 makes V.TxBuf 16 bytes
|
|
113
|
|
114 name FCC /ll/
|
|
115 IFNE TC3
|
|
116 FCS /tc3/
|
|
117 ELSE
|
|
118 IFNE KTLR
|
|
119 FCS /ktlr/
|
|
120 ELSE
|
|
121 IFNE D4N1+HDII
|
|
122 FCS /disto/
|
|
123 ENDC
|
|
124 ENDC
|
|
125 ENDC
|
|
126
|
|
127 start bra ll_init
|
|
128 nop
|
|
129 lbra ll_read
|
|
130 lbra ll_write
|
|
131 bra ll_getstat
|
|
132 nop
|
|
133 lbra ll_setstat
|
|
134 * lbra ll_term
|
|
135
|
|
136 * ll_term
|
|
137 *
|
|
138 * Entry:
|
|
139 * Y = address of device descriptor
|
|
140 * U = address of device memory area
|
|
141 *
|
|
142 * Exit:
|
|
143 * CC = carry set on error
|
|
144 * B = error code
|
|
145 *
|
|
146 ll_term
|
|
147 clrb
|
|
148 rts
|
|
149
|
|
150 * ll_init
|
|
151 *
|
|
152 * Entry:
|
|
153 * Y = address of device descriptor
|
|
154 * U = address of device memory area
|
|
155 *
|
|
156 * Exit:
|
|
157 * CC = carry set on error
|
|
158 * B = error code
|
|
159 *
|
|
160 ll_init
|
|
161 IFNE D4N1+HDII
|
|
162 * Disto 4-N-1 and HD-II: Get MPI slot select value from descriptor
|
|
163 * and save it in our static storage.
|
|
164 lda IT.MPI,y
|
|
165 anda #$0F preserve *SCS bits only
|
|
166 sta V.MPISlot,u
|
|
167 ENDC
|
|
168 clrb
|
|
169 rts
|
|
170
|
|
171
|
|
172 * ll_getstat
|
|
173 *
|
|
174 * Entry:
|
|
175 * Y = address of path descriptor
|
|
176 * U = address of device memory area
|
|
177 *
|
|
178 * Exit:
|
|
179 * CC = carry set on error
|
|
180 * B = error code
|
|
181 *
|
|
182 ll_getstat
|
|
183 ldx PD.RGS,y
|
|
184 lda R$B,x
|
|
185 cmpa #SS.DSize
|
|
186 beq SSDSize
|
|
187 ldb #E$UnkSvc
|
|
188 coma
|
|
189 rts
|
|
190
|
|
191
|
|
192 * SS.DSize - Return size information about a device
|
|
193 *
|
|
194 * Entry: B = SS.DSize
|
|
195 * Exit: Carry = 1; error with code in B
|
|
196 * Carry = 0:
|
|
197 * IF B = 0
|
|
198 * A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048)
|
|
199 * X = Number of Sectors (bits 31-16)
|
|
200 * Y = Number of Sectors (Bits 15-0)
|
|
201 * IF B != 0
|
|
202 * A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048)
|
|
203 * X = Number of Logical Cylinders
|
|
204 * B = Number of Logical Sides
|
|
205 * Y = Number of Logical Sectors/Track
|
|
206 *
|
|
207 SSDSize
|
|
208 pshs u,y
|
|
209 bsr DSize
|
|
210 bcs ex@
|
|
211 ldu ,s get path desc in U
|
|
212 ldu PD.RGS,u
|
|
213 std R$D,u
|
|
214 stx R$X,u
|
|
215 sty R$Y,u
|
|
216 clrb
|
|
217 ex@ puls y,u,pc
|
|
218
|
|
219 * DSize - Get SCSI disk size
|
|
220 *
|
|
221 * Exit: Carry = 1; error with code in B
|
|
222 * Carry = 0:
|
|
223 * IF B = 0
|
|
224 * A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048)
|
|
225 * X = Number of Sectors (bits 31-16)
|
|
226 * Y = Number of Sectors (Bits 15-0)
|
|
227 * IF B != 0
|
|
228 * A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048)
|
|
229 * X = Number of Logical Cylinders
|
|
230 * B = Number of Logical Sides
|
|
231 * Y = Number of Logical Sectors/Track
|
|
232 DSize lbsr SCSIPrep do SCSI prep stuff
|
|
233 lda #S$RCAP
|
|
234 sta V.SCSICMD,u
|
|
235 leax V.TxBuf,u
|
|
236 stx V.TfrBuf,u
|
|
237 IFNE D4N1+HDII
|
|
238 lbsr MPIIn
|
|
239 ENDC
|
|
240 lbsr SCSIXfer
|
|
241 bcs ex@
|
|
242 ldd V.TxBuf+2,u get bits 15-0 of block count
|
|
243 addd #$0001 add 1 to count
|
|
244 std V.TxBuf+2,u resave
|
|
245 bcc b@
|
|
246 ldd V.TxBuf,u get bits 31-16
|
|
247 addd #$0001 add 1
|
|
248 std V.TxBuf,u resave
|
|
249 b@ lda V.TxBuf+6,u
|
|
250 clrb
|
|
251 ldx V.TxBuf,u
|
|
252 ldy V.TxBuf+2,u
|
|
253 ex@
|
|
254 IFNE D4N1+HDII
|
|
255 lbra MPIOut
|
|
256 ELSE
|
|
257 rts
|
|
258 ENDC
|
|
259
|
|
260
|
|
261 * ll_setstat
|
|
262 *
|
|
263 * Entry:
|
|
264 * Y = address of path descriptor
|
|
265 * U = address of device memory area
|
|
266 *
|
|
267 * Exit:
|
|
268 * CC = carry set on error
|
|
269 * B = error code
|
|
270 *
|
|
271 ll_setstat
|
|
272 ldx PD.RGS,y
|
|
273 lda R$B,x
|
|
274 cmpa #SS.SQD
|
|
275 beq StopUnit
|
|
276 cmpa #SS.DCmd
|
|
277 bne n@
|
|
278 pshs x save pointer to caller registers
|
|
279 bsr DCmd call DCmd
|
|
280 puls x get pointer to caller registers
|
|
281 sta R$A,x save status byte in A
|
|
282 n@ clrb
|
|
283 ex rts
|
|
284
|
|
285 * Entry:
|
|
286 * R$B = SS.SQD
|
|
287 StopUnit
|
|
288 lbsr SCSIPrep do SCSI prep stuff
|
|
289 lda #S$UNIT
|
|
290 sta V.SCSICMD,u
|
|
291 clr V.SCSIPrm2,u we want to STOP unit
|
|
292 s@
|
|
293 IFNE D4N1+HDII
|
|
294 lbsr MPIIn
|
|
295 ENDC
|
|
296 lbra SCSIXfer
|
|
297
|
|
298 noperms comb
|
|
299 ldb #E$FNA
|
|
300 rts
|
|
301
|
|
302 * Entry:
|
|
303 * X = caller regs
|
|
304 * Y = path descriptor
|
|
305 *
|
|
306 * R$B = SS.DCmd
|
|
307 * R$X = Transfer buffer
|
|
308 * R$Y = SCSI command packet
|
|
309 DCmd
|
|
310 * Fixed bug where Y was not being saved when doing os9 F$ID
|
|
311 pshs y
|
|
312 os9 F$ID get the user ID of the calling process
|
|
313 cmpy #$0000 is it 0 (superuser)?
|
|
314 puls y
|
|
315 bne noperms no, don't allow the call
|
|
316 lbsr SCSIPrep
|
|
317 ldy R$X,x get caller's transfer buffer
|
|
318 sty V.UTxBuf,u save off in mem for later
|
|
319 ldx R$Y,x get ptr to caller's SCSI command buffer
|
|
320 IFGT Level-1
|
|
321 ldy D.Proc get current process ptr
|
|
322 lda P$Task,y get task # for current process
|
|
323 ldb D.SysTsk get system task #
|
|
324 ldy #SCSIPkLn max size of SCSI command
|
|
325 pshs u save on stack
|
|
326 leau V.SCSICMD,u point to SCSI command buffer in our statics
|
|
327 os9 F$Move copy from caller to temporary task
|
|
328 puls u
|
|
329 bcs ex error copying, exit
|
|
330 ELSE
|
|
331 ldb #SCSIPkLn
|
|
332 leay V.SCSICMD,u
|
|
333 cl@ lda ,x+
|
|
334 sta ,y+
|
|
335 decb
|
|
336 bne cl@
|
|
337 ENDC
|
|
338 ldy V.PORT-UOFFSET,u get hw address (because we overwrite Y earlier)
|
|
339 IFNE D4N1+HDII
|
|
340 lbsr MPIIn
|
|
341 ENDC
|
|
342 inc V.OS9Err,u we want real SCSI errors returned
|
|
343 inc V.CchDirty,u and make cache dirty
|
|
344 leax retry@,pcr
|
|
345 stx V.RetryVct,u
|
|
346 retry@ lbsr SCSISend
|
|
347 IFNE D4N1+HDII
|
|
348 lbcs MPIOut
|
|
349 ELSE
|
|
350 bcs ex
|
|
351 ENDC
|
|
352 IFGT Level-1
|
|
353 ldx D.Proc get current process ptr
|
|
354 ldb P$Task,x get task # for current process
|
|
355 ENDC
|
|
356 ldx V.UTxBuf,u
|
|
357
|
|
358 msgloop@ lbsr Wait4REQ wait for REQ to be asserted
|
|
359 bita #CMD command phase?
|
|
360 lbne PostXfr yes, return
|
|
361 io@ bita #INOUT data coming in or going out?
|
|
362 bne in@ branch if coming in...
|
|
363 IFGT Level-1
|
|
364 os9 F$LDABX
|
|
365 leax 1,x
|
|
366 ELSE
|
|
367 lda ,x+
|
|
368 ENDC
|
|
369 sta SCSIDATA,y
|
|
370 bra msgloop@
|
|
371 in@ lda SCSIDATA,y
|
|
372 IFGT Level-1
|
|
373 os9 F$STABX
|
|
374 leax 1,x
|
|
375 ELSE
|
|
376 sta ,x+
|
|
377 ENDC
|
|
378 bra msgloop@
|
|
379
|
|
380
|
|
381 * ll_read
|
|
382 *
|
|
383 * Entry:
|
|
384 * Y = address of path descriptor
|
|
385 * U = address of device memory area
|
|
386 *
|
|
387 * Static memory referenced:
|
|
388 * V.CchPSpot = address of spot in cache where physical sector data will go
|
|
389 * sectsize = sector size (0=256,1=512,2=1024,3=2048)
|
|
390 * V.SectCnt = sectors to read
|
|
391 * V.PhysSect = physical sector to start read from
|
|
392 ll_read
|
|
393 IFNE D4N1+HDII
|
|
394 lbsr MPIIn
|
|
395 ENDC
|
|
396 IFNE SIZEMATTERS
|
|
397 bsr SCSIPrep do SCSI prep stuff
|
|
398 bsr MakeRead make read command packet
|
|
399 ldx V.CchPSpot,u
|
|
400 stx V.TfrBuf,u
|
|
401 lbra SCSIXfer
|
|
402 ELSE
|
|
403 leax SCSIReadRetry,pcr
|
|
404 stx V.RetryVct,u
|
|
405 lbsr SCSIPrep do SCSI prep stuff
|
|
406 lbsr MakeRead make read command packet
|
|
407 SCSIReadRetry
|
|
408 lbsr SCSISend
|
|
409 bcs mpiex
|
|
410 bita #CMD
|
|
411 lbne PostXfr
|
|
412 ldb V.SectCnt,u
|
|
413 pshs b
|
|
414 * Set up appropriate read call (regular or turbo)
|
|
415 tst V.Turbo,u
|
|
416 beq reg@
|
|
417 leax TurboRead,pcr
|
|
418 bra do@
|
|
419 reg@ leax RegRead256,pcr
|
|
420 do@ stx V.ReadVct,u
|
|
421 ldx V.CchPSpot,u get pointer to physical sector in cache for data in
|
|
422 again@
|
|
423 ldb V.Log2Phys,u
|
|
424 pshs b
|
|
425 loop@
|
|
426 jsr [V.ReadVct,u]
|
|
427 dec ,s
|
|
428 bne loop@
|
|
429 puls b
|
|
430 dec ,s
|
|
431 bne again@
|
|
432 puls a
|
|
433 lbra PostXfr
|
|
434 mpiex
|
|
435 IFNE D4N1+HDII
|
|
436 lbra MPIOut
|
|
437 ELSE
|
|
438 rts
|
|
439 ENDC
|
|
440
|
|
441 TurboRead
|
|
442 IFNE H6309
|
|
443
|
|
444 * 6309 Turbo READ
|
|
445 ldw #256
|
|
446 orcc #IntMasks we have to mask interrupts for Level 1
|
|
447 tfm y,x+ do the transfer
|
|
448 andcc #^IntMasks we have to unmask interrupts for Level 1
|
|
449 lbsr DeauxDeaux
|
|
450 rts
|
|
451
|
|
452 ELSE
|
|
453
|
|
454 * 6809 Turbo READ
|
|
455 lda #16
|
|
456 pshs a
|
|
457 l2@ lda SCSIDATA,y
|
|
458 ldb SCSIDATA,y
|
|
459 std ,x
|
|
460 lda SCSIDATA,y
|
|
461 ldb SCSIDATA,y
|
|
462 std $02,x
|
|
463 lda SCSIDATA,y
|
|
464 ldb SCSIDATA,y
|
|
465 std $04,x
|
|
466 lda SCSIDATA,y
|
|
467 ldb SCSIDATA,y
|
|
468 std $06,x
|
|
469 lda SCSIDATA,y
|
|
470 ldb SCSIDATA,y
|
|
471 std $08,x
|
|
472 lda SCSIDATA,y
|
|
473 ldb SCSIDATA,y
|
|
474 std $0A,x
|
|
475 lda SCSIDATA,y
|
|
476 ldb SCSIDATA,y
|
|
477 std $0C,x
|
|
478 lda SCSIDATA,y
|
|
479 ldb SCSIDATA,y
|
|
480 std $0E,x
|
|
481 leax 16,x
|
|
482 dec ,s decrement counter
|
|
483 bne l2@
|
|
484 puls a,pc
|
|
485 ENDC
|
|
486
|
|
487 RegRead256
|
|
488 clrb
|
|
489 *
|
|
490 * "Non-Turbo" Read Data from controller
|
|
491 *
|
|
492 * Passed: B = bytes to read
|
|
493 * X = Address of buffer
|
|
494 * Y = Controller Address
|
|
495 *
|
|
496 RegRead
|
|
497 * We wait for REQ in an infinite, faster loop here
|
|
498 lda SCSISTAT,y get SCSI status byte
|
|
499 bita #REQ REQ?
|
|
500 beq RegRead
|
|
501 lda SCSIDATA,y
|
|
502 sta ,x+
|
|
503 decb
|
|
504 bne RegRead
|
|
505 rts
|
|
506
|
|
507
|
|
508 ENDC
|
|
509
|
|
510
|
|
511 * Make Read/Write Packet
|
|
512 * Entry:
|
|
513 * A = SCSI command
|
|
514 * V.PhysSect = 3 byte physical sector to read/write
|
|
515 MakeWrite lda #S$WRITEX
|
|
516 fcb $8C skip next two bytes
|
|
517 MakeRead lda #S$READEX
|
|
518 MakeRW sta V.SCSICMD,u put passed SCSI command
|
|
519 lda V.SectCnt,u 'V.SectCnt' logical blocks
|
|
520 * Make SCSI Read/Write 6 byte CDB here
|
|
521 * sta V.SCSIPrm2,u
|
|
522 * lda V.PhysSect,u
|
|
523 * sta V.SCSILUN,u
|
|
524 * ldd V.PhysSect+1,u
|
|
525 * std V.SCSIPrm0,u
|
|
526 * rts
|
|
527 * Make SCSI Read/Write Extended 10 byte CDB here
|
|
528 sta V.SCSIPrm6,u
|
|
529 lda V.PhysSect,u
|
|
530 sta V.SCSIPrm1,u
|
|
531 ldd V.PhysSect+1,u
|
|
532 std V.SCSIPrm2,u
|
|
533 rts
|
|
534
|
|
535 * Prep for SCSI transfer
|
|
536 * Preserves all regs
|
|
537 * Entry: Y = path descriptor
|
|
538 * Exit: Y = hardware address
|
|
539 SCSIPrep pshs x,d
|
|
540 leax V.SCSICMD,u
|
|
541 ldb #SCSIPkLn
|
|
542 l@ clr ,x+
|
|
543 decb
|
|
544 bne l@
|
|
545 ldb PD.DNS,y and DNS byte
|
|
546 stb V.DnsByte,u save in our statics
|
|
547 andb #DNS.TURBO mask out all but turbo bit
|
|
548 stb V.Turbo,u and save state
|
|
549 lda #NUMTRIES get retry count
|
|
550 sta V.Retries,u and reset retry counter
|
|
551 clr V.OS9Err,u we want real SCSI errors returned
|
|
552 ldy V.PORT-UOFFSET,u get hw address
|
|
553 puls x,d,pc
|
|
554
|
|
555 * Check Transfer Status
|
|
556 * This routine is passed the address of another routine to call in case
|
|
557 * the device is busy or there is an error returned.
|
|
558 *
|
|
559 * Passed: V.RetryVct,u = address of routine to call if SCSI device is busy
|
|
560 PostXfr lbsr GetStatB get transfer status byte
|
|
561 bita #X$BUSY device BUSY?
|
|
562 bne retry@ attempt a retry if so...
|
|
563 chkerr@ bita #X$ERROR error?
|
|
564 beq ok@ branch if not...
|
|
565 * Error occurred.. retry
|
|
566 retry@ dec V.Retries,u decrement retry count
|
|
567 bne jmp@ try again if not at end
|
|
568 IFNE D4N1+HDII
|
|
569 lbsr SCSIErr
|
|
570 lbra MPIOut
|
|
571 ELSE
|
|
572 lbra SCSIErr
|
|
573 ENDC
|
|
574 jmp@ jmp [V.RetryVct,u]
|
|
575 ok@ clrb
|
|
576 IFNE D4N1+HDII
|
|
577 lbra MPIOut
|
|
578 ELSE
|
|
579 rts
|
|
580 ENDC
|
|
581
|
|
582
|
|
583 * ll_write
|
|
584 *
|
|
585 * Entry:
|
|
586 * Y = address of path descriptor
|
|
587 * U = address of device memory area
|
|
588 *
|
|
589 * Static memory referenced:
|
|
590 * V.CchPSpot = address of spot in cache where physical sector data is
|
|
591 * sectsize = sector size (0=256,1=512,2=1024,3=2048)
|
|
592 * V.SectCnt = sectors to read
|
|
593 * V.PhysSect = physical sector to start read from
|
|
594 ll_write
|
|
595 IFNE D4N1+HDII
|
|
596 lbsr MPIIn
|
|
597 ENDC
|
|
598 IFNE SIZEMATTERS
|
|
599 bsr SCSIPrep do SCSI prep stuff
|
|
600 bsr MakeWrite make read command packet
|
|
601 ldx V.CchPSpot,u
|
|
602 stx V.TfrBuf,u
|
|
603 ELSE
|
|
604 leax SCSIWriteRetry,pcr
|
|
605 stx V.RetryVct,u
|
|
606 bsr SCSIPrep do SCSI prep stuff
|
|
607 lbsr MakeWrite
|
|
608 SCSIWriteRetry lbsr SCSISend
|
|
609 lbcs mpiex
|
|
610 bita #CMD
|
|
611 bne PostXfr
|
|
612 ldb V.SectCnt,u
|
|
613 pshs b
|
|
614 * Set up appropriate write call (regular or turbo)
|
|
615 tst V.Turbo,u
|
|
616 beq reg@
|
|
617 leax TurboWrite,pcr
|
|
618 bra do@
|
|
619 reg@ leax RegWrite,pcr
|
|
620 do@ stx V.WriteVct,u
|
|
621 ldx V.CchPSpot,u
|
|
622 again@ ldb V.Log2Phys,u
|
|
623 pshs b
|
|
624 loop@ jsr [V.WriteVct,u]
|
|
625 dec ,s
|
|
626 bne loop@
|
|
627 puls b
|
|
628 dec ,s
|
|
629 bne again@
|
|
630 puls a
|
|
631 bra PostXfr
|
|
632
|
|
633 TurboWrite
|
|
634 IFNE H6309
|
|
635
|
|
636 * 6309 Turbo WRITE
|
|
637 loop@ orcc #IntMasks we have to mask interrupts for Level 1
|
|
638 ldw #256
|
|
639 tfm x+,y
|
|
640 andcc #^IntMasks we have to unmask interrupts for Level 1
|
|
641 lbsr DeauxDeaux
|
|
642 rts
|
|
643
|
|
644 ELSE
|
|
645
|
|
646 * 6809 Turbo WRITE
|
|
647 lda #16
|
|
648 pshs a
|
|
649 l2@ ldd ,x
|
|
650 sta SCSIDATA,y
|
|
651 stb SCSIDATA,y
|
|
652 ldd $02,x
|
|
653 sta SCSIDATA,y
|
|
654 stb SCSIDATA,y
|
|
655 ldd $04,x
|
|
656 sta SCSIDATA,y
|
|
657 stb SCSIDATA,y
|
|
658 ldd $06,x
|
|
659 sta SCSIDATA,y
|
|
660 stb SCSIDATA,y
|
|
661 ldd $08,x
|
|
662 sta SCSIDATA,y
|
|
663 stb SCSIDATA,y
|
|
664 ldd $0A,x
|
|
665 sta SCSIDATA,y
|
|
666 stb SCSIDATA,y
|
|
667 ldd $0C,x
|
|
668 sta SCSIDATA,y
|
|
669 stb SCSIDATA,y
|
|
670 ldd $0E,x
|
|
671 sta SCSIDATA,y
|
|
672 stb SCSIDATA,y
|
|
673 leax 16,x
|
|
674 dec ,s decrement counter
|
|
675 bne l2@
|
|
676 puls a,pc
|
|
677
|
|
678 ENDC
|
|
679
|
|
680 *
|
|
681 * "Non-Turbo" Write Data to controller
|
|
682 *
|
|
683 * Passed: X = Address of data to write
|
|
684 * Y = Controller Address
|
|
685 *
|
|
686 RegWrite clrb
|
|
687 loop@ lda SCSISTAT,y
|
|
688 bita #REQ
|
|
689 beq loop@
|
|
690 lda ,x+
|
|
691 sta SCSIDATA,y
|
|
692 decb
|
|
693 bne loop@
|
|
694 rts
|
|
695
|
|
696 ENDC
|
|
697
|
|
698 IFNE D4N1+HDII
|
|
699 * Disto 4-N-1/HD-II: Map in MPI HERE
|
|
700 MPIIn pshs cc,a
|
|
701 lda MPI.Slct get MPI value
|
|
702 sta V.MPISave,u save off in our statics
|
|
703 anda #$F0 preserve CTS slot bits (%1111000)
|
|
704 ora V.MPISlot,u OR in MPI slot of our HW
|
|
705 MPIWrite sta MPI.Slct write out to MPI
|
|
706 puls a,cc,pc
|
|
707
|
|
708 MPIOut pshs cc,a
|
|
709 lda V.MPISave,u
|
|
710 bra MPIWrite
|
|
711 ENDC
|
|
712
|
|
713
|
|
714 * SCSIXfer
|
|
715 *
|
|
716 * Entry:
|
|
717 * Y = hardware address
|
|
718 * U = address of device memory area
|
|
719 *
|
|
720 * Static memory referenced:
|
|
721 * V.TfrBuf,u = address of transfer/receive buffer
|
|
722 SCSIXfer leax retry@,pcr
|
|
723 stx V.RetryVct,u
|
|
724 retry@ bsr SCSISend
|
|
725 bcs sr@
|
|
726 ldx V.TfrBuf,u
|
|
727 tfr@ lbsr Wait4REQ wait for REQ to be asserted
|
|
728 bita #CMD
|
|
729 lbne PostXfr COMMAND phase...
|
|
730 * If here, we're in DATA PHASE
|
|
731 bita #INOUT data coming in or going out?
|
|
732 bne in@ branch if coming in...
|
|
733 out@ lda ,x+
|
|
734 sta SCSIDATA,y
|
|
735 bra tfr@
|
|
736 in@ lda SCSIDATA,y
|
|
737 sta ,x+
|
|
738 bra tfr@
|
|
739 sr@ rts
|
|
740
|
|
741
|
|
742 * Give up timeslice several times unless this is the system
|
|
743 DeauxDeaux pshs x
|
|
744 IFGT Level-1
|
|
745 ldx D.Proc get proc descriptor
|
|
746 cmpx D.SysPrc system?
|
|
747 beq WaitDone yep, system cannot sleep
|
|
748 ENDC
|
|
749 * ldx D.AProcQ get active proc queue
|
|
750 * beq WaitDone if empty, return
|
|
751 * ldx #$0001
|
|
752 * os9 F$Sleep give up timeslice
|
|
753 * ldx D.AProcQ get active proc queue
|
|
754 * beq WaitDone if empty, return
|
|
755 ldx #$0001
|
|
756 os9 F$Sleep give up timeslice
|
|
757 WaitDone puls x,pc return to caller
|
|
758
|
|
759 * Get Status Byte from SCSI controller
|
|
760 * Exit: A = status byte
|
|
761 GetStatB bsr Wait4REQ
|
|
762 lda SCSIDATA,y
|
|
763 pshs a
|
|
764 bsr Wait4REQ
|
|
765 clr SCSIDATA,y
|
|
766 puls pc,a
|
|
767
|
|
768 * SCSI ID table with hi-bit set for SCSI-3 compliance
|
|
769 IDTBL FCB $80+1,$80+2,$80+4,$80+8,$80+16,$80+32,$80+64,128
|
|
770
|
|
771 *
|
|
772 * SCSI Packet Send Routine
|
|
773 *
|
|
774 * Sets LUN for SCSI Packet, then sends command packet to controller
|
|
775 *
|
|
776 * Passed: Y = Device Address
|
|
777 *
|
|
778 * Returns: A = SCSI Status byte
|
|
779 *
|
|
780 * Destroys: X
|
|
781 *
|
|
782 SCSISend ldb V.SCSILUN,u get SCSI LUN
|
|
783 andb #%00011111 mask out LUN
|
|
784 stb V.SCSILUN,u
|
|
785 ldb V.DnsByte,u get DNS byte
|
|
786 andb #%11100000 get SCSI LUN from byte
|
|
787 orb V.SCSILUN,u OR with SCSI LUN byte
|
|
788 stb V.SCSILUN,u save off
|
|
789 ldd #BUSY*256 we want /BUSY
|
|
790 bsr StatusWait
|
|
791 bcs ex4
|
|
792 * BUSY is clear, put initiator/target IDs on bus
|
|
793 lda V.DnsByte,u get DNS byte
|
|
794 anda #$07 mask out all but SCSI IDs
|
|
795 leax IDTBL,pcr point to device ID table
|
|
796 lda a,x get ID value
|
|
797 sta SCSIDATA,y write out to controller
|
|
798 sta SCSISEL,y here too...
|
|
799 ldd #BUSY*256+BUSY we want BUSY
|
|
800 bsr StatusWait
|
|
801 bcs ex4
|
|
802 * BUSY is set
|
|
803 * Here we send the packet to the controller.
|
|
804 chkok@ leax V.SCSICMD,u point X to SCSI command packet
|
|
805 tfrloop@ bsr Wait4REQ wait for REQ
|
|
806 bita #CMD SCSI CMD bit set?
|
|
807 beq ex4 branch if not...
|
|
808 bita #INOUT INOUT set?
|
|
809 bne ckmsg@ branch if target->initiator
|
|
810 lda ,x+ get byte from SCSI CMD packet
|
|
811 sta SCSIDATA,y write to controller
|
|
812 bra tfrloop@
|
|
813 ckmsg@ bita #MSG MESSAGE IN (target->initiator)
|
|
814 beq ex4
|
|
815 *
|
|
816 * MESSAGE IN phase code
|
|
817 *
|
|
818 MSGIn lda SCSIDATA,y extended message?
|
|
819 deca
|
|
820 bne SCSISend nope, restart target initiation
|
|
821 ldb SCSIDATA,y get extended message length
|
|
822 * Note: We ignore extended messages
|
|
823 l@ tst SCSIDATA,y read extended message data
|
|
824 decb
|
|
825 bne l@
|
|
826 bra SCSISend message read, restart target initiation
|
|
827 ex4 rts
|
|
828
|
|
829 *
|
|
830 * Loop until REQ bit is set
|
|
831 *
|
|
832 * Passed: Y = Device Address
|
|
833 *
|
|
834 * Returns: A = SCSI Status byte
|
|
835 *
|
|
836 Wait4REQ
|
|
837 loop@ lda SCSISTAT,y get SCSI status byte
|
|
838 bita #REQ REQ?
|
|
839 beq sleep@ +
|
|
840 rts +
|
|
841 sleep@ lbsr DeauxDeaux
|
|
842 bra loop@
|
|
843
|
|
844 * Wait for a set of conditions in the status register to be TRUE
|
|
845 * This yields a delay of about 5 seconds.
|
|
846 *
|
|
847 * Entry: Y = HW address
|
|
848 * A = flip (if bit set, that bit is tested)
|
|
849 * B = mask (result must match this byte)
|
|
850 StatusWait
|
|
851 pshs x,d
|
|
852 IFEQ Level-1
|
|
853 ldb #$02
|
|
854 ldx #$0000
|
|
855 ELSE
|
|
856 ldb #$04
|
|
857 ldx #$0000
|
|
858 ENDC
|
|
859 l@ lda SCSISTAT,y
|
|
860 anda ,s apply flip
|
|
861 cmpa 1,s compare to mask
|
|
862 bne dec@ branch if not equal (not what we want)
|
|
863 lda SCSISTAT,y
|
|
864 clrb clear carry
|
|
865 bra ok@
|
|
866 dec@ leax -1,x count down
|
|
867 bne l@
|
|
868 decb decrement bits 23-16
|
|
869 bpl l@ if >=0, keep going
|
|
870 comb set carry
|
|
871 ldb #E$NotRdy
|
|
872 ok@ leas 2,s
|
|
873 puls x,pc
|
|
874
|
|
875 *
|
|
876 * Send a REQSENSE message to the SCSI controller
|
|
877 *
|
|
878 SndMSG lbsr Wait4REQ wait for REQ to be asserted
|
|
879 bita #CMD command phase?
|
|
880 bne ex4 yes, return
|
|
881 beq INorOUT no, check for in/out
|
|
882 rts
|
|
883 INorOUT bita #INOUT data coming in or going out?
|
|
884 bne ComingIn branch if coming in...
|
|
885 lda ,x+
|
|
886 sta SCSIDATA,y
|
|
887 bra SndMSG
|
|
888 ComingIn lda SCSIDATA,y
|
|
889 sta ,x+
|
|
890 bra SndMSG
|
|
891
|
|
892
|
|
893 * SCSIErr - Attemps a REQUEST SENSE to find a SCSI error
|
|
894 *
|
|
895 * Entry:
|
|
896 * Y = address of hardware
|
|
897 * U = address of device memory area
|
|
898 *
|
|
899 * Exit:
|
|
900 * CC = carry set
|
|
901 * B = error code
|
|
902 *
|
|
903 SCSIErr lda #S$REQSEN REQUEST SENSE command
|
|
904 sta V.SCSICMD,u
|
|
905 clra
|
|
906 clrb
|
|
907 sta V.SCSILUN,u
|
|
908 std V.SCSIPrm0,u
|
|
909 lda #ReqPkL set allocation length
|
|
910 std V.SCSIPrm2,u
|
|
911 lbsr SCSISend send command
|
|
912 bcs ex4 branch if error
|
|
913 leax V.R$Err,u point to return data buffer
|
|
914 bsr SndMSG get response data
|
|
915 lbsr GetStatB
|
|
916 clra
|
|
917 pshs a
|
|
918 lda V.R$Err,u get error code
|
|
919 anda #$7F wipe out hi bit
|
|
920 cmpa #$70 "current" error?
|
|
921 bne L05A3 branch if not...
|
|
922 lda V.R$Err2,u get more detailed error
|
|
923 anda #%00001111
|
|
924 sta ,s save off stack
|
|
925 lda V.R$AdSns,u get additional sense code
|
|
926 L05A3 tst V.OS9Err,u send OS-9 error?
|
|
927 L05A7 beq L05AD branch if so...
|
|
928 tfr a,b else put SCSI error in B
|
|
929 clr V.OS9Err,u and clear SCSI error flag
|
|
930 bra ErrErr and return with error
|
|
931 * Walk error table to find OS-9 error
|
|
932 L05AD leax >ErrTbl,pcr
|
|
933 ldb #E$Unit
|
|
934 L05B3 tst ,x
|
|
935 beq ErrErr
|
|
936 cmpa ,x++
|
|
937 blt L05B3
|
|
938 ldb -1,x
|
|
939 ErrErr coma
|
|
940 puls pc,a
|
|
941
|
|
942
|
|
943
|
|
944 * Error Table - Maps SCSI errors to OS-9 errors
|
|
945 * This table is contructed so that gaps are actually continuations of
|
|
946 * the previous entry. For example, $14 maps to E$Seek, and so does $15 and
|
|
947 * $16.
|
|
948 ErrTbl FCB $01,E$NotRdy
|
|
949 FCB $02,E$Seek
|
|
950 FCB $03,E$Write
|
|
951 FCB $04,E$NotRdy
|
|
952 FCB $06,E$Seek
|
|
953 FCB $10,E$CRC
|
|
954 FCB $11,E$Read
|
|
955 FCB $14,E$Seek
|
|
956 FCB $17,E$CRC
|
|
957 FCB $19,E$IllArg
|
|
958 FCB $1C,E$Read
|
|
959 FCB $1E,E$CRC
|
|
960 FCB $20,E$IllCmd
|
|
961 FCB $21,E$Sect
|
|
962 FCB $25,E$IllArg
|
|
963 FCB $29,E$NotRdy
|
|
964 FCB $00
|
|
965
|
|
966
|
|
967 EMOD
|
|
968 eom EQU *
|
|
969 END
|
|
970
|