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

  1. ;+
  2. ; Edit History
  3. ;
  4. ; May-22-89    ml.    Started this with AHDI 3.00.
  5. ; Aug-21-89    ml.    Added format code.  It's seperated because it waits
  6. ;            forever for command completion.
  7. ; Sep-08-89    ml.    Added a 1 microsec delay (rstdelay()) after each 
  8. ;            access to the DMA chip which may reset the chip.
  9. ; Sep-13-89    ml.    If need to execute a command more than once to
  10. ;            get all bytes into RAM, use the original allocation
  11. ;            length for subsequent calls.
  12. ; Oct-06-89    ml.    Added start/stop unit code.  It's seperated because
  13. ;            it needs longer timeouts.
  14. ; Nov-08-89    ml.    Added a delay in _rcvacsi() when looping to do more
  15. ;            than one _sblkacsi().
  16. ; Nov-27-89    ml.    Added .even after declaring control.
  17. ; Dec-05-89    ml.    Flushing of D cache before reading status byte.
  18. ; Apr-09-90    ml.    Added a "read" from WDL to actually "set" the bit
  19. ;            for the new MMU chip.  It's a bug in the chip.  
  20. ;            Temporary only.
  21. ; Apr-20-90    ml.    Made the "read" added on Apr-09-90 conditional
  22. ;            assembly.  RDWDL flag defined in defs.h.
  23. ;-
  24.  
  25.  
  26. .include    "defs.h"
  27. .include    "sysvar.h"
  28. .include    "68030.s"
  29.  
  30.  
  31. ;+
  32. ;  Hardware definitions for ACSI
  33. ;-
  34. WDC        equ    $ffff8604
  35. WDL        equ    $ffff8606
  36. WDCWDL        equ    WDC        ; used for long writes
  37. XWDL        equ    WDL-WDC        ; offset from wdc to wdl
  38.  
  39. DMAHI        equ    $ffff8609
  40. DMAMID        equ    DMAHI+2
  41. DMALOW        equ    DMAMID+2
  42. GPIP        equ    $fffffa01
  43.  
  44.  
  45. ;+
  46. ;  Tunable (delay) values for ACSI
  47. ;-
  48. ACLTMOUT    equ    600        ; long-timeout (3 S)
  49. ACSTMOUT    equ    20        ; short-timeout (100 mS)
  50. SLWACLTO    equ    5000        ; long-timeout (25 S) for slow ACSI
  51. SLWACSTO    equ    42        ; short-timeout (205 mS) for slow ACSI
  52.  
  53.  
  54. ;+
  55. ; Declarations
  56. ;-
  57. lastacstm:    dc.l    0        ; controller last accessed time
  58. control:    dc.b    0        ; flag for sending control byte
  59. .even
  60.  
  61. .extern        _cmdblk
  62.  
  63.  
  64. ;+
  65. ; LONG _qdone() - Wait for command byte handshake
  66. ; LONG _fdone() - Wait for operation complete
  67. ; Passed:    nothing
  68. ;
  69. ; Returns:    EQ: no timeout
  70. ;        MI: timeout condition
  71. ;
  72. ; Uses:        D0
  73. ;
  74. ;-
  75. _slwfdone:                ; fdone for slow response
  76.     move.l    #SLWACLTO,d0
  77.     bra.s    qd0
  78.  
  79. _fdone:    move.l    #ACLTMOUT,d0
  80.     bra.s    qd0
  81.  
  82. _slwqdone:                ; qdone for slow response
  83.     moveq    #SLWACSTO,d0    
  84.     bra.s    qd0
  85.  
  86. _qdone:    moveq    #ACSTMOUT,d0
  87.  
  88. qd0:    
  89. .if    !DRIVER
  90.     move.l    d0,-(sp)        ; save timeout value
  91.     moveq    #2,d0            ; delay for slow response devices
  92. sdelay:    add.l    _hz_200,d0        ; minimum 20 microsec.
  93.     cmp.l    _hz_200,d0
  94.     bge.s    sdelay
  95.     move.l    (sp)+,d0        ; restore timeout value
  96. .endif
  97.     add.l    _hz_200,d0
  98. qd1:    cmp.l    _hz_200,d0        ; timeout?
  99.     bcs.s    qdq            ; (i give up, return NE)
  100.     btst    #5,GPIP            ; interrupt?
  101.     bne.s    qd1            ; (not yet)
  102.  
  103.     moveq    #0,d0            ; return EQ (no timeout)
  104.     rts
  105.  
  106. qdq:    moveq    #-1,d0
  107.     rts
  108.  
  109.  
  110. ;+
  111. ; Wait for end of SASI command
  112. ;
  113. ; Passed:    d1 value to be written to wdl
  114. ;
  115. ; Returns:    EQ: success (error code in D0.W)
  116. ;        MI: timeout (-1 in D0.W)
  117. ;        NE: failure (SASI error code in D0.W)
  118. ;
  119. ; Uses:        d0
  120. ;
  121. ; Comments: (12/05/89)
  122. ;    The flushing of D cache is necessary per Jim Tittsler.  For
  123. ; detail, refer to mail sent by jwt on 12/04/89 about ACSI DMA.
  124. ;-
  125. .if    !DRIVER
  126.     .globl    _cachexst
  127. _cachexst:    dc.b    0
  128. .else
  129.     .extern    _cachexst
  130. .endif
  131. _slwendcmd:
  132.     bsr    _slwfdone        ; wait for operation complete
  133.     bra.s    end0
  134.  
  135. _endcmd:
  136.     bsr    _fdone            ; wait for operation complete
  137. end0:    bmi.s    endce            ; (timed-out, so complain)
  138.  
  139. cmdcmp:    tst.b    _cachexst        ; '030 cache exists
  140.     beq.s    end1            ; if not, fine
  141.                     ; else, dump D cache
  142.     move.w    sr,-(sp)        ; go to IPL 7
  143.     ori.w    #$700,sr        ; no interrupts right now kudasai
  144.     movecacrd0            ; d0 = (cache control register)
  145.     ori.w    #$800,d0        ; dump the D cache
  146.     moved0cacr            ; update cache control register
  147.     move.w    (sp)+,sr        ; restore interrupt state
  148.  
  149. end1:    move.w    d1,WDL
  150.     move.w    WDC,d0            ; get the result
  151.     and.w    #$00ff,d0        ; (clean it up), if non-zero should
  152.                     ; do a ReadSense command to learn more
  153. endce:    move.l    _hz_200,lastacstm    ; update controller last accessed time
  154.     addq.l    #2,lastacstm        ; lastacstm = _hz_200 + 2;
  155.     rts                
  156.  
  157.  
  158. ;+
  159. ;  Unlock DMA chip and return completion status;
  160. ;-
  161. _hdone:    move.w    #$80,WDL    ; Landon's code seems to presume we put 
  162.                 ;  $80 there
  163.     clr    flock        ; NOW, signal that we are done
  164.     rts
  165.  
  166.  
  167. ;+
  168. ; delay()
  169. ;    5 - 10ms kludge delay for message byte sent back by controller.
  170. ;-
  171. _delay:    move.l    d0,-(sp)        ; preserve d0
  172.     move.l    lastacstm,d0        ; d0 = controller last accessed time
  173. wait:    cmp.l    _hz_200,d0        ; while (_hz_200 <= lastacstm)
  174.     bcc.s    wait            ;    wait()
  175.     move.l    (sp)+,d0        ; restore d0
  176.     rts
  177.  
  178.  
  179. ;+
  180. ; smplacsi() - send a simple ACSI command (ie. no DMA involved)
  181. ;
  182. ;    d0.w = physical unit number
  183. ;    d1.l = transfer length (in bytes)
  184. ;    d2.w = command length (NCMD or LCMD)
  185. ;    a0.l = buffer address
  186. ;-
  187.     .globl    _smplacsi
  188. _smplacsi:
  189.     st    flock            ; lock FIFO
  190.     bsr    _delay            ; delay if necessary
  191.     movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  192.     andi.w    #7,d0            ; mask off the flags to get unit num
  193.     moveq    #0,d1            ; no DMA
  194.     bsr    sblkacsi        ; send command block
  195.     bra    _hdone            ; cleanup after IRQ
  196.  
  197.  
  198. ;+
  199. ; rcvacsi() - send a ACSI command which receives data back.
  200. ;
  201. ; Passed:
  202. ;    d0.w = physical unit number
  203. ;    d1.l = transfer length (in bytes)
  204. ;    d2.w = command length (NCMD or LCMD)
  205. ;    a0.l = buffer address
  206. ;
  207. ; Comments:
  208. ;    This routine assumes that if you are transferring more than 512
  209. ; bytes, the transfer length must be a multiple of 16 bytes.  It also 
  210. ; assumes the allocation length byte is always at byte 4 in the command
  211. ; block. (Therefore, it won't work with Receive Diagnostic ($1c) if data
  212. ; length is not a multiple of 16 bytes.  But Receive Diagnostic has never
  213. ; been used.)
  214. ;-
  215.     .globl    _rcvacsi
  216. _rcvacsi:
  217.     st    flock            ; lock FIFO
  218.     move.w    d3,-(sp)        ; preserve d3
  219.     bsr    _delay            ; delay if necessary
  220.     movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  221.  
  222.     bsr    setadma            ; set DMA pointer
  223.     move.w    #$190,XWDL(a1)    ;WDL    ; toggle DMA chip for "receive"
  224.     bsr    rstdelay        ; delay
  225.     move.w    #$090,XWDL(a1)    ;WDL
  226.     bsr    rstdelay        ; delay
  227.  
  228. .if    RDWDL
  229.     tst.w    XWDL(a1)        ; to point MMU to correct direction
  230. .endif    ;RDWDL
  231.  
  232.     bsr    setacnt            ; set DMA count
  233.  
  234.     andi.w    #7,d0            ; mask off the flags to get unit num
  235.                     ; find # times need to send it
  236.     cmpi.l    #512,d1            ; transferring < 512 bytes?
  237.     bcs.s    .0            ; if so, go find # times to send
  238.     moveq    #0,d1            ; else assume it's 16*n, send once
  239.     bra.s    .4
  240.  
  241. .0:    move.w    d1,d3            ; d3 = transfer length
  242.     cmpi.w    #16,d1            ; transferring < 16 bytes?
  243.     bcs.s    .1            ; if so, find # times to make 16 bytes
  244.  
  245.     divu    #16,d1            ; else, is it multiple of 16 bytes?
  246.     move.w    #0,d1            ; have to do at least once
  247.     bra.s    .2
  248.  
  249. .1:    moveq    #16,d1            ; find # times to make 16 bytes
  250.     divu    d3,d1            ; d1.w = 16 / transfer length
  251.     subq.w    #1,d1            ; dbra likes one less
  252.  
  253. .2:    swap    d1            ; d1.w = remainder
  254.     tst.w    d1            ; any remainder?
  255.     bne.s    .3            ; if yes, go add one to the quotient
  256.     swap    d1            ; if no, # times to send = quotient
  257.     bra.s    .4
  258.  
  259. .3:    swap    d1            ; d1.w    = # times to send command
  260.     addq.w    #1,d1            ;    = quotient + 1
  261.  
  262. .4:    lea    _cmdblk,a0        ; a0 = address of command block
  263. .5:    movem.l    d0-d2/a0,-(sp)        ; save d0 through d2 and a0
  264.     moveq    #0,d1            ; direction of DMA is IN
  265.     bsr    _delay            ; delay if necessary
  266.     bsr    sblkacsi        ; send the command block
  267.     tst.w    d0            ; successful?
  268.     bne.s    .7            ; if not, quit
  269.     movem.l    (sp)+,d0-d2/a0        ; else restore d0 through d2 and a0
  270.     dbra    d1,.6            ; done yet?
  271.     moveq    #0,d0            ; command block sent successfully
  272.     bra.s    raend            ; phone home...
  273.  
  274. .6:    moveq    #-1,d0            ; unit number already in command block
  275.     move.b    d3,4(a0)        ; modify transfer length
  276.     bra.s    .5            ; send it enough times
  277.  
  278. .7:    adda    #16,sp            ; cleanup stack
  279. raend:    move.w    (sp)+,d3        ; restore d3
  280.     bra    _hdone            ; cleanup after IRQ
  281.  
  282.  
  283. ;+
  284. ; wrtacsi() - send an ACSI command which will write data to the target
  285. ;
  286. ; Passed:
  287. ;    d0.w = physical unit number
  288. ;    d1.l = transfer length (in bytes)
  289. ;    d2.w = command length (NCMD or LCMD)
  290. ;    a0.l = buffer address
  291. ;-
  292.     .globl    _wrtacsi
  293. _wrtacsi:
  294.     st    flock            ; lock FIFO
  295.     bsr    _delay
  296.     movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  297.  
  298.     bsr    setadma            ; set DMA pointer
  299.     move.w    #$90,XWDL(a1)    ;WDL    ; toggle DMA chip for "send"
  300.     bsr    rstdelay        ; delay 
  301.     move.w    #$190,XWDL(a1)    ;WDL
  302.     bsr    rstdelay        ; delay
  303.  
  304. .if    RDWDL
  305.     tst.w    XWDL(a1)        ; to point MMU to correct direction
  306. .endif    ;RDWDL
  307.  
  308.     bsr    setacnt            ; set DMA count
  309.     
  310.     andi.w    #7,d0            ; mask off the flags to get unit num
  311.     move.l    #$0100,d1        ; d1 = direction of DMA is OUT
  312.     bsr    sblkacsi        ; send the command block
  313.  
  314. waend:    bra    _hdone            ; cleanup after IRQ
  315.  
  316.  
  317. ;+
  318. ; sblkacsi() - set DMA pointer and count and send command block
  319. ;
  320. ; Passed:
  321. ;    d0.w = physical unit number
  322. ;    d1.l = direction of DMA ($0000 for IN or $0100 for OUT)
  323. ;    d2.w = command length (NCMD or LCMD)
  324. ;    a1.l = pointer to DMA chip
  325. ;
  326. ; Returns:
  327. ;    d0.l =  0 if successful
  328. ;    d0.l = -1 if timeout
  329. ;
  330. ; Trashes:
  331. ;    d0, d1, d2, a2
  332. ;-
  333. sblkacsi:
  334.     move.b    #$88,d1            ; next byte is the opcode
  335.     move.w    d1,XWDL(a1)    ;WDL
  336.  
  337.     move.b    #$8a,d1            ; following bytes are operands
  338.     lea    _cmdblk,a2        ; a2 = address of command block
  339.  
  340.     tst.w    d0            ; is unit # already in command block
  341.     bmi.s    .0            ; if yes, just send command block
  342.                     ; else integrate unit # into cmd blk
  343.     lsl.b    #5,d0            ; shift unit number into place
  344.     or.b    d0,(a2)            ; first command byte = unit # | opcode
  345.                     ; control byte is sent seperately
  346. .0:    subq.w    #2,d2            ; and dbra likes one less 
  347. .1:    swap    d1            ; d1.hw = operand
  348.     move.b    (a2)+,d1        ; d1.lw = tells controller next byte
  349.     swap    d1            ;      is an operand
  350.     move.l    d1,(a1)        ;WDCWDL
  351.     bsr    _qdone
  352.     bmi.s    sbaend            ; if timeout, returns
  353.     dbra    d2,.1            ; else send rest of command block
  354.  
  355.     move.w    d1,XWDL(a1)    ;WDL    ; else get ready to send control byte
  356.     move.b    #0,d1            ; signal sending control byte
  357.     swap    d1            ; d1.hw = operand
  358.     move.b    (a2),d1            ; d1.lw = tells controller it's end
  359.     swap    d1            ;      of command
  360.     move.l    d1,(a1)            ; send it
  361.  
  362.     move.b    #$8a,d1            ; d1 = wdl value
  363. ;    bsr    _slwendcmd        ; wait for command completion
  364.     bsr    _endcmd            ; wait for command completion
  365. sbaend: rts                ; heading home
  366.  
  367.  
  368. ;+
  369. ; setadma() - set the ACSI DMA pointer
  370. ;
  371. ; Passed:
  372. ;    a0.l = buffer address
  373. ;-
  374. setadma:
  375.     move.l    a0,-(sp)        ; move it on stack
  376.     move.b    3(sp),DMALOW        ; set low-byte of address
  377.     move.b    2(sp),DMAMID        ; set mid-byte of address
  378.     move.b    1(sp),DMAHI        ; set high-byte of address
  379.     addq.l    #4,sp            ; clean up stack
  380.     rts
  381.  
  382.  
  383. ;+
  384. ; setacnt() - set the ACSI DMA counter
  385. ;
  386. ; Passed:
  387. ;    d1.l = count (in bytes)
  388. ;    a1.l = pointer to DMA chip
  389. ;-
  390. setacnt:
  391.     cmpi.l    #512,d1            ; transferring more than 512 bytes?
  392.     bhi.s    .0            ; if so, find transfer len in blocks
  393.     move.w    #$01,(a1)    ;WDC    ; else set DMA count to 1 block
  394.     bra.s    sacend
  395. .0:    move.l    d1,-(sp)        ; save transfer length (in bytes)
  396.     lsr.l    #8,d1            ; find transfer length (in blocks)
  397.     lsr.l    #1,d1            ; d1 >>= 9 = transfer len (in blocks)
  398.     move.w    d1,(a1)        ;WDC    ; set DMA count
  399.     move.l    (sp)+,d1        ; restore transfer length (in bytes)
  400. sacend:    rts
  401.  
  402.  
  403.  
  404. .if    !DRIVER                ; not to be included in driver
  405.  
  406. ;+
  407. ; fmtacsi() - format an ACSI unit
  408. ;
  409. ;    d0.w = physical unit number
  410. ;    d2.w = command length (NCMD or LCMD)
  411. ;-
  412.     .globl    _fmtacsi
  413.     .extern    _cmdblk
  414. _fmtacsi:
  415.     st    flock            ; lock FIFO
  416.     bsr    _delay            ; delay if necessary
  417.     movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  418.     andi.w    #7,d0            ; mask off the flags to get unit num
  419.     moveq    #0,d1            ; clear d1
  420.     move.b    #$88,d1            ; next byte is the opcode
  421.     move.w    d1,XWDL(a1)    ;WDL
  422.  
  423.     move.b    #$8a,d1            ; following bytes are operands
  424.     lea    _cmdblk,a2        ; a2 = address of command block
  425.                     ; integrate unit # into cmd blk
  426.     lsl.w    #5,d0            ; shift unit number into place
  427.     or.b    d0,(a2)            ; first command byte = unit # | opcode
  428.                     ; control byte is sent seperately
  429.     subq.w    #2,d2            ; and dbra likes one less 
  430. .0:    swap    d1            ; d1.hw = operand
  431.     move.b    (a2)+,d1        ; d1.lw = tells controller next byte
  432.     swap    d1            ;      is an operand
  433.     move.l    d1,(a1)        ;WDCWDL
  434.     bsr    _qdone
  435.     beq.s    .1            ; if successful, go on
  436.     rts                ; else it timed-out, returns
  437. .1:    dbra    d2,.0            ; send rest of command block
  438.  
  439.     move.w    d1,XWDL(a1)    ;WDL    ; else get ready to send control byte
  440.     move.b    #0,d1            ; signal sending control byte
  441.     swap    d1            ; d1.hw = operand
  442.     move.b    (a2),d1            ; d1.lw = tells controller it's end
  443.     swap    d1            ;      of command
  444.     move.l    d1,(a1)            ; send it
  445.  
  446.     move.b    #$8a,d1            ; d1 = wdl value
  447. .2:    btst    #5,GPIP            ; wait forever for command completion
  448.     bne.s    .2
  449.     bsr    cmdcmp            ; command completed
  450.     bra    _hdone            ; cleanup after IRQ
  451.  
  452.  
  453. ;+
  454. ; stacsi() - start/stop an ACSI unit
  455. ;
  456. ;    d0.w = physical unit number
  457. ;    d2.w = command length (NCMD or LCMD)
  458. ;-
  459.     .globl    _stacsi
  460.     .extern    _cmdblk
  461. _stacsi:
  462.     st    flock            ; lock FIFO
  463.     bsr    _delay            ; delay if necessary
  464.     movea.l    #WDC,a1            ; a1 = pointer to DMA chip
  465.     andi.w    #7,d0            ; mask off the flags to get unit num
  466.     moveq    #0,d1            ; clear d1
  467.     move.b    #$88,d1            ; next byte is the opcode
  468.     move.w    d1,XWDL(a1)    ;WDL
  469.  
  470.     move.b    #$8a,d1            ; following bytes are operands
  471.     lea    _cmdblk,a2        ; a2 = address of command block
  472.                     ; integrate unit # into cmd blk
  473.     lsl.w    #5,d0            ; shift unit number into place
  474.     or.b    d0,(a2)            ; first command byte = unit # | opcode
  475.                     ; control byte is sent seperately
  476.     subq.w    #2,d2            ; and dbra likes one less 
  477. .0:    swap    d1            ; d1.hw = operand
  478.     move.b    (a2)+,d1        ; d1.lw = tells controller next byte
  479.     swap    d1            ;      is an operand
  480.     move.l    d1,(a1)        ;WDCWDL
  481.     bsr    _slwqdone        ; needs a longer short timeout
  482.     beq.s    .1            ; if successful, go on
  483.     rts                ; else it timed-out, returns
  484. .1:    dbra    d2,.0            ; send rest of command block
  485.  
  486.     move.w    d1,XWDL(a1)    ;WDL    ; else get ready to send control byte
  487.     move.b    #0,d1            ; signal sending control byte
  488.     swap    d1            ; d1.hw = operand
  489.     move.b    (a2),d1            ; d1.lw = tells controller it's end
  490.     swap    d1            ;      of command
  491.     move.l    d1,(a1)            ; send it
  492.  
  493.     move.b    #$8a,d1            ; d1 = wdl value
  494.     bsr    _slwendcmd        ; wait for command completion
  495.     bra    _hdone            ; cleanup after IRQ
  496.  
  497. .endif    ;!DRIVER
  498.  
  499.  
  500. ;+
  501. ; Rstdelay()
  502. ;    After talking to the DMA chip in a way that may reset it, 
  503. ; we need a 8 8Mhz clocks (ie. 1 microsec) delay, before we can
  504. ; talk to the chip again.
  505. ;-
  506. rstdelay:
  507.     tst.b    GPIP            ; delay for 1 microsec
  508.     tst.b    GPIP            ; this amounts to 16 16Mhz clocks
  509.     tst.b    GPIP
  510.     tst.b    GPIP
  511.     rts
  512.  
  513.