53c7xx.scr
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:46k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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