1 u32 SCRIPT[] = { 2 /* 3 4 5 ; NCR 53c810 driver, main script 6 ; Sponsored by 7 ; iX Multiuser Multitasking Magazine 8 ; hm@ix.de 9 ; 10 ; Copyright 1993, 1994, 1995 Drew Eckhardt 11 ; Visionary Computing 12 ; (Unix and Linux consulting and custom programming) 13 ; drew@PoohSticks.ORG 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 conscisely, 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 accomodate 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 accomodate 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 contataining 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_tranfer_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 discoverred, 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 ; hasnt 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 allready 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 accomodate 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;