|
|
1.1 root 1:
2: ; Copyright: 1997, 1998 by Apple Computer, Inc., all rights reserved.
3: ;
4: ; File Ownership:
5: ;
6: ; DRI: Mike Johnson
7: ;
8: ; Other Contact: Russ Berkoff
9: ;
10: ; Technology: SCSI
11: ;
12: ; Writers:
13: ;
14: ; (MLJ) Mike Johnson
15: ; (RRA) Rick Auricchio
16:
17:
18: ; NCR Errata Listing 125 Item 1 : Clear the SCNTL0 start bit
19: ; when jump to reselect during select (try_reselect)
20: ;
21: ; NCR Errata Listing 117 Item 4 : Bad parity if odd bytes during
22: ; wide transfer. Only for DATA OUT in Initiator mode.
23: ; (Confirm by Manfred Eierle 3rd June 93 not during DATA IN)
24:
25: ARCH 825A ;specifically for 825a and 875 (new instructions)
26:
27:
28: ;*****************************************************************
29: ;
30: ; Phase codes - These values represent which action is being handled
31: ;
32: ;*****************************************************************
33:
34: ABSOLUTE kphase_DATA_OUT = 0x00
35: ABSOLUTE kphase_DATA_IN = 0x01
36: ABSOLUTE kphase_COMMAND = 0x02
37: ABSOLUTE kphase_STATUS = 0x03
38: ABSOLUTE kphase_MSG_OUT = 0x06
39: ABSOLUTE kphase_MSG_IN = 0x07
40: ABSOLUTE kphase_SELECT = 0x08
41: ABSOLUTE kphase_RESELECT = 0x09
42: ABSOLUTE kphase_ABORT_CURRENT = 0x0A
43: ABSOLUTE kphase_ABORT_MAILBOX = 0x0B
44: ABSOLUTE kphase_CMD_COMPLETE = 0x0C
45: ABSOLUTE kphase_DISCONNECT = 0x0D
46: ABSOLUTE kphase_saveDataPointer = 0x0E ; ??? driver work to be done
47: ABSOLUTE kphase_restoreDataPointer = 0x0F ; ??? driver work to be done
48:
49:
50: ;*****************************************************************
51: ; interrupt codes
52: ;*****************************************************************
53:
54: ABSOLUTE unknown_phase = 0x00 ; A spurious phase on SCSI Bus
55: ABSOLUTE status_error = 0x01 ; IO completes, but with status error
56: ABSOLUTE unexpected_msg = 0x02 ; An 'unknown' message is in ld_message var
57: ABSOLUTE unexpected_ext_msg = 0x03 ; An 'unknown' extended message in ld_message
58: ABSOLUTE wide_32_not_supported = 0x04 ; The device wants 32 bits data phase
59: ABSOLUTE no_msgin_after_reselect = 0x05 ; No message-in after reselection
60: ABSOLUTE reqack_too_large = 0x06 ; The device answer ReqAck offset is greater than 8
61: ABSOLUTE unknown_reselect = 0x07 ; The valid bit in SFBR reg not set
62: ABSOLUTE unallocated_nexus = 0x08 ; nexus index -> 0xFFFFFFFF
63: ABSOLUTE abort_mailbox = 0x09 ; Abort/BDR mailbox completed
64: ABSOLUTE abort_current = 0x0A ; Abort/BDR current op completed
65: ABSOLUTE unknown_message_out = 0x0B ; Unknown phase before message out
66: ABSOLUTE unknown_msg_reject = 0x0C ; Unknown message reject
67: ABSOLUTE negotiateSDTR = 0x0D ; Sync negotiation rx'd
68: ABSOLUTE negotiateWDTR = 0x0E ; Wide negotiation rx'd
69: ABSOLUTE sglist_complete = 0x0F ; SGList complete
70:
71:
72: ;*****************************************************************
73: ;
74: ; Data structure for T/L/Q Nexus:
75: ;
76: ;*****************************************************************
77:
78: ABSOLUTE TLQ_SCSI_ID = 0 ; 4 SCSI ID et al for SELECT instruction
79: ABSOLUTE TLQ_xferAdr = 4 ; 4 Physical address of CHMOV instructions
80: ABSOLUTE TLQ_MSGOp = 8 ; 8 Byte count, data adr -> TLQ_MSGO
81: ABSOLUTE TLQ_CDBp = 16 ; 8 Byte count, data adr -> TLQ_CDB
82: ABSOLUTE TLQ_CDP = 24 ; 4 Current Data Pointer
83: ABSOLUTE TLQ_SDP = 28 ; 4 Saved Data Pointer
84: ABSOLUTE TLQ_index = 32 ; 1 index into nexus array
85: ABSOLUTE TLQ_xferStarted= 33 ; 1 transfer started flag
86: ABSOLUTE TLQ_IWR = 34 ; 1 flag to Ignore Wide Residue
87: ABSOLUTE TLQ_pad = 35 ; 1 pad byte
88:
89:
90: ;*****************************************************************
91: ;
92: ; ENTRY declarations - Declare entry points for driver
93: ;
94: ;*****************************************************************
95:
96: ENTRY select_phase
97: ENTRY phase_handler
98: ENTRY issueMessageOut ; for negotiation and Reject messages
99: ENTRY issueAbort_BDR ; to immediately Abort or Bus-Device-Reset
100: ENTRY clearACK ; MsgIn done - clr ACK, jump to phase handler
101:
102:
103: ;*****************************************************************
104: ;
105: ; Define local data structure at start of SCRIPTS.
106: ; This structure is allocated by the following nops.
107: ;
108: ;*****************************************************************
109: ;
110:
111: RELATIVE local_data \
112: ld_AbortCode = 4{??}\ ; 1 byte code to Abort or BDR
113: ld_zeroes = 4{??}\ ; 4 bytes of 0 to clear registers
114: ld_status = 4{??}\ ; Status byte from target
115: ld_counter = 4{??}\ ; index into mailbox array
116: ld_AbortBdr_mailbox = 4{??}\ ; Abort/BusDeviceReset mailbox
117: ld_IOdone_mailbox = 4{??}\ ; [ nexus 0 0 semaphore ]
118: ld_sched_mlbx_base_adr = 4{??}\ ; base addr of mailbox array
119: ld_mailboxp = 4{??}\ ; address of current mailbox
120: ld_scsi_id = 4{??}\ ; ptr to current mailbox
121: ld_nexus_array_base = 4{??}\ ; base address of Nexus pointers
122: ld_nexus_index = 4{??}\ ; index to Nexus pointer
123: ld_nexus = 4{??}\ ; address of Nexus
124: ld_phase_flag = 4{??}\ ; for debugging
125: ld_device_table_base_adr = 4{??}\ ; device configuration table
126: ld_scratch = 4{??}\ ; scratch memory
127: ld_unused = 4{??}\ ; unused
128: ld_message = 4{??}\ ; buffer for MsgIn bytes
129: ld_message4 = 4{??}\ ; buffer continuation
130: ld_pad = 4{??}\ ; padding
131: ld_size = 4{??} ; size of this structure
132:
133:
134: PROC BSC_SCRIPT:
135:
136: ; *** These NOPs must be at address 0. ***
137: ; *** This is reserved space for the structure "local_data". ***
138: ; *** The driver inits this area to zero. ***
139:
140: nop 0 ; ld_AbortCode, ld_zeroes
141: nop 0 ; ld_status, ld_counter
142:
143: nop 0 ; ld_AbortBdr_mailbox, ld_IOdone_mailbox
144: nop 0 ; ld_sched_mlbx_base_adr, ld_mailboxp
145:
146: nop 0 ; ld_scsi_id, ld_nexus_array_base
147: nop 0 ; ld_nexus_index, ld_nexus
148:
149: nop 0 ; ld_phase_flag, ld_device_table_base_adr
150: nop 0 ; ld_scratch, ld_unused
151:
152: nop 0 ; ld_message, ld_message4
153: nop ld_size ; ld_pad, ld_size (Use ld_size or lose it)
154:
155: nop sglist_complete ; use sglist_complete or lose it from gen'd output file
156:
157: ;****************************************************************************
158: ;
159: ; findNexusFromIndex - load DSA with pointer to Nexus given a Nexus index:
160: ;
161: ;****************************************************************************
162:
163: findNexusFromIndex:
164:
165: load SCRATCHA0, 4, ld_nexus_index ; load index and leading zeroes
166: clear CARRY
167: move SCRATCHA0 SHL 0 to SCRATCHA0 ; double the index
168: move SCRATCHA1 SHL 0 to SCRATCHA1
169: move SCRATCHA0 SHL 0 to SCRATCHA0 ; double again
170: move SCRATCHA1 SHL 0 to SCRATCHA1 ; A0 now has index to 4-byte address
171: store SCRATCHA0, 4, patchArrayOffset+4 ; *** patch the code
172:
173: load DSA0, 4, ld_nexus_array_base ; load base address of array of Nexus pointers
174: patchArrayOffset:
175: load DSA0, 4, DSAREL( 0 ) ; *** patched offset. Load pointer.
176:
177: move DSA0 to SFBR ; Ensure pointer is not 0xFFFFFFFF
178: int unallocated_nexus, if 0xFF ; Interrupt if NFG
179:
180: store DSA0, 4, ld_nexus ; Store the Nexus pointer
181: return ; end findNexusFromIndex
182:
183:
184: ;****************************************************************************
185: ;
186: ; initContext - Initialize the registers for Sync and Wide using
187: ; values stored in the device configuration table.
188: ; Return with values in SCRATCHB for Select code.
189: ;
190: ;****************************************************************************
191:
192: initContext:
193:
194: load SCRATCHB0, 4, ld_scsi_id ; load 4-bit SCSI ID and zeroes
195: clear CARRY
196: move SCRATCHB0 SHL SCRATCHB0 ; * 2
197: move SCRATCHB0 SHL SCRATCHB0 ; * 2 -> UInt32 index
198: store SCRATCHB0, 4, patchGetDevConfigOffset+4 ; *** Patch load code
199:
200: load DSA0, 4, ld_device_table_base_adr ; load base physical addr of tables
201:
202: patchGetDevConfigOffset:
203: load SCRATCHB0, 4, DSAREL( 0 ) ; *** Patched table offset ***
204:
205: ; SCRATCHB0 = 0
206: ; SCRATCHB1 = TP,MO (SXFER bits7-5 bits3-0)
207: ; SCRATCHB2 = 0 (position for SCSI ID)
208: ; SCRATCHB3 = SCCF,EWS (SCNTL3 bits6-4 bit 3)
209:
210: move SCRATCHB1 to SFBR ; init SXFER from B1
211: move SFBR to SXFER
212: ; Init SCNTL3 from B3
213: move SCRATCHB3 to SFBR
214: move SFBR to SCNTL3
215: return ; return with SCRATCHB intact.
216:
217:
218: ;*****************************************************************
219: ;
220: ; Select_phase:
221: ; Clear the SIGP bit.
222: ; Check if any Abort/BusDeviceReset request waiting.
223: ; Nexus is found in the list of 256 mailboxes.
224: ; If current mailbox is empty, jump to reselect_phase.
225: ; SCRIPTS tries to select device.
226: ; If select fails due to reselect, jump to reselect_phase
227: ; Select Timeout handled by driver.
228: ; If select succeeds, clear the mailbox entry
229: ; and increment the mailbox counter.
230: ; Jump to the phase_handler (hopefully for MSG_OUT)
231: ;
232: ;*****************************************************************
233:
234: select_phase:
235:
236: move CTEST2 | 0x00 to CTEST2 ; Clear SIGP bit from ISTAT reg
237:
238: ; Check abort mailbox:
239:
240: load SCRATCHA0, 4, ld_AbortBdr_mailbox ; Get AbortBdr mailbox
241: ; The Identify byte in byte 0 is also the semaphore
242: ; A0 = Identify byte (0xC0 + LUN N.B. Disconnect allowed)
243: ; A1 = Tag, if any
244: ; A2 = SCSI ID
245: ; A3 = Abort code Abort=0x06; Abort Tag=0D; Bus Device Reset=0x0C
246: move SCRATCHA0 to SFBR ; test the semaphore/Identify
247: jump rel( AbortMailbox ), if not 0 ; jump if aborting
248:
249:
250: ; Get the next IO nexus in the mailboxes circular list.
251: ; Calculate current mailbox address as so:
252: ; counter byte index * 4 to get mailbox index
253: ; add base physical address of mailboxes giving current mailbox address
254:
255: load SCRATCHA0, 4, ld_counter ; get 1-byte mailbox counter & 0s
256: clear CARRY
257: move SCRATCHA0 SHL 0 to SCRATCHA0 ; double it
258: move SCRATCHA1 SHL 0 to SCRATCHA1
259: move SCRATCHA0 SHL 0 to SCRATCHA0 ; double it again
260: move SCRATCHA1 SHL 0 to SCRATCHA1 ; now have a UInt32 index
261: store SCRATCHA0, 4, fetchMailbox+4 ; *** patch the load DSA instruction
262: store SCRATCHA0, 4, clear_mailbox+4 ; *** patch the store DSA instruction
263:
264: load DSA0, 4, ld_sched_mlbx_base_adr ; load base physical address of mailboxes
265:
266: fetchMailbox:
267: load DSA0, 4, DSAREL( 0 ) ; *** Patched offset. Load Nexus address
268: store DSA0, 4, ld_nexus ; save pointer to current Nexus
269: load SCRATCHA0, 4, ld_nexus ; copy to A0
270:
271: move SCRATCHA0 to SFBR ; if non-zero, have implicit semaphore
272: move SCRATCHA1 | SFBR to SFBR
273: move SCRATCHA2 | SFBR to SFBR
274: move SCRATCHA3 | SFBR to SFBR
275: jump rel( reselect_phase ), if 0 ; go to reselect_phase if empty
276:
277: ;*****************************************************************
278: ;
279: ; Something in mailbox: we have work to do
280: ;
281: ;*****************************************************************
282:
283: move kphase_SELECT to SCRATCHB0 ; set phase indicator
284: store SCRATCHB0, 1, ld_phase_flag
285:
286: load SCRATCHB0, 4, ld_zeroes ; clr the invalid-nexus-index flag
287: load SCRATCHB0, 1, DSAREL( TLQ_index ) ; get index byte from nexus
288: store SCRATCHB0, 4, ld_nexus_index ; save it in local data
289:
290: load DSA0, 4, ld_nexus ; restore DSA register
291: load SCRATCHB2, 1, DSAREL( TLQ_SCSI_ID+2 ) ; get Target's SCSI ID
292: move SCRATCHB2 to SFBR
293: move SFBR to SCRATCHB0 ; position it
294: store SCRATCHB0, 1, ld_scsi_id ; save it
295: call rel( initContext ) ; setup Sync/Wide regs in SCRATCHB
296: load DSA0, 4, ld_nexus ; restore DSA register
297: store SCRATCHB1, 1, DSAREL( TLQ_SCSI_ID+1 ) ; SXFER
298: store SCRATCHB3, 1, DSAREL( TLQ_SCSI_ID+3 ) ; SCNTL3
299:
300: ;********************** select the device ********************************
301: SELECT ATN from TLQ_SCSI_ID, rel( try_reselect ) ; ************************
302: ;*************************************************************************
303:
304: ; looking good - clear the mailbox:
305:
306: load SCRATCHA0, 4, ld_zeroes ; zero out scratch register A
307: load DSA0, 4, ld_sched_mlbx_base_adr ; load base physical address of mailboxes
308: clear_mailbox:
309: store SCRATCHA0, 4, DSAREL( 0 ) ; *** Patched offset. Zero the mailbox
310:
311: ; Update the index to the mailbox circular list:
312: load SCRATCHB0, 1, ld_counter ; get counter (mailbox index)
313: move SCRATCHB0 + 1 to SCRATCHB0 ; add 1
314: store SCRATCHB0, 1, ld_counter ; put it back
315: ; *** FALL THROUGH TO phase_handler ***
316:
317:
318: ;*****************************************************************
319: ;
320: ; Phase_handler
321: ; The phase handler script is a dispatcher function of SCSI phase
322: ;
323: ;*****************************************************************
324:
325: phase_handler:
326: load DSA0, 4, ld_nexus ; reload DSA
327: jump rel( command_phase ), when CMD ; wait for REQ
328: jump rel( data_out_phase ), if DATA_OUT ; already latched REQ signal
329: jump rel( message_out_phase ), if MSG_OUT
330: jump rel( data_in_phase ), if DATA_IN
331: jump rel( status_phase ), if STATUS
332: jump rel( message_in_phase ), if MSG_IN
333: int unknown_phase
334:
335:
336: ;*****************************************************************
337: ;
338: ; Message-Out phase
339: ;
340: ;*****************************************************************
341:
342: message_out_phase:
343: move kphase_MSG_OUT to SCRATCHB0 ; Set phase indicator
344: store SCRATCHB0, 1, ld_phase_flag
345:
346: move from TLQ_MSGOp, when MSG_OUT ; put out the message(s)
347: jump rel( phase_handler )
348:
349:
350: ; issueMessageOut - Driver entry point for Sync/Wide negotiation and
351: ; to issue message Reject:
352:
353: issueMessageOut:
354: set ATN ; tell Target we have something to say
355: clear ACK
356: jump rel( message_out_phase ), when MSG_OUT ; wait for REQ. Jump if msg-out phase.
357: jump rel( phase_handler ), if not MSG_IN ; jump if weird phase
358: move 1, ld_scratch+1, when MSG_IN ; dump the msg byte
359: clear ACK ; accept Target's last msg-in byte
360: jump rel( issueMessageOut )
361:
362:
363: ;*****************************************************************
364: ;
365: ; Command phase
366: ;
367: ;*****************************************************************
368:
369: command_phase:
370: move kphase_COMMAND to SCRATCHB0 ; Set phase indicator
371: store SCRATCHB0, 1, ld_phase_flag
372:
373: clear ATN ; In case we missed the sending nego
374: move FROM TLQ_CDBp, when CMD ; issue the CDB
375: jump rel( phase_handler )
376:
377:
378: ;*****************************************************************
379: ;
380: ; Data_out_phase
381: ;
382: ;*****************************************************************
383:
384: data_out_phase:
385: move kphase_DATA_OUT to SCRATCHB0 ; Set phase indicator
386: store SCRATCHB0, 1, ld_phase_flag
387:
388: call rel( driverXfer ) ; call driver-built CHMOV instructions
389: jump rel( phase_handler ) ; if all data xfer'd, get next phase
390:
391: driverXfer: ; get here from data-in code also
392: load SCRATCHA0, 4, DSAREL( TLQ_xferAdr )
393: store SCRATCHA0, 4, doItPatch+4 ; *** patch the JUMP address
394: move 0xFF to SCRATCHA1
395: store SCRATCHA1, 1, DSAREL( TLQ_xferStarted )
396:
397: doItPatch:
398: jump 0x0333 ; *** patched address
399:
400:
401:
402: ;*****************************************************************
403: ;
404: ; Data_in_phase
405: ; 875 sets ATN if bad parity detected.
406: ; Use of CHMOV instructions assures that we properly handle
407: ; a leftover wide byte in the SWIDE or SODL register, depending
408: ; on the data direction. This can happen in either of two conditions:
409: ; 1. The Target disconnects at an odd boundary. This is
410: ; extremely unlikely with disk devices.
411: ; 2. The client passes either an odd buffer address or
412: ; an odd transfer count. When the Target disconnects (at
413: ; an even boundary, we end up with the extra wide
414: ; byte in SWIDE or SODL. MacOS does this with VM on.
415: ;
416: ;*****************************************************************
417:
418: data_in_phase:
419: move kphase_DATA_IN to SCRATCHB0 ; Set phase indicator
420: store SCRATCHB0, 1, ld_phase_flag
421:
422: call rel( driverXfer ) ; call driver-built CHMOV instructions
423:
424: ; The driver gets interrupted if a phase mismatch occurs as when
425: ; the Target goes MSG-IN with a Disconnect.
426: ; The driver codes either a RETURN if the Scatter/Gather list is complete or
427: ; an INT if more Scatter/Gather elements need to be generated.
428: ; On the Macintosh, client programs expect extra incoming data to be dumped.
429: ; For example, during boot the ROM reads 512 bytes from a 2K-byte-sector CD.
430:
431: bucket_loop:
432: jump rel( phase_handler ), when not DATA_IN ; wait for phase, exit if changed
433: CHMOV 1, ld_status, when DATA_IN ; eat a byte
434: jump rel( bucket_loop ); ; keep dumping bytes
435:
436:
437: ;*****************************************************************
438: ;
439: ; Status phase
440: ;
441: ;*****************************************************************
442:
443: status_phase:
444: move kphase_STATUS to SCRATCHB0 ; Set phase indicator
445: store SCRATCHB0, 1, ld_phase_flag
446:
447: move 1, ld_status, when STATUS ; Read Status byte from bus
448: jump rel( phase_handler )
449:
450:
451: ;*****************************************************************
452: ;
453: ; Message-In phase
454: ;
455: ;*****************************************************************
456:
457: message_in_phase:
458: move kphase_MSG_IN to SCRATCHB0 ; Set phase indicator
459: store SCRATCHB0, 1, ld_phase_flag
460:
461: move 1, ld_message, when MSG_IN ; Read byte from bus
462:
463: jump rel( cmdComplete ), if 0x00 ; Command Complete
464: jump rel( saveDataPointer ), if 0x02 ; Save Data Pointer
465: jump rel( disconnect_msg ), if 0x04 ; Disconnect
466: jump rel( ignoreWideResidue ), if 0x23 ; Ignore Wide Residue
467: jump rel( restoreDataPointer ), if 0x03 ; Restore Data Pointer
468: jump rel( extended_msg ), if 0x01 ; Extended message
469: jump rel( msg_reject ), if 0x07 ; Message Reject
470: ; Identify, if 0x80-FF ; Identify + LUN
471: ; simple_queue_tag, if 0x20 ; Simple Queue Tag
472: ; initiate_recovery, if 0x0F ; Initiate Recovery
473: ; linked_cde_complete, if 0x0A/0x0B
474: int unexpected_msg ; unknown
475:
476: msg_reject:
477: int unknown_msg_reject
478:
479: clearACK: ; ENTRY point to end negotiation
480: clear ACK
481: jump rel( phase_handler )
482:
483:
484:
485: ;*****************************************************************
486: ;
487: ; Ignore Wide Residue
488: ;
489: ;*****************************************************************
490:
491: ignoreWideResidue: ; this is a two byte message so snag the 2nd byte here
492: clear ACK
493: move 1, ld_message+1, when MSG_IN ; save residue count
494: move SFBR to SCRATCHB2 ; byte is still in SFBR. Position it.
495: store SCRATCHB2, 1, DSAREL( TLQ_IWR ) ; Store residue count in Nexus for driver.
496: clear ACK
497: jump rel( phase_handler )
498:
499:
500: ;*****************************************************************
501: ;
502: ; Extended message
503: ; Accept Wide and Synchronous Data Transfer messages
504: ;
505: ;*****************************************************************
506:
507: extended_msg:
508: clear ACK
509: move 1, ld_message+1, when MSG_IN ; read msg length byte from bus
510: clear ACK
511: move 1, ld_message+2, when MSG_IN ; read ext msg code from bus
512: clear ACK
513: ; extended_identify, IF 0x02
514: ; modify_data_pointer, if 0x00
515: jump rel( sdtr ), if 0x01 ; jump if SDTR, sync negotiation msg
516: jump rel( wdtr ), if 0x03 ; jump if WDTR, wide negotiation msg
517: int unexpected_ext_msg ; let driver deal with unknown
518:
519:
520: ;*****************************************************************
521: ;
522: ; Command complete
523: ; The Command-Complete message is sent to indicate that the
524: ; IO operation has completed and valid status has been sent.
525: ; The Target should then disconnect.
526: ; SCRIPTS must spin until the IOdone mailbox is empty.
527: ; Then it sets the IOdone mailbox with the current Nexus.
528: ; The status message is analyzed.
529: ; If status is good, INTF the driver and jump to select_phase.
530: ; If status is NG, save it in the NEXUS and INT the driver.
531: ;
532: ;*****************************************************************
533:
534: cmdComplete:
535: move kphase_CMD_COMPLETE to SCRATCHB0 ; Set phase indicator
536: store SCRATCHB0, 1, ld_phase_flag
537:
538: move SCNTL2 & 0X7F to SCNTL2 ; Clr SDU: SCSI Disconnect Unexpected
539: clear ACK
540: WAIT DISCONNECT
541:
542: testMbxLp: ; loop until IOdone mailbox empty
543: load SCRATCHA0, 4, ld_IOdone_mailbox
544: move SCRATCHA3 to SFBR ; A3 = semaphore
545: jump rel( testMbxLp ), if not 0
546:
547: ; Fill in the IOdone mailbox with the following:
548: ; A0 = index to Nexus
549: ; A1 = Status
550: ; A2 = 0
551: ; A3 = semaphore (FF = set)
552: load SCRATCHA0, 1, ld_nexus_index ; A0 = index to Nexus
553: load SCRATCHB0, 1, ld_status
554: move SCRATCHB0 to SFBR
555: move SFBR to SCRATCHA1 ; A1 = Status
556: move 0x00 to SCRATCHA2 ; A2 = 0
557: move 0xFF to SCRATCHA3 ; A3 = semaphore IOdone mailbox
558: store SCRATCHA0, 4, ld_IOdone_mailbox
559:
560: move SCRATCHA1 to SFBR ; Test the Status of this IO
561: ; SFBR = status msg
562: ; Test status - If good, Interrupt on the fly and jump to select phase
563: intfly 0xFF, if 0 and mask 0xC1 ; mask off reserved bits
564: jump rel( select_phase ), if 0 and mask 0xC1
565: int status_error ; Status err. Interrupt driver & stop
566:
567:
568: ;*****************************************************************
569: ;
570: ; Disconnect
571: ; The 8xx Accepts the disconnection and jumps to the select_phase
572: ; to check for another IO
573: ;
574: ;*****************************************************************
575:
576: disconnect_msg:
577: load SCRATCHB0, 1, ld_phase_flag
578: move SCRATCHB0 to SFBR
579: ; If we got here from reselect just bailout since ld_nexus is
580: ; not setup and the code using it is not needed anyway (no data xfer)
581: jump rel( bailout ), if kphase_RESELECT
582:
583: move kphase_DISCONNECT to SCRATCHB0
584: store SCRATCHB0, 1, ld_phase_flag
585:
586: bailout:
587: move 0xFF to SCRATCHB3 ; invalidate nexus index for driver
588: store SCRATCHB3, 1, ld_nexus_index+3
589: move SCNTL2 & 0x7F to SCNTL2 ; Clr SDU: SCSI Disconnect Unexpected
590: clear ACK
591: WAIT DISCONNECT ; wait for bus-free
592: jump rel( select_phase ) ; go see if more to do
593:
594:
595: ;******************************************************************
596: ;
597: ; ??? mlj - saveDataPointer and restoreDataPointer are incorrect.
598: ; ??? They basically do nothing.
599: ; Save Data Pointer
600: ;
601: ;*****************************************************************
602:
603: saveDataPointer:
604: move kphase_saveDataPointer to SCRATCHB0
605: store SCRATCHB0, 1, ld_phase_flag
606: clear ACK
607: jump rel( phase_handler )
608:
609:
610: ;******************************************************************
611: ;
612: ; ??? mlj - saveDataPointer and restoreDataPointer are incorrect.
613: ; ??? They basically do nothing.
614: ; Restore Data Pointer
615: ; The local values still blocks, still bytes and data address
616: ; must be loaded from the corresponding NEXUS data set.
617: ; This message should followed an IDE (parity error)
618: ;
619: ;*****************************************************************
620:
621: restoreDataPointer:
622: move kphase_restoreDataPointer to SCRATCHB0
623: store SCRATCHB0, 1, ld_phase_flag
624: clear ACK
625: jump rel( phase_handler )
626:
627:
628: ;*****************************************************************
629: ;
630: ; Synchronous data transfer request or response
631: ;
632: ;*****************************************************************
633: sdtr:
634: move 2, ld_message+3, when MSG_IN ; Read period & offset from bus
635: int negotiateSDTR
636:
637:
638: ;***************************************************************************
639: ;
640: ; Wide Data Transfer request or response
641: ;
642: ;***************************************************************************
643: wdtr:
644: move 1, ld_message+3, when MSG_IN ; get Transfer Width Exponent fm bus
645: int negotiateWDTR
646:
647:
648: ;*****************************************************************
649: ;
650: ; Reselect phase
651: ; The chip waits here either for a Reselection from a Target or
652: ; a SIGP from the driver indicating something in the mailbox.
653: ; If reselected, the script uses the Nexus value which is either
654: ; a Tag or a SCSI ID/LUN combo to lookup the Nexus.
655: ; Then init the SXFER and SCNTL3 registers from the device config table.
656: ;
657: ;*****************************************************************
658:
659: try_reselect: ; Select failed - probably reselecting
660: ; Cf NCR Errata Listing 117 Item 1:
661: move SCNTL0 & 0xDF to SCNTL0 ; clr Start bit
662: move CTEST2 | 0x00 to CTEST2 ; Clear SIGP bit from ISTAT reg
663:
664: reselect_phase:
665: move kphase_RESELECT to SCRATCHB0 ; Set phase indicator
666: store SCRATCHB0, 1, ld_phase_flag
667:
668: move 0xFF to SCRATCHB3 ; invalidate nexus index for driver
669: store SCRATCHB3, 1, ld_nexus_index+3
670:
671: ; wait here for reselect from a Target
672: ; or SIGP from the driver
673:
674: WAIT RESELECT REL( select_phase ) ; jump if SIGP
675:
676: ; Reselected:
677:
678: move SSID to SFBR ; SSID = [ Valxxx Scsi_id ]
679: int unknown_reselect, if 0 and mask 0x7F; Interrupt if VAL bit not set
680: move SFBR & 0x0F to SCRATCHB0 ; B0 = Target ID
681: store SCRATCHB0, 1, ld_scsi_id ; save it
682:
683: call rel( initContext ) ; setup sync regs here
684:
685: int no_msgin_after_reselect, when not MSG_IN
686:
687: move 1, ld_message, when MSG_IN ; Read Identify byte from bus
688:
689: ; if another REQ is asserted, a SimpleQueueTag message should be next
690:
691: clear ACK ; notify Target: msg byte rx'd
692: jump rel( getNextMsg ), when MSG_IN ; jump if SimpleQueueTag coming
693:
694: ; untagged operation:
695:
696: move SFBR & 0x07 to SCRATCHA0 ; isolate LUN from Identify byte
697:
698: load SCRATCHB0, 1, ld_scsi_id ; B0 = Target ID
699: clear CARRY
700: move SCRATCHB0 SHL SFBR ; shift left #1
701: move SFBR SHL SCRATCHB0 ; shift left #2
702: move SCRATCHB0 SHL SFBR ; shift left #3
703: move SCRATCHA0 | SFBR to SCRATCHA0 ; form Nexus index = 0b0TTTTLLL
704:
705: store SCRATCHA0, 1, ld_nexus_index ; store as index to Nexus
706: jump rel( haveNexusIndex )
707:
708: ; should be tagged operation:
709:
710: getNextMsg:
711: move 1, ld_message, when MSG_IN ; read message byte from bus
712: jump rel( disconnect_msg ), if 0x04 ; if Disconnect, oh well.
713: clear ACK
714: jump rel( phase_handler ), if not 0x20; Branch if not Queue tag code
715: ; get the Queue Tag and save as the nexus index
716: move 1, ld_nexus_index, when MSG_IN ; Nexus index <- Tag from bus
717: clear ACK ; acknowledge it
718:
719: haveNexusIndex:
720: move 0x00 to SCRATCHB3 ; clear invalid-nexus-index flag
721: store SCRATCHB3, 1, ld_nexus_index+3
722: call rel( findNexusFromIndex ) ; set DSA <- Nexus pointer
723: jump rel( phase_handler ) ; start handling phases.
724:
725:
726: ;*****************************************************************
727: ;
728: ; AbortMailbox - Abort (or BusDeviceReset) the mailbox entry.
729: ; This is a queued operation - not an immediate
730: ; operation as is issueAbort_BDR.
731: ; The Abort message clears all IO processes for the
732: ; selecting Initiator on the specified LUN.
733: ;
734: ; The Bus Device Reset message clears all IO processes for
735: ; all Initiators on all LUNs of selected Target.
736: ; It forces a hard reset condition to the selected SCSI device.
737: ;
738: ; A0 = Identify byte (0xC0 + LUN N.B. Disconnect allowed)
739: ; A1 = Tag, if any
740: ; A2 = SCSI ID
741: ; A3 = Abort code Abort=0x06; Abort Tag=0D; Bus Device Reset=0x0C
742: ;
743: ; Mailbox not cleared by SCRIPTS so that driver can find SCSI ID when done
744: ; N.B.: Device is Async and Narrow after BDR!!!
745: ; Driver must set the device config table values accordingly.
746: ;*****************************************************************
747:
748: AbortMailbox:
749: move kphase_ABORT_MAILBOX to SCRATCHB0 ; Set phase code
750: store SCRATCHB0, 1, ld_phase_flag
751:
752: move 0xFF to SCRATCHB3 ; invalidate nexus index for driver
753: store SCRATCHB3, 1, ld_nexus_index+3
754:
755: load SCRATCHB0, 4, ld_zeroes ; clear Scratch B
756: load SCRATCHB2, 1, ld_AbortBdr_mailbox+2 ; get SCSI ID
757: store SCRATCHB0, 4, AbortSelect+4 ; *** Patch the Select/ATN instruction
758:
759: AbortSelect:
760: SELECT ATN 0, REL( try_reselect ) ; *** Patched SCSI ID
761:
762: move SCRATCHA1 to SFBR ; check for Tag
763: jump rel( taggedAbort ) if not 0x00 ; jump if tagged abort
764:
765: ; untagged Abort or BusDeviceReset:
766:
767: move SCRATCHA3 to SFBR ; position the abort code
768: move SFBR to SCRATCHA1
769: store SCRATCHA0, 2, ld_scratch ; Store Identify and Abort msgs
770: move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected
771: move 2, ld_scratch , when MSG_OUT ; emit Identify and Abort messages
772: WAIT DISCONNECT
773: int abort_mailbox
774:
775: ; AbortTag:
776:
777: taggedAbort:
778: move SCRATCHA1 to SFBR ; position the Tag
779: move SFBR to SCRATCHA2
780: move 0x20 to SCRATCHA1 ; gen SimpleQueueTag code
781: store SCRATCHA0, 4, ld_scratch ; store Identify, SQT, Tag, AbortTag
782: move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected
783: move 4, ld_scratch, when MSG_OUT ; emit all 4 bytes
784: WAIT DISCONNECT
785: int abort_mailbox
786:
787:
788: ;*****************************************************************
789: ;
790: ; issueAbort_BDR - Abort (or BusDeviceReset) the current operation.
791: ; This is an immediate operation - not a queued operation
792: ; as is AbortMailbox.
793: ; The Abort message clears all IO processes for the
794: ; selecting Initiator on the specified LUN.
795: ;
796: ; The Bus Device Reset message clears all IO processes for
797: ; all Initiators on all LUNs of selected Target.
798: ; It forces a hard reset condition to the selected SCSI device.
799: ;
800: ;*****************************************************************
801:
802: issueAbort_BDR:
803: move kphase_ABORT_CURRENT to SCRATCHB0 ; Set phase code
804: store SCRATCHB0, 1, ld_phase_flag
805:
806: move ISTAT & 0x08 to SFBR ; see if Target connected to bus
807: int abort_current, if 0 ; interrupt driver if not connected
808:
809: SET ATN ; get Target's attention
810: load DSA0, 4, ld_nexus ; load pointer to Nexus
811:
812: bucketLoop:
813: clear ACK
814: jump rel( sendAbortBDR ), when MSG_OUT ; wait for REQ. Jump if OK.
815:
816: jump rel( BucketInStatus ), if STATUS ; bit bucket in
817: jump rel( BucketInMsg ), if MSG_IN ; bit bucket in
818: jump rel( BucketInData ), if DATA_IN ; bit bucket in
819:
820: move 0xAD to SCRATCHA0
821: jump rel( BucketOutData ), if DATA_OUT ; bit bucket out
822: jump rel( BucketOutCmd ), if CMD ; bit bucket out
823: int unknown_phase ; back to driver for harsher measures
824:
825:
826: BucketInStatus:
827: move 1, ld_scratch, when STATUS ; eat the Status byte
828: jump rel( bucketLoop ); ; keep bit-bucketing bytes
829:
830: BucketInMsg:
831: move 1, ld_scratch, when MSG_IN ; eat a message byte
832: jump rel( bucketLoop ); ; keep bit-bucketing bytes
833:
834: BucketInData:
835: move 1, ld_scratch, when DATA_IN ; eat a data byte
836: jump rel( bucketLoop ); ; keep bit-bucketing bytes
837:
838: BucketOutData:
839: move SCRATCHA0 xor 0x73 to SCRATCHA0 ; gen 0xDEAD ...
840: store SCRATCHA0, 1, ld_scratch
841: move 1, ld_scratch, when DATA_OUT ; pad a byte out
842: jump rel( bucketLoop ); ; keep bit-bucketing bytes
843:
844: BucketOutCmd:
845: move 0x00 to SCRATCHA0 ; load Null, TestUnitReady, whatever
846: store SCRATCHA0, 1, ld_scratch
847: move 1, ld_scratch, when CMD ; pad a byte out
848: jump rel( bucketLoop ); ; keep bit-bucketing bytes
849:
850:
851: sendAbortBDR:
852: move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected
853: move 1, ld_AbortCode, when MSG_OUT ; Send Abort(06) or BDR(0C) message
854: load SCRATCHA0, 4, ld_zeroes ; load 0's
855: store SCRATCHA0, 4, ld_AbortCode ; clear the Abort code
856: WAIT DISCONNECT
857: int abort_current ; went BusFree - tell Driver
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.