|
|
1.1 root 1: u32 SCRIPT[] = {
2: /*
3:
4:
5: ; NCR 53c810 driver, main script
6: ; Sponsored by
7: ; iX Multiuser Multitasking Magazine
8: ; [email protected]
9: ;
10: ; Copyright 1993, 1994, 1995 Drew Eckhardt
11: ; Visionary Computing
12: ; (Unix and Linux consulting and custom programming)
13: ; [email protected]
14: ; +1 (303) 786-7975
15: ;
16: ; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
17: ;
18: ; PRE-ALPHA
19: ;
20: ; For more information, please consult
21: ;
22: ; NCR 53C810
23: ; PCI-SCSI I/O Processor
24: ; Data Manual
25: ;
26: ; NCR 53C710
27: ; SCSI I/O Processor
28: ; Programmers Guide
29: ;
30: ; NCR Microelectronics
31: ; 1635 Aeroplaza Drive
32: ; Colorado Springs, CO 80916
33: ; 1+ (719) 578-3400
34: ;
35: ; Toll free literature number
36: ; +1 (800) 334-5454
37: ;
38: ; IMPORTANT : This code is self modifying due to the limitations of
39: ; the NCR53c7,8xx series chips. Persons debugging this code with
40: ; the remote debugger should take this into account, and NOT set
41: ; breakpoints in modified instructions.
42: ;
43: ; Design:
44: ; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard
45: ; microcontroller using a simple instruction set.
46: ;
47: ; So, to minimize the effects of interrupt latency, and to maximize
48: ; throughput, this driver offloads the practical maximum amount
49: ; of processing to the SCSI chip while still maintaining a common
50: ; structure.
51: ;
52: ; Where tradeoffs were needed between efficiency on the older
53: ; chips and the newer NCR53c800 series, the NCR53c800 series
54: ; was chosen.
55: ;
56: ; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
57: ; automate SCSI transfers without host processor intervention, this
58: ; isn't the case with the NCR53c710 and newer chips which allow
59: ;
60: ; - reads and writes to the internal registers from within the SCSI
61: ; scripts, allowing the SCSI SCRIPTS(tm) code to save processor
62: ; state so that multiple threads of execution are possible, and also
63: ; provide an ALU for loop control, etc.
64: ;
65: ; - table indirect addressing for some instructions. This allows
66: ; pointers to be located relative to the DSA ((Data Structure
67: ; Address) register.
68: ;
69: ; These features make it possible to implement a mailbox style interface,
70: ; where the same piece of code is run to handle I/O for multiple threads
71: ; at once minimizing our need to relocate code. Since the NCR53c700/
72: ; NCR53c800 series have a unique combination of features, making a
73: ; a standard ingoing/outgoing mailbox system, costly, I've modified it.
74: ;
75: ; - Mailboxes are a mixture of code and data. This lets us greatly
76: ; simplify the NCR53c810 code and do things that would otherwise
77: ; not be possible.
78: ;
79: ; The saved data pointer is now implemented as follows :
80: ;
81: ; Control flow has been architected such that if control reaches
82: ; munge_save_data_pointer, on a restore pointers message or
83: ; reconnection, a jump to the address formerly in the TEMP register
84: ; will allow the SCSI command to resume execution.
85: ;
86:
87: ;
88: ; Note : the DSA structures must be aligned on 32 bit boundaries,
89: ; since the source and destination of MOVE MEMORY instructions
90: ; must share the same alignment and this is the alignment of the
91: ; NCR registers.
92: ;
93:
94: ABSOLUTE dsa_temp_lun = 0 ; Patch to lun for current dsa
95: ABSOLUTE dsa_temp_next = 0 ; Patch to dsa next for current dsa
96: ABSOLUTE dsa_temp_addr_next = 0 ; Patch to address of dsa next address
97: ; for current dsa
98: ABSOLUTE dsa_temp_sync = 0 ; Patch to address of per-target
99: ; sync routine
100: ABSOLUTE dsa_temp_target = 0 ; Patch to id for current dsa
101: ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
102: ; saved data pointer
103: ABSOLUTE dsa_temp_addr_residual = 0 ; Patch to address of per-command
104: ; current residual code
105: ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
106: ; saved residual code
107: ABSOLUTE dsa_temp_addr_new_value = 0 ; Address of value for JUMP operand
108: ABSOLUTE dsa_temp_addr_array_value = 0 ; Address to copy to
109: ABSOLUTE dsa_temp_addr_dsa_value = 0 ; Address of this DSA value
110:
111: ;
112: ; Once a device has initiated reselection, we need to compare it
113: ; against the singly linked list of commands which have disconnected
114: ; and are pending reselection. These commands are maintained in
115: ; an unordered singly linked list of DSA structures, through the
116: ; DSA pointers at their 'centers' headed by the reconnect_dsa_head
117: ; pointer.
118: ;
119: ; To avoid complications in removing commands from the list,
120: ; I minimize the amount of expensive (at eight operations per
121: ; addition @ 500-600ns each) pointer operations which must
122: ; be done in the NCR driver by precomputing them on the
123: ; host processor during dsa structure generation.
124: ;
125: ; The fixed-up per DSA code knows how to recognize the nexus
126: ; associated with the corresponding SCSI command, and modifies
127: ; the source and destination pointers for the MOVE MEMORY
128: ; instruction which is executed when reselected_ok is called
129: ; to remove the command from the list. Similarly, DSA is
130: ; loaded with the address of the next DSA structure and
131: ; reselected_check_next is called if a failure occurs.
132: ;
133: ; Perhaps more concisely, the net effect of the mess is
134: ;
135: ; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head,
136: ; src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
137: ; src = &dsa->next;
138: ; if (target_id == dsa->id && target_lun == dsa->lun) {
139: ; *dest = *src;
140: ; break;
141: ; }
142: ; }
143: ;
144: ; if (!dsa)
145: ; error (int_err_unexpected_reselect);
146: ; else
147: ; longjmp (dsa->jump_resume, 0);
148: ;
149: ;
150:
151:
152: ; Define DSA structure used for mailboxes
153: ENTRY dsa_code_template
154: dsa_code_template:
155: ENTRY dsa_code_begin
156: dsa_code_begin:
157: MOVE dmode_memory_to_ncr TO DMODE
158:
159: at 0x00000000 : */ 0x78380000,0x00000000,
160: /*
161: MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
162:
163: at 0x00000002 : */ 0xc0000004,0x00000000,0x00000000,
164: /*
165: MOVE dmode_memory_to_memory TO DMODE
166:
167: at 0x00000005 : */ 0x78380000,0x00000000,
168: /*
169: CALL scratch_to_dsa
170:
171: at 0x00000007 : */ 0x88080000,0x00000980,
172: /*
173: CALL select
174:
175: at 0x00000009 : */ 0x88080000,0x000001fc,
176: /*
177: ; Handle the phase mismatch which may have resulted from the
178: ; MOVE FROM dsa_msgout if we returned here. The CLEAR ATN
179: ; may or may not be necessary, and we should update script_asm.pl
180: ; to handle multiple pieces.
181: CLEAR ATN
182:
183: at 0x0000000b : */ 0x60000008,0x00000000,
184: /*
185: CLEAR ACK
186:
187: at 0x0000000d : */ 0x60000040,0x00000000,
188: /*
189:
190: ; Replace second operand with address of JUMP instruction dest operand
191: ; in schedule table for this DSA. Becomes dsa_jump_dest in 53c7,8xx.c.
192: ENTRY dsa_code_fix_jump
193: dsa_code_fix_jump:
194: MOVE MEMORY 4, NOP_insn, 0
195:
196: at 0x0000000f : */ 0xc0000004,0x00000000,0x00000000,
197: /*
198: JUMP select_done
199:
200: at 0x00000012 : */ 0x80080000,0x00000224,
201: /*
202:
203: ; wrong_dsa loads the DSA register with the value of the dsa_next
204: ; field.
205: ;
206: wrong_dsa:
207: ; Patch the MOVE MEMORY INSTRUCTION such that
208: ; the destination address is the address of the OLD
209: ; next pointer.
210: ;
211: MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 8
212:
213: at 0x00000014 : */ 0xc0000004,0x00000000,0x00000758,
214: /*
215: MOVE dmode_memory_to_ncr TO DMODE
216:
217: at 0x00000017 : */ 0x78380000,0x00000000,
218: /*
219: ;
220: ; Move the _contents_ of the next pointer into the DSA register as
221: ; the next I_T_L or I_T_L_Q tupple to check against the established
222: ; nexus.
223: ;
224: MOVE MEMORY 4, dsa_temp_next, addr_scratch
225:
226: at 0x00000019 : */ 0xc0000004,0x00000000,0x00000000,
227: /*
228: MOVE dmode_memory_to_memory TO DMODE
229:
230: at 0x0000001c : */ 0x78380000,0x00000000,
231: /*
232: CALL scratch_to_dsa
233:
234: at 0x0000001e : */ 0x88080000,0x00000980,
235: /*
236: JUMP reselected_check_next
237:
238: at 0x00000020 : */ 0x80080000,0x000006a4,
239: /*
240:
241: ABSOLUTE dsa_save_data_pointer = 0
242: ENTRY dsa_code_save_data_pointer
243: dsa_code_save_data_pointer:
244: MOVE dmode_ncr_to_memory TO DMODE
245:
246: at 0x00000022 : */ 0x78380000,0x00000000,
247: /*
248: MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer
249:
250: at 0x00000024 : */ 0xc0000004,0x00000000,0x00000000,
251: /*
252: MOVE dmode_memory_to_memory TO DMODE
253:
254: at 0x00000027 : */ 0x78380000,0x00000000,
255: /*
256: ; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
257: MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
258:
259: at 0x00000029 : */ 0xc0000018,0x00000000,0x00000000,
260: /*
261: CLEAR ACK
262:
263: at 0x0000002c : */ 0x60000040,0x00000000,
264: /*
265:
266:
267:
268: RETURN
269:
270: at 0x0000002e : */ 0x90080000,0x00000000,
271: /*
272: ABSOLUTE dsa_restore_pointers = 0
273: ENTRY dsa_code_restore_pointers
274: dsa_code_restore_pointers:
275: MOVE dmode_memory_to_ncr TO DMODE
276:
277: at 0x00000030 : */ 0x78380000,0x00000000,
278: /*
279: MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp
280:
281: at 0x00000032 : */ 0xc0000004,0x00000000,0x00000000,
282: /*
283: MOVE dmode_memory_to_memory TO DMODE
284:
285: at 0x00000035 : */ 0x78380000,0x00000000,
286: /*
287: ; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
288: MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
289:
290: at 0x00000037 : */ 0xc0000018,0x00000000,0x00000000,
291: /*
292: CLEAR ACK
293:
294: at 0x0000003a : */ 0x60000040,0x00000000,
295: /*
296:
297:
298:
299: RETURN
300:
301: at 0x0000003c : */ 0x90080000,0x00000000,
302: /*
303:
304: ABSOLUTE dsa_check_reselect = 0
305: ; dsa_check_reselect determines whether or not the current target and
306: ; lun match the current DSA
307: ENTRY dsa_code_check_reselect
308: dsa_code_check_reselect:
309: MOVE SSID TO SFBR ; SSID contains 3 bit target ID
310:
311: at 0x0000003e : */ 0x720a0000,0x00000000,
312: /*
313: ; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
314: JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8
315:
316: at 0x00000040 : */ 0x8084f800,0x00ffff48,
317: /*
318: ;
319: ; Hack - move to scratch first, since SFBR is not writeable
320: ; via the CPU and hence a MOVE MEMORY instruction.
321: ;
322: MOVE dmode_memory_to_ncr TO DMODE
323:
324: at 0x00000042 : */ 0x78380000,0x00000000,
325: /*
326: MOVE MEMORY 1, reselected_identify, addr_scratch
327:
328: at 0x00000044 : */ 0xc0000001,0x00000000,0x00000000,
329: /*
330: MOVE dmode_memory_to_memory TO DMODE
331:
332: at 0x00000047 : */ 0x78380000,0x00000000,
333: /*
334: MOVE SCRATCH0 TO SFBR
335:
336: at 0x00000049 : */ 0x72340000,0x00000000,
337: /*
338: ; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
339: JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
340:
341: at 0x0000004b : */ 0x8084f800,0x00ffff1c,
342: /*
343: ; Patch the MOVE MEMORY INSTRUCTION such that
344: ; the source address is the address of this dsa's
345: ; next pointer.
346: MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 4
347:
348: at 0x0000004d : */ 0xc0000004,0x00000000,0x00000754,
349: /*
350: CALL reselected_ok
351:
352: at 0x00000050 : */ 0x88080000,0x00000750,
353: /*
354: CALL dsa_temp_sync
355:
356: at 0x00000052 : */ 0x88080000,0x00000000,
357: /*
358: ; Release ACK on the IDENTIFY message _after_ we've set the synchronous
359: ; transfer parameters!
360: CLEAR ACK
361:
362: at 0x00000054 : */ 0x60000040,0x00000000,
363: /*
364: ; Implicitly restore pointers on reselection, so a RETURN
365: ; will transfer control back to the right spot.
366: CALL REL (dsa_code_restore_pointers)
367:
368: at 0x00000056 : */ 0x88880000,0x00ffff60,
369: /*
370: RETURN
371:
372: at 0x00000058 : */ 0x90080000,0x00000000,
373: /*
374: ENTRY dsa_zero
375: dsa_zero:
376: ENTRY dsa_code_template_end
377: dsa_code_template_end:
378:
379: ; Perform sanity check for dsa_fields_start == dsa_code_template_end -
380: ; dsa_zero, puke.
381:
382: ABSOLUTE dsa_fields_start = 0 ; Sanity marker
383: ; pad 48 bytes (fix this RSN)
384: ABSOLUTE dsa_next = 48 ; len 4 Next DSA
385: ; del 4 Previous DSA address
386: ABSOLUTE dsa_cmnd = 56 ; len 4 Scsi_Cmnd * for this thread.
387: ABSOLUTE dsa_select = 60 ; len 4 Device ID, Period, Offset for
388: ; table indirect select
389: ABSOLUTE dsa_msgout = 64 ; len 8 table indirect move parameter for
390: ; select message
391: ABSOLUTE dsa_cmdout = 72 ; len 8 table indirect move parameter for
392: ; command
393: ABSOLUTE dsa_dataout = 80 ; len 4 code pointer for dataout
394: ABSOLUTE dsa_datain = 84 ; len 4 code pointer for datain
395: ABSOLUTE dsa_msgin = 88 ; len 8 table indirect move for msgin
396: ABSOLUTE dsa_status = 96 ; len 8 table indirect move for status byte
397: ABSOLUTE dsa_msgout_other = 104 ; len 8 table indirect for normal message out
398: ; (Synchronous transfer negotiation, etc).
399: ABSOLUTE dsa_end = 112
400:
401: ABSOLUTE schedule = 0 ; Array of JUMP dsa_begin or JUMP (next),
402: ; terminated by a call to JUMP wait_reselect
403:
404: ; Linked lists of DSA structures
405: ABSOLUTE reconnect_dsa_head = 0 ; Link list of DSAs which can reconnect
406: ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
407: ; address of reconnect_dsa_head
408:
409: ; These select the source and destination of a MOVE MEMORY instruction
410: ABSOLUTE dmode_memory_to_memory = 0x0
411: ABSOLUTE dmode_memory_to_ncr = 0x0
412: ABSOLUTE dmode_ncr_to_memory = 0x0
413:
414: ABSOLUTE addr_scratch = 0x0
415: ABSOLUTE addr_temp = 0x0
416:
417:
418: ; Interrupts -
419: ; MSB indicates type
420: ; 0 handle error condition
421: ; 1 handle message
422: ; 2 handle normal condition
423: ; 3 debugging interrupt
424: ; 4 testing interrupt
425: ; Next byte indicates specific error
426:
427: ; XXX not yet implemented, I'm not sure if I want to -
428: ; Next byte indicates the routine the error occurred in
429: ; The LSB indicates the specific place the error occurred
430:
431: ABSOLUTE int_err_unexpected_phase = 0x00000000 ; Unexpected phase encountered
432: ABSOLUTE int_err_selected = 0x00010000 ; SELECTED (nee RESELECTED)
433: ABSOLUTE int_err_unexpected_reselect = 0x00020000
434: ABSOLUTE int_err_check_condition = 0x00030000
435: ABSOLUTE int_err_no_phase = 0x00040000
436: ABSOLUTE int_msg_wdtr = 0x01000000 ; WDTR message received
437: ABSOLUTE int_msg_sdtr = 0x01010000 ; SDTR received
438: ABSOLUTE int_msg_1 = 0x01020000 ; single byte special message
439: ; received
440:
441: ABSOLUTE int_norm_select_complete = 0x02000000 ; Select complete, reprogram
442: ; registers.
443: ABSOLUTE int_norm_reselect_complete = 0x02010000 ; Nexus established
444: ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
445: ABSOLUTE int_norm_disconnected = 0x02030000 ; Disconnected
446: ABSOLUTE int_norm_aborted =0x02040000 ; Aborted *dsa
447: ABSOLUTE int_norm_reset = 0x02050000 ; Generated BUS reset.
448: ABSOLUTE int_debug_break = 0x03000000 ; Break point
449:
450: ABSOLUTE int_debug_panic = 0x030b0000 ; Panic driver
451:
452:
453: ABSOLUTE int_test_1 = 0x04000000 ; Test 1 complete
454: ABSOLUTE int_test_2 = 0x04010000 ; Test 2 complete
455: ABSOLUTE int_test_3 = 0x04020000 ; Test 3 complete
456:
457:
458: ; These should start with 0x05000000, with low bits incrementing for
459: ; each one.
460:
461:
462:
463: ABSOLUTE NCR53c7xx_msg_abort = 0 ; Pointer to abort message
464: ABSOLUTE NCR53c7xx_msg_reject = 0 ; Pointer to reject message
465: ABSOLUTE NCR53c7xx_zero = 0 ; long with zero in it, use for source
466: ABSOLUTE NCR53c7xx_sink = 0 ; long to dump worthless data in
467: ABSOLUTE NOP_insn = 0 ; NOP instruction
468:
469: ; Pointer to message, potentially multi-byte
470: ABSOLUTE msg_buf = 0
471:
472: ; Pointer to holding area for reselection information
473: ABSOLUTE reselected_identify = 0
474: ABSOLUTE reselected_tag = 0
475:
476: ; Request sense command pointer, it's a 6 byte command, should
477: ; be constant for all commands since we always want 16 bytes of
478: ; sense and we don't need to change any fields as we did under
479: ; SCSI-I when we actually cared about the LUN field.
480: ;EXTERNAL NCR53c7xx_sense ; Request sense command
481:
482:
483: ; dsa_schedule
484: ; PURPOSE : after a DISCONNECT message has been received, and pointers
485: ; saved, insert the current DSA structure at the head of the
486: ; disconnected queue and fall through to the scheduler.
487: ;
488: ; CALLS : OK
489: ;
490: ; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
491: ; of disconnected commands
492: ;
493: ; MODIFIES : SCRATCH, reconnect_dsa_head
494: ;
495: ; EXITS : always passes control to schedule
496:
497: ENTRY dsa_schedule
498: dsa_schedule:
499:
500:
501:
502:
503: ;
504: ; Calculate the address of the next pointer within the DSA
505: ; structure of the command that is currently disconnecting
506: ;
507: CALL dsa_to_scratch
508:
509: at 0x0000005a : */ 0x88080000,0x00000938,
510: /*
511: MOVE SCRATCH0 + dsa_next TO SCRATCH0
512:
513: at 0x0000005c : */ 0x7e343000,0x00000000,
514: /*
515: MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
516:
517: at 0x0000005e : */ 0x7f350000,0x00000000,
518: /*
519: MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
520:
521: at 0x00000060 : */ 0x7f360000,0x00000000,
522: /*
523: MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
524:
525: at 0x00000062 : */ 0x7f370000,0x00000000,
526: /*
527:
528: ; Point the next field of this DSA structure at the current disconnected
529: ; list
530: MOVE dmode_ncr_to_memory TO DMODE
531:
532: at 0x00000064 : */ 0x78380000,0x00000000,
533: /*
534: MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
535:
536: at 0x00000066 : */ 0xc0000004,0x00000000,0x000001b4,
537: /*
538: MOVE dmode_memory_to_memory TO DMODE
539:
540: at 0x00000069 : */ 0x78380000,0x00000000,
541: /*
542: dsa_schedule_insert:
543: MOVE MEMORY 4, reconnect_dsa_head, 0
544:
545: at 0x0000006b : */ 0xc0000004,0x00000000,0x00000000,
546: /*
547:
548: ; And update the head pointer.
549: CALL dsa_to_scratch
550:
551: at 0x0000006e : */ 0x88080000,0x00000938,
552: /*
553: MOVE dmode_ncr_to_memory TO DMODE
554:
555: at 0x00000070 : */ 0x78380000,0x00000000,
556: /*
557: MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
558:
559: at 0x00000072 : */ 0xc0000004,0x00000000,0x00000000,
560: /*
561: MOVE dmode_memory_to_memory TO DMODE
562:
563: at 0x00000075 : */ 0x78380000,0x00000000,
564: /*
565:
566:
567: MOVE SCNTL2 & 0x7f TO SCNTL2
568:
569: at 0x00000077 : */ 0x7c027f00,0x00000000,
570: /*
571: CLEAR ACK
572:
573: at 0x00000079 : */ 0x60000040,0x00000000,
574: /*
575:
576: WAIT DISCONNECT
577:
578: at 0x0000007b : */ 0x48000000,0x00000000,
579: /*
580:
581:
582:
583:
584:
585:
586: JUMP schedule
587:
588: at 0x0000007d : */ 0x80080000,0x00000000,
589: /*
590:
591:
592: ;
593: ; select
594: ;
595: ; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
596: ; On success, the current DSA structure is removed from the issue
597: ; queue. Usually, this is entered as a fall-through from schedule,
598: ; although the contingent allegiance handling code will write
599: ; the select entry address to the DSP to restart a command as a
600: ; REQUEST SENSE. A message is sent (usually IDENTIFY, although
601: ; additional SDTR or WDTR messages may be sent). COMMAND OUT
602: ; is handled.
603: ;
604: ; INPUTS : DSA - SCSI command, issue_dsa_head
605: ;
606: ; CALLS : NOT OK
607: ;
608: ; MODIFIES : SCRATCH, issue_dsa_head
609: ;
610: ; EXITS : on reselection or selection, go to select_failed
611: ; otherwise, RETURN so control is passed back to
612: ; dsa_begin.
613: ;
614:
615: ENTRY select
616: select:
617:
618:
619:
620:
621:
622:
623:
624:
625:
626:
627:
628:
629: CLEAR TARGET
630:
631: at 0x0000007f : */ 0x60000200,0x00000000,
632: /*
633:
634: ; XXX
635: ;
636: ; In effect, SELECTION operations are backgrounded, with execution
637: ; continuing until code which waits for REQ or a fatal interrupt is
638: ; encountered.
639: ;
640: ; So, for more performance, we could overlap the code which removes
641: ; the command from the NCRs issue queue with the selection, but
642: ; at this point I don't want to deal with the error recovery.
643: ;
644:
645:
646: SELECT ATN FROM dsa_select, select_failed
647:
648: at 0x00000081 : */ 0x4300003c,0x000007a4,
649: /*
650: JUMP select_msgout, WHEN MSG_OUT
651:
652: at 0x00000083 : */ 0x860b0000,0x00000214,
653: /*
654: ENTRY select_msgout
655: select_msgout:
656: MOVE FROM dsa_msgout, WHEN MSG_OUT
657:
658: at 0x00000085 : */ 0x1e000000,0x00000040,
659: /*
660:
661:
662:
663:
664:
665:
666:
667:
668:
669:
670: RETURN
671:
672: at 0x00000087 : */ 0x90080000,0x00000000,
673: /*
674:
675: ;
676: ; select_done
677: ;
678: ; PURPOSE: continue on to normal data transfer; called as the exit
679: ; point from dsa_begin.
680: ;
681: ; INPUTS: dsa
682: ;
683: ; CALLS: OK
684: ;
685: ;
686:
687: select_done:
688:
689:
690:
691:
692:
693:
694:
695: ; After a successful selection, we should get either a CMD phase or
696: ; some transfer request negotiation message.
697:
698: JUMP cmdout, WHEN CMD
699:
700: at 0x00000089 : */ 0x820b0000,0x00000244,
701: /*
702: INT int_err_unexpected_phase, WHEN NOT MSG_IN
703:
704: at 0x0000008b : */ 0x9f030000,0x00000000,
705: /*
706:
707: select_msg_in:
708: CALL msg_in, WHEN MSG_IN
709:
710: at 0x0000008d : */ 0x8f0b0000,0x00000404,
711: /*
712: JUMP select_msg_in, WHEN MSG_IN
713:
714: at 0x0000008f : */ 0x870b0000,0x00000234,
715: /*
716:
717: cmdout:
718: INT int_err_unexpected_phase, WHEN NOT CMD
719:
720: at 0x00000091 : */ 0x9a030000,0x00000000,
721: /*
722:
723:
724:
725: ENTRY cmdout_cmdout
726: cmdout_cmdout:
727:
728: MOVE FROM dsa_cmdout, WHEN CMD
729:
730: at 0x00000093 : */ 0x1a000000,0x00000048,
731: /*
732:
733:
734:
735:
736: ;
737: ; data_transfer
738: ; other_out
739: ; other_in
740: ; other_transfer
741: ;
742: ; PURPOSE : handle the main data transfer for a SCSI command in
743: ; several parts. In the first part, data_transfer, DATA_IN
744: ; and DATA_OUT phases are allowed, with the user provided
745: ; code (usually dynamically generated based on the scatter/gather
746: ; list associated with a SCSI command) called to handle these
747: ; phases.
748: ;
749: ; After control has passed to one of the user provided
750: ; DATA_IN or DATA_OUT routines, back calls are made to
751: ; other_transfer_in or other_transfer_out to handle non-DATA IN
752: ; and DATA OUT phases respectively, with the state of the active
753: ; data pointer being preserved in TEMP.
754: ;
755: ; On completion, the user code passes control to other_transfer
756: ; which causes DATA_IN and DATA_OUT to result in unexpected_phase
757: ; interrupts so that data overruns may be trapped.
758: ;
759: ; INPUTS : DSA - SCSI command
760: ;
761: ; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
762: ; other_transfer
763: ;
764: ; MODIFIES : SCRATCH
765: ;
766: ; EXITS : if STATUS IN is detected, signifying command completion,
767: ; the NCR jumps to command_complete. If MSG IN occurs, a
768: ; CALL is made to msg_in. Otherwise, other_transfer runs in
769: ; an infinite loop.
770: ;
771:
772: ENTRY data_transfer
773: data_transfer:
774: JUMP cmdout_cmdout, WHEN CMD
775:
776: at 0x00000095 : */ 0x820b0000,0x0000024c,
777: /*
778: CALL msg_in, WHEN MSG_IN
779:
780: at 0x00000097 : */ 0x8f0b0000,0x00000404,
781: /*
782: INT int_err_unexpected_phase, WHEN MSG_OUT
783:
784: at 0x00000099 : */ 0x9e0b0000,0x00000000,
785: /*
786: JUMP do_dataout, WHEN DATA_OUT
787:
788: at 0x0000009b : */ 0x800b0000,0x0000028c,
789: /*
790: JUMP do_datain, WHEN DATA_IN
791:
792: at 0x0000009d : */ 0x810b0000,0x000002e4,
793: /*
794: JUMP command_complete, WHEN STATUS
795:
796: at 0x0000009f : */ 0x830b0000,0x0000060c,
797: /*
798: JUMP data_transfer
799:
800: at 0x000000a1 : */ 0x80080000,0x00000254,
801: /*
802: ENTRY end_data_transfer
803: end_data_transfer:
804:
805: ;
806: ; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain
807: ; should be fixed up whenever the nexus changes so it can point to the
808: ; correct routine for that command.
809: ;
810:
811:
812: ; Nasty jump to dsa->dataout
813: do_dataout:
814: CALL dsa_to_scratch
815:
816: at 0x000000a3 : */ 0x88080000,0x00000938,
817: /*
818: MOVE SCRATCH0 + dsa_dataout TO SCRATCH0
819:
820: at 0x000000a5 : */ 0x7e345000,0x00000000,
821: /*
822: MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
823:
824: at 0x000000a7 : */ 0x7f350000,0x00000000,
825: /*
826: MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
827:
828: at 0x000000a9 : */ 0x7f360000,0x00000000,
829: /*
830: MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
831:
832: at 0x000000ab : */ 0x7f370000,0x00000000,
833: /*
834: MOVE dmode_ncr_to_memory TO DMODE
835:
836: at 0x000000ad : */ 0x78380000,0x00000000,
837: /*
838: MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
839:
840: at 0x000000af : */ 0xc0000004,0x00000000,0x000002d4,
841: /*
842: MOVE dmode_memory_to_memory TO DMODE
843:
844: at 0x000000b2 : */ 0x78380000,0x00000000,
845: /*
846: dataout_to_jump:
847: MOVE MEMORY 4, 0, dataout_jump + 4
848:
849: at 0x000000b4 : */ 0xc0000004,0x00000000,0x000002e0,
850: /*
851: dataout_jump:
852: JUMP 0
853:
854: at 0x000000b7 : */ 0x80080000,0x00000000,
855: /*
856:
857: ; Nasty jump to dsa->dsain
858: do_datain:
859: CALL dsa_to_scratch
860:
861: at 0x000000b9 : */ 0x88080000,0x00000938,
862: /*
863: MOVE SCRATCH0 + dsa_datain TO SCRATCH0
864:
865: at 0x000000bb : */ 0x7e345400,0x00000000,
866: /*
867: MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
868:
869: at 0x000000bd : */ 0x7f350000,0x00000000,
870: /*
871: MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
872:
873: at 0x000000bf : */ 0x7f360000,0x00000000,
874: /*
875: MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
876:
877: at 0x000000c1 : */ 0x7f370000,0x00000000,
878: /*
879: MOVE dmode_ncr_to_memory TO DMODE
880:
881: at 0x000000c3 : */ 0x78380000,0x00000000,
882: /*
883: MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
884:
885: at 0x000000c5 : */ 0xc0000004,0x00000000,0x0000032c,
886: /*
887: MOVE dmode_memory_to_memory TO DMODE
888:
889: at 0x000000c8 : */ 0x78380000,0x00000000,
890: /*
891: ENTRY datain_to_jump
892: datain_to_jump:
893: MOVE MEMORY 4, 0, datain_jump + 4
894:
895: at 0x000000ca : */ 0xc0000004,0x00000000,0x00000338,
896: /*
897:
898:
899:
900: datain_jump:
901: JUMP 0
902:
903: at 0x000000cd : */ 0x80080000,0x00000000,
904: /*
905:
906:
907:
908: ; Note that other_out and other_in loop until a non-data phase
909: ; is discovered, so we only execute return statements when we
910: ; can go on to the next data phase block move statement.
911:
912: ENTRY other_out
913: other_out:
914:
915:
916:
917: INT int_err_unexpected_phase, WHEN CMD
918:
919: at 0x000000cf : */ 0x9a0b0000,0x00000000,
920: /*
921: JUMP msg_in_restart, WHEN MSG_IN
922:
923: at 0x000000d1 : */ 0x870b0000,0x000003e4,
924: /*
925: INT int_err_unexpected_phase, WHEN MSG_OUT
926:
927: at 0x000000d3 : */ 0x9e0b0000,0x00000000,
928: /*
929: INT int_err_unexpected_phase, WHEN DATA_IN
930:
931: at 0x000000d5 : */ 0x990b0000,0x00000000,
932: /*
933: JUMP command_complete, WHEN STATUS
934:
935: at 0x000000d7 : */ 0x830b0000,0x0000060c,
936: /*
937: JUMP other_out, WHEN NOT DATA_OUT
938:
939: at 0x000000d9 : */ 0x80030000,0x0000033c,
940: /*
941: RETURN
942:
943: at 0x000000db : */ 0x90080000,0x00000000,
944: /*
945:
946: ENTRY other_in
947: other_in:
948:
949:
950:
951: INT int_err_unexpected_phase, WHEN CMD
952:
953: at 0x000000dd : */ 0x9a0b0000,0x00000000,
954: /*
955: JUMP msg_in_restart, WHEN MSG_IN
956:
957: at 0x000000df : */ 0x870b0000,0x000003e4,
958: /*
959: INT int_err_unexpected_phase, WHEN MSG_OUT
960:
961: at 0x000000e1 : */ 0x9e0b0000,0x00000000,
962: /*
963: INT int_err_unexpected_phase, WHEN DATA_OUT
964:
965: at 0x000000e3 : */ 0x980b0000,0x00000000,
966: /*
967: JUMP command_complete, WHEN STATUS
968:
969: at 0x000000e5 : */ 0x830b0000,0x0000060c,
970: /*
971: JUMP other_in, WHEN NOT DATA_IN
972:
973: at 0x000000e7 : */ 0x81030000,0x00000374,
974: /*
975: RETURN
976:
977: at 0x000000e9 : */ 0x90080000,0x00000000,
978: /*
979:
980:
981: ENTRY other_transfer
982: other_transfer:
983: INT int_err_unexpected_phase, WHEN CMD
984:
985: at 0x000000eb : */ 0x9a0b0000,0x00000000,
986: /*
987: CALL msg_in, WHEN MSG_IN
988:
989: at 0x000000ed : */ 0x8f0b0000,0x00000404,
990: /*
991: INT int_err_unexpected_phase, WHEN MSG_OUT
992:
993: at 0x000000ef : */ 0x9e0b0000,0x00000000,
994: /*
995: INT int_err_unexpected_phase, WHEN DATA_OUT
996:
997: at 0x000000f1 : */ 0x980b0000,0x00000000,
998: /*
999: INT int_err_unexpected_phase, WHEN DATA_IN
1000:
1001: at 0x000000f3 : */ 0x990b0000,0x00000000,
1002: /*
1003: JUMP command_complete, WHEN STATUS
1004:
1005: at 0x000000f5 : */ 0x830b0000,0x0000060c,
1006: /*
1007: JUMP other_transfer
1008:
1009: at 0x000000f7 : */ 0x80080000,0x000003ac,
1010: /*
1011:
1012: ;
1013: ; msg_in_restart
1014: ; msg_in
1015: ; munge_msg
1016: ;
1017: ; PURPOSE : process messages from a target. msg_in is called when the
1018: ; caller hasn't read the first byte of the message. munge_message
1019: ; is called when the caller has read the first byte of the message,
1020: ; and left it in SFBR. msg_in_restart is called when the caller
1021: ; hasn't read the first byte of the message, and wishes RETURN
1022: ; to transfer control back to the address of the conditional
1023: ; CALL instruction rather than to the instruction after it.
1024: ;
1025: ; Various int_* interrupts are generated when the host system
1026: ; needs to intervene, as is the case with SDTR, WDTR, and
1027: ; INITIATE RECOVERY messages.
1028: ;
1029: ; When the host system handles one of these interrupts,
1030: ; it can respond by reentering at reject_message,
1031: ; which rejects the message and returns control to
1032: ; the caller of msg_in or munge_msg, accept_message
1033: ; which clears ACK and returns control, or reply_message
1034: ; which sends the message pointed to by the DSA
1035: ; msgout_other table indirect field.
1036: ;
1037: ; DISCONNECT messages are handled by moving the command
1038: ; to the reconnect_dsa_queue.
1039: ;
1040: ; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
1041: ; only)
1042: ;
1043: ; CALLS : NO. The TEMP register isn't backed up to allow nested calls.
1044: ;
1045: ; MODIFIES : SCRATCH, DSA on DISCONNECT
1046: ;
1047: ; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
1048: ; and normal return from message handlers running under
1049: ; Linux, control is returned to the caller. Receipt
1050: ; of DISCONNECT messages pass control to dsa_schedule.
1051: ;
1052: ENTRY msg_in_restart
1053: msg_in_restart:
1054: ; XXX - hackish
1055: ;
1056: ; Since it's easier to debug changes to the statically
1057: ; compiled code, rather than the dynamically generated
1058: ; stuff, such as
1059: ;
1060: ; MOVE x, y, WHEN data_phase
1061: ; CALL other_z, WHEN NOT data_phase
1062: ; MOVE x, y, WHEN data_phase
1063: ;
1064: ; I'd like to have certain routines (notably the message handler)
1065: ; restart on the conditional call rather than the next instruction.
1066: ;
1067: ; So, subtract 8 from the return address
1068:
1069: MOVE TEMP0 + 0xf8 TO TEMP0
1070:
1071: at 0x000000f9 : */ 0x7e1cf800,0x00000000,
1072: /*
1073: MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
1074:
1075: at 0x000000fb : */ 0x7f1dff00,0x00000000,
1076: /*
1077: MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
1078:
1079: at 0x000000fd : */ 0x7f1eff00,0x00000000,
1080: /*
1081: MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
1082:
1083: at 0x000000ff : */ 0x7f1fff00,0x00000000,
1084: /*
1085:
1086: ENTRY msg_in
1087: msg_in:
1088: MOVE 1, msg_buf, WHEN MSG_IN
1089:
1090: at 0x00000101 : */ 0x0f000001,0x00000000,
1091: /*
1092:
1093: munge_msg:
1094: JUMP munge_extended, IF 0x01 ; EXTENDED MESSAGE
1095:
1096: at 0x00000103 : */ 0x800c0001,0x00000524,
1097: /*
1098: JUMP munge_2, IF 0x20, AND MASK 0xdf ; two byte message
1099:
1100: at 0x00000105 : */ 0x800cdf20,0x0000044c,
1101: /*
1102: ;
1103: ; XXX - I've seen a handful of broken SCSI devices which fail to issue
1104: ; a SAVE POINTERS message before disconnecting in the middle of
1105: ; a transfer, assuming that the DATA POINTER will be implicitly
1106: ; restored.
1107: ;
1108: ; Historically, I've often done an implicit save when the DISCONNECT
1109: ; message is processed. We may want to consider having the option of
1110: ; doing that here.
1111: ;
1112: JUMP munge_save_data_pointer, IF 0x02 ; SAVE DATA POINTER
1113:
1114: at 0x00000107 : */ 0x800c0002,0x00000454,
1115: /*
1116: JUMP munge_restore_pointers, IF 0x03 ; RESTORE POINTERS
1117:
1118: at 0x00000109 : */ 0x800c0003,0x000004b8,
1119: /*
1120: JUMP munge_disconnect, IF 0x04 ; DISCONNECT
1121:
1122: at 0x0000010b : */ 0x800c0004,0x0000051c,
1123: /*
1124: INT int_msg_1, IF 0x07 ; MESSAGE REJECT
1125:
1126: at 0x0000010d : */ 0x980c0007,0x01020000,
1127: /*
1128: INT int_msg_1, IF 0x0f ; INITIATE RECOVERY
1129:
1130: at 0x0000010f : */ 0x980c000f,0x01020000,
1131: /*
1132:
1133:
1134:
1135: JUMP reject_message
1136:
1137: at 0x00000111 : */ 0x80080000,0x000005b4,
1138: /*
1139:
1140: munge_2:
1141: JUMP reject_message
1142:
1143: at 0x00000113 : */ 0x80080000,0x000005b4,
1144: /*
1145: ;
1146: ; The SCSI standard allows targets to recover from transient
1147: ; error conditions by backing up the data pointer with a
1148: ; RESTORE POINTERS message.
1149: ;
1150: ; So, we must save and restore the _residual_ code as well as
1151: ; the current instruction pointer. Because of this messiness,
1152: ; it is simpler to put dynamic code in the dsa for this and to
1153: ; just do a simple jump down there.
1154: ;
1155:
1156: munge_save_data_pointer:
1157: MOVE DSA0 + dsa_save_data_pointer TO SFBR
1158:
1159: at 0x00000115 : */ 0x76100000,0x00000000,
1160: /*
1161: MOVE SFBR TO SCRATCH0
1162:
1163: at 0x00000117 : */ 0x6a340000,0x00000000,
1164: /*
1165: MOVE DSA1 + 0xff TO SFBR WITH CARRY
1166:
1167: at 0x00000119 : */ 0x7711ff00,0x00000000,
1168: /*
1169: MOVE SFBR TO SCRATCH1
1170:
1171: at 0x0000011b : */ 0x6a350000,0x00000000,
1172: /*
1173: MOVE DSA2 + 0xff TO SFBR WITH CARRY
1174:
1175: at 0x0000011d : */ 0x7712ff00,0x00000000,
1176: /*
1177: MOVE SFBR TO SCRATCH2
1178:
1179: at 0x0000011f : */ 0x6a360000,0x00000000,
1180: /*
1181: MOVE DSA3 + 0xff TO SFBR WITH CARRY
1182:
1183: at 0x00000121 : */ 0x7713ff00,0x00000000,
1184: /*
1185: MOVE SFBR TO SCRATCH3
1186:
1187: at 0x00000123 : */ 0x6a370000,0x00000000,
1188: /*
1189:
1190: MOVE dmode_ncr_to_memory TO DMODE
1191:
1192: at 0x00000125 : */ 0x78380000,0x00000000,
1193: /*
1194: MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
1195:
1196: at 0x00000127 : */ 0xc0000004,0x00000000,0x000004b4,
1197: /*
1198: MOVE dmode_memory_to_memory TO DMODE
1199:
1200: at 0x0000012a : */ 0x78380000,0x00000000,
1201: /*
1202: jump_dsa_save:
1203: JUMP 0
1204:
1205: at 0x0000012c : */ 0x80080000,0x00000000,
1206: /*
1207:
1208: munge_restore_pointers:
1209: MOVE DSA0 + dsa_restore_pointers TO SFBR
1210:
1211: at 0x0000012e : */ 0x76100000,0x00000000,
1212: /*
1213: MOVE SFBR TO SCRATCH0
1214:
1215: at 0x00000130 : */ 0x6a340000,0x00000000,
1216: /*
1217: MOVE DSA1 + 0xff TO SFBR WITH CARRY
1218:
1219: at 0x00000132 : */ 0x7711ff00,0x00000000,
1220: /*
1221: MOVE SFBR TO SCRATCH1
1222:
1223: at 0x00000134 : */ 0x6a350000,0x00000000,
1224: /*
1225: MOVE DSA2 + 0xff TO SFBR WITH CARRY
1226:
1227: at 0x00000136 : */ 0x7712ff00,0x00000000,
1228: /*
1229: MOVE SFBR TO SCRATCH2
1230:
1231: at 0x00000138 : */ 0x6a360000,0x00000000,
1232: /*
1233: MOVE DSA3 + 0xff TO SFBR WITH CARRY
1234:
1235: at 0x0000013a : */ 0x7713ff00,0x00000000,
1236: /*
1237: MOVE SFBR TO SCRATCH3
1238:
1239: at 0x0000013c : */ 0x6a370000,0x00000000,
1240: /*
1241:
1242: MOVE dmode_ncr_to_memory TO DMODE
1243:
1244: at 0x0000013e : */ 0x78380000,0x00000000,
1245: /*
1246: MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
1247:
1248: at 0x00000140 : */ 0xc0000004,0x00000000,0x00000518,
1249: /*
1250: MOVE dmode_memory_to_memory TO DMODE
1251:
1252: at 0x00000143 : */ 0x78380000,0x00000000,
1253: /*
1254: jump_dsa_restore:
1255: JUMP 0
1256:
1257: at 0x00000145 : */ 0x80080000,0x00000000,
1258: /*
1259:
1260:
1261: munge_disconnect:
1262:
1263:
1264:
1265:
1266:
1267:
1268:
1269:
1270:
1271:
1272:
1273:
1274:
1275:
1276:
1277:
1278: JUMP dsa_schedule
1279:
1280: at 0x00000147 : */ 0x80080000,0x00000168,
1281: /*
1282:
1283:
1284:
1285:
1286:
1287: munge_extended:
1288: CLEAR ACK
1289:
1290: at 0x00000149 : */ 0x60000040,0x00000000,
1291: /*
1292: INT int_err_unexpected_phase, WHEN NOT MSG_IN
1293:
1294: at 0x0000014b : */ 0x9f030000,0x00000000,
1295: /*
1296: MOVE 1, msg_buf + 1, WHEN MSG_IN
1297:
1298: at 0x0000014d : */ 0x0f000001,0x00000001,
1299: /*
1300: JUMP munge_extended_2, IF 0x02
1301:
1302: at 0x0000014f : */ 0x800c0002,0x00000554,
1303: /*
1304: JUMP munge_extended_3, IF 0x03
1305:
1306: at 0x00000151 : */ 0x800c0003,0x00000584,
1307: /*
1308: JUMP reject_message
1309:
1310: at 0x00000153 : */ 0x80080000,0x000005b4,
1311: /*
1312:
1313: munge_extended_2:
1314: CLEAR ACK
1315:
1316: at 0x00000155 : */ 0x60000040,0x00000000,
1317: /*
1318: MOVE 1, msg_buf + 2, WHEN MSG_IN
1319:
1320: at 0x00000157 : */ 0x0f000001,0x00000002,
1321: /*
1322: JUMP reject_message, IF NOT 0x02 ; Must be WDTR
1323:
1324: at 0x00000159 : */ 0x80040002,0x000005b4,
1325: /*
1326: CLEAR ACK
1327:
1328: at 0x0000015b : */ 0x60000040,0x00000000,
1329: /*
1330: MOVE 1, msg_buf + 3, WHEN MSG_IN
1331:
1332: at 0x0000015d : */ 0x0f000001,0x00000003,
1333: /*
1334: INT int_msg_wdtr
1335:
1336: at 0x0000015f : */ 0x98080000,0x01000000,
1337: /*
1338:
1339: munge_extended_3:
1340: CLEAR ACK
1341:
1342: at 0x00000161 : */ 0x60000040,0x00000000,
1343: /*
1344: MOVE 1, msg_buf + 2, WHEN MSG_IN
1345:
1346: at 0x00000163 : */ 0x0f000001,0x00000002,
1347: /*
1348: JUMP reject_message, IF NOT 0x01 ; Must be SDTR
1349:
1350: at 0x00000165 : */ 0x80040001,0x000005b4,
1351: /*
1352: CLEAR ACK
1353:
1354: at 0x00000167 : */ 0x60000040,0x00000000,
1355: /*
1356: MOVE 2, msg_buf + 3, WHEN MSG_IN
1357:
1358: at 0x00000169 : */ 0x0f000002,0x00000003,
1359: /*
1360: INT int_msg_sdtr
1361:
1362: at 0x0000016b : */ 0x98080000,0x01010000,
1363: /*
1364:
1365: ENTRY reject_message
1366: reject_message:
1367: SET ATN
1368:
1369: at 0x0000016d : */ 0x58000008,0x00000000,
1370: /*
1371: CLEAR ACK
1372:
1373: at 0x0000016f : */ 0x60000040,0x00000000,
1374: /*
1375: MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
1376:
1377: at 0x00000171 : */ 0x0e000001,0x00000000,
1378: /*
1379: RETURN
1380:
1381: at 0x00000173 : */ 0x90080000,0x00000000,
1382: /*
1383:
1384: ENTRY accept_message
1385: accept_message:
1386: CLEAR ATN
1387:
1388: at 0x00000175 : */ 0x60000008,0x00000000,
1389: /*
1390: CLEAR ACK
1391:
1392: at 0x00000177 : */ 0x60000040,0x00000000,
1393: /*
1394: RETURN
1395:
1396: at 0x00000179 : */ 0x90080000,0x00000000,
1397: /*
1398:
1399: ENTRY respond_message
1400: respond_message:
1401: SET ATN
1402:
1403: at 0x0000017b : */ 0x58000008,0x00000000,
1404: /*
1405: CLEAR ACK
1406:
1407: at 0x0000017d : */ 0x60000040,0x00000000,
1408: /*
1409: MOVE FROM dsa_msgout_other, WHEN MSG_OUT
1410:
1411: at 0x0000017f : */ 0x1e000000,0x00000068,
1412: /*
1413: RETURN
1414:
1415: at 0x00000181 : */ 0x90080000,0x00000000,
1416: /*
1417:
1418: ;
1419: ; command_complete
1420: ;
1421: ; PURPOSE : handle command termination when STATUS IN is detected by reading
1422: ; a status byte followed by a command termination message.
1423: ;
1424: ; Normal termination results in an INTFLY instruction, and
1425: ; the host system can pick out which command terminated by
1426: ; examining the MESSAGE and STATUS buffers of all currently
1427: ; executing commands;
1428: ;
1429: ; Abnormal (CHECK_CONDITION) termination results in an
1430: ; int_err_check_condition interrupt so that a REQUEST SENSE
1431: ; command can be issued out-of-order so that no other command
1432: ; clears the contingent allegiance condition.
1433: ;
1434: ;
1435: ; INPUTS : DSA - command
1436: ;
1437: ; CALLS : OK
1438: ;
1439: ; EXITS : On successful termination, control is passed to schedule.
1440: ; On abnormal termination, the user will usually modify the
1441: ; DSA fields and corresponding buffers and return control
1442: ; to select.
1443: ;
1444:
1445: ENTRY command_complete
1446: command_complete:
1447: MOVE FROM dsa_status, WHEN STATUS
1448:
1449: at 0x00000183 : */ 0x1b000000,0x00000060,
1450: /*
1451:
1452: MOVE SFBR TO SCRATCH0 ; Save status
1453:
1454: at 0x00000185 : */ 0x6a340000,0x00000000,
1455: /*
1456:
1457: ENTRY command_complete_msgin
1458: command_complete_msgin:
1459: MOVE FROM dsa_msgin, WHEN MSG_IN
1460:
1461: at 0x00000187 : */ 0x1f000000,0x00000058,
1462: /*
1463: ; Indicate that we should be expecting a disconnect
1464: MOVE SCNTL2 & 0x7f TO SCNTL2
1465:
1466: at 0x00000189 : */ 0x7c027f00,0x00000000,
1467: /*
1468: CLEAR ACK
1469:
1470: at 0x0000018b : */ 0x60000040,0x00000000,
1471: /*
1472:
1473: WAIT DISCONNECT
1474:
1475: at 0x0000018d : */ 0x48000000,0x00000000,
1476: /*
1477:
1478: ;
1479: ; The SCSI specification states that when a UNIT ATTENTION condition
1480: ; is pending, as indicated by a CHECK CONDITION status message,
1481: ; the target shall revert to asynchronous transfers. Since
1482: ; synchronous transfers parameters are maintained on a per INITIATOR/TARGET
1483: ; basis, and returning control to our scheduler could work on a command
1484: ; running on another lun on that target using the old parameters, we must
1485: ; interrupt the host processor to get them changed, or change them ourselves.
1486: ;
1487: ; Once SCSI-II tagged queueing is implemented, things will be even more
1488: ; hairy, since contingent allegiance conditions exist on a per-target/lun
1489: ; basis, and issuing a new command with a different tag would clear it.
1490: ; In these cases, we must interrupt the host processor to get a request
1491: ; added to the HEAD of the queue with the request sense command, or we
1492: ; must automatically issue the request sense command.
1493:
1494:
1495:
1496:
1497:
1498: INTFLY
1499:
1500: at 0x0000018f : */ 0x98180000,0x00000000,
1501: /*
1502:
1503:
1504:
1505:
1506:
1507: JUMP schedule
1508:
1509: at 0x00000191 : */ 0x80080000,0x00000000,
1510: /*
1511: command_failed:
1512: INT int_err_check_condition
1513:
1514: at 0x00000193 : */ 0x98080000,0x00030000,
1515: /*
1516:
1517:
1518:
1519:
1520: ;
1521: ; wait_reselect
1522: ;
1523: ; PURPOSE : This is essentially the idle routine, where control lands
1524: ; when there are no new processes to schedule. wait_reselect
1525: ; waits for reselection, selection, and new commands.
1526: ;
1527: ; When a successful reselection occurs, with the aid
1528: ; of fixed up code in each DSA, wait_reselect walks the
1529: ; reconnect_dsa_queue, asking each dsa if the target ID
1530: ; and LUN match its.
1531: ;
1532: ; If a match is found, a call is made back to reselected_ok,
1533: ; which through the miracles of self modifying code, extracts
1534: ; the found DSA from the reconnect_dsa_queue and then
1535: ; returns control to the DSAs thread of execution.
1536: ;
1537: ; INPUTS : NONE
1538: ;
1539: ; CALLS : OK
1540: ;
1541: ; MODIFIES : DSA,
1542: ;
1543: ; EXITS : On successful reselection, control is returned to the
1544: ; DSA which called reselected_ok. If the WAIT RESELECT
1545: ; was interrupted by a new commands arrival signaled by
1546: ; SIG_P, control is passed to schedule. If the NCR is
1547: ; selected, the host system is interrupted with an
1548: ; int_err_selected which is usually responded to by
1549: ; setting DSP to the target_abort address.
1550:
1551: ENTRY wait_reselect
1552: wait_reselect:
1553:
1554:
1555:
1556:
1557:
1558:
1559: WAIT RESELECT wait_reselect_failed
1560:
1561: at 0x00000195 : */ 0x50000000,0x0000076c,
1562: /*
1563:
1564: reselected:
1565:
1566:
1567:
1568: CLEAR TARGET
1569:
1570: at 0x00000197 : */ 0x60000200,0x00000000,
1571: /*
1572: MOVE dmode_memory_to_memory TO DMODE
1573:
1574: at 0x00000199 : */ 0x78380000,0x00000000,
1575: /*
1576: ; Read all data needed to reestablish the nexus -
1577: MOVE 1, reselected_identify, WHEN MSG_IN
1578:
1579: at 0x0000019b : */ 0x0f000001,0x00000000,
1580: /*
1581: ; We used to CLEAR ACK here.
1582:
1583:
1584:
1585:
1586:
1587: ; Point DSA at the current head of the disconnected queue.
1588: MOVE dmode_memory_to_ncr TO DMODE
1589:
1590: at 0x0000019d : */ 0x78380000,0x00000000,
1591: /*
1592: MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
1593:
1594: at 0x0000019f : */ 0xc0000004,0x00000000,0x00000000,
1595: /*
1596: MOVE dmode_memory_to_memory TO DMODE
1597:
1598: at 0x000001a2 : */ 0x78380000,0x00000000,
1599: /*
1600: CALL scratch_to_dsa
1601:
1602: at 0x000001a4 : */ 0x88080000,0x00000980,
1603: /*
1604:
1605: ; Fix the update-next pointer so that the reconnect_dsa_head
1606: ; pointer is the one that will be updated if this DSA is a hit
1607: ; and we remove it from the queue.
1608:
1609: MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok + 8
1610:
1611: at 0x000001a6 : */ 0xc0000004,0x00000000,0x00000758,
1612: /*
1613:
1614: ENTRY reselected_check_next
1615: reselected_check_next:
1616:
1617:
1618:
1619: ; Check for a NULL pointer.
1620: MOVE DSA0 TO SFBR
1621:
1622: at 0x000001a9 : */ 0x72100000,0x00000000,
1623: /*
1624: JUMP reselected_not_end, IF NOT 0
1625:
1626: at 0x000001ab : */ 0x80040000,0x000006ec,
1627: /*
1628: MOVE DSA1 TO SFBR
1629:
1630: at 0x000001ad : */ 0x72110000,0x00000000,
1631: /*
1632: JUMP reselected_not_end, IF NOT 0
1633:
1634: at 0x000001af : */ 0x80040000,0x000006ec,
1635: /*
1636: MOVE DSA2 TO SFBR
1637:
1638: at 0x000001b1 : */ 0x72120000,0x00000000,
1639: /*
1640: JUMP reselected_not_end, IF NOT 0
1641:
1642: at 0x000001b3 : */ 0x80040000,0x000006ec,
1643: /*
1644: MOVE DSA3 TO SFBR
1645:
1646: at 0x000001b5 : */ 0x72130000,0x00000000,
1647: /*
1648: JUMP reselected_not_end, IF NOT 0
1649:
1650: at 0x000001b7 : */ 0x80040000,0x000006ec,
1651: /*
1652: INT int_err_unexpected_reselect
1653:
1654: at 0x000001b9 : */ 0x98080000,0x00020000,
1655: /*
1656:
1657: reselected_not_end:
1658: ;
1659: ; XXX the ALU is only eight bits wide, and the assembler
1660: ; wont do the dirt work for us. As long as dsa_check_reselect
1661: ; is negative, we need to sign extend with 1 bits to the full
1662: ; 32 bit width of the address.
1663: ;
1664: ; A potential work around would be to have a known alignment
1665: ; of the DSA structure such that the base address plus
1666: ; dsa_check_reselect doesn't require carrying from bytes
1667: ; higher than the LSB.
1668: ;
1669:
1670: MOVE DSA0 TO SFBR
1671:
1672: at 0x000001bb : */ 0x72100000,0x00000000,
1673: /*
1674: MOVE SFBR + dsa_check_reselect TO SCRATCH0
1675:
1676: at 0x000001bd : */ 0x6e340000,0x00000000,
1677: /*
1678: MOVE DSA1 TO SFBR
1679:
1680: at 0x000001bf : */ 0x72110000,0x00000000,
1681: /*
1682: MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
1683:
1684: at 0x000001c1 : */ 0x6f35ff00,0x00000000,
1685: /*
1686: MOVE DSA2 TO SFBR
1687:
1688: at 0x000001c3 : */ 0x72120000,0x00000000,
1689: /*
1690: MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
1691:
1692: at 0x000001c5 : */ 0x6f36ff00,0x00000000,
1693: /*
1694: MOVE DSA3 TO SFBR
1695:
1696: at 0x000001c7 : */ 0x72130000,0x00000000,
1697: /*
1698: MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
1699:
1700: at 0x000001c9 : */ 0x6f37ff00,0x00000000,
1701: /*
1702:
1703: MOVE dmode_ncr_to_memory TO DMODE
1704:
1705: at 0x000001cb : */ 0x78380000,0x00000000,
1706: /*
1707: MOVE MEMORY 4, addr_scratch, reselected_check + 4
1708:
1709: at 0x000001cd : */ 0xc0000004,0x00000000,0x0000074c,
1710: /*
1711: MOVE dmode_memory_to_memory TO DMODE
1712:
1713: at 0x000001d0 : */ 0x78380000,0x00000000,
1714: /*
1715: reselected_check:
1716: JUMP 0
1717:
1718: at 0x000001d2 : */ 0x80080000,0x00000000,
1719: /*
1720:
1721:
1722: ;
1723: ;
1724: ENTRY reselected_ok
1725: reselected_ok:
1726: MOVE MEMORY 4, 0, 0 ; Patched : first word
1727:
1728: at 0x000001d4 : */ 0xc0000004,0x00000000,0x00000000,
1729: /*
1730: ; is address of
1731: ; successful dsa_next
1732: ; Second word is last
1733: ; unsuccessful dsa_next,
1734: ; starting with
1735: ; dsa_reconnect_head
1736: ; We used to CLEAR ACK here.
1737:
1738:
1739:
1740:
1741:
1742:
1743: RETURN ; Return control to where
1744:
1745: at 0x000001d7 : */ 0x90080000,0x00000000,
1746: /*
1747:
1748:
1749:
1750:
1751: selected:
1752: INT int_err_selected;
1753:
1754: at 0x000001d9 : */ 0x98080000,0x00010000,
1755: /*
1756:
1757: ;
1758: ; A select or reselect failure can be caused by one of two conditions :
1759: ; 1. SIG_P was set. This will be the case if the user has written
1760: ; a new value to a previously NULL head of the issue queue.
1761: ;
1762: ; 2. The NCR53c810 was selected or reselected by another device.
1763: ;
1764: ; 3. The bus was already busy since we were selected or reselected
1765: ; before starting the command.
1766:
1767: wait_reselect_failed:
1768:
1769:
1770:
1771: ; Check selected bit.
1772: MOVE SIST0 & 0x20 TO SFBR
1773:
1774: at 0x000001db : */ 0x74422000,0x00000000,
1775: /*
1776: JUMP selected, IF 0x20
1777:
1778: at 0x000001dd : */ 0x800c0020,0x00000764,
1779: /*
1780: ; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
1781: MOVE CTEST2 & 0x40 TO SFBR
1782:
1783: at 0x000001df : */ 0x741a4000,0x00000000,
1784: /*
1785: JUMP schedule, IF 0x40
1786:
1787: at 0x000001e1 : */ 0x800c0040,0x00000000,
1788: /*
1789: ; Check connected bit.
1790: ; FIXME: this needs to change if we support target mode
1791: MOVE ISTAT & 0x08 TO SFBR
1792:
1793: at 0x000001e3 : */ 0x74140800,0x00000000,
1794: /*
1795: JUMP reselected, IF 0x08
1796:
1797: at 0x000001e5 : */ 0x800c0008,0x0000065c,
1798: /*
1799: ; FIXME : Something bogus happened, and we shouldn't fail silently.
1800:
1801:
1802:
1803: INT int_debug_panic
1804:
1805: at 0x000001e7 : */ 0x98080000,0x030b0000,
1806: /*
1807:
1808:
1809:
1810: select_failed:
1811:
1812:
1813:
1814: ; Otherwise, mask the selected and reselected bits off SIST0
1815: MOVE SIST0 & 0x30 TO SFBR
1816:
1817: at 0x000001e9 : */ 0x74423000,0x00000000,
1818: /*
1819: JUMP selected, IF 0x20
1820:
1821: at 0x000001eb : */ 0x800c0020,0x00000764,
1822: /*
1823: JUMP reselected, IF 0x10
1824:
1825: at 0x000001ed : */ 0x800c0010,0x0000065c,
1826: /*
1827: ; If SIGP is set, the user just gave us another command, and
1828: ; we should restart or return to the scheduler.
1829: ; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
1830: MOVE CTEST2 & 0x40 TO SFBR
1831:
1832: at 0x000001ef : */ 0x741a4000,0x00000000,
1833: /*
1834: JUMP select, IF 0x40
1835:
1836: at 0x000001f1 : */ 0x800c0040,0x000001fc,
1837: /*
1838: ; Check connected bit.
1839: ; FIXME: this needs to change if we support target mode
1840: ; FIXME: is this really necessary?
1841: MOVE ISTAT & 0x08 TO SFBR
1842:
1843: at 0x000001f3 : */ 0x74140800,0x00000000,
1844: /*
1845: JUMP reselected, IF 0x08
1846:
1847: at 0x000001f5 : */ 0x800c0008,0x0000065c,
1848: /*
1849: ; FIXME : Something bogus happened, and we shouldn't fail silently.
1850:
1851:
1852:
1853: INT int_debug_panic
1854:
1855: at 0x000001f7 : */ 0x98080000,0x030b0000,
1856: /*
1857:
1858:
1859: ;
1860: ; test_1
1861: ; test_2
1862: ;
1863: ; PURPOSE : run some verification tests on the NCR. test_1
1864: ; copies test_src to test_dest and interrupts the host
1865: ; processor, testing for cache coherency and interrupt
1866: ; problems in the processes.
1867: ;
1868: ; test_2 runs a command with offsets relative to the
1869: ; DSA on entry, and is useful for miscellaneous experimentation.
1870: ;
1871:
1872: ; Verify that interrupts are working correctly and that we don't
1873: ; have a cache invalidation problem.
1874:
1875: ABSOLUTE test_src = 0, test_dest = 0
1876: ENTRY test_1
1877: test_1:
1878: MOVE MEMORY 4, test_src, test_dest
1879:
1880: at 0x000001f9 : */ 0xc0000004,0x00000000,0x00000000,
1881: /*
1882: INT int_test_1
1883:
1884: at 0x000001fc : */ 0x98080000,0x04000000,
1885: /*
1886:
1887: ;
1888: ; Run arbitrary commands, with test code establishing a DSA
1889: ;
1890:
1891: ENTRY test_2
1892: test_2:
1893: CLEAR TARGET
1894:
1895: at 0x000001fe : */ 0x60000200,0x00000000,
1896: /*
1897: SELECT ATN FROM 0, test_2_fail
1898:
1899: at 0x00000200 : */ 0x43000000,0x00000850,
1900: /*
1901: JUMP test_2_msgout, WHEN MSG_OUT
1902:
1903: at 0x00000202 : */ 0x860b0000,0x00000810,
1904: /*
1905: ENTRY test_2_msgout
1906: test_2_msgout:
1907: MOVE FROM 8, WHEN MSG_OUT
1908:
1909: at 0x00000204 : */ 0x1e000000,0x00000008,
1910: /*
1911: MOVE FROM 16, WHEN CMD
1912:
1913: at 0x00000206 : */ 0x1a000000,0x00000010,
1914: /*
1915: MOVE FROM 24, WHEN DATA_IN
1916:
1917: at 0x00000208 : */ 0x19000000,0x00000018,
1918: /*
1919: MOVE FROM 32, WHEN STATUS
1920:
1921: at 0x0000020a : */ 0x1b000000,0x00000020,
1922: /*
1923: MOVE FROM 40, WHEN MSG_IN
1924:
1925: at 0x0000020c : */ 0x1f000000,0x00000028,
1926: /*
1927: MOVE SCNTL2 & 0x7f TO SCNTL2
1928:
1929: at 0x0000020e : */ 0x7c027f00,0x00000000,
1930: /*
1931: CLEAR ACK
1932:
1933: at 0x00000210 : */ 0x60000040,0x00000000,
1934: /*
1935: WAIT DISCONNECT
1936:
1937: at 0x00000212 : */ 0x48000000,0x00000000,
1938: /*
1939: test_2_fail:
1940: INT int_test_2
1941:
1942: at 0x00000214 : */ 0x98080000,0x04010000,
1943: /*
1944:
1945: ENTRY debug_break
1946: debug_break:
1947: INT int_debug_break
1948:
1949: at 0x00000216 : */ 0x98080000,0x03000000,
1950: /*
1951:
1952: ;
1953: ; initiator_abort
1954: ; target_abort
1955: ;
1956: ; PURPOSE : Abort the currently established nexus from with initiator
1957: ; or target mode.
1958: ;
1959: ;
1960:
1961: ENTRY target_abort
1962: target_abort:
1963: SET TARGET
1964:
1965: at 0x00000218 : */ 0x58000200,0x00000000,
1966: /*
1967: DISCONNECT
1968:
1969: at 0x0000021a : */ 0x48000000,0x00000000,
1970: /*
1971: CLEAR TARGET
1972:
1973: at 0x0000021c : */ 0x60000200,0x00000000,
1974: /*
1975: JUMP schedule
1976:
1977: at 0x0000021e : */ 0x80080000,0x00000000,
1978: /*
1979:
1980: ENTRY initiator_abort
1981: initiator_abort:
1982: SET ATN
1983:
1984: at 0x00000220 : */ 0x58000008,0x00000000,
1985: /*
1986: ;
1987: ; The SCSI-I specification says that targets may go into MSG out at
1988: ; their leisure upon receipt of the ATN single. On all versions of the
1989: ; specification, we can't change phases until REQ transitions true->false,
1990: ; so we need to sink/source one byte of data to allow the transition.
1991: ;
1992: ; For the sake of safety, we'll only source one byte of data in all
1993: ; cases, but to accommodate the SCSI-I dain bramage, we'll sink an
1994: ; arbitrary number of bytes.
1995: JUMP spew_cmd, WHEN CMD
1996:
1997: at 0x00000222 : */ 0x820b0000,0x000008b8,
1998: /*
1999: JUMP eat_msgin, WHEN MSG_IN
2000:
2001: at 0x00000224 : */ 0x870b0000,0x000008c8,
2002: /*
2003: JUMP eat_datain, WHEN DATA_IN
2004:
2005: at 0x00000226 : */ 0x810b0000,0x000008f8,
2006: /*
2007: JUMP eat_status, WHEN STATUS
2008:
2009: at 0x00000228 : */ 0x830b0000,0x000008e0,
2010: /*
2011: JUMP spew_dataout, WHEN DATA_OUT
2012:
2013: at 0x0000022a : */ 0x800b0000,0x00000910,
2014: /*
2015: JUMP sated
2016:
2017: at 0x0000022c : */ 0x80080000,0x00000918,
2018: /*
2019: spew_cmd:
2020: MOVE 1, NCR53c7xx_zero, WHEN CMD
2021:
2022: at 0x0000022e : */ 0x0a000001,0x00000000,
2023: /*
2024: JUMP sated
2025:
2026: at 0x00000230 : */ 0x80080000,0x00000918,
2027: /*
2028: eat_msgin:
2029: MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
2030:
2031: at 0x00000232 : */ 0x0f000001,0x00000000,
2032: /*
2033: JUMP eat_msgin, WHEN MSG_IN
2034:
2035: at 0x00000234 : */ 0x870b0000,0x000008c8,
2036: /*
2037: JUMP sated
2038:
2039: at 0x00000236 : */ 0x80080000,0x00000918,
2040: /*
2041: eat_status:
2042: MOVE 1, NCR53c7xx_sink, WHEN STATUS
2043:
2044: at 0x00000238 : */ 0x0b000001,0x00000000,
2045: /*
2046: JUMP eat_status, WHEN STATUS
2047:
2048: at 0x0000023a : */ 0x830b0000,0x000008e0,
2049: /*
2050: JUMP sated
2051:
2052: at 0x0000023c : */ 0x80080000,0x00000918,
2053: /*
2054: eat_datain:
2055: MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
2056:
2057: at 0x0000023e : */ 0x09000001,0x00000000,
2058: /*
2059: JUMP eat_datain, WHEN DATA_IN
2060:
2061: at 0x00000240 : */ 0x810b0000,0x000008f8,
2062: /*
2063: JUMP sated
2064:
2065: at 0x00000242 : */ 0x80080000,0x00000918,
2066: /*
2067: spew_dataout:
2068: MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
2069:
2070: at 0x00000244 : */ 0x08000001,0x00000000,
2071: /*
2072: sated:
2073: MOVE SCNTL2 & 0x7f TO SCNTL2
2074:
2075: at 0x00000246 : */ 0x7c027f00,0x00000000,
2076: /*
2077: MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
2078:
2079: at 0x00000248 : */ 0x0e000001,0x00000000,
2080: /*
2081: WAIT DISCONNECT
2082:
2083: at 0x0000024a : */ 0x48000000,0x00000000,
2084: /*
2085: INT int_norm_aborted
2086:
2087: at 0x0000024c : */ 0x98080000,0x02040000,
2088: /*
2089:
2090: ;
2091: ; dsa_to_scratch
2092: ; scratch_to_dsa
2093: ;
2094: ; PURPOSE :
2095: ; The NCR chips cannot do a move memory instruction with the DSA register
2096: ; as the source or destination. So, we provide a couple of subroutines
2097: ; that let us switch between the DSA register and scratch register.
2098: ;
2099: ; Memory moves to/from the DSPS register also don't work, but we
2100: ; don't use them.
2101: ;
2102: ;
2103:
2104:
2105: dsa_to_scratch:
2106: MOVE DSA0 TO SFBR
2107:
2108: at 0x0000024e : */ 0x72100000,0x00000000,
2109: /*
2110: MOVE SFBR TO SCRATCH0
2111:
2112: at 0x00000250 : */ 0x6a340000,0x00000000,
2113: /*
2114: MOVE DSA1 TO SFBR
2115:
2116: at 0x00000252 : */ 0x72110000,0x00000000,
2117: /*
2118: MOVE SFBR TO SCRATCH1
2119:
2120: at 0x00000254 : */ 0x6a350000,0x00000000,
2121: /*
2122: MOVE DSA2 TO SFBR
2123:
2124: at 0x00000256 : */ 0x72120000,0x00000000,
2125: /*
2126: MOVE SFBR TO SCRATCH2
2127:
2128: at 0x00000258 : */ 0x6a360000,0x00000000,
2129: /*
2130: MOVE DSA3 TO SFBR
2131:
2132: at 0x0000025a : */ 0x72130000,0x00000000,
2133: /*
2134: MOVE SFBR TO SCRATCH3
2135:
2136: at 0x0000025c : */ 0x6a370000,0x00000000,
2137: /*
2138: RETURN
2139:
2140: at 0x0000025e : */ 0x90080000,0x00000000,
2141: /*
2142:
2143: scratch_to_dsa:
2144: MOVE SCRATCH0 TO SFBR
2145:
2146: at 0x00000260 : */ 0x72340000,0x00000000,
2147: /*
2148: MOVE SFBR TO DSA0
2149:
2150: at 0x00000262 : */ 0x6a100000,0x00000000,
2151: /*
2152: MOVE SCRATCH1 TO SFBR
2153:
2154: at 0x00000264 : */ 0x72350000,0x00000000,
2155: /*
2156: MOVE SFBR TO DSA1
2157:
2158: at 0x00000266 : */ 0x6a110000,0x00000000,
2159: /*
2160: MOVE SCRATCH2 TO SFBR
2161:
2162: at 0x00000268 : */ 0x72360000,0x00000000,
2163: /*
2164: MOVE SFBR TO DSA2
2165:
2166: at 0x0000026a : */ 0x6a120000,0x00000000,
2167: /*
2168: MOVE SCRATCH3 TO SFBR
2169:
2170: at 0x0000026c : */ 0x72370000,0x00000000,
2171: /*
2172: MOVE SFBR TO DSA3
2173:
2174: at 0x0000026e : */ 0x6a130000,0x00000000,
2175: /*
2176: RETURN
2177:
2178: at 0x00000270 : */ 0x90080000,0x00000000,
2179: };
2180:
2181: #define A_NCR53c7xx_msg_abort 0x00000000
2182: u32 A_NCR53c7xx_msg_abort_used[] = {
2183: 0x00000249,
2184: };
2185:
2186: #define A_NCR53c7xx_msg_reject 0x00000000
2187: u32 A_NCR53c7xx_msg_reject_used[] = {
2188: 0x00000172,
2189: };
2190:
2191: #define A_NCR53c7xx_sink 0x00000000
2192: u32 A_NCR53c7xx_sink_used[] = {
2193: 0x00000233,
2194: 0x00000239,
2195: 0x0000023f,
2196: };
2197:
2198: #define A_NCR53c7xx_zero 0x00000000
2199: u32 A_NCR53c7xx_zero_used[] = {
2200: 0x0000022f,
2201: 0x00000245,
2202: };
2203:
2204: #define A_NOP_insn 0x00000000
2205: u32 A_NOP_insn_used[] = {
2206: 0x00000010,
2207: };
2208:
2209: #define A_addr_reconnect_dsa_head 0x00000000
2210: u32 A_addr_reconnect_dsa_head_used[] = {
2211: 0x000001a7,
2212: };
2213:
2214: #define A_addr_scratch 0x00000000
2215: u32 A_addr_scratch_used[] = {
2216: 0x00000004,
2217: 0x0000001b,
2218: 0x00000046,
2219: 0x00000067,
2220: 0x00000073,
2221: 0x000000b0,
2222: 0x000000c6,
2223: 0x00000128,
2224: 0x00000141,
2225: 0x000001a1,
2226: 0x000001ce,
2227: };
2228:
2229: #define A_addr_temp 0x00000000
2230: u32 A_addr_temp_used[] = {
2231: 0x00000025,
2232: 0x00000034,
2233: };
2234:
2235: #define A_dmode_memory_to_memory 0x00000000
2236: u32 A_dmode_memory_to_memory_used[] = {
2237: 0x00000005,
2238: 0x0000001c,
2239: 0x00000027,
2240: 0x00000035,
2241: 0x00000047,
2242: 0x00000069,
2243: 0x00000075,
2244: 0x000000b2,
2245: 0x000000c8,
2246: 0x0000012a,
2247: 0x00000143,
2248: 0x00000199,
2249: 0x000001a2,
2250: 0x000001d0,
2251: };
2252:
2253: #define A_dmode_memory_to_ncr 0x00000000
2254: u32 A_dmode_memory_to_ncr_used[] = {
2255: 0x00000000,
2256: 0x00000017,
2257: 0x00000030,
2258: 0x00000042,
2259: 0x0000019d,
2260: };
2261:
2262: #define A_dmode_ncr_to_memory 0x00000000
2263: u32 A_dmode_ncr_to_memory_used[] = {
2264: 0x00000022,
2265: 0x00000064,
2266: 0x00000070,
2267: 0x000000ad,
2268: 0x000000c3,
2269: 0x00000125,
2270: 0x0000013e,
2271: 0x000001cb,
2272: };
2273:
2274: #define A_dsa_check_reselect 0x00000000
2275: u32 A_dsa_check_reselect_used[] = {
2276: 0x000001bd,
2277: };
2278:
2279: #define A_dsa_cmdout 0x00000048
2280: u32 A_dsa_cmdout_used[] = {
2281: 0x00000094,
2282: };
2283:
2284: #define A_dsa_cmnd 0x00000038
2285: u32 A_dsa_cmnd_used[] = {
2286: };
2287:
2288: #define A_dsa_datain 0x00000054
2289: u32 A_dsa_datain_used[] = {
2290: 0x000000bb,
2291: };
2292:
2293: #define A_dsa_dataout 0x00000050
2294: u32 A_dsa_dataout_used[] = {
2295: 0x000000a5,
2296: };
2297:
2298: #define A_dsa_end 0x00000070
2299: u32 A_dsa_end_used[] = {
2300: };
2301:
2302: #define A_dsa_fields_start 0x00000000
2303: u32 A_dsa_fields_start_used[] = {
2304: };
2305:
2306: #define A_dsa_msgin 0x00000058
2307: u32 A_dsa_msgin_used[] = {
2308: 0x00000188,
2309: };
2310:
2311: #define A_dsa_msgout 0x00000040
2312: u32 A_dsa_msgout_used[] = {
2313: 0x00000086,
2314: };
2315:
2316: #define A_dsa_msgout_other 0x00000068
2317: u32 A_dsa_msgout_other_used[] = {
2318: 0x00000180,
2319: };
2320:
2321: #define A_dsa_next 0x00000030
2322: u32 A_dsa_next_used[] = {
2323: 0x0000005c,
2324: };
2325:
2326: #define A_dsa_restore_pointers 0x00000000
2327: u32 A_dsa_restore_pointers_used[] = {
2328: 0x0000012e,
2329: };
2330:
2331: #define A_dsa_save_data_pointer 0x00000000
2332: u32 A_dsa_save_data_pointer_used[] = {
2333: 0x00000115,
2334: };
2335:
2336: #define A_dsa_select 0x0000003c
2337: u32 A_dsa_select_used[] = {
2338: 0x00000081,
2339: };
2340:
2341: #define A_dsa_status 0x00000060
2342: u32 A_dsa_status_used[] = {
2343: 0x00000184,
2344: };
2345:
2346: #define A_dsa_temp_addr_array_value 0x00000000
2347: u32 A_dsa_temp_addr_array_value_used[] = {
2348: };
2349:
2350: #define A_dsa_temp_addr_dsa_value 0x00000000
2351: u32 A_dsa_temp_addr_dsa_value_used[] = {
2352: 0x00000003,
2353: };
2354:
2355: #define A_dsa_temp_addr_new_value 0x00000000
2356: u32 A_dsa_temp_addr_new_value_used[] = {
2357: };
2358:
2359: #define A_dsa_temp_addr_next 0x00000000
2360: u32 A_dsa_temp_addr_next_used[] = {
2361: 0x00000015,
2362: 0x0000004e,
2363: };
2364:
2365: #define A_dsa_temp_addr_residual 0x00000000
2366: u32 A_dsa_temp_addr_residual_used[] = {
2367: 0x0000002a,
2368: 0x00000039,
2369: };
2370:
2371: #define A_dsa_temp_addr_saved_pointer 0x00000000
2372: u32 A_dsa_temp_addr_saved_pointer_used[] = {
2373: 0x00000026,
2374: 0x00000033,
2375: };
2376:
2377: #define A_dsa_temp_addr_saved_residual 0x00000000
2378: u32 A_dsa_temp_addr_saved_residual_used[] = {
2379: 0x0000002b,
2380: 0x00000038,
2381: };
2382:
2383: #define A_dsa_temp_lun 0x00000000
2384: u32 A_dsa_temp_lun_used[] = {
2385: 0x0000004b,
2386: };
2387:
2388: #define A_dsa_temp_next 0x00000000
2389: u32 A_dsa_temp_next_used[] = {
2390: 0x0000001a,
2391: };
2392:
2393: #define A_dsa_temp_sync 0x00000000
2394: u32 A_dsa_temp_sync_used[] = {
2395: 0x00000053,
2396: };
2397:
2398: #define A_dsa_temp_target 0x00000000
2399: u32 A_dsa_temp_target_used[] = {
2400: 0x00000040,
2401: };
2402:
2403: #define A_int_debug_break 0x03000000
2404: u32 A_int_debug_break_used[] = {
2405: 0x00000217,
2406: };
2407:
2408: #define A_int_debug_panic 0x030b0000
2409: u32 A_int_debug_panic_used[] = {
2410: 0x000001e8,
2411: 0x000001f8,
2412: };
2413:
2414: #define A_int_err_check_condition 0x00030000
2415: u32 A_int_err_check_condition_used[] = {
2416: 0x00000194,
2417: };
2418:
2419: #define A_int_err_no_phase 0x00040000
2420: u32 A_int_err_no_phase_used[] = {
2421: };
2422:
2423: #define A_int_err_selected 0x00010000
2424: u32 A_int_err_selected_used[] = {
2425: 0x000001da,
2426: };
2427:
2428: #define A_int_err_unexpected_phase 0x00000000
2429: u32 A_int_err_unexpected_phase_used[] = {
2430: 0x0000008c,
2431: 0x00000092,
2432: 0x0000009a,
2433: 0x000000d0,
2434: 0x000000d4,
2435: 0x000000d6,
2436: 0x000000de,
2437: 0x000000e2,
2438: 0x000000e4,
2439: 0x000000ec,
2440: 0x000000f0,
2441: 0x000000f2,
2442: 0x000000f4,
2443: 0x0000014c,
2444: };
2445:
2446: #define A_int_err_unexpected_reselect 0x00020000
2447: u32 A_int_err_unexpected_reselect_used[] = {
2448: 0x000001ba,
2449: };
2450:
2451: #define A_int_msg_1 0x01020000
2452: u32 A_int_msg_1_used[] = {
2453: 0x0000010e,
2454: 0x00000110,
2455: };
2456:
2457: #define A_int_msg_sdtr 0x01010000
2458: u32 A_int_msg_sdtr_used[] = {
2459: 0x0000016c,
2460: };
2461:
2462: #define A_int_msg_wdtr 0x01000000
2463: u32 A_int_msg_wdtr_used[] = {
2464: 0x00000160,
2465: };
2466:
2467: #define A_int_norm_aborted 0x02040000
2468: u32 A_int_norm_aborted_used[] = {
2469: 0x0000024d,
2470: };
2471:
2472: #define A_int_norm_command_complete 0x02020000
2473: u32 A_int_norm_command_complete_used[] = {
2474: };
2475:
2476: #define A_int_norm_disconnected 0x02030000
2477: u32 A_int_norm_disconnected_used[] = {
2478: };
2479:
2480: #define A_int_norm_reselect_complete 0x02010000
2481: u32 A_int_norm_reselect_complete_used[] = {
2482: };
2483:
2484: #define A_int_norm_reset 0x02050000
2485: u32 A_int_norm_reset_used[] = {
2486: };
2487:
2488: #define A_int_norm_select_complete 0x02000000
2489: u32 A_int_norm_select_complete_used[] = {
2490: };
2491:
2492: #define A_int_test_1 0x04000000
2493: u32 A_int_test_1_used[] = {
2494: 0x000001fd,
2495: };
2496:
2497: #define A_int_test_2 0x04010000
2498: u32 A_int_test_2_used[] = {
2499: 0x00000215,
2500: };
2501:
2502: #define A_int_test_3 0x04020000
2503: u32 A_int_test_3_used[] = {
2504: };
2505:
2506: #define A_msg_buf 0x00000000
2507: u32 A_msg_buf_used[] = {
2508: 0x00000102,
2509: 0x0000014e,
2510: 0x00000158,
2511: 0x0000015e,
2512: 0x00000164,
2513: 0x0000016a,
2514: };
2515:
2516: #define A_reconnect_dsa_head 0x00000000
2517: u32 A_reconnect_dsa_head_used[] = {
2518: 0x0000006c,
2519: 0x00000074,
2520: 0x000001a0,
2521: };
2522:
2523: #define A_reselected_identify 0x00000000
2524: u32 A_reselected_identify_used[] = {
2525: 0x00000045,
2526: 0x0000019c,
2527: };
2528:
2529: #define A_reselected_tag 0x00000000
2530: u32 A_reselected_tag_used[] = {
2531: };
2532:
2533: #define A_schedule 0x00000000
2534: u32 A_schedule_used[] = {
2535: 0x0000007e,
2536: 0x00000192,
2537: 0x000001e2,
2538: 0x0000021f,
2539: };
2540:
2541: #define A_test_dest 0x00000000
2542: u32 A_test_dest_used[] = {
2543: 0x000001fb,
2544: };
2545:
2546: #define A_test_src 0x00000000
2547: u32 A_test_src_used[] = {
2548: 0x000001fa,
2549: };
2550:
2551: #define Ent_accept_message 0x000005d4
2552: #define Ent_cmdout_cmdout 0x0000024c
2553: #define Ent_command_complete 0x0000060c
2554: #define Ent_command_complete_msgin 0x0000061c
2555: #define Ent_data_transfer 0x00000254
2556: #define Ent_datain_to_jump 0x00000328
2557: #define Ent_debug_break 0x00000858
2558: #define Ent_dsa_code_begin 0x00000000
2559: #define Ent_dsa_code_check_reselect 0x000000f8
2560: #define Ent_dsa_code_fix_jump 0x0000003c
2561: #define Ent_dsa_code_restore_pointers 0x000000c0
2562: #define Ent_dsa_code_save_data_pointer 0x00000088
2563: #define Ent_dsa_code_template 0x00000000
2564: #define Ent_dsa_code_template_end 0x00000168
2565: #define Ent_dsa_schedule 0x00000168
2566: #define Ent_dsa_zero 0x00000168
2567: #define Ent_end_data_transfer 0x0000028c
2568: #define Ent_initiator_abort 0x00000880
2569: #define Ent_msg_in 0x00000404
2570: #define Ent_msg_in_restart 0x000003e4
2571: #define Ent_other_in 0x00000374
2572: #define Ent_other_out 0x0000033c
2573: #define Ent_other_transfer 0x000003ac
2574: #define Ent_reject_message 0x000005b4
2575: #define Ent_reselected_check_next 0x000006a4
2576: #define Ent_reselected_ok 0x00000750
2577: #define Ent_respond_message 0x000005ec
2578: #define Ent_select 0x000001fc
2579: #define Ent_select_msgout 0x00000214
2580: #define Ent_target_abort 0x00000860
2581: #define Ent_test_1 0x000007e4
2582: #define Ent_test_2 0x000007f8
2583: #define Ent_test_2_msgout 0x00000810
2584: #define Ent_wait_reselect 0x00000654
2585: u32 LABELPATCHES[] = {
2586: 0x00000008,
2587: 0x0000000a,
2588: 0x00000013,
2589: 0x00000016,
2590: 0x0000001f,
2591: 0x00000021,
2592: 0x0000004f,
2593: 0x00000051,
2594: 0x0000005b,
2595: 0x00000068,
2596: 0x0000006f,
2597: 0x00000082,
2598: 0x00000084,
2599: 0x0000008a,
2600: 0x0000008e,
2601: 0x00000090,
2602: 0x00000096,
2603: 0x00000098,
2604: 0x0000009c,
2605: 0x0000009e,
2606: 0x000000a0,
2607: 0x000000a2,
2608: 0x000000a4,
2609: 0x000000b1,
2610: 0x000000b6,
2611: 0x000000ba,
2612: 0x000000c7,
2613: 0x000000cc,
2614: 0x000000d2,
2615: 0x000000d8,
2616: 0x000000da,
2617: 0x000000e0,
2618: 0x000000e6,
2619: 0x000000e8,
2620: 0x000000ee,
2621: 0x000000f6,
2622: 0x000000f8,
2623: 0x00000104,
2624: 0x00000106,
2625: 0x00000108,
2626: 0x0000010a,
2627: 0x0000010c,
2628: 0x00000112,
2629: 0x00000114,
2630: 0x00000129,
2631: 0x00000142,
2632: 0x00000148,
2633: 0x00000150,
2634: 0x00000152,
2635: 0x00000154,
2636: 0x0000015a,
2637: 0x00000166,
2638: 0x00000196,
2639: 0x000001a5,
2640: 0x000001a8,
2641: 0x000001ac,
2642: 0x000001b0,
2643: 0x000001b4,
2644: 0x000001b8,
2645: 0x000001cf,
2646: 0x000001de,
2647: 0x000001e6,
2648: 0x000001ec,
2649: 0x000001ee,
2650: 0x000001f2,
2651: 0x000001f6,
2652: 0x00000201,
2653: 0x00000203,
2654: 0x00000223,
2655: 0x00000225,
2656: 0x00000227,
2657: 0x00000229,
2658: 0x0000022b,
2659: 0x0000022d,
2660: 0x00000231,
2661: 0x00000235,
2662: 0x00000237,
2663: 0x0000023b,
2664: 0x0000023d,
2665: 0x00000241,
2666: 0x00000243,
2667: };
2668:
2669: struct {
2670: u32 offset;
2671: void *address;
2672: } EXTERNAL_PATCHES[] = {
2673: };
2674:
2675: u32 INSTRUCTIONS = 301;
2676: u32 PATCHES = 81;
2677: u32 EXTERNAL_PATCHES_LEN = 0;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.