53c7,8xx.scr
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:38k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #undef DEBUG
  2. #undef EVENTS
  3. ; NCR 53c810 driver, main script
  4. ; Sponsored by 
  5. ; iX Multiuser Multitasking Magazine
  6. ; hm@ix.de
  7. ;
  8. ; Copyright 1993, 1994, 1995 Drew Eckhardt
  9. ;      Visionary Computing 
  10. ;      (Unix and Linux consulting and custom programming)
  11. ;      drew@PoohSticks.ORG
  12. ;      +1 (303) 786-7975
  13. ;
  14. ; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
  15. ;
  16. ; PRE-ALPHA
  17. ;
  18. ; For more information, please consult 
  19. ;
  20. ; NCR 53C810
  21. ; PCI-SCSI I/O Processor
  22. ; Data Manual
  23. ;
  24. ; NCR 53C710 
  25. ; SCSI I/O Processor
  26. ; Programmers Guide
  27. ;
  28. ; NCR Microelectronics
  29. ; 1635 Aeroplaza Drive
  30. ; Colorado Springs, CO 80916
  31. ; 1+ (719) 578-3400
  32. ;
  33. ; Toll free literature number
  34. ; +1 (800) 334-5454
  35. ;
  36. ; IMPORTANT : This code is self modifying due to the limitations of 
  37. ; the NCR53c7,8xx series chips.  Persons debugging this code with
  38. ; the remote debugger should take this into account, and NOT set
  39. ; breakpoints in modified instructions.
  40. ;
  41. ; Design:
  42. ; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard 
  43. ; microcontroller using a simple instruction set.   
  44. ;
  45. ; So, to minimize the effects of interrupt latency, and to maximize 
  46. ; throughput, this driver offloads the practical maximum amount 
  47. ; of processing to the SCSI chip while still maintaining a common
  48. ; structure.
  49. ;
  50. ; Where tradeoffs were needed between efficiency on the older
  51. ; chips and the newer NCR53c800 series, the NCR53c800 series 
  52. ; was chosen.
  53. ;
  54. ; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
  55. ; automate SCSI transfers without host processor intervention, this 
  56. ; isn't the case with the NCR53c710 and newer chips which allow 
  57. ;
  58. ; - reads and writes to the internal registers from within the SCSI
  59. ;  scripts, allowing the SCSI SCRIPTS(tm) code to save processor
  60. ;  state so that multiple threads of execution are possible, and also
  61. ;  provide an ALU for loop control, etc.
  62. ; - table indirect addressing for some instructions. This allows 
  63. ; pointers to be located relative to the DSA ((Data Structure
  64. ; Address) register.
  65. ;
  66. ; These features make it possible to implement a mailbox style interface,
  67. ; where the same piece of code is run to handle I/O for multiple threads
  68. ; at once minimizing our need to relocate code.  Since the NCR53c700/
  69. ; NCR53c800 series have a unique combination of features, making a 
  70. ; a standard ingoing/outgoing mailbox system, costly, I've modified it.
  71. ;
  72. ; - Mailboxes are a mixture of code and data.  This lets us greatly
  73. ;  simplify the NCR53c810 code and do things that would otherwise
  74. ; not be possible.
  75. ;
  76. ; The saved data pointer is now implemented as follows :
  77. ;
  78. ;  Control flow has been architected such that if control reaches
  79. ; munge_save_data_pointer, on a restore pointers message or 
  80. ; reconnection, a jump to the address formerly in the TEMP register
  81. ; will allow the SCSI command to resume execution.
  82. ;
  83. ;
  84. ; Note : the DSA structures must be aligned on 32 bit boundaries,
  85. ; since the source and destination of MOVE MEMORY instructions 
  86. ; must share the same alignment and this is the alignment of the
  87. ; NCR registers.
  88. ;
  89. ABSOLUTE dsa_temp_lun = 0 ; Patch to lun for current dsa
  90. ABSOLUTE dsa_temp_next = 0 ; Patch to dsa next for current dsa
  91. ABSOLUTE dsa_temp_addr_next = 0 ; Patch to address of dsa next address 
  92. ;  for current dsa
  93. ABSOLUTE dsa_temp_sync = 0 ; Patch to address of per-target
  94. ; sync routine
  95. ABSOLUTE dsa_temp_target = 0 ; Patch to id for current dsa
  96. ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
  97. ;  saved data pointer
  98. ABSOLUTE dsa_temp_addr_residual = 0 ; Patch to address of per-command
  99. ; current residual code
  100. ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
  101. ; saved residual code
  102. ABSOLUTE dsa_temp_addr_new_value = 0 ; Address of value for JUMP operand
  103. ABSOLUTE dsa_temp_addr_array_value = 0  ; Address to copy to
  104. ABSOLUTE dsa_temp_addr_dsa_value = 0 ; Address of this DSA value
  105. ;
  106. ; Once a device has initiated reselection, we need to compare it 
  107. ; against the singly linked list of commands which have disconnected
  108. ; and are pending reselection.  These commands are maintained in 
  109. ; an unordered singly linked list of DSA structures, through the
  110. ; DSA pointers at their 'centers' headed by the reconnect_dsa_head
  111. ; pointer.
  112. ; To avoid complications in removing commands from the list,
  113. ; I minimize the amount of expensive (at eight operations per
  114. ; addition @ 500-600ns each) pointer operations which must
  115. ; be done in the NCR driver by precomputing them on the 
  116. ; host processor during dsa structure generation.
  117. ;
  118. ; The fixed-up per DSA code knows how to recognize the nexus
  119. ; associated with the corresponding SCSI command, and modifies
  120. ; the source and destination pointers for the MOVE MEMORY 
  121. ; instruction which is executed when reselected_ok is called
  122. ; to remove the command from the list.  Similarly, DSA is 
  123. ; loaded with the address of the next DSA structure and
  124. ; reselected_check_next is called if a failure occurs.
  125. ;
  126. ; Perhaps more concisely, the net effect of the mess is 
  127. ;
  128. ; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head, 
  129. ;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
  130. ;  src = &dsa->next;
  131. ;  if (target_id == dsa->id && target_lun == dsa->lun) {
  132. ;  *dest = *src;
  133. ;  break;
  134. ;         }
  135. ; }
  136. ;
  137. ; if (!dsa)
  138. ;           error (int_err_unexpected_reselect);
  139. ; else  
  140. ;     longjmp (dsa->jump_resume, 0);
  141. ;
  142. #if (CHIP != 700) && (CHIP != 70066)
  143. ; Define DSA structure used for mailboxes
  144. ENTRY dsa_code_template
  145. dsa_code_template:
  146. ENTRY dsa_code_begin
  147. dsa_code_begin:
  148. MOVE dmode_memory_to_ncr TO DMODE
  149. MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
  150. MOVE dmode_memory_to_memory TO DMODE
  151. CALL scratch_to_dsa
  152. CALL select
  153. ; Handle the phase mismatch which may have resulted from the 
  154. ; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN 
  155. ; may or may not be necessary, and we should update script_asm.pl
  156. ; to handle multiple pieces.
  157.     CLEAR ATN
  158.     CLEAR ACK
  159. ; Replace second operand with address of JUMP instruction dest operand
  160. ; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
  161. ENTRY dsa_code_fix_jump
  162. dsa_code_fix_jump:
  163. MOVE MEMORY 4, NOP_insn, 0
  164. JUMP select_done
  165. ; wrong_dsa loads the DSA register with the value of the dsa_next
  166. ; field.
  167. ;
  168. wrong_dsa:
  169. ; Patch the MOVE MEMORY INSTRUCTION such that 
  170. ; the destination address is the address of the OLD 
  171. ; next pointer.
  172. ;
  173. MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 8
  174. MOVE dmode_memory_to_ncr TO DMODE
  175. ;
  176. ;  Move the _contents_ of the next pointer into the DSA register as 
  177. ; the next I_T_L or I_T_L_Q tupple to check against the established
  178. ; nexus.
  179. ;
  180. MOVE MEMORY 4, dsa_temp_next, addr_scratch
  181. MOVE dmode_memory_to_memory TO DMODE
  182. CALL scratch_to_dsa
  183. JUMP reselected_check_next
  184. ABSOLUTE dsa_save_data_pointer = 0
  185. ENTRY dsa_code_save_data_pointer
  186. dsa_code_save_data_pointer:
  187.      MOVE dmode_ncr_to_memory TO DMODE
  188.      MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer
  189.      MOVE dmode_memory_to_memory TO DMODE
  190. ; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
  191.      MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
  192.         CLEAR ACK
  193. #ifdef DEBUG
  194.         INT int_debug_saved
  195. #endif
  196.      RETURN
  197. ABSOLUTE dsa_restore_pointers = 0
  198. ENTRY dsa_code_restore_pointers
  199. dsa_code_restore_pointers:
  200.      MOVE dmode_memory_to_ncr TO DMODE
  201.      MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp
  202.      MOVE dmode_memory_to_memory TO DMODE
  203. ; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
  204.      MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
  205.         CLEAR ACK
  206. #ifdef DEBUG
  207.         INT int_debug_restored
  208. #endif
  209.      RETURN
  210. ABSOLUTE dsa_check_reselect = 0
  211. ; dsa_check_reselect determines whether or not the current target and
  212. ; lun match the current DSA
  213. ENTRY dsa_code_check_reselect
  214. dsa_code_check_reselect:
  215. MOVE SSID TO SFBR ; SSID contains 3 bit target ID
  216. ; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
  217. JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8
  218. ;
  219. ; Hack - move to scratch first, since SFBR is not writeable
  220. ;  via the CPU and hence a MOVE MEMORY instruction.
  221. ;
  222. MOVE dmode_memory_to_ncr TO DMODE
  223. MOVE MEMORY 1, reselected_identify, addr_scratch
  224. MOVE dmode_memory_to_memory TO DMODE
  225. MOVE SCRATCH0 TO SFBR
  226. ; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
  227. JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
  228. ; Patch the MOVE MEMORY INSTRUCTION such that
  229. ; the source address is the address of this dsa's
  230. ; next pointer.
  231. MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 4
  232. CALL reselected_ok
  233. CALL dsa_temp_sync
  234. ; Release ACK on the IDENTIFY message _after_ we've set the synchronous 
  235. ; transfer parameters! 
  236. CLEAR ACK
  237. ; Implicitly restore pointers on reselection, so a RETURN
  238. ; will transfer control back to the right spot.
  239.      CALL REL (dsa_code_restore_pointers)
  240.      RETURN
  241. ENTRY dsa_zero
  242. dsa_zero:
  243. ENTRY dsa_code_template_end
  244. dsa_code_template_end:
  245. ; Perform sanity check for dsa_fields_start == dsa_code_template_end - 
  246. ; dsa_zero, puke.
  247. ABSOLUTE dsa_fields_start =  0 ; Sanity marker
  248. ;  pad 48 bytes (fix this RSN)
  249. ABSOLUTE dsa_next = 48 ; len 4 Next DSA
  250.   ; del 4 Previous DSA address
  251. ABSOLUTE dsa_cmnd = 56 ; len 4 Scsi_Cmnd * for this thread.
  252. ABSOLUTE dsa_select = 60 ; len 4 Device ID, Period, Offset for 
  253.   ; table indirect select
  254. ABSOLUTE dsa_msgout = 64 ; len 8 table indirect move parameter for 
  255. ;       select message
  256. ABSOLUTE dsa_cmdout = 72 ; len 8 table indirect move parameter for 
  257. ; command
  258. ABSOLUTE dsa_dataout = 80 ; len 4 code pointer for dataout
  259. ABSOLUTE dsa_datain = 84 ; len 4 code pointer for datain
  260. ABSOLUTE dsa_msgin = 88 ; len 8 table indirect move for msgin
  261. ABSOLUTE dsa_status = 96  ; len 8 table indirect move for status byte
  262. ABSOLUTE dsa_msgout_other = 104 ; len 8 table indirect for normal message out
  263. ; (Synchronous transfer negotiation, etc).
  264. ABSOLUTE dsa_end = 112
  265. ABSOLUTE schedule = 0  ; Array of JUMP dsa_begin or JUMP (next),
  266. ; terminated by a call to JUMP wait_reselect
  267. ; Linked lists of DSA structures
  268. ABSOLUTE reconnect_dsa_head = 0 ; Link list of DSAs which can reconnect
  269. ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
  270. ; address of reconnect_dsa_head
  271. ; These select the source and destination of a MOVE MEMORY instruction
  272. ABSOLUTE dmode_memory_to_memory = 0x0
  273. ABSOLUTE dmode_memory_to_ncr = 0x0
  274. ABSOLUTE dmode_ncr_to_memory = 0x0
  275. ABSOLUTE addr_scratch = 0x0
  276. ABSOLUTE addr_temp = 0x0
  277. #endif /* CHIP != 700 && CHIP != 70066 */
  278. ; Interrupts - 
  279. ; MSB indicates type
  280. ; 0 handle error condition
  281. ; 1  handle message 
  282. ; 2  handle normal condition
  283. ; 3 debugging interrupt
  284. ; 4  testing interrupt 
  285. ; Next byte indicates specific error
  286. ; XXX not yet implemented, I'm not sure if I want to - 
  287. ; Next byte indicates the routine the error occurred in
  288. ; The LSB indicates the specific place the error occurred
  289.  
  290. ABSOLUTE int_err_unexpected_phase = 0x00000000 ; Unexpected phase encountered
  291. ABSOLUTE int_err_selected = 0x00010000 ; SELECTED (nee RESELECTED)
  292. ABSOLUTE int_err_unexpected_reselect = 0x00020000 
  293. ABSOLUTE int_err_check_condition = 0x00030000
  294. ABSOLUTE int_err_no_phase = 0x00040000
  295. ABSOLUTE int_msg_wdtr = 0x01000000 ; WDTR message received
  296. ABSOLUTE int_msg_sdtr = 0x01010000 ; SDTR received
  297. ABSOLUTE int_msg_1 = 0x01020000 ; single byte special message
  298. ; received
  299. ABSOLUTE int_norm_select_complete = 0x02000000 ; Select complete, reprogram
  300. ; registers.
  301. ABSOLUTE int_norm_reselect_complete = 0x02010000 ; Nexus established
  302. ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
  303. ABSOLUTE int_norm_disconnected = 0x02030000 ; Disconnected 
  304. ABSOLUTE int_norm_aborted =0x02040000 ; Aborted *dsa
  305. ABSOLUTE int_norm_reset = 0x02050000 ; Generated BUS reset.
  306. ABSOLUTE int_debug_break = 0x03000000 ; Break point
  307. #ifdef DEBUG
  308. ABSOLUTE int_debug_scheduled = 0x03010000 ; new I/O scheduled 
  309. ABSOLUTE int_debug_idle = 0x03020000 ; scheduler is idle
  310. ABSOLUTE int_debug_dsa_loaded = 0x03030000 ; dsa reloaded
  311. ABSOLUTE int_debug_reselected = 0x03040000 ; NCR reselected
  312. ABSOLUTE int_debug_head = 0x03050000 ; issue head overwritten
  313. ABSOLUTE int_debug_disconnected = 0x03060000 ; disconnected
  314. ABSOLUTE int_debug_disconnect_msg = 0x03070000 ; got message to disconnect
  315. ABSOLUTE int_debug_dsa_schedule = 0x03080000 ; in dsa_schedule
  316. ABSOLUTE int_debug_reselect_check = 0x03090000  ; Check for reselection of DSA
  317. ABSOLUTE int_debug_reselected_ok = 0x030a0000  ; Reselection accepted
  318. #endif
  319. ABSOLUTE int_debug_panic = 0x030b0000 ; Panic driver
  320. #ifdef DEBUG
  321. ABSOLUTE int_debug_saved = 0x030c0000  ; save/restore pointers
  322. ABSOLUTE int_debug_restored = 0x030d0000
  323. ABSOLUTE int_debug_sync = 0x030e0000 ; Sanity check synchronous 
  324. ; parameters. 
  325. ABSOLUTE int_debug_datain = 0x030f0000 ; going into data in phase 
  326. ; now.
  327. ABSOLUTE int_debug_check_dsa = 0x03100000 ; Sanity check DSA against
  328. ; SDID.
  329. #endif
  330. ABSOLUTE int_test_1 = 0x04000000 ; Test 1 complete
  331. ABSOLUTE int_test_2 = 0x04010000 ; Test 2 complete
  332. ABSOLUTE int_test_3 = 0x04020000 ; Test 3 complete
  333. ; These should start with 0x05000000, with low bits incrementing for 
  334. ; each one.
  335. #ifdef EVENTS
  336. ABSOLUTE int_EVENT_SELECT = 0
  337. ABSOLUTE int_EVENT_DISCONNECT = 0
  338. ABSOLUTE int_EVENT_RESELECT = 0
  339. ABSOLUTE int_EVENT_COMPLETE = 0
  340. ABSOLUTE int_EVENT_IDLE = 0
  341. ABSOLUTE int_EVENT_SELECT_FAILED = 0
  342. ABSOLUTE int_EVENT_BEFORE_SELECT = 0
  343. ABSOLUTE int_EVENT_RESELECT_FAILED = 0
  344. #endif
  345. ABSOLUTE NCR53c7xx_msg_abort = 0 ; Pointer to abort message
  346. ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
  347. ABSOLUTE NCR53c7xx_zero = 0 ; long with zero in it, use for source
  348. ABSOLUTE NCR53c7xx_sink = 0 ; long to dump worthless data in
  349. ABSOLUTE NOP_insn = 0 ; NOP instruction
  350. ; Pointer to message, potentially multi-byte
  351. ABSOLUTE msg_buf = 0
  352. ; Pointer to holding area for reselection information
  353. ABSOLUTE reselected_identify = 0
  354. ABSOLUTE reselected_tag = 0
  355. ; Request sense command pointer, it's a 6 byte command, should
  356. ; be constant for all commands since we always want 16 bytes of 
  357. ; sense and we don't need to change any fields as we did under 
  358. ; SCSI-I when we actually cared about the LUN field.
  359. ;EXTERNAL NCR53c7xx_sense ; Request sense command
  360. #if (CHIP != 700) && (CHIP != 70066)
  361. ; dsa_schedule  
  362. ; PURPOSE : after a DISCONNECT message has been received, and pointers
  363. ; saved, insert the current DSA structure at the head of the 
  364. ;  disconnected queue and fall through to the scheduler.
  365. ;
  366. ; CALLS : OK
  367. ;
  368. ; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
  369. ; of disconnected commands
  370. ;
  371. ; MODIFIES : SCRATCH, reconnect_dsa_head
  372. ; EXITS : always passes control to schedule
  373. ENTRY dsa_schedule
  374. dsa_schedule:
  375. #if 0
  376.     INT int_debug_dsa_schedule
  377. #endif
  378. ;
  379. ; Calculate the address of the next pointer within the DSA 
  380. ; structure of the command that is currently disconnecting
  381. ;
  382.     CALL dsa_to_scratch
  383.     MOVE SCRATCH0 + dsa_next TO SCRATCH0
  384.     MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
  385.     MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
  386.     MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
  387. ; Point the next field of this DSA structure at the current disconnected 
  388. ; list
  389.     MOVE dmode_ncr_to_memory TO DMODE
  390.     MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
  391.     MOVE dmode_memory_to_memory TO DMODE
  392. dsa_schedule_insert:
  393.     MOVE MEMORY 4, reconnect_dsa_head, 0 
  394. ; And update the head pointer.
  395.     CALL dsa_to_scratch
  396.     MOVE dmode_ncr_to_memory TO DMODE
  397.     MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
  398.     MOVE dmode_memory_to_memory TO DMODE
  399. /* Temporarily, see what happens. */
  400. #ifndef ORIGINAL
  401.     MOVE SCNTL2 & 0x7f TO SCNTL2
  402.     CLEAR ACK
  403. #endif
  404.     WAIT DISCONNECT
  405. #ifdef EVENTS
  406.     INT int_EVENT_DISCONNECT;
  407. #endif
  408. #if 0
  409.     INT int_debug_disconnected
  410. #endif
  411.     JUMP schedule
  412. #endif 
  413. ;
  414. ; select
  415. ;
  416. ; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
  417. ; On success, the current DSA structure is removed from the issue 
  418. ; queue.  Usually, this is entered as a fall-through from schedule,
  419. ; although the contingent allegiance handling code will write
  420. ; the select entry address to the DSP to restart a command as a 
  421. ; REQUEST SENSE.  A message is sent (usually IDENTIFY, although
  422. ; additional SDTR or WDTR messages may be sent).  COMMAND OUT
  423. ; is handled.
  424. ;
  425. ; INPUTS : DSA - SCSI command, issue_dsa_head
  426. ;
  427. ; CALLS : NOT OK
  428. ;
  429. ; MODIFIES : SCRATCH, issue_dsa_head
  430. ;
  431. ; EXITS : on reselection or selection, go to select_failed
  432. ; otherwise, RETURN so control is passed back to 
  433. ; dsa_begin.
  434. ;
  435. ENTRY select
  436. select:
  437. #if 0
  438. #ifdef EVENTS
  439.     INT int_EVENT_BEFORE_SELECT
  440. #endif
  441. #endif
  442. #if 0
  443. #ifdef DEBUG
  444.     INT int_debug_scheduled
  445. #endif
  446. #endif
  447.     CLEAR TARGET
  448. ; XXX
  449. ;
  450. ; In effect, SELECTION operations are backgrounded, with execution
  451. ; continuing until code which waits for REQ or a fatal interrupt is 
  452. ; encountered.
  453. ;
  454. ; So, for more performance, we could overlap the code which removes 
  455. ; the command from the NCRs issue queue with the selection, but 
  456. ; at this point I don't want to deal with the error recovery.
  457. ;
  458. #if (CHIP != 700) && (CHIP != 70066)
  459.     SELECT ATN FROM dsa_select, select_failed
  460.     JUMP select_msgout, WHEN MSG_OUT
  461. ENTRY select_msgout
  462. select_msgout:
  463.     MOVE FROM dsa_msgout, WHEN MSG_OUT
  464. #else
  465. ENTRY select_msgout
  466.     SELECT ATN 0, select_failed
  467. select_msgout:
  468.     MOVE 0, 0, WHEN MSGOUT
  469. #endif
  470. #ifdef EVENTS
  471.    INT int_EVENT_SELECT
  472. #endif
  473.    RETURN
  474. ; select_done
  475. ; PURPOSE: continue on to normal data transfer; called as the exit 
  476. ; point from dsa_begin.
  477. ;
  478. ; INPUTS: dsa
  479. ;
  480. ; CALLS: OK
  481. ;
  482. ;
  483. select_done:
  484. #ifdef DEBUG
  485. ENTRY select_check_dsa
  486. select_check_dsa:
  487.     INT int_debug_check_dsa
  488. #endif
  489. ; After a successful selection, we should get either a CMD phase or 
  490. ; some transfer request negotiation message.
  491.     JUMP cmdout, WHEN CMD
  492.     INT int_err_unexpected_phase, WHEN NOT MSG_IN 
  493. select_msg_in:
  494.     CALL msg_in, WHEN MSG_IN
  495.     JUMP select_msg_in, WHEN MSG_IN
  496. cmdout:
  497.     INT int_err_unexpected_phase, WHEN NOT CMD
  498. #if (CHIP == 700)
  499.     INT int_norm_selected
  500. #endif
  501. ENTRY cmdout_cmdout
  502. cmdout_cmdout:
  503. #if (CHIP != 700) && (CHIP != 70066)
  504.     MOVE FROM dsa_cmdout, WHEN CMD
  505. #else
  506.     MOVE 0, 0, WHEN CMD
  507. #endif /* (CHIP != 700) && (CHIP != 70066) */
  508. ;
  509. ; data_transfer  
  510. ; other_out
  511. ; other_in
  512. ; other_transfer
  513. ;
  514. ; PURPOSE : handle the main data transfer for a SCSI command in 
  515. ; several parts.  In the first part, data_transfer, DATA_IN
  516. ; and DATA_OUT phases are allowed, with the user provided
  517. ; code (usually dynamically generated based on the scatter/gather
  518. ; list associated with a SCSI command) called to handle these 
  519. ; phases.
  520. ;
  521. ; After control has passed to one of the user provided 
  522. ; DATA_IN or DATA_OUT routines, back calls are made to 
  523. ; other_transfer_in or other_transfer_out to handle non-DATA IN
  524. ; and DATA OUT phases respectively, with the state of the active
  525. ; data pointer being preserved in TEMP.
  526. ;
  527. ; On completion, the user code passes control to other_transfer
  528. ; which causes DATA_IN and DATA_OUT to result in unexpected_phase
  529. ; interrupts so that data overruns may be trapped.
  530. ;
  531. ; INPUTS : DSA - SCSI command
  532. ;
  533. ; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
  534. ; other_transfer
  535. ;
  536. ; MODIFIES : SCRATCH
  537. ;
  538. ; EXITS : if STATUS IN is detected, signifying command completion,
  539. ; the NCR jumps to command_complete.  If MSG IN occurs, a 
  540. ; CALL is made to msg_in.  Otherwise, other_transfer runs in 
  541. ; an infinite loop.
  542. ;
  543. ENTRY data_transfer
  544. data_transfer:
  545.     JUMP cmdout_cmdout, WHEN CMD
  546.     CALL msg_in, WHEN MSG_IN
  547.     INT int_err_unexpected_phase, WHEN MSG_OUT
  548.     JUMP do_dataout, WHEN DATA_OUT
  549.     JUMP do_datain, WHEN DATA_IN
  550.     JUMP command_complete, WHEN STATUS
  551.     JUMP data_transfer
  552. ENTRY end_data_transfer
  553. end_data_transfer:
  554. ;
  555. ; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain 
  556. ; should be fixed up whenever the nexus changes so it can point to the 
  557. ; correct routine for that command.
  558. ;
  559. #if (CHIP != 700) && (CHIP != 70066)
  560. ; Nasty jump to dsa->dataout
  561. do_dataout:
  562.     CALL dsa_to_scratch
  563.     MOVE SCRATCH0 + dsa_dataout TO SCRATCH0
  564.     MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
  565.     MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
  566.     MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
  567.     MOVE dmode_ncr_to_memory TO DMODE
  568.     MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
  569.     MOVE dmode_memory_to_memory TO DMODE
  570. dataout_to_jump:
  571.     MOVE MEMORY 4, 0, dataout_jump + 4 
  572. dataout_jump:
  573.     JUMP 0
  574. ; Nasty jump to dsa->dsain
  575. do_datain:
  576.     CALL dsa_to_scratch
  577.     MOVE SCRATCH0 + dsa_datain TO SCRATCH0
  578.     MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY 
  579.     MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY 
  580.     MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY 
  581.     MOVE dmode_ncr_to_memory TO DMODE
  582.     MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
  583.     MOVE dmode_memory_to_memory TO DMODE
  584. ENTRY datain_to_jump
  585. datain_to_jump:
  586.     MOVE MEMORY 4, 0, datain_jump + 4
  587. #if 0
  588.     INT int_debug_datain
  589. #endif
  590. datain_jump:
  591.     JUMP 0
  592. #endif /* (CHIP != 700) && (CHIP != 70066) */
  593. ; Note that other_out and other_in loop until a non-data phase
  594. ; is discovered, so we only execute return statements when we
  595. ; can go on to the next data phase block move statement.
  596. ENTRY other_out
  597. other_out:
  598. #if 0
  599.     INT 0x03ffdead
  600. #endif
  601.     INT int_err_unexpected_phase, WHEN CMD
  602.     JUMP msg_in_restart, WHEN MSG_IN 
  603.     INT int_err_unexpected_phase, WHEN MSG_OUT
  604.     INT int_err_unexpected_phase, WHEN DATA_IN
  605.     JUMP command_complete, WHEN STATUS
  606.     JUMP other_out, WHEN NOT DATA_OUT
  607.     RETURN
  608. ENTRY other_in
  609. other_in:
  610. #if 0
  611.     INT 0x03ffdead
  612. #endif
  613.     INT int_err_unexpected_phase, WHEN CMD
  614.     JUMP msg_in_restart, WHEN MSG_IN 
  615.     INT int_err_unexpected_phase, WHEN MSG_OUT
  616.     INT int_err_unexpected_phase, WHEN DATA_OUT
  617.     JUMP command_complete, WHEN STATUS
  618.     JUMP other_in, WHEN NOT DATA_IN
  619.     RETURN
  620. ENTRY other_transfer
  621. other_transfer:
  622.     INT int_err_unexpected_phase, WHEN CMD
  623.     CALL msg_in, WHEN MSG_IN
  624.     INT int_err_unexpected_phase, WHEN MSG_OUT
  625.     INT int_err_unexpected_phase, WHEN DATA_OUT
  626.     INT int_err_unexpected_phase, WHEN DATA_IN
  627.     JUMP command_complete, WHEN STATUS
  628.     JUMP other_transfer
  629. ;
  630. ; msg_in_restart
  631. ; msg_in
  632. ; munge_msg
  633. ;
  634. ; PURPOSE : process messages from a target.  msg_in is called when the 
  635. ; caller hasn't read the first byte of the message.  munge_message
  636. ; is called when the caller has read the first byte of the message,
  637. ; and left it in SFBR.  msg_in_restart is called when the caller 
  638. ; hasn't read the first byte of the message, and wishes RETURN
  639. ; to transfer control back to the address of the conditional
  640. ; CALL instruction rather than to the instruction after it.
  641. ;
  642. ; Various int_* interrupts are generated when the host system
  643. ; needs to intervene, as is the case with SDTR, WDTR, and
  644. ; INITIATE RECOVERY messages.
  645. ;
  646. ; When the host system handles one of these interrupts,
  647. ; it can respond by reentering at reject_message, 
  648. ; which rejects the message and returns control to
  649. ; the caller of msg_in or munge_msg, accept_message
  650. ; which clears ACK and returns control, or reply_message
  651. ; which sends the message pointed to by the DSA 
  652. ; msgout_other table indirect field.
  653. ;
  654. ; DISCONNECT messages are handled by moving the command
  655. ; to the reconnect_dsa_queue.
  656. ;
  657. ; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
  658. ; only)
  659. ;
  660. ; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
  661. ;
  662. ; MODIFIES : SCRATCH, DSA on DISCONNECT
  663. ;
  664. ; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
  665. ; and normal return from message handlers running under
  666. ; Linux, control is returned to the caller.  Receipt
  667. ; of DISCONNECT messages pass control to dsa_schedule.
  668. ;
  669. ENTRY msg_in_restart
  670. msg_in_restart:
  671. ; XXX - hackish
  672. ;
  673. ; Since it's easier to debug changes to the statically 
  674. ; compiled code, rather than the dynamically generated 
  675. ; stuff, such as
  676. ;
  677. ;  MOVE x, y, WHEN data_phase
  678. ;  CALL other_z, WHEN NOT data_phase
  679. ;  MOVE x, y, WHEN data_phase
  680. ;
  681. ; I'd like to have certain routines (notably the message handler)
  682. ; restart on the conditional call rather than the next instruction.
  683. ;
  684. ; So, subtract 8 from the return address
  685.     MOVE TEMP0 + 0xf8 TO TEMP0
  686.     MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
  687.     MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
  688.     MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
  689. ENTRY msg_in
  690. msg_in:
  691.     MOVE 1, msg_buf, WHEN MSG_IN
  692. munge_msg:
  693.     JUMP munge_extended, IF 0x01 ; EXTENDED MESSAGE
  694.     JUMP munge_2, IF 0x20, AND MASK 0xdf ; two byte message
  695. ;
  696. ; XXX - I've seen a handful of broken SCSI devices which fail to issue
  697. ;  a SAVE POINTERS message before disconnecting in the middle of 
  698. ;  a transfer, assuming that the DATA POINTER will be implicitly 
  699. ;  restored.  
  700. ;
  701. ; Historically, I've often done an implicit save when the DISCONNECT
  702. ; message is processed.  We may want to consider having the option of 
  703. ; doing that here. 
  704. ;
  705.     JUMP munge_save_data_pointer, IF 0x02 ; SAVE DATA POINTER
  706.     JUMP munge_restore_pointers, IF 0x03 ; RESTORE POINTERS 
  707.     JUMP munge_disconnect, IF 0x04 ; DISCONNECT
  708.     INT int_msg_1, IF 0x07 ; MESSAGE REJECT
  709.     INT int_msg_1, IF 0x0f ; INITIATE RECOVERY
  710. #ifdef EVENTS 
  711.     INT int_EVENT_SELECT_FAILED 
  712. #endif
  713.     JUMP reject_message
  714. munge_2:
  715.     JUMP reject_message
  716. ;
  717. ; The SCSI standard allows targets to recover from transient 
  718. ; error conditions by backing up the data pointer with a 
  719. ; RESTORE POINTERS message.  
  720. ;
  721. ; So, we must save and restore the _residual_ code as well as 
  722. ; the current instruction pointer.  Because of this messiness,
  723. ; it is simpler to put dynamic code in the dsa for this and to
  724. ; just do a simple jump down there. 
  725. ;
  726. munge_save_data_pointer:
  727.     MOVE DSA0 + dsa_save_data_pointer TO SFBR
  728.     MOVE SFBR TO SCRATCH0
  729.     MOVE DSA1 + 0xff TO SFBR WITH CARRY
  730.     MOVE SFBR TO SCRATCH1
  731.     MOVE DSA2 + 0xff TO SFBR WITH CARRY 
  732.     MOVE SFBR TO SCRATCH2
  733.     MOVE DSA3 + 0xff TO SFBR WITH CARRY
  734.     MOVE SFBR TO SCRATCH3
  735.     MOVE dmode_ncr_to_memory TO DMODE
  736.     MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
  737.     MOVE dmode_memory_to_memory TO DMODE
  738. jump_dsa_save:
  739.     JUMP 0
  740. munge_restore_pointers:
  741.     MOVE DSA0 + dsa_restore_pointers TO SFBR
  742.     MOVE SFBR TO SCRATCH0
  743.     MOVE DSA1 + 0xff TO SFBR WITH CARRY
  744.     MOVE SFBR TO SCRATCH1
  745.     MOVE DSA2 + 0xff TO SFBR WITH CARRY
  746.     MOVE SFBR TO SCRATCH2
  747.     MOVE DSA3 + 0xff TO SFBR WITH CARRY
  748.     MOVE SFBR TO SCRATCH3
  749.     MOVE dmode_ncr_to_memory TO DMODE
  750.     MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
  751.     MOVE dmode_memory_to_memory TO DMODE
  752. jump_dsa_restore:
  753.     JUMP 0
  754. munge_disconnect:
  755. #if 0
  756.     INT int_debug_disconnect_msg
  757. #endif
  758. /* 
  759.  * Before, we overlapped processing with waiting for disconnect, but
  760.  * debugging was beginning to appear messy.  Temporarily move things
  761.  * to just before the WAIT DISCONNECT.
  762.  */
  763.  
  764. #ifdef ORIGINAL
  765.     MOVE SCNTL2 & 0x7f TO SCNTL2
  766.     CLEAR ACK
  767. #endif
  768. #if (CHIP != 700) && (CHIP != 70066)
  769.     JUMP dsa_schedule
  770. #else
  771.     WAIT DISCONNECT
  772.     INT int_norm_disconnected
  773. #endif
  774. munge_extended:
  775.     CLEAR ACK
  776.     INT int_err_unexpected_phase, WHEN NOT MSG_IN
  777.     MOVE 1, msg_buf + 1, WHEN MSG_IN
  778.     JUMP munge_extended_2, IF 0x02
  779.     JUMP munge_extended_3, IF 0x03 
  780.     JUMP reject_message
  781. munge_extended_2:
  782.     CLEAR ACK
  783.     MOVE 1, msg_buf + 2, WHEN MSG_IN
  784.     JUMP reject_message, IF NOT 0x02 ; Must be WDTR
  785.     CLEAR ACK
  786.     MOVE 1, msg_buf + 3, WHEN MSG_IN
  787.     INT int_msg_wdtr
  788. munge_extended_3:
  789.     CLEAR ACK
  790.     MOVE 1, msg_buf + 2, WHEN MSG_IN
  791.     JUMP reject_message, IF NOT 0x01 ; Must be SDTR
  792.     CLEAR ACK
  793.     MOVE 2, msg_buf + 3, WHEN MSG_IN
  794.     INT int_msg_sdtr
  795. ENTRY reject_message
  796. reject_message:
  797.     SET ATN
  798.     CLEAR ACK
  799.     MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
  800.     RETURN
  801. ENTRY accept_message
  802. accept_message:
  803.     CLEAR ATN
  804.     CLEAR ACK
  805.     RETURN
  806. ENTRY respond_message
  807. respond_message:
  808.     SET ATN
  809.     CLEAR ACK
  810.     MOVE FROM dsa_msgout_other, WHEN MSG_OUT
  811.     RETURN
  812. ;
  813. ; command_complete
  814. ;
  815. ; PURPOSE : handle command termination when STATUS IN is detected by reading
  816. ; a status byte followed by a command termination message. 
  817. ;
  818. ; Normal termination results in an INTFLY instruction, and 
  819. ; the host system can pick out which command terminated by 
  820. ; examining the MESSAGE and STATUS buffers of all currently 
  821. ; executing commands;
  822. ;
  823. ; Abnormal (CHECK_CONDITION) termination results in an
  824. ; int_err_check_condition interrupt so that a REQUEST SENSE
  825. ; command can be issued out-of-order so that no other command
  826. ; clears the contingent allegiance condition.
  827. ;
  828. ;
  829. ; INPUTS : DSA - command
  830. ;
  831. ; CALLS : OK
  832. ;
  833. ; EXITS : On successful termination, control is passed to schedule.
  834. ; On abnormal termination, the user will usually modify the 
  835. ; DSA fields and corresponding buffers and return control
  836. ; to select.
  837. ;
  838. ENTRY command_complete
  839. command_complete:
  840.     MOVE FROM dsa_status, WHEN STATUS
  841. #if (CHIP != 700) && (CHIP != 70066)
  842.     MOVE SFBR TO SCRATCH0 ; Save status
  843. #endif /* (CHIP != 700) && (CHIP != 70066) */
  844. ENTRY command_complete_msgin
  845. command_complete_msgin:
  846.     MOVE FROM dsa_msgin, WHEN MSG_IN
  847. ; Indicate that we should be expecting a disconnect
  848.     MOVE SCNTL2 & 0x7f TO SCNTL2
  849.     CLEAR ACK
  850. #if (CHIP != 700) && (CHIP != 70066)
  851.     WAIT DISCONNECT
  852. ;
  853. ; The SCSI specification states that when a UNIT ATTENTION condition
  854. ; is pending, as indicated by a CHECK CONDITION status message,
  855. ; the target shall revert to asynchronous transfers.  Since
  856. ; synchronous transfers parameters are maintained on a per INITIATOR/TARGET 
  857. ; basis, and returning control to our scheduler could work on a command
  858. ; running on another lun on that target using the old parameters, we must
  859. ; interrupt the host processor to get them changed, or change them ourselves.
  860. ;
  861. ; Once SCSI-II tagged queueing is implemented, things will be even more
  862. ; hairy, since contingent allegiance conditions exist on a per-target/lun
  863. ; basis, and issuing a new command with a different tag would clear it.
  864. ; In these cases, we must interrupt the host processor to get a request 
  865. ; added to the HEAD of the queue with the request sense command, or we
  866. ; must automatically issue the request sense command.
  867. #if 0
  868.     MOVE SCRATCH0 TO SFBR
  869.     JUMP command_failed, IF 0x02
  870. #endif
  871.     INTFLY
  872. #endif /* (CHIP != 700) && (CHIP != 70066) */
  873. #ifdef EVENTS
  874.     INT int_EVENT_COMPLETE
  875. #endif
  876. #if (CHIP != 700) && (CHIP != 70066)
  877.     JUMP schedule
  878. command_failed:
  879.     INT int_err_check_condition
  880. #else
  881.     INT int_norm_command_complete
  882. #endif
  883. ;
  884. ; wait_reselect
  885. ;
  886. ; PURPOSE : This is essentially the idle routine, where control lands
  887. ; when there are no new processes to schedule.  wait_reselect
  888. ; waits for reselection, selection, and new commands.
  889. ;
  890. ; When a successful reselection occurs, with the aid 
  891. ; of fixed up code in each DSA, wait_reselect walks the 
  892. ; reconnect_dsa_queue, asking each dsa if the target ID
  893. ; and LUN match its.
  894. ;
  895. ; If a match is found, a call is made back to reselected_ok,
  896. ; which through the miracles of self modifying code, extracts
  897. ; the found DSA from the reconnect_dsa_queue and then 
  898. ; returns control to the DSAs thread of execution.
  899. ;
  900. ; INPUTS : NONE
  901. ;
  902. ; CALLS : OK
  903. ;
  904. ; MODIFIES : DSA,
  905. ;
  906. ; EXITS : On successful reselection, control is returned to the 
  907. ; DSA which called reselected_ok.  If the WAIT RESELECT
  908. ; was interrupted by a new commands arrival signaled by 
  909. ; SIG_P, control is passed to schedule.  If the NCR is 
  910. ; selected, the host system is interrupted with an 
  911. ; int_err_selected which is usually responded to by
  912. ; setting DSP to the target_abort address.
  913. ENTRY wait_reselect
  914. wait_reselect:
  915. #ifdef EVENTS
  916.     int int_EVENT_IDLE
  917. #endif
  918. #if 0
  919.     int int_debug_idle
  920. #endif
  921.     WAIT RESELECT wait_reselect_failed
  922. reselected:
  923. #ifdef EVENTS
  924.     int int_EVENT_RESELECT
  925. #endif
  926.     CLEAR TARGET
  927.     MOVE dmode_memory_to_memory TO DMODE
  928.     ; Read all data needed to reestablish the nexus - 
  929.     MOVE 1, reselected_identify, WHEN MSG_IN
  930.     ; We used to CLEAR ACK here.
  931. #if (CHIP != 700) && (CHIP != 70066)
  932. #if 0
  933.     int int_debug_reselected
  934. #endif
  935.     ; Point DSA at the current head of the disconnected queue.
  936.     MOVE dmode_memory_to_ncr  TO DMODE
  937.     MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
  938.     MOVE dmode_memory_to_memory TO DMODE
  939.     CALL scratch_to_dsa
  940.     ; Fix the update-next pointer so that the reconnect_dsa_head
  941.     ; pointer is the one that will be updated if this DSA is a hit 
  942.     ; and we remove it from the queue.
  943.     MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok + 8
  944. ENTRY reselected_check_next
  945. reselected_check_next:
  946. #if 0
  947.     INT int_debug_reselect_check
  948. #endif
  949.     ; Check for a NULL pointer.
  950.     MOVE DSA0 TO SFBR
  951.     JUMP reselected_not_end, IF NOT 0
  952.     MOVE DSA1 TO SFBR
  953.     JUMP reselected_not_end, IF NOT 0
  954.     MOVE DSA2 TO SFBR
  955.     JUMP reselected_not_end, IF NOT 0
  956.     MOVE DSA3 TO SFBR
  957.     JUMP reselected_not_end, IF NOT 0
  958.     INT int_err_unexpected_reselect
  959. reselected_not_end:
  960.     ;
  961.     ; XXX the ALU is only eight bits wide, and the assembler
  962.     ; wont do the dirt work for us.  As long as dsa_check_reselect
  963.     ; is negative, we need to sign extend with 1 bits to the full
  964.     ; 32 bit width of the address.
  965.     ;
  966.     ; A potential work around would be to have a known alignment 
  967.     ; of the DSA structure such that the base address plus 
  968.     ; dsa_check_reselect doesn't require carrying from bytes 
  969.     ; higher than the LSB.
  970.     ;
  971.     MOVE DSA0 TO SFBR
  972.     MOVE SFBR + dsa_check_reselect TO SCRATCH0
  973.     MOVE DSA1 TO SFBR
  974.     MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
  975.     MOVE DSA2 TO SFBR
  976.     MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
  977.     MOVE DSA3 TO SFBR
  978.     MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
  979.     MOVE dmode_ncr_to_memory TO DMODE
  980.     MOVE MEMORY 4, addr_scratch, reselected_check + 4
  981.     MOVE dmode_memory_to_memory TO DMODE
  982. reselected_check:
  983.     JUMP 0
  984. ;
  985. ;
  986. ENTRY reselected_ok
  987. reselected_ok:
  988.     MOVE MEMORY 4, 0, 0 ; Patched : first word
  989. ;  is address of 
  990. ;       successful dsa_next
  991. ; Second word is last 
  992. ; unsuccessful dsa_next,
  993. ; starting with 
  994. ;       dsa_reconnect_head
  995.     ; We used to CLEAR ACK here.
  996. #if 0
  997.     INT int_debug_reselected_ok
  998. #endif
  999. #ifdef DEBUG
  1000.     INT int_debug_check_dsa
  1001. #endif
  1002.     RETURN ; Return control to where
  1003. #else
  1004.     INT int_norm_reselected
  1005. #endif /* (CHIP != 700) && (CHIP != 70066) */
  1006. selected:
  1007.     INT int_err_selected;
  1008. ;
  1009. ; A select or reselect failure can be caused by one of two conditions : 
  1010. ; 1.  SIG_P was set.  This will be the case if the user has written
  1011. ; a new value to a previously NULL head of the issue queue.
  1012. ;
  1013. ; 2.  The NCR53c810 was selected or reselected by another device.
  1014. ;
  1015. ; 3.  The bus was already busy since we were selected or reselected
  1016. ; before starting the command.
  1017. wait_reselect_failed:
  1018. #ifdef EVENTS 
  1019. INT int_EVENT_RESELECT_FAILED
  1020. #endif
  1021. ; Check selected bit.  
  1022.     MOVE SIST0 & 0x20 TO SFBR
  1023.     JUMP selected, IF 0x20
  1024. ; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
  1025.     MOVE CTEST2 & 0x40 TO SFBR
  1026.     JUMP schedule, IF 0x40
  1027. ; Check connected bit.  
  1028. ; FIXME: this needs to change if we support target mode
  1029.     MOVE ISTAT & 0x08 TO SFBR
  1030.     JUMP reselected, IF 0x08
  1031. ; FIXME : Something bogus happened, and we shouldn't fail silently.
  1032. #if 0
  1033.     JUMP schedule
  1034. #else
  1035.     INT int_debug_panic
  1036. #endif
  1037. select_failed:
  1038. #ifdef EVENTS
  1039.   int int_EVENT_SELECT_FAILED
  1040. #endif
  1041. ; Otherwise, mask the selected and reselected bits off SIST0
  1042.     MOVE SIST0 & 0x30 TO SFBR
  1043.     JUMP selected, IF 0x20
  1044.     JUMP reselected, IF 0x10 
  1045. ; If SIGP is set, the user just gave us another command, and
  1046. ; we should restart or return to the scheduler.
  1047. ; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
  1048.     MOVE CTEST2 & 0x40 TO SFBR
  1049.     JUMP select, IF 0x40
  1050. ; Check connected bit.  
  1051. ; FIXME: this needs to change if we support target mode
  1052. ; FIXME: is this really necessary? 
  1053.     MOVE ISTAT & 0x08 TO SFBR
  1054.     JUMP reselected, IF 0x08
  1055. ; FIXME : Something bogus happened, and we shouldn't fail silently.
  1056. #if 0
  1057.     JUMP schedule
  1058. #else
  1059.     INT int_debug_panic
  1060. #endif
  1061. ;
  1062. ; test_1
  1063. ; test_2
  1064. ;
  1065. ; PURPOSE : run some verification tests on the NCR.  test_1
  1066. ; copies test_src to test_dest and interrupts the host
  1067. ; processor, testing for cache coherency and interrupt
  1068. ;  problems in the processes.
  1069. ;
  1070. ; test_2 runs a command with offsets relative to the 
  1071. ; DSA on entry, and is useful for miscellaneous experimentation.
  1072. ;
  1073. ; Verify that interrupts are working correctly and that we don't 
  1074. ; have a cache invalidation problem.
  1075. ABSOLUTE test_src = 0, test_dest = 0
  1076. ENTRY test_1
  1077. test_1:
  1078.     MOVE MEMORY 4, test_src, test_dest
  1079.     INT int_test_1
  1080. ;
  1081. ; Run arbitrary commands, with test code establishing a DSA
  1082. ;
  1083.  
  1084. ENTRY test_2
  1085. test_2:
  1086.     CLEAR TARGET
  1087.     SELECT ATN FROM 0, test_2_fail
  1088.     JUMP test_2_msgout, WHEN MSG_OUT
  1089. ENTRY test_2_msgout
  1090. test_2_msgout:
  1091.     MOVE FROM 8, WHEN MSG_OUT
  1092.     MOVE FROM 16, WHEN CMD 
  1093.     MOVE FROM 24, WHEN DATA_IN
  1094.     MOVE FROM 32, WHEN STATUS
  1095.     MOVE FROM 40, WHEN MSG_IN
  1096.     MOVE SCNTL2 & 0x7f TO SCNTL2
  1097.     CLEAR ACK
  1098.     WAIT DISCONNECT
  1099. test_2_fail:
  1100.     INT int_test_2
  1101. ENTRY debug_break
  1102. debug_break:
  1103.     INT int_debug_break
  1104. ;
  1105. ; initiator_abort
  1106. ; target_abort
  1107. ;
  1108. ; PURPOSE : Abort the currently established nexus from with initiator
  1109. ; or target mode.
  1110. ;
  1111. ;  
  1112. ENTRY target_abort
  1113. target_abort:
  1114.     SET TARGET
  1115.     DISCONNECT
  1116.     CLEAR TARGET
  1117.     JUMP schedule
  1118.     
  1119. ENTRY initiator_abort
  1120. initiator_abort:
  1121.     SET ATN
  1122. ;
  1123. ; The SCSI-I specification says that targets may go into MSG out at 
  1124. ; their leisure upon receipt of the ATN single.  On all versions of the 
  1125. ; specification, we can't change phases until REQ transitions true->false, 
  1126. ; so we need to sink/source one byte of data to allow the transition.
  1127. ;
  1128. ; For the sake of safety, we'll only source one byte of data in all 
  1129. ; cases, but to accommodate the SCSI-I dain bramage, we'll sink an  
  1130. ; arbitrary number of bytes.
  1131.     JUMP spew_cmd, WHEN CMD
  1132.     JUMP eat_msgin, WHEN MSG_IN
  1133.     JUMP eat_datain, WHEN DATA_IN
  1134.     JUMP eat_status, WHEN STATUS
  1135.     JUMP spew_dataout, WHEN DATA_OUT
  1136.     JUMP sated
  1137. spew_cmd:
  1138.     MOVE 1, NCR53c7xx_zero, WHEN CMD
  1139.     JUMP sated
  1140. eat_msgin:
  1141.     MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
  1142.     JUMP eat_msgin, WHEN MSG_IN
  1143.     JUMP sated
  1144. eat_status:
  1145.     MOVE 1, NCR53c7xx_sink, WHEN STATUS
  1146.     JUMP eat_status, WHEN STATUS
  1147.     JUMP sated
  1148. eat_datain:
  1149.     MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
  1150.     JUMP eat_datain, WHEN DATA_IN
  1151.     JUMP sated
  1152. spew_dataout:
  1153.     MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
  1154. sated:
  1155.     MOVE SCNTL2 & 0x7f TO SCNTL2
  1156.     MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
  1157.     WAIT DISCONNECT
  1158.     INT int_norm_aborted
  1159. ;
  1160. ; dsa_to_scratch
  1161. ; scratch_to_dsa
  1162. ;
  1163. ; PURPOSE :
  1164. ;  The NCR chips cannot do a move memory instruction with the DSA register 
  1165. ;  as the source or destination.  So, we provide a couple of subroutines
  1166. ;  that let us switch between the DSA register and scratch register.
  1167. ;
  1168. ;  Memory moves to/from the DSPS  register also don't work, but we 
  1169. ;  don't use them.
  1170. ;
  1171. ;
  1172.  
  1173. dsa_to_scratch:
  1174.     MOVE DSA0 TO SFBR
  1175.     MOVE SFBR TO SCRATCH0
  1176.     MOVE DSA1 TO SFBR
  1177.     MOVE SFBR TO SCRATCH1
  1178.     MOVE DSA2 TO SFBR
  1179.     MOVE SFBR TO SCRATCH2
  1180.     MOVE DSA3 TO SFBR
  1181.     MOVE SFBR TO SCRATCH3
  1182.     RETURN
  1183. scratch_to_dsa:
  1184.     MOVE SCRATCH0 TO SFBR
  1185.     MOVE SFBR TO DSA0
  1186.     MOVE SCRATCH1 TO SFBR
  1187.     MOVE SFBR TO DSA1
  1188.     MOVE SCRATCH2 TO SFBR
  1189.     MOVE SFBR TO DSA2
  1190.     MOVE SCRATCH3 TO SFBR
  1191.     MOVE SFBR TO DSA3
  1192.     RETURN
  1193.