home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / AHDI606 / SPSCSI.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  16.9 KB  |  585 lines

  1. ;+
  2. ; Edit History
  3. ;
  4. ; Nov-25-91 ml.    The ACSI DMA channel will be used in the Sparrow's
  5. ;        SCSI.  (Argh!)  So, code is modified to talk to the
  6. ;        5380 through wdl and wdc.  This means Sparrow's SCSI
  7. ;        inherited all the restrictions of ACSI, except for
  8. ;        the opcode of a command (now we get all 8 bits.)
  9. ;        This is a merge of acsi.s and scsi.s of v5.00.
  10. ;
  11. ; Dec-10-91 ml.    Don't need to have extra long timeout in _rcvspscsi()
  12. ;        and _wrtspscsi() because extended read and write are 
  13. ;        not supported due to the 8 bit counter in the DMAC.
  14. ;
  15. ; Jan-27-92 ml.    Try optimizing it.
  16. ;        *NOTE*  Do NOT use 'move.l's to select the SCSI 
  17. ;            registers and write data to them.  It is
  18. ;            because 680x0 writes the high word first.
  19. ;            So, writing a long word to WDCWDL means
  20. ;            writing the data before pointing to the
  21. ;            correct register.  In the ACSI code, the
  22. ;            move.l's are writing data to the previous
  23. ;            address, and setting up the address for
  24. ;            the next access.  It was confusing, and it
  25. ;            is not done here.
  26. ;
  27. ; Jan-28-92 ml.    In order for AHDI to work at IPL 7, Timer C is used
  28. ;        instead of hz_200 for timeout purposes.
  29. ;
  30. ; Feb-12-92 ml.    Modified to use the "flush" bit and the extended counter.
  31. ;
  32. ; Mar-19-93 jye. Fixed a timing bug in 'dospack()', by added some codes that
  33. ;            will wait for the REQ come before do the rest transfering, so that 
  34. ;            it can do the DMA trasfer data for those slow drives like the 
  35. ;            SyQuest 88MB and IMB OEM 0663E15.
  36. ;-
  37.  
  38.  
  39. .include    "defs.h"
  40. .include    "sysvar.h"
  41. .include    "mfp.h"
  42. .include    "acsi.h"
  43. .include    "spscsi.h"
  44. .include    "macros.h"
  45. .include    "68030.s"
  46.  
  47. ;+
  48. ; Command length
  49. ;-
  50. NCMD    equ    6        ; length of short command (in bytes)
  51.  
  52.  
  53. .if    !DRIVER            ; not to be included in driver
  54. scxltmout:  dc.l    12001   ; SCSI extra long-timeout (>1 min)
  55. slwsclto:   dc.l    5000    ; SCSI long-timeout (>25 S) for stunit()
  56. slwscsto:   dc.l    42        ; SCSI short-timeout (>205 mS) for stunit()
  57. scltmout:   dc.l    201        ; SCSI long-timeout (>1000 ms)
  58. scstmout:   dc.l    101        ; SCSI short-timeout (>500 ms)
  59. rcaltm:        dc.l    801        ; time for drive recalibration (>4s)
  60. .else    ;!DRIVER
  61. .extern    scxltmout, slwsclto, slwscsto, scltmout, scstmout, rcaltm
  62. .endif    ;!DRIVER
  63.  
  64.  
  65. .extern    setadma, setacnt, _hdone
  66. stat:        dc.w    0        ; status byte
  67. flush:        dc.b    0        ; flush flag
  68. .even
  69.  
  70. ;+
  71. ; smplspscsi() - send a simple SCSI command (ie. no DMA involved)
  72. ;
  73. ;    d0.w = physical unit number
  74. ;    d1.l = transfer length (in bytes)
  75. ;    d2.w = command length (NCMD or LCMD)
  76. ;    a0.l = buffer address
  77. ;-
  78.     .globl    _smplspscsi
  79. _smplspscsi:
  80.     st    flock
  81.     andi.w    #7,d0            ; mask off the flags to get unit num
  82.     bsr    sblkspscsi        ; send command block
  83.     tst.w    d0            ; successful?
  84.     bmi.s    .0            ; if not, go clean up
  85.     bsr    w4spstat        ; else wait for status
  86. .0:    RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  87.     bra    _hdone            ; go clean up
  88.  
  89.  
  90.  
  91. ;+
  92. ; rcvspscsi() - send a SCSI command which receives data back.
  93. ;
  94. ; Passed:
  95. ;    d0.w = physical unit number
  96. ;    d1.l = transfer length (in bytes)
  97. ;    d2.w = command length (NCMD or LCMD)
  98. ;    a0.l = buffer address
  99. ;-
  100.     .extern    _cachexst
  101.     .globl    _rcvspscsi
  102. _rcvspscsi:
  103.     st    flock            ; lock FIFO
  104.     andi.w    #7,d0            ; mask off the flags to get unit num
  105.     movem.l    d1-d2/a0,-(sp)        ; save buffer address and cmd length
  106.     bsr    sblkspscsi        ; send command block
  107.     movem.l    (sp)+,d1-d2/a0        ; restore buffer address and cmd len
  108.     tst.w    d0            ; successful?
  109.     bmi    rspend            ; if not successful, return
  110.  
  111. ;+
  112. ; Feb-13-1992    Check whether FIFO needs to be flushed.
  113.     sf    flush            ; assume no need to flush
  114.     move.l    d1,d0            ; d0 = transfer length
  115.     andi.l    #$0f,d0            ; multiple of 16?
  116.     beq.s    rdma0            ; if so, no need to flush
  117.     st    flush            ; else, set flush flag
  118. ;-
  119.  
  120. rdma0:    WSCSI    #0,#SPSCSIICR        ; deassert the data bus
  121.     WSCSI    #1,#SPSCSITCR        ; set data in phase
  122.     RSCSI    #SPSCSIREI,d0        ; clear potential interrupt
  123.  
  124. .if    SPSCDMA                ; Set up the DMAC for data transfer
  125. ;    cmpi.l    #512,d1            ; transferring >= 512 bytes?
  126. ;    bcs    rpio            ; if not, do programmed IO
  127. ;                    ; else set up DMA chip for DMA
  128.  
  129.     WSCSI    #2,#SPSCSIMR        ; enable DMA mode
  130.      movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  131.     bsr    setadma            ; set DMA pointer
  132.     move.w    #$190,XWDL(a1)    ;WDL    ; toggle DMA chip for "receive"
  133.     RSTDELAY            ; delay
  134.     move.w    #$090,XWDL(a1)    ;WDL
  135.     RSTDELAY            ; delay
  136.     bsr    setacnt
  137.  
  138. rdma1:    btst.b    #STA,WDSR        ; wait till it's safe to access
  139.     bne.s    rdma1            ;  the DMA channel
  140.  
  141. ;    TMOUT    #2,d0            ; delay before using DMA channel
  142. ;    CNTALL    d0
  143.  
  144.     WSCSI    #0,#SPSCSIDIR        ; start the DMA receive
  145.     move.w    #0,WDL
  146.  
  147. ;+
  148. ; Dec-10-1991    ml.    Don't need to have extra long timeout because
  149. ;            extended read and write are not supported due
  150. ;            to the 8 bit counter in the DMAC.
  151. ;
  152. ; Feb-13-1992    ml.    Put code back in because DMAC has been modified
  153. ;            to have a 14-bit counter.
  154.     moveq    #0,d0            ; assume no extra timeout
  155.     cmpi.w    #NCMD,d2        ; is this a long command?
  156.     beq.s    rdma2            ; if not, just go on
  157.     move.l    scxltmout,d0        ; set up an extra long timeout
  158. ;-
  159.  
  160. rdma2:    bsr    w4spint            ; wait for interrupts
  161.     tst.w    d0            ; successful?
  162.     bne.s    rspend            ; if error, returns
  163.  
  164. ;+
  165. ; Feb-13-1992    ml.    Added code to use the flush bit on the DMAC.
  166. ;            Now, we can do DMA without sending a command
  167. ;            multiple times, to write everything from the 
  168. ;            FIFO to memory, for transfers of non-multiple
  169. ;            of 16 bytes.  Using this flush function requires
  170. ;            the buffer provided for the command to be as big 
  171. ;            as the closest multiple of 16 to receive all data.
  172. ;            
  173.     tst.b    flush            ; need to flush FIFO?
  174.     beq.s    rdma3            ; if not, proceed    
  175.     move.w    #$0020,WDL        ; else flush (Whoosh!)
  176. ;-
  177. rdma3:    tst.b    _cachexst        ; is there a cache to flush?
  178.     beq.s    rstat            ; if not, go get status
  179.     move    sr,-(sp)        ; go to IPL 7
  180.     ori    #$700,sr        ; no interrupts right now kudasai
  181.     movecacrd0            ; d0 = (cache control register)
  182.     ori.w    #$808,d0        ; dump both the D and I cache
  183.     moved0cacr            ; update cache control register
  184.     move    (sp)+,sr        ; restore interrupt state
  185.     bra.s    rstat            ; go read status 
  186. .endif    ;SPSCDMA
  187.  
  188. rpio:    movea.l    a0,a1            ; a1 -> buffer to read into
  189. rnxtb:    bsr    w4spdreq        ; wait for REQ for data to come
  190.     bmi.s    rspend            ; if timed out, returns
  191.     RSCSI    #SPSCSIDSR,d0        ; still in data in phase?
  192.     btst    #3,d0            
  193.     beq    rstat            ; if not, go get status
  194.     RSCSI    #bSPSCSI,d0        ; else read the next data byte
  195.     move.b    d0,(a1)+    
  196.     bsr    dospack
  197.     bra.s    rnxtb            ; do next byte
  198. rstat:    bsr    w4spstat        ; go get status byte
  199. rspend:    RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  200.     bra    _hdone            ; go clean up
  201.  
  202.  
  203.  
  204. ;+
  205. ; wrtspscsi() - send a SCSI command which will write data to the target
  206. ;
  207. ; Passed:
  208. ;    d0.w = physical unit number
  209. ;    d1.l = transfer length (in bytes)
  210. ;    d2.w = command length (NCMD or LCMD)
  211. ;    a0.l = buffer address
  212. ;
  213. ; Comments: 
  214. ; 12/04/89 ml
  215. ;    Bus error occurs when doing a write to the disk that ends at top
  216. ; of memory.  The DMA counter is decremented when the bytes are written 
  217. ; from the ping pong buffers to the device, not when bytes are grapped 
  218. ; from RAM to the ping pong buffers.  Well, AFTER the last 8 bytes are 
  219. ; read into the ping pong buffers and BEFORE they are written to the 
  220. ; device, the chip will attempt to read the NEXT 8 bytes into the ping 
  221. ; pong buffers which results in a bus error because it will be reading 
  222. ; pass top of memory.  To get around this HARDWARE BUG, the code will 
  223. ; ALWAYS handshake the last 8 bytes over instead of DMAing them.
  224. ;
  225. ; 01/23/90 ml
  226. ;    A. Pratt said he's willing to move the screen down and sacrifice
  227. ; 16 bytes of memory.  So, code added on 12/04/89 is commented out.
  228. ;-
  229.     .globl    _wrtspscsi
  230. _wrtspscsi:
  231.     st    flock            ; lock FIFO
  232.     andi.w    #7,d0            ; mask off the flags to get unit num
  233.  
  234.     movem.l    d1-d2/a0,-(sp)        ; save beginning buffer address
  235.     bsr    sblkspscsi        ; send command block
  236.     movem.l    (sp)+,d1-d2/a0        ; a0 = where DMA ends
  237.     tst.w    d0            ; successful?
  238.     bmi    wspend            ; if not, go clean up
  239.  
  240.     WSCSI    #0,#SPSCSITCR        ; set data out phase
  241.     RSCSI    #SPSCSIREI,d0        ; clear potential interrupt
  242.  
  243. .if    SPSCDMA
  244.                     ; Set up the DMAC for data transfer
  245.     cmpi.l    #512,d1            ; transferring >= 512 bytes?
  246.     bcs.s    wpio            ; if not, do programmed IO
  247.                     ; else do DMA
  248.     WSCSI    #2,#SPSCSIMR        ; enable DMA mode
  249.  
  250.     movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  251.  
  252.     bsr    setadma            ; set DMA pointer
  253.     move.w    #$90,XWDL(a1)    ;WDL    ; toggle DMA chip for "send"
  254.     RSTDELAY            ; delay 
  255.     move.w    #$190,XWDL(a1)    ;WDL
  256.     RSTDELAY            ; delay
  257.     bsr    setacnt            ; set DMA count
  258.  
  259. wdma0:    btst.b    #STA,WDSR        ; wait till it's safe to access
  260.     bne.s    wdma0            ;  the DMA channel
  261.  
  262. ;    TMOUT    #2,d0            ; delay before using DMA channel
  263. ;    CNTALL    d0
  264.  
  265.     WSCSI    #0,#($100|SPSCSIDS)    ; start the DMA send
  266.     move.w    #$100,WDL
  267.  
  268. ;+
  269. ; Dec-10-1991    ml.    Don't need to have extra long timeout because
  270. ;            extended read and write are not supported due
  271. ;            to the 8 bit counter in the DMAC.
  272. ;
  273.     moveq    #0,d0            ; assume no extra timeout
  274.     cmpi.w    #NCMD,d2        ; is this a long command?
  275.     beq.s    wdma1            ; if not, just go on
  276.     move.l    scxltmout,d0        ; set up an extra long timeout
  277. ;-
  278.  
  279. wdma1:    bsr    w4spint            ; wait for interrupts
  280.     tst.w    d0
  281.     beq.s    wstat            ; if ok, wait for status byte
  282.     bra.s    wspend            ; else return
  283. .endif    ;SPSCDMA
  284.                     ; hand shake data over the bus
  285. wpio:    movea.l    a0,a1            ; a1 -> buffer to write from
  286. wnxtb:    bsr    w4spdreq        ; wait for REQ for data to come
  287.     bmi.s    wspend            ; if timed out, returns
  288.     RSCSI    #SPSCSIDSR,d0
  289.     btst    #3,d0            ; still in data out phase?
  290.     beq.s    wstat            ; if not, go get status
  291.     moveq    #0,d0
  292.     move.b    (a1)+,d0        ; write the next data byte
  293.     WSCSI    d0,#bSPSCSI
  294.     bsr    dospack
  295.     bra.s    wnxtb            ; do next byte
  296. wstat:    bsr    w4spstat        ; get status byte
  297. wspend:    RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  298.     bra    _hdone            ; go clean up
  299.  
  300.  
  301.  
  302. ;+
  303. ; sblkspscsi() - set DMA pointer and count and send command block
  304. ;
  305. ; Passed:
  306. ;    d0.w = physical unit number
  307. ;    d1.l = transfer length (in bytes)
  308. ;    d2.w = command length (NCMD or LCMD)
  309. ;    a0.l = buffer address
  310. ;
  311. ; Returns:
  312. ;    d0.l =  0 if successful
  313. ;    d0.l = -1 if timeout
  314. ;-
  315.     .extern    _cmdblk
  316. sblkspscsi:
  317.     movem.l    d1-d2/a0,-(sp)        ; preserve d1, d2 and a0
  318.     move.w    d0,-(sp)        ; physical unit #
  319.     bsr    selspscsi        ; select the unit
  320.     addq.l    #2,sp            ; clean up stack
  321.     movem.l    (sp)+,d1-d2/a0        ; restore d1, d2 and a0
  322.     tst.w    d0            ; selection successful?
  323.     bmi.s    sbspend            ; if timed out, return
  324.                     ; else proceed
  325.     WSCSI    #2,#SPSCSITCR        ; assert C/D
  326.     WSCSI    #1,#SPSCSIICR        ; assert data bus
  327.  
  328.     lea    _cmdblk,a1        ; a1 -> command block
  329.     subq.w    #1,d2            ; dbra likes one less
  330. sbs0:    bsr    w4spreq            ; wait for REQ to come
  331.     bmi.s    sbspend            ; if timed out, returns
  332.     move.b    (a1)+,d0        ; d0.b = byte to be sent
  333.     WSCSI    d0,#SPSCSIDB        ; write a byte out to data bus
  334.     bsr    dospack            ; assert ACK
  335.     dbra    d2,sbs0            ; until whole command block is sent
  336.     moveq    #0,d0            ; all operations successful
  337. sbspend: rts                ; heading home
  338.  
  339.  
  340. ;+
  341. ; BOOLEAN selspscsi(SCSIUnit) 
  342. ; WORD SCSIUnit;
  343. ;-
  344. selspscsi:
  345.     TMOUT    scstmout,d1        ; set up a short timeout
  346.     move.w    #SPSCSICR,WDL
  347. .0:    move.w    WDC,d0
  348.     btst    #6,d0            ; STILL busy from last time?
  349.     beq.s    .1            ; if not, it's available
  350.     CNTDN1    d1,.0            ; else if not timed-out, wait longer
  351.     bra    .3            ; else, return error
  352.  
  353. .1:    WSCSI    #0,#SPSCSITCR        ; data out phase
  354.     WSCSI    #0,#SPSCSIISR        ; no interrupt from selection
  355.     WSCSI    #$0c,#SPSCSIICR        ; assert BSY and SEL
  356. ; set dest SCSI IDs
  357.     clr.w    d0
  358.     move.w    4(sp),d1        ; get the SCSI unit desired
  359.     bset    d1,d0            ; set the appropriate bit
  360.     WSCSI    d0,#SPSCSIODR        ; (real code would set ours too)
  361.  
  362. ;    WSCSI    #$0d,#SPSCSIICR        ; assert BUSY, SEL and data bus
  363.     WSCSI    #$05,#SPSCSIICR        ; assert SEL and data bus
  364.     RSCSI    #SPSCSIMR,d0        ; read Mode Register
  365.     andi.b    #$fe,d0            ; clear arbitrate bit
  366.     move.w    d0,WDC
  367.     RSCSI    #SPSCSIICR,d0        ; read Initiator Command Register
  368.     andi.b    #$f7,d0            ; clear BUSY
  369.     move.w    d0,WDC
  370.     nop                ; 2 deskew delays
  371.     nop
  372.  
  373.     TMOUT    scstmout,d1        ; set up timeout counter
  374.     move.w    #SPSCSICR,WDL
  375. .2:    move.w    WDC,d0            ; wait for bus to be busy
  376.     btst    #6,d0
  377.     bne.s    .4
  378.  
  379.     CNTDN1    d1,.2            ; if not timed-out, wait some more
  380.  
  381. .3:    moveq    #-1,d0            ; time out
  382.     bra.s    .5
  383.     
  384. .4:    clr.w    d0            ; selection successful
  385. .5:    WSCSI    #0,#SPSCSIICR        ; clear SEL and data bus assertion
  386.     rts
  387.  
  388.  
  389. ;+
  390. ; VOID resetspscsi();
  391. ;
  392. ; Feb-14-1992    ml.    Added code to reset DMAC before talking through
  393. ;            it to reset the SCSI bus.  To protect DMAC from
  394. ;            locking up, check if it's safe to access it
  395. ;            before doing any of the above.
  396. ;-
  397.     .globl    resetspscsi
  398.     .extern    setscstmout
  399.     .extern    setscltmout
  400. resetspscsi:
  401. rst0:    btst.b    #STA,WDSR    ; wait till it's safe to access
  402.     bne.s    rst0        ;  the DMA channel
  403.  
  404.     move.w    #$190,WDL    ; reset DMA chip
  405.     RSTDELAY        ; delay
  406.     move.w    #$090,WDL
  407.     RSTDELAY
  408.                 ; reset SCSI bus
  409.     WSCSI    #$80,#SPSCSIICR    ; assert RST
  410. ;    TMOUT    scstmout,d1    ; wait (at least) 250 ms
  411. ;    CNTALL    d1
  412.     bsr    setscstmout    ; wait (at least) 250 ms
  413. .0:    cmp.l    (a0),d1
  414.     bhi.s    .0
  415. ;    move.w    #0,WDC
  416.     WSCSI    #0,#SPSCSIICR    ; clear RST
  417. ;    TMOUT    scltmout,d1    ; wait (at least) 1000 ms
  418. ;    CNTALL    d1
  419.     bsr    setscltmout    ; wait (at least) 1000 ms
  420. .1:    cmp.l    (a0),d1
  421.     bhi.s    .1
  422.     rts
  423.  
  424.  
  425. ;+
  426. ; w4spint - wait for interrupts from 5380 or DMAC during DMA tranfers
  427. ;
  428. ; Returns:
  429. ;    d0.l = returned status or timeout error
  430. ;
  431. ; Comments:
  432. ;    When 5380 is interrupted, it indicates a change of data to
  433. ; status phase (i.e., DMA is done), or ...
  434. ;    When DMAC is interrupted, it indicates either DMA count is
  435. ; zero, or there is an internal bus error.
  436. ;-
  437. w4spint:
  438.     TMOUT    rcaltm,d1        ; set timeout (incl. recalibration)
  439.     add.l    d0,d1
  440. .0:    btst    #5,GPIP            ; interrupt?
  441.     beq.s    .1            ; active LOW
  442.     CNTDN1    d1,.0            ; if there's more time, keep waiting
  443.                     ; else timed-out
  444.     bsr    resetspscsi        ; reset the SCSI bus
  445.     moveq    #-1,d0            ; return timeout
  446.     bra.s    w4spiend
  447.  
  448. .1:    moveq    #0,d0            ; DMA is successful
  449.     RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  450.     WSCSI    #0,#SPSCSIMR        ; disable DMA mode
  451.     WSCSI    #0,#SPSCSIICR        ; make sure data bus is not asserted
  452. w4spiend:
  453.     rts
  454.  
  455.  
  456. ;+
  457. ; w4spstat - wait for status byte and message byte.
  458. ;
  459. ; Returns:
  460. ;    d0.l = returned status or timeout error
  461. ;-
  462. w4spstat:
  463.     WSCSI    #3,#SPSCSITCR        ; status in phase
  464.     RSCSI    #SPSCSIREI,d0        ; clear potential interrupt
  465.  
  466.     bsr    w4spreq            ; wait for status byte
  467.     bmi.s    w4spend            ; if timed-out, returns
  468. gspstat:
  469.     RSCSI    #SPSCSIDB,d0        ; get the status byte
  470.     andi.w    #$ff,d0
  471.     move.w    d0,stat            ; save the status byte
  472.     bsr    dospack            ; signal that status byte is here
  473.  
  474. .1:    bsr    w4spreq            ; wait for message byte
  475.     bmi.s    w4spend            ; if timed-out, returns
  476.  
  477.     RSCSI    #SPSCSIDB,d0        ; get and ignore message byte
  478.     bsr    dospack            ; signal that message byte is here
  479.     move.w    stat,d0            ; recall the status byte
  480. w4spend:
  481.     rts                ; return
  482.  
  483.  
  484. ;+
  485. ; w4spdreq() - wait for REQ to come during hand shake of data bytes
  486. ; w4spreq() - wait for REQ to come during hand shake of non-data bytes
  487. ;
  488. ; Returns:
  489. ;     0 - if successful
  490. ;    -1 - times out
  491. ;-
  492. w4spdreq:
  493.     TMOUT    rcaltm,d1        ; add time for recalibration
  494.     bra.s    w4req0
  495. w4spreq:
  496.     TMOUT    scstmout,d1        ; set up timeout counter
  497. w4req0:    move.w    #SPSCSICR,WDL
  498. .1:    move.w    WDC,d0            ; read Control Register
  499.     btst    #5,d0            ; waiting for REQ to come
  500.     bne.s    .2            ; if REQ comes, done
  501.     CNTDN1    d1,.1            ; if there is more time, keep waiting
  502.     moveq    #-1,d0            ; else, returns timed out
  503.     bra.s    w4sprend
  504. .2:    moveq    #0,d0            ; returns successful
  505. w4sprend:
  506.     rts
  507.  
  508.  
  509. ;+
  510. ; dospack() - assert ACK
  511. ;
  512. ; Returns:
  513. ;     0 - always successful
  514. ;-
  515. dospack:    
  516.     move.l    d1, -(sp)        ; save the date in d1
  517.     move.w     #$ff, d1        ; set the time out counter
  518.     RSCSI    #SPSCSIICR,d0        ; read Initiator Command Register
  519.     ori.b    #$11,d0            ; assert ACK (and data bus)
  520.     move.w    d0,WDC
  521.     move.w     #SPSCSITCR, WDL    ; move the target command register
  522.                             ; to the DMA mode control register
  523. w4come:
  524.     move.w    WDC, d0            ; move the DMA data register to d0
  525.     btst    #3, d0            ; waiting for ??? to come 
  526.     bne.s    donespa            ; if ??? comes, done
  527.     dbra    d1, w4come        ; else check if it is time out, if not, wait for it
  528.                             ; else give up,
  529. donespa:
  530.     RSCSI    #SPSCSIICR,d0        ; read Initiator Command Register
  531.     andi.b    #$ef,d0            ; clear ACK
  532.     move.w    d0,WDC
  533.     moveq    #0,d0
  534.     move.l    (sp)+, d1        ; restore the d1
  535.     rts
  536.  
  537.  
  538. .if    !DRIVER                ; not to be included in driver
  539.  
  540. ;+
  541. ; fmtspscsi() - format a SCSI unit
  542. ;
  543. ;    d0.w = physical unit number
  544. ;    d1.l = transfer length (in bytes)
  545. ;    d2.w = command length (NCMD or LCMD)
  546. ;    a0.l = buffer address
  547. ;-
  548.     .globl    _fmtspscsi
  549. _fmtspscsi:
  550.     st    flock            ; lock FIFO
  551.     andi.w    #7,d0            ; mask off the flags to get unit num
  552.     bsr    sblkspscsi        ; send command block
  553.     bpl.s    .0            ; if successful, wait for status byte
  554.     rts                ; else return
  555. .0:    WSCSI    #3,#SPSCSITCR        ; status in phase
  556.     RSCSI    #SPSCSIREI,d0        ; clear potential interrupt
  557. .1:    RSCSI    #SPSCSICR,d0        ; read Control Register
  558.     btst    #5,d0            ; wait forever for REQ to come
  559.  
  560.  
  561. .if    DEBUG
  562.  
  563.     bne.s    .3            ; For debugging purpose - 
  564.     move.l    #_hz_200,a0        ;    add a delay in this "tight" 
  565.     moveq    #2,d1            ;    loop to slow down SCSI chip 
  566.     add.l    (a0),d1            ;    accessing.
  567. .2:    cmp.l    (a0),d1
  568.     bhi.s    .2
  569.     bra.s    .1
  570.  
  571. .else    ;DEBUG
  572.  
  573.     beq.s    .1
  574.  
  575. .endif    ;DEBUG
  576.  
  577. .3:    bsr    gspstat            ; when REQ comes, get status byte
  578.     RSCSI    #SPSCSIREI,d1        ; clear potential interrupt
  579.     bra    _hdone            ; go clean up
  580.  
  581. .endif    ;!DRIVER
  582.  
  583.  
  584.  
  585.