]> git.saurik.com Git - apple/xnu.git/blob - iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.ss
xnu-201.19.tar.gz
[apple/xnu.git] / iokit / Drivers / scsi / drvSymbios8xx / Sym8xxScript.ss
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