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