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