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 / TTFHDX / IDE.500 < prev    next >
Encoding:
Text File  |  2001-02-09  |  21.4 KB  |  797 lines

  1. ;+
  2. ; Edit History
  3. ;
  4. ; Sep-05-90    ml.    Created this for drives on the IDE bus.
  5. ;
  6. ; Mar-28-91    ml.    Do not use the IDE Sector Count Register 
  7. ;            to count down mulitiple sectors read or
  8. ;            write.  Some vendors (e.g. Conner and 
  9. ;            Seagate) seem to update this register 
  10. ;            too early, and every now and then, the
  11. ;            last sector of data would remain in the
  12. ;            internal sector buffer.  
  13. ;            
  14. ;            Code in ideread() and idewrite() are modified
  15. ;            not to use the IDE Sector Count Register.
  16. ;
  17. ; Aug-16-91    ml.    W4int() has been modified, in the case of
  18. ;            an error occurred, to return value in the 
  19. ;            Status register for driver code, and return 
  20. ;            value in the Error register for non-driver
  21. ;            code.
  22. ;-
  23.  
  24. .include    "defs.h"
  25. .include    "sysvar.h"
  26. .include    "mfp.h"
  27. .include    "error.h"
  28. .include    "ide.h"
  29. .include    "blitter.h"
  30.  
  31. .if    DRIVER
  32. .extern    _useblit
  33. .else
  34. _useblit:    dc.b    0
  35. .endif    ;DRIVER
  36.  
  37. ;+
  38. ; Wait for status to come back
  39. ;-
  40. w4int:    move.l    #D_WORST,d0    ; d0 = timeout limit
  41.     add.l    _hz_200,d0    ; d0 = expiration time
  42. .0:    btst.b    #5,GPIP        ; interrupt?
  43.     beq.s    .1        ; if so, out of the loop
  44.     cmp.l    _hz_200,d0    ; timeout?
  45.     bhi.s    .0        ; if not, wait some more
  46.     moveq    #$ff,d0        ; else, return timeout
  47.     bra.s    .3
  48. .1:    moveq    #0,d0        ; clear d0
  49.     move.b    IDESR,d0    ; d0.b = status returned
  50.     btst    #ERR,d0        ; any error?
  51.  
  52. .if    !DRIVER            ; for non-driver code
  53.     beq.s    .2        ; if no error, go on
  54.     move.b    IDEER,d0    ; else d0.b = error bits
  55.     bra.s    .3        ; return with error
  56.  
  57. .else                ; for driver code
  58.     bne.s    .3        ; if error, return
  59. .endif    ;!DRIVER
  60.  
  61. .2:    btst    #DRQ,d0        ; else DRQ?
  62.     bne.s    .3        ; if so, just return
  63.     moveq    #0,d0        ; else return OK
  64. .3:    rts            ; return status or error code
  65.  
  66.  
  67.  
  68. ;+
  69. ; ideread() - reads from 1 to 256 sectors as specified in the Task File,
  70. ;        beginning at the specified sector.
  71. ;        - sector count equal to 0 requests 256 sectors.
  72. ;
  73. ; ideread(nhd, nspt, sectnum, count, buf, pdev)
  74. ; WORD    nhd;        4(sp).w        ; # of data heads on pdev
  75. ; WORD    nspt;        6(sp).w        ; # of sectors per track
  76. ; LONG    sectnum;    8(sp).l        ; logical block address
  77. ; WORD    count;        $c(sp).w    ; # of sectors to read
  78. ; BYTE    *buf;        $e(sp).l    ; $f(sp)=high $10(sp)=mid $11(sp)=low
  79. ; WORD    pdev;        $12(sp).w    ; physical device number
  80. ;-
  81.     .globl    _ideread
  82. _ideread:
  83.     bsr    set_dhcs    ; set physical address
  84.     move.l    $e(sp),a0    ; a0 -> buffer to read into
  85.     move.b    $d(sp),IDESC    ; set sector count
  86.  
  87.     move.w    $c(sp),d1    ; d1.w = # of sectors to read
  88.     subq    #1,d1        ; dbra likes one less
  89.  
  90.     tst.b    _useblit    ; BLiTTER exists?
  91.     beq.s    .0        ; if not, don't use it
  92.     moveq    #0,d0        ; else it's a read
  93.     bsr    initblit    ; initialize the BLiTTER
  94.  
  95. .0:    move.b    #0,IDEDOR    ; enable interrupt
  96.     move.b    #READ,IDECR    ; set command code
  97. .1:    bsr    w4int        ; wait for interrupt
  98.     tst.w    d0        ; successful?
  99.     bmi.s    .2        ; if timed-out, return
  100.     btst    #DRQ,d0        ; DRQ?
  101.     beq.s    .2        ; if not, return
  102.                 ; else
  103.     bsr    readbuf        ; transfer data
  104.     dbra    d1,.1        ; go wait for next interrupt
  105.     moveq    #0,d0        ; everything is fine
  106. .2:    rts
  107.  
  108.  
  109. ;+
  110. ; idewrite() - writes from 1 to 256 sectors as specified in the Task File,
  111. ;        beginning at the specified sector.
  112. ;         - sector count equal to 0 requests 256 sectors.
  113. ;
  114. ; idewrite(nhd, nspt, sectnum, count, buf, pdev)
  115. ; WORD    nhd;        4(sp).w        ; # of data heads on pdev
  116. ; WORD    nspt;        6(sp).w        ; # of sectors per track
  117. ; LONG    sectnum;    8(sp).l        ; logical block address
  118. ; WORD    count;        $c(sp).w    ; # sectors to read
  119. ; BYTE    *buf;        $e(sp).l    ; $f(sp)=high $10(sp)=mid $11(sp)=low
  120. ; WORD    pdev;        $12(sp).w    ; physical device number
  121. ;-
  122.     .globl    _idewrite
  123. _idewrite:    
  124.     bsr    set_dhcs    ; set physical address
  125.     move.l    $e(sp),a0    ; a0 -> buffer to write from
  126.     move.b    $d(sp),IDESC    ; set sector count
  127.  
  128.     move.w    $c(sp),d1    ; d1.w = # of sectors to read
  129.     subq    #1,d1        ; dbra likes one less
  130.  
  131.     tst.b    _useblit    ; BLiTTER exists?
  132.     beq.s    .0        ; if not, don't use it
  133.     moveq    #1,d0        ; it's a write
  134.     bsr    initblit    ; initialize the BLiTTER
  135.  
  136. .0:    move.b    #0,IDEDOR    ; enable interrupt
  137.     move.b    #WRITE,IDECR    ; set command code
  138. .1:    btst.b    #DRQ,IDEASR    ; DRQ?
  139.     beq.s    .1        ; if not, wait longer
  140.  
  141. .2:    bsr    wrtbuf        ; transfer data
  142.     bsr    w4int        ; wait for interrupt
  143.     tst.w    d0        ; successful?
  144.     bmi.s    .3        ; if timed-out, return
  145.     btst    #DRQ,d0        ; DRQ?
  146.     beq.s    .3        ; if not, return
  147.     dbra    d1,.2        ; else go transfer data
  148.     moveq    #0,d0        ; everything is fine
  149. .3:    rts
  150.  
  151.  
  152. ;+
  153. ; set_dhcs() - convert a logical block address into a physical address.
  154. ;         - set drive #, head #, cylinder # and sector # in task file.
  155. ;
  156. ; Passed:
  157. ;    8(sp).w = nhd = # of data heads
  158. ;    $a(sp).w = nspt = # of sectors per track
  159. ;    $c(sp).l = logical block address
  160. ;    $16(sp).w = physical unit #
  161. ;-
  162. set_dhcs:
  163.     move.l    $c(sp),d1    ; d1.l = logical block address
  164.     move.w    8(sp),d2    ; d2.w = # of data heads
  165.     move.w    $a(sp),d0    ; d0.w = # of sectors per track
  166.     mulu    d0,d2        ; d2.l = # of sectors per cylinder
  167.                 ;      = # heads * # of sectors per track
  168.     divu.w    d2,d1        ; d1.w = cylinder #
  169.                 ;      = log block addr / #spc
  170.     move.b    d1,IDECL    ; set cylinder low
  171.     lsr.l    #8,d1        ; d1.b = cylinder high
  172.     move.b    d1,IDECH    ; set cylinder high
  173.     lsr.l    #8,d1        ; d1.l = sector # within the cyl
  174.     divu.w    d0,d1        ; d1.w = head #
  175.                 ;      = sector # within cyl / #spt
  176.     move.w    $16(sp),d0    ; d0.w = physical unit #
  177.     andi.b    #7,d0        ; mask off flags from physical unit #
  178.     lsl.b    #4,d0        ; shift unit # to place
  179.     or.b    d0,d1        ; or in drive #
  180.     move.b    d1,IDESDH    ; set drive and head #
  181.     swap    d1        ; d1.w = sector # (base 0)
  182.     addq.w    #1,d1        ;      = sector # + 1 (base 1)
  183.     move.b    d1,IDESN    ; set sector #
  184.     rts
  185.  
  186. ;+
  187. ; identify() - allows the Host to receive parameter information from
  188. ;           the drive.
  189. ;
  190. ; identify(pdev, buf)
  191. ; WORD    pdev;    4(sp).w        ; physical unit #
  192. ; BYTE    *buf;    6(sp).l        ; buffer to put data
  193. ;-
  194.     .globl    _identify
  195. _identify:
  196.     move.w    4(sp),d0    ; d0 = physical unit #
  197.     andi.b    #7,d0        ; mask off flags (if any)
  198.     lsl.b    #4,d0        ; shift unit # to place
  199.     move.b    d0,IDESDH    ; set drive #
  200.     move.l    6(sp),a0    ; a0 -> buffer
  201.  
  202.     tst.b    _useblit    ; BLiTTER exists?
  203.     beq.s    .0        ; if not, no need to init it
  204.     moveq    #0,d0        ; it's a read
  205.     bsr    initblit    ; initialize the BLiTTER
  206.  
  207. .0:    move.b    #0,IDEDOR    ; enable interrupt
  208.     move.b    #IDENTIFY,IDECR    ; set command code
  209.     bsr    w4int        ; wait for interrupt
  210.     tst.w    d0        ; successful?
  211.     bmi.s    .1        ; if timed-out, return
  212.     btst    #DRQ,d0        ; DRQ?
  213.     beq.s    .1        ; if not, return with error
  214.  
  215.     bsr    readbuf        ; read data
  216.     moveq    #0,d0        ; everything is fine
  217. .1:    rts 
  218.  
  219.  
  220. ;+
  221. ; awto() - set drive to Active mode with timeout counter (in 5s increments)
  222. ;
  223. ; awto(pdev, timeout)
  224. ; WORD    pdev;        4(sp).w        ; physical unit #
  225. ; WORD    timeout;    6(sp).w
  226. ;-
  227.     .globl    _awto
  228. _awto:    
  229.     move.w    4(sp),d0    ; d0 = physical unit #
  230.     andi.b    #7,d0        ; mask off flags (if any)
  231.     lsl.b    #4,d0        ; shift unit # to place
  232.     move.b    d0,IDESDH    ; set drive #
  233.     move.b    7(sp),IDESC    ; set timeout counter
  234.     move.b    #AWTO,IDECR    ; set command code
  235.     bra    w4int        ; go wait for interrupt
  236.  
  237.  
  238. ;+
  239. ; readbuf() - reads 512 bytes (128 longs) of data from the sector
  240. ;        buffer.
  241. ;
  242. ; Comments:
  243. ;    A tower of 8 move.l is used to try to speed up the transfer.
  244. ;
  245. ; Passed:
  246. ;    a0.l = buffer to store data read from sector buffer
  247. ;
  248. ;    if BLiTTER code
  249. ;    a1.l = base address of BLiTTER
  250. ;-
  251. readbuf:
  252.     tst.b    _useblit    ; BLiTTER exists?
  253.     beq.s    .0        ; if not, do programmed IO
  254.     move.w    #1,YCNT(a1)    ; one destination line
  255.     move.b    #$80,BUSY(a1)    ; start the BLiTTER
  256.     bsr    restart
  257.     addq.l    #2,DESTADDR(a1)    ; advance to next word of destination
  258.     rts
  259.                 ; Programmed IO
  260. .0:    moveq    #15,d0        ; d0 = (# of longs to read / 8) - 1
  261.     lea    IDEDR,a1    ; a1 -> data bus
  262. .1:    move.l    (a1),(a0)+    ; read data from bus
  263.     move.l    (a1),(a0)+    ; read data from bus
  264.     move.l    (a1),(a0)+    ; read data from bus
  265.     move.l    (a1),(a0)+    ; read data from bus
  266.     move.l    (a1),(a0)+    ; read data from bus
  267.     move.l    (a1),(a0)+    ; read data from bus
  268.     move.l    (a1),(a0)+    ; read data from bus
  269.     move.l    (a1),(a0)+    ; read data from bus
  270.     dbra    d0,.1        ; repeat until all done
  271.     rts
  272.  
  273.  
  274. ;+
  275. ; wrtbuf() - writes 512 bytes (128 longs) of data to sector buffer.
  276. ;
  277. ; Passed:
  278. ;    a0.l = buffer with data to write to sector buffer
  279. ;-
  280. wrtbuf:
  281.     tst.b    _useblit    ; BLiTTER exists?
  282.     beq.s    .0        ; if not, do programmed IO
  283.     move.w    #1,YCNT(a1)    ; one destination line
  284.     move.b    #$80,BUSY(a1)    ; start the BLiTTER
  285.     bsr    restart
  286.     addq.l    #2,SRCADDR(a1)    ; advance to next word of source
  287.     rts
  288.                 ; Programmed IO
  289. .0:    moveq    #15,d0        ; d0 = (# longs to write / 8) - 1
  290.     lea    IDEDR,a1    ; a1 -> data bus
  291. .1:    move.l    (a0)+,(a1)    ; write data to bus
  292.     move.l    (a0)+,(a1)    ; write data to bus
  293.     move.l    (a0)+,(a1)    ; write data to bus
  294.     move.l    (a0)+,(a1)    ; write data to bus
  295.     move.l    (a0)+,(a1)    ; write data to bus
  296.     move.l    (a0)+,(a1)    ; write data to bus
  297.     move.l    (a0)+,(a1)    ; write data to bus
  298.     move.l    (a0)+,(a1)    ; write data to bus
  299.     dbra    d0,.1        ;  repeat until all done
  300.     rts
  301.  
  302.  
  303. ;+
  304. ; initblit() - initialize the BLiTTER chip for 512 bytes I/O transfer
  305. ;
  306. ; Passed:
  307. ;    a0.l = destination address if read; source address if write
  308. ;    d0.w = flag to tell whether it's a read or a write
  309. ;-
  310. initblit:
  311.     lea    bBLiTTER,a1        ; a1 -> BLiTTER register map
  312.     tst.b    d0            ; read or write?
  313.     bne.s    ib0            ; (write)
  314.     move.l    #IDEDR,SRCADDR(a1)    ; source addr = IDE data register
  315.     move.l    a0,DESTADDR(a1)        ; destination addr = given buffer
  316.     move.w    #2,DESTXINC(a1)        ; words read
  317.     moveq    #0,d0
  318.     move.w    d0,SRCXINC(a1)        ; never increment source X
  319.     bra.s    ib1
  320.                     ; initialize BLiTTER to write to disk
  321. ib0:    move.l    a0,SRCADDR(a1)        ; source addr = write buffer
  322.     move.l    #IDEDR,DESTADDR(a1)    ; destination addr = IDE data reg
  323.     move.w    #2,SRCXINC(a1)        ; words write
  324.     moveq    #0,d0
  325.     move.w    d0,DESTXINC(a1)        ; never increment destination X
  326.  
  327. ib1:    move.w    d0,SRCYINC(a1)        ; never increment source Y
  328.     move.w    d0,DESTYINC(a1)        ; never increment destination Y
  329.     move.b    d0,SKEW(a1)        ; no skew
  330.     moveq    #$ff,d0
  331.     move.l    d0,ENDMASK1(a1)        ; change all bits at destination
  332.     move.w    d0,ENDMASK3(a1)        ; change all bits at destination
  333.     move.w    #$203,HOP(a1)        ; set HOP and OP to source
  334.     move.w    #256,XCNT(a1)        ; num of words to transfer
  335.     rts
  336.  
  337.  
  338. ;+
  339. ; restart() - restart the BLiTTER
  340. ;
  341. ; Passed:
  342. ;    a1.l = base address of BLiTTER
  343. ;-
  344. restart:
  345.     nop
  346.     tas    BUSY(a1)    ; restart BLiTTER and test if busy
  347.     bmi.s    restart        ; quit if not busy
  348.     rts
  349.  
  350.  
  351. .if    !DRIVER
  352.  
  353. ;+
  354. ; clrsbuf() - clear the scratch buffer
  355. ;-
  356. clrsbuf:
  357.     movem.l    d0/a0,-(sp)    ; save d0 and a0
  358.     lea    sbuf,a0        ; a0 -> scratch buffer
  359.     move.w    #127,d0        ; d0 = counter
  360. .0:    clr.l    (a0)+        ; clear 4 bytes
  361.     dbra    d0,.0        ; repeat until done
  362.     movem.l    (sp)+,d0/a0    ; restore d0 and a0
  363.     rts
  364.  
  365.  
  366. ;+
  367. ; recal() - moves the R/W heads from anywhere on the disk to cylinder 0.
  368. ;
  369. ; recal(pdev)
  370. ; WORD    pdev;    $4(sp).w
  371. ;-
  372.     .globl    _recal
  373. _recal:    move.w    4(sp),d0    ; d0 = physical unit #
  374.     andi.b    #7,d0        ; mask off flags (if any)
  375.     lsl.b    #4,d0        ; shift unit # to place
  376.     move.b    d0,IDESDH    ; write drive #
  377.     move.b    #0,IDEDOR    ; enable interrupt
  378.     move.b    #RECAL,IDECR    ; write command code
  379.     bra    w4int        ; go wait for interrupt
  380.  
  381.  
  382. ;+
  383. ; verify() - functions similarly to read() except that no data is
  384. ;         transferred to the host.
  385. ;-
  386.     .globl    _verify
  387. _verify:
  388.     move.w    $e(sp),d0    ; d0.w = physical unit #
  389.     move.l    4(sp),d1    ; d1.l = starting logical sector #
  390.     bsr    set_dhcs    ; set drive#, head#, cylinder# and sector#
  391.     move.l    $a(sp),a0    ; a0 -> buffer to write from
  392.     move.b    9(sp),IDESC    ; set sector count
  393.     move.b    #0,IDEDOR    ; enable interrupt
  394.     move.b    #VERIFY,IDECR    ; set command code
  395. .0:    bsr    w4int        ; wait for interrupt
  396.     bne.s    .1        ; if has error, return
  397.     tst.b    IDESC        ; more to verify?
  398.     bne.s    .0        ; if so, continue
  399.     moveq    #0,d0        ; everything's fine
  400. .1:    rts
  401.  
  402.  
  403. ;+
  404. ; fmtunt() - formats a unit
  405. ;       - always formats sectors as good ones.
  406. ;       - interleave 1:1.
  407. ;
  408. ; fmtunt(pdev)
  409. ; WORD    pdev;    4(sp).w
  410. ;-
  411.     .globl    _fmtunt
  412. _fmtunt:
  413.     pea    sbuf        ; scratch buffer
  414.     move.w    $8(sp),-(sp)    ; physical unit #
  415.     bsr    _identify    ; identify(pdev, buf)
  416.     addq.w    #6,sp        ; clean up stack
  417.     tst.w    d0        ; successful?
  418.     bne    .4        ; if not, return
  419.                 ; else 
  420.     move.l    #sbuf,-(sp)    ; get default drive parameters
  421.     bsr    getdparm    ;  from _identify() data
  422.     addq    #4,sp        ; clean up stack
  423.  
  424.     movem.l    d0-d2,-(sp)    ; save drive parameters
  425.     move.w    d2,-(sp)    ; sectors per track
  426.     move.w    d1,-(sp)    ; # of heads
  427.     move.w    $14(sp),-(sp)    ; physical unit #
  428.     bsr    _initparm    ; set drive to default mode
  429.     addq.w    #6,sp        ; clean up stack
  430.     tst.w    d0        ; successful?
  431.     beq.s    .5        ; if so, go format
  432.     adda.l    #12,sp        ; else clean up stack
  433.     bra    .4        ; and return
  434.  
  435. .5:    movem.l    (sp)+,d0-d2    ; restore drive parameters
  436.                 ; fill format data
  437.     bsr    clrsbuf        ; clear scratch buffer
  438.     move.l    d3,-(sp)    ; save d3
  439.     moveq    #1,d3        ; d3 = sector # (starts with sector 1)
  440.     lea    sbuf,a1        ; a1 -> _identify() data buffer
  441. .0:    move.b    d3,(a1)+    ; set sector #
  442.     clr.b    (a1)+        ; format sector good
  443.     addq.b    #1,d3        ; next sector #
  444.     cmp.b    d3,d2        ; all sector # set?
  445.     bcc.s    .0        ; if not, continue
  446.     move.l    (sp)+,d3    ; restore d3
  447.                 ; format unit
  448.     move.w    4(sp),d2    ; d2.w = physical unit #
  449.     andi.b    #7,d2        ; mask off flags (if any)
  450.     lsl.b    #4,d2        ; shift physical unit # into place
  451.     move.b    d2,IDESDH    ; set physical unit #
  452.     subq.w    #1,d0        ; dbra likes one less
  453.     subq.w    #1,d1        ; dbra likes one less
  454.     move.w    d1,d2        ; d2 = # heads - 1
  455. .1:    move.w    d2,d1        ; reinitialize head number for next cylinder
  456.     lea    sbuf,a0        ; a0 -> format data
  457. .2:    movem.l    d0-d2/a0,-(sp)    ; save cylinder and head counts
  458.     bsr    _fmttrk        ; format track of current cylinder and head
  459.     beq.s    .3        ; if successful, continue
  460.     adda.l    #16,sp        ; else clean up stack
  461.     rts            ; and return
  462. .3:    movem.l    (sp)+,d0-d2/a0    ; restore cylinder and head counts
  463.     dbra    d1,.2        ; for all heads
  464.     dbra    d0,.1        ; for all cylinders
  465.     moveq    #0,d0        ; everything's fine
  466. .4:    rts
  467.  
  468.  
  469. ;+
  470. ; fmttrk() - formats a track with format data provided.
  471. ;
  472. ; Passed:
  473. ;    d0.w = cylinder #
  474. ;    d1.w = head #
  475. ;    a0.l -> format data
  476. ;-
  477.     .globl    _fmttrk
  478. _fmttrk:
  479.     andi.b    #$f0,IDESDH    ; erase previous head #
  480.     or.b    d1,IDESDH    ; set new head #
  481.     move.b    d0,IDECL    ; set cylinder low
  482.     lsr.w    #8,d0        ; d0.b = cylinder high
  483.     move.b    d0,IDECH    ; set cylinder high
  484.     move.b    #0,IDEDOR    ; enable interrupt
  485.     move.w    #256,d1        ; d1.w = word count
  486.  
  487.     tst.b    _useblit    ; use BLiTTER?
  488.     beq.s    .0        ; if not, no need to init it
  489.     moveq    #1,d0        ; write through BLiTTER
  490.     bsr    initblit    ; initialize the BLiTTER
  491.  
  492. .0:    move.b    #FMTTRK,IDECR    ; set command code
  493. .1:    btst.b    #DRQ,IDEASR    ; DRQ?
  494.     beq.s    .1        ; if not, wait longer
  495.  
  496.     bsr    wrtbuf        ; write format data to sector buffer
  497.     bra    w4int
  498.  
  499.  
  500. ;+
  501. ; getdparm() - get default drive parameters from the data buffer
  502. ;        returned by _identify().
  503. ;
  504. ; getdparm(buf)
  505. ; WORD    *buf;    $4(sp).l
  506. ;
  507. ; Returns:
  508. ;    d0.w = # of default cylinders
  509. ;    d1.w = # of default heads
  510. ;    d2.w = # of default sectors per track
  511. ;
  512. ; Comments:
  513. ;    This routine distinguishes the Conner drives from the rest
  514. ; because Conner put their default values in a reserved area.
  515. ;-
  516. getdparm:
  517.     move.l    4(sp),a1    ; a1 <- ptr to data buffer
  518.     move.l    a1,a2        ; a2 <- ptr to data buffer
  519.     adda.l    #MDLNUM,a1    ; a1 <- ptr to drive model number
  520.     cmpi.b    #'C',(a1)+    ; check if it's a Conner drive
  521.     bne.s    other        ; if not, get parameters at 
  522.     cmpi.b    #'o',(a1)+    ;   common location
  523.     bne.s    other
  524.     cmpi.b    #'n',(a1)+
  525.     bne.s    other
  526.     cmpi.b    #'n',(a1)+
  527.     bne.s    other
  528.     cmpi.b    #'e',(a1)+
  529.     bne.s    other
  530.     cmpi.b    #'r',(a1)+
  531.     bne.s    other
  532.  
  533.     move.w    CPNCYL(a2),d0    ; else get parameters at Conner
  534.     moveq    #0,d1        ;   reserved location
  535.     move.b    CPNHEAD(a2),d1
  536.     moveq    #0,d2
  537.     move.b    CPNSPT(a2),d2
  538.     rts
  539.  
  540. other:    move.w    NCYL(a2),d0    ; d0.w = # of cylinders
  541.     move.w    NHEAD(a2),d1    ; d1.w = # of heads
  542.     move.w    NSPT(a2),d2    ; d2.w = # of sectors per track
  543.     rts
  544.  
  545.  
  546. ;+
  547. ; seek() - initiates a seek to the track and selects the head 
  548. ;       specified in the Task File.
  549. ;
  550. ; seek(pdev, head, cyl)
  551. ; WORD    pdev;    $4(sp).w
  552. ; WORD    head;    $6(sp).w
  553. ; WORD    cyl;    $8(sp).w
  554. ;-
  555.     .globl    _seek
  556. _seek:    move.w    4(sp),d0    ; d0 = physical unit #
  557.     andi.b    #7,d0        ; mask off flags
  558.     lsl.b    #4,d0        ; shift unit # to place
  559.     or.b    7(sp),d0    ; b4 of d0 = drive #; b3-b0 of d0 = head #;
  560.     move.b    d0,IDESDH    ; set drive and head #
  561.     move.b    #0,IDEDOR    ; enable interrupt
  562.     move.b    9(sp),IDECL    ; set cylinder low
  563.     move.b    8(sp),IDECH    ; set cylinder high
  564.     move.b    #SEEK,IDECR    ; set command code
  565.     bra    w4int        ; go wait for interrupt
  566.  
  567.  
  568. ;+
  569. ; diag() - performs the internal diagnostic tests implemented by 
  570. ;       the drive.
  571. ;-
  572.     .globl    _diag
  573. _diag:    move.b    #0,IDEDOR    ; enable interrupt
  574.     move.b    #DIAG,IDECR    ; set command code
  575.     bra    w4int
  576.  
  577.  
  578. ;+
  579. ; initparm() - enables the host to set the head switch and cylinder
  580. ;           increment points for multiple sector operations.
  581. ;
  582. ; initparm(pdev, head, spt)
  583. ; WORD     pdev;    4(sp).w
  584. ; WORD    head;    6(sp).w
  585. ; WORD    spt;    8(sp).w
  586. ;-
  587.     .globl    _initparm
  588. _initparm:
  589.     move.w    4(sp),d0    ; d0 = physical unit #
  590.     andi.b    #7,d0        ; mask off flags
  591.     lsl.w    #4,d0        ; shift it into place
  592.     move.b    d0,IDESDH    ; set physical unit #
  593.     move.w    6(sp),d0    ; d0 = # of heads
  594.     subq.b    #1,d0        ; maximum head #
  595.     or.b    d0,IDESDH    ; set head #
  596.     move.b    9(sp),IDESC    ; set sectors per track
  597.     move.b    #0,IDEDOR    ; enable interrupt
  598.     move.b    #INITPARM,IDECR    ; set command code
  599.     bra    w4int        ; go wait for interrupt
  600.  
  601.  
  602. ;+
  603. ; rsbuf() - allows the Host to read the current contents of the
  604. ;        drive's sector buffer.
  605. ;
  606. ; rsbuf(pdev, buf)
  607. ; WORD    pdev;    4(sp).w
  608. ; BYTE    *buf;    6(sp).l
  609. ;-
  610.     .globl    _rsbuf
  611. _rsbuf:    move.w    4(sp),d0    ; d0 = physical unit #
  612.     andi.b    #7,d0        ; mask off flags (if any)
  613.     lsl.w    #4,d0        ; shift it into place
  614.     move.b    d0,IDESDH    ; set physical unit #
  615.     move.l    6(sp),a0    ; a0 -> buffer
  616.     move.w    #256,d1
  617.  
  618.     tst.b    _useblit    ; BLiTTER exists?
  619.     beq.s    .0        ; if not, don't use it
  620.     moveq    #0,d0        ; it's a read
  621.     bsr    initblit    ; initialize the BLiTTER
  622.  
  623. .0:    move.b    #0,IDEDOR    ; enable interrupt
  624.     move.b    #RSBUF,IDECR    ; set command code
  625.     bsr    w4int        ; go wait for interrupt
  626.     tst.w    d0        ; successful?
  627.     bmi.s    .1        ; if timed-out, return
  628.     btst    #DRQ,d0        ; DRQ?
  629.     beq.s    .1        ; if not, return with error
  630.  
  631.     bsr    readbuf        ; read data
  632.     moveq    #0,d0        ; everything is fine
  633. .1:    rts 
  634.  
  635.  
  636. ;+
  637. ; wsbuf() - allows the Host to overwrite the contents of the drive's
  638. ;        sector buffer.
  639. ;
  640. ; wsbuf(pdev, buf)
  641. ; WORD    pdev;    4(sp).w
  642. ; BYTE    *buf;    6(sp).l
  643. ;-
  644.     .globl    _wsbuf
  645. _wsbuf:    move.w    4(sp),d0    ; d0 = physical unit #
  646.     andi.b    #7,d0        ; mask off flags (if any)
  647.     lsl.w    #4,d0        ; shift it into place
  648.      move.b    d0,IDESDH    ; set physical unit #
  649.     move.l    6(sp),a0    ; a0 -> buffer
  650.     move.w    #256,d0        ; d0 = word count
  651.  
  652.     tst.b    _useblit    ; BLiTTER exists?
  653.     beq.s    .0        ; if not, don't use it
  654.     moveq    #0,d0        ; it's a read
  655.     bsr    initblit    ; initialize the BLiTTER
  656.  
  657. .0:    move.b    #WSBUF,IDECR    ; set command code
  658. .1:    btst    #DRQ,IDESR    ; DRQ?
  659.     beq.s    .1        ; if not, wait some more
  660.  
  661.     bsr    wrtbuf        ; write data
  662.     moveq    #0,d0        ; everything is fine
  663.     rts
  664.  
  665.  
  666. ;+
  667. ; standby() - set drive to Standby mode
  668. ;
  669. ; standby(pdev)
  670. ; WORD    pdev;    4(sp).w        ; physical unit #
  671. ;-
  672.     .globl    _standby
  673. _standby:
  674.     move.w    4(sp),d0    ; d0 = physical unit #
  675.     andi.b    #7,d0        ; mask off flags (if any)
  676.     lsl.b    #4,d0        ; shift unit # to place
  677.     move.b    d0,IDESDH    ; set drive #
  678.     move.b    #STANDBY,IDECR    ; set command code
  679.     bra    w4int        ; go wait for interrupt
  680.  
  681.  
  682. ;+
  683. ; active() - set drive to Active mode
  684. ;
  685. ; active(pdev)
  686. ; WORD    pdev;    4(sp).w        ; physical unit #
  687. ;-
  688.     .globl    _active
  689. _active:
  690.     move.w    4(sp),d0    ; d0 = physical unit #
  691.     andi.b    #7,d0        ; mask off flags (if any)
  692.     lsl.b    #4,d0        ; shift unit # to place
  693.     move.b    d0,IDESDH    ; set drive #
  694.     move.b    #ACTIVE,IDECR    ; set command code
  695.     bra    w4int        ; go wait for interrupt
  696.  
  697.  
  698. ;+
  699. ; sbwto() - set drive to Standby mode with timeout counter (in 5s increments)
  700. ;
  701. ; sbwto(pdev, timeout)
  702. ; WORD    pdev;        4(sp).w        ; physical unit #
  703. ; WORD    timeout;    6(sp).w
  704. ;-
  705.     .globl    _sbwto
  706. _sbwto:    
  707.     move.w    4(sp),d0    ; d0 = physical unit #
  708.     andi.b    #7,d0        ; mask off flags (if any)
  709.     lsl.b    #4,d0        ; shift unit # to place
  710.     move.b    d0,IDESDH    ; set drive #
  711.     move.b    7(sp),IDESC    ; set timeout counter
  712.     move.b    #SBWTO,IDECR    ; set command code
  713.     bra    w4int        ; go wait for interrupt
  714.  
  715.  
  716. ;+
  717. ; ssc() - set sector count wrt current mode of drive
  718. ;
  719. ; ssc(pdev)
  720. ; WORD    pdev;    4(sp).w        ; physical unit #
  721. ;-
  722.     .globl    _ssc
  723. _ssc:    
  724.     move.w    4(sp),d0    ; d0 = physical unit #
  725.     andi.b    #7,d0        ; mask off flags (if any)
  726.     lsl.b    #4,d0        ; shift unit # to place
  727.     move.b    d0,IDESDH    ; set drive #
  728.     move.b    #SSC,IDECR    ; set command code
  729.     bra    w4int        ; go wait for interrupt
  730.  
  731.  
  732. ;+
  733. ; sbres() - set drive to Standby mode.
  734. ;      - drive will not wake up until reset is sent to drive
  735. ;
  736. ; sbres(pdev)
  737. ; WORD    pdev;    4(sp).w        ; physical unit #
  738. ;-
  739.     .globl    _sbres
  740. _sbres:    
  741.     move.w    4(sp),d0    ; d0 = physical unit #
  742.     andi.b    #7,d0        ; mask off flags (if any)
  743.     lsl.b    #4,d0        ; shift unit # to place
  744.     move.b    d0,IDESDH    ; set drive #
  745.     move.b    #SBRES,IDECR    ; set command code
  746.     bra    w4int        ; go wait for interrupt
  747.  
  748.  
  749. ;+
  750. ; slave() - test if the slave drive exists
  751. ;
  752. ; Returns: 0 - if slave does not exist
  753. ;       1 - if slave exists
  754. ;-
  755.     .globl    _slave
  756. _slave:    moveq    #0,d0        ; assume slave does NOT exist
  757.     bset.b    #4,IDESDH    ; set drive bit to 1 (slave)
  758.     btst.b    #DRDY,IDESR    ; is slave ready?
  759.     beq.s    .0        ; if not, no slave
  760.     moveq    #1,d0        ; else, slave exists
  761. .0:    rts
  762.  
  763.  
  764. ;+
  765. ; _iderdy() - test if the IDE drive is ready
  766. ;
  767. ; Passed:
  768. ;    d0.b = IDE drive unit #
  769. ;
  770. ; Returns: 0 - if drive is NOT ready
  771. ;       1 - if drive is ready
  772. ;-
  773.     .globl    _iderdy
  774. _iderdy:
  775.     andi.b    #7,d0        ; mask off flags (if any)
  776.     lsl.b    #4,d0        ; shift unit # to place
  777.     move.b    d0,IDESDH    ; set drive #
  778.     move.b    #$50,d1        ; ready status
  779.     move.l    #IDERDY,d0    ; set up timer
  780.     add.l    _hz_200,d0
  781. ir0:    cmp.b    IDEASR,d1    ; is drive ready and not busy?
  782.     beq.b    ir1        ; if so, return with drive ready
  783.     cmp.l    _hz_200,d0    ; time-out yet?
  784.     bcc.b    ir0        ; if not, wait longer
  785.     moveq    #0,d0        ; else return drive NOT ready
  786.     rts
  787. ir1:    moveq    #1,d0        ; else, drive is ready
  788.     rts
  789.  
  790.  
  791. .data
  792. sbuf:    dcb.b    512,0        ; scratch buffer
  793.  
  794. .endif    ;!DRIVER
  795.  
  796.  
  797.