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