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 / JWTSP.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  40.3 KB  |  1,884 lines

  1. * spscsi.s
  2.     .include "version.s"
  3.  
  4. sermsg        equ    0        ; for timeout messages
  5. MC68030        equ    0        ; running on a '30
  6. VERBOSE        equ    0        ; messages out ST MFP port task time
  7. SCDMA        equ    1        ; use DMA for SCSI transfers
  8. * HWDBUG    equ    1        ; DEFINE for hardware debug checks
  9. * NOCNT        equ    1        ; DEFINE for no DMA byte counting
  10.  
  11. ;;;
  12. ;
  13. ;    Sparrow SCSI hard disk driver
  14. ;    Copyright 1991 Atari Corp.
  15. ;
  16. ;  91.11.02 jtittsler    derived from acsc.s hack for the TT
  17. ;
  18.  
  19.   .if MC68030
  20.     .include "68030.s"
  21.   .endif ;MC68030
  22.  
  23. wdc        equ    $ffff8604
  24. wdl        equ    $ffff8606
  25. wdcwdl        equ    wdc        ; used for long writes
  26. xwdl        equ    wdl-wdc        ; offset from wdc to wdl
  27.  
  28. dmahi        equ    $ffff8609
  29. dmamid        equ    dmahi+2
  30. dmalow        equ    dmamid+2
  31. gpip        equ    $fffffa01
  32.  
  33. etv_critic    equ    $404        ; critical error handoff vector
  34. phystop        equ    $42e        ; physical top of memory
  35. flock        equ    $43e        ; FIFO lock variable
  36. _bootdev    equ    $446        ; default boot device
  37. _hz_200        equ    $4ba        ; system 200hz timer
  38. hdv_init    equ    $46a        ; hdv_init()
  39. hdv_bpb        equ    $472        ; hdv_bpb(dev)
  40. hdv_rw        equ    $476        ; hdv_rw(rw, buf, count, recno, dev)
  41. hdv_boot    equ    $47a        ; hdv_boot()
  42. hdv_mediach    equ    $47e        ; hdv_mediach(dev)
  43. _drvbits    equ    $4c2        ; block device bitVector
  44. _dskbufp    equ    $4c6        ; pointer to common disk buffer
  45. pun_ptr        equ    $516        ; pointer to physical unit table
  46.  
  47. maxunits    equ    16        ; maximum number of units
  48.   .if (^^defined HWDBUG)
  49. nretries    equ    1-1        ; #retries-1
  50.   .else ; HWDBUG
  51. nretries    equ    4-1        ; #retries-1
  52.   .endif ; HWDBUG
  53. MAXSECTORS    equ    254        ; maximum number of sectors at one gulp
  54.  
  55. EWRITF        equ    -10        ; GEMDOS error codes
  56. EREADF        equ    -11
  57. CRITRETRY    equ    $00010000    ; "retry" return code
  58.  
  59. * ---------------- Installer ----------------
  60.     .globl    i_sasi
  61. i_sasi:    bra.w    i_sasi1            ; GEMDOS entry-point
  62.     st    bootloaded        ; boot entry-point, set flag
  63.     move.l    a2,baseaddr        ; install base address
  64.     bra    i_sasi1            ; (continue with normal initialization)
  65.  
  66. bootloaded:    dc.w    0        ; nonzero if loaded from boot sector
  67. baseaddr:    dc.l    0        ; -> base addr of .PRG file
  68.  
  69.     dc.b    '@(#)spscsi.s '
  70.   .if !SCDMA
  71.     dc.b    '(NoDMA) '
  72.   .endif ;SCDMA
  73.   .if (^^defined HWDBUG)
  74.     dc.b    '(Hardware Debug) '
  75.   .endif ;HWDBUG
  76.   .if (^^defined NOCNT)
  77.     dc.b    '(NoByteCount) '
  78.   .endif ;NOCNT
  79.     dc.b    $0d,$0a
  80.     VERSION
  81.     dc.b    $0d,$0a,0,$1A
  82.     .even
  83.  
  84. * page 
  85. * ---------------- Front End ----------------
  86.  
  87.  
  88. *+
  89. * LONG hbpb(dev) - return ptr to BPB (or NULL)
  90. *
  91. * Passed:    dev    4(sp).W
  92. *
  93. *-
  94. hbpb:
  95.     move.w    4(sp),d0        ; d0 = devno
  96.     clr    d1            ; d1 = 0, physical op not possible
  97.     move.l    o_bpb,a0        ; a0 -> pass-through vector
  98.     lea    _sasi_bpb(pc),a1    ; a1 -> our handler
  99.     bra    check_dev        ; do it
  100.  
  101.  
  102.  
  103. *+
  104. * LONG hrw(rw, buf, count, recno, dev)
  105. *
  106. * Passed:    dev    $e(sp).W
  107. *        recno    $c(sp).W
  108. *        count    $a(sp).W
  109. *        buf    6(sp).L
  110. *        rw    4(sp).W
  111. *
  112. *-
  113. hrw:
  114.     move.w    $e(sp),d0        ; d0 = devno
  115.     move.w    4(sp),d1        ; d1 includes physical device flag
  116.     move.l    o_rw,a0            ; a0 -> pass-through vector
  117.     lea    _sasi_rw(pc),a1        ; a1 -> our handler
  118.     bra    check_dev        ; do it
  119.  
  120.  
  121.  
  122. *+
  123. * LONG hmediach(dev)
  124. *
  125. * Passed:    dev    4(sp).W
  126. *
  127. *-
  128. hmediach:
  129.     move.w    4(sp),d0        ; d0 = devno
  130.     clr    d1            ; physical operation not possible
  131.     move.l    o_mediach,a0        ; a0 -> pass-through vector
  132.     lea    _sasi_mediach(pc),a1    ; a1 -> our handler
  133.  
  134.  
  135. *+
  136. * check_dev - use handler, or pass vector through
  137. *
  138. * Passed:    d0.w = device#
  139. *        d1, bit 3  1=physical operation
  140. *        a0 ->  old handler
  141. *        a1 ->  new handler
  142. *        a5 ->  $0000 (zero-page ptr)
  143. *
  144. * Jumps-to:    (a1) if dev in range for this handler
  145. *        (a0) otherwise
  146. *
  147. *-
  148. check_dev:
  149.     btst    #3,d1            ; is this a physical unit operation?
  150.     beq    chkd_a
  151.  
  152. ;    subq    #2,d0            ; lowest device is C
  153. ;    bmi    chkd_f            ; not one of ours
  154.  
  155. ;    cmp    puns,d0
  156. ;    bge    chkd_f
  157.     bra    chkd_s
  158.  
  159. chkd_a:    lea    pun,a2            ; pointer to pun map
  160.     tst.b    0(a2,d0.w)        ; must be positive for a real unit
  161.     bmi    chkd_f
  162. chkd_s:    move.l    a1,a0            ; yes -- follow success vector
  163. chkd_f:    jmp    (a0)            ; do it
  164.  
  165.  
  166.  
  167. * page 
  168. * ---------------- Medium level driver ----------------
  169.  
  170. *+
  171. * _sasi_init - initialize SASI dev
  172. * Passed:    nothing
  173. * Returns:    d0 < 0: error
  174. *        d0 ==0: success
  175. *-
  176.     .globl    _sasi_init
  177. _sasi_init:
  178.     clr.l    d0
  179.     rts
  180.  
  181. *+
  182. * _sasi_bpb - return BPB for hard drive
  183. * Synopsis:    LONG _sasi_bpb(dev)
  184. *        WORD dev;
  185. *
  186. * Returns:    NULL, or a pointer to the BPB buffer
  187. *
  188. *-
  189.     .globl    _sasi_bpb
  190. _sasi_bpb:
  191.     move.w    4(sp),d0        ; get device number
  192.     mulu.w    #BPBLEN,d0
  193.     add.l    #bpbs,d0
  194.     rts
  195.  
  196. * page 
  197. *+
  198. * _ahdi_rw - read/write hard sectors
  199. *     aka _sasi_rw for historical reasons
  200. *
  201. * Synopsis:    _ahdi_rw(rw, buf, count, recno, dev)
  202. *
  203. * Passed:    dev    $e(sp).W
  204. *        recno    $c(sp).W
  205. *        count    $a(sp).W
  206. *        buf    6(sp).L
  207. *        rw    4(sp).W        ; non-zero -> write
  208. *
  209. *-
  210.  
  211. * stack frame offsets
  212. xrw    equ    8
  213. xbuf    equ    10
  214. xcount    equ    14
  215. xrecno    equ    16
  216. xdev    equ    18
  217. xlrecno    equ    20
  218.  
  219.     .globl    _sasi_rw
  220.     .globl    _ahdi_rw
  221. _sasi_rw:
  222. _ahdi_rw:
  223.     link    a6,#0            ; create a frame pointer
  224.  
  225. ahrw1:    move.w    xcount(a6),d2        ; is there anything to be done?
  226.     beq    ahrw6            ; no, so done with no errors
  227.  
  228.   .if ^^defined physops
  229.     move.w    xdev(a6),d1        ; get the device number
  230.     move.w    xrw(a6),d3        ; see if this is to be a phys op
  231.     btst    #3,d3
  232.     beq.s    .1            ; no, logical operation
  233.     cmpi.w    #9,d1            ; is it bigger than largest ACSI unit?
  234.     ble.s    ahrw11            ; no, so must be phys ACSI
  235.     bra    scrw
  236.  
  237. .1:    lea    pun,a2
  238.     move.b    0(a2,d1.w),d0        ; get logical unit flags
  239.     btst    #6,d0            ; is the SCSI bit set?
  240.     bne    scrw            ; yes, so a SCSI operation
  241.   .endif ;physops
  242.     
  243. ahrw11:    move.l    xbuf(a6),d1        ; if all goes well, this is our buffer
  244.  
  245.     cmpi.w    #MAXSECTORS,d2        ; more than one DMAfull?
  246.     ble    ahrw2
  247.     move.w    #MAXSECTORS,d2        ; yes, so only do this many this time
  248.  
  249. ahrw2:    btst    #0,xbuf+3(a6)        ; an odd boundary?
  250.     beq    ahrw4            ; no, so do normally
  251.  
  252.     cmpi.w    #2,d2            ; can only do 2 at a time tops this way
  253.     ble    ahrw3
  254.     move.w    #2,d2
  255.  
  256. ahrw3:    move.l    _dskbufp,d1        ; use the bios buffer for this transfer
  257.  
  258.     btst    #0,xrw+1(a6)        ; is this a write?
  259.     beq    ahrw4            ; no, so go fill buffer from disk
  260.  
  261.     movea.l    d1,a1            ; dest
  262.     movea.l    xbuf(a6),a2        ; source
  263.     bsr    smove            ; move d2 sectors from a2 to a1
  264.  
  265. ahrw4:    move.w    d2,-(sp)        ; preserve count this time
  266.  
  267.     move.w    xdev(a6),-(sp)
  268.     move.w    xrecno(a6),-(sp)
  269.     move.w    d2,-(sp)        ; count
  270.     move.l    d1,-(sp)        ; buffer
  271.     move.w    xrw(a6),-(sp)
  272.     bsr    _do_rw
  273.     adda.w    #12,sp
  274.  
  275.     move.w    (sp)+,d2        ; restore count for this op
  276.  
  277.     tst.l    d0            ; any errors there?
  278.     bne    ahrw7            ; yes, so give up
  279.  
  280.     btst    #0,xbuf+3(a6)        ; if odd boundary
  281.     beq    ahrw5
  282.     btst    #0,xrw+1(a6)        ; and a read
  283.     bne    ahrw5
  284.  
  285.     movea.l    xbuf(a6),a1        ; we must move dskbuf to desired dest
  286.     movea.l    _dskbufp,a2
  287.     bsr    smove
  288.  
  289. ahrw5:    move.w    d2,d0            ; number we did
  290.     ext.l    d0
  291.     asl.l    #8,d0            ; *512
  292.     asl.l    #1,d0
  293.     add.l    d0,xbuf(a6)        ; buf += (sectors_done * sector size)
  294.     add.w    d2,xrecno(a6)
  295.     sub.w    d2,xcount(a6)
  296.     bne    ahrw1
  297.  
  298. ahrw6:    clr.l    d0        ; got here with no errors!
  299. ahrw7:
  300.   .if MC68030
  301.     move.l    d0,-(sp)    ; save the status
  302.     move    sr,-(sp)
  303.     ori    #$700,sr    ; no interrupts right now please
  304.  
  305.     movecacrd0
  306.  
  307.     btst    #7,xrw(a6)    ; are we supposed to leave I cache alone?
  308.     bne.s    .91        ; yes
  309.  
  310.     ori    #$8,d0        ; dump the I cache
  311.  
  312. .91:    btst    #6,xrw(a6)    ; are we supposed to leave D cache alone?
  313.     bne.s    .92        ; yes
  314.  
  315.     ori    #$800,d0    ; dump the D cache
  316.  
  317. .92:    moved0cacr
  318.     move    (sp)+,sr    ; restore interrupt state
  319.  
  320.     move.l    (sp)+,d0    ; restore the return value
  321.   .endif ;MC68030
  322.     unlk    a6
  323.     rts
  324.  
  325. *+
  326. * smove -- move d2.w sectors from a2 to a1
  327. *    d2 is known to be either 1 or 2
  328. *-
  329.  
  330. smove:    move.w    d2,d0
  331.     asl.w    #8,d0
  332.     asl.w    #1,d0
  333.     subq.w    #1,d0            ; dbra likes one less
  334. smove1:    move.b    (a2)+,(a1)+
  335.     dbra    d0,smove1
  336.     rts
  337.  
  338. * page 
  339. *+
  340. * scrw -- a SCSI disk rwabs()
  341. *-
  342. ; 68901 MFP definitions
  343.  
  344. MFP    EQU    $FFFFFA01
  345.  
  346. ;GPIP    EQU    MFP+$00
  347. AER    EQU    MFP+$02
  348. DDR    EQU    MFP+$04
  349. IERA    EQU    MFP+$06
  350. IERB    EQU    MFP+$08
  351. IPRA    EQU    MFP+$0A
  352. IPRB    EQU    MFP+$0C
  353. ISRA    EQU    MFP+$0E
  354. ISRB    EQU    MFP+$10
  355. IMRA    EQU    MFP+$12
  356. IMRB    EQU    MFP+$14
  357. VR    EQU    MFP+$16
  358. TACR    EQU    MFP+$18
  359. TBCR    EQU    MFP+$1A
  360. TCDCR    EQU    MFP+$1C
  361. TADR    EQU    MFP+$1E
  362. TBDR    EQU    MFP+$20
  363. TCDR    EQU    MFP+$22
  364. TDDR    EQU    MFP+$24
  365. SCR    EQU    MFP+$26
  366. UCR    EQU    MFP+$28
  367. RSR    EQU    MFP+$2A
  368. TSR    EQU    MFP+$2C
  369. UDR    EQU    MFP+$2E
  370.  
  371. SREG0    EQU    $88+0
  372. SREG1    EQU    $88+1
  373. SREG2    EQU    $88+2
  374. SREG3    EQU    $88+3
  375. SREG4    EQU    $88+4
  376. SREG5    EQU    $88+5
  377. SREG6    EQU    $88+6
  378. SREG7    EQU    $88+7
  379.  
  380.   .macro WSCSI    value,sreg
  381.     move.w    \sreg,wdl
  382.     move.w    \value,wdc
  383.   .endm
  384.  
  385.   .macro RSCSI    sreg,place
  386.     move.w    \sreg,wdl
  387.     move.w    wdc,\place
  388.   .endm
  389.  
  390.   .macro w4req
  391. .1\~:    RSCSI    #SREG4,d0
  392.     btst    #5,d0
  393.     beq.s    .1\~
  394.   .endm
  395.  
  396.   .macro doack
  397.     RSCSI    #SREG1,d0
  398.     ori.w    #$11,d0            ; assert ACK (and data bus)
  399.     WSCSI    d0,#SREG1
  400. .1\~:    RSCSI    #SREG4,d0        ; wait for REQ to go away
  401.     btst    #5,d0
  402.     bne.s    .1\~
  403.     RSCSI    #SREG1,d0
  404.     andi.b    #$ef,d0            ; clear ACK
  405.     WSCSI    d0,#SREG1
  406.   .endm
  407.  
  408.   .macro hshake    xbyte
  409.     w4req
  410.     WSCSI    \xbyte,#SREG0
  411.     doack
  412.   .endm
  413.  
  414.   .macro w4irq
  415. .1\~:    btst    #5,GPIP
  416.     bne.s    .1\~
  417.   .endm
  418.  
  419. SCSIID    EQU    6        ; our (host) SCSI ID
  420.  
  421. scrw:    move.w    _retries,retrycnt    ; setup retry counter
  422. scrw0:    move.w    xdev(a6),d0    ; get the unit number
  423.     btst    #3,xrw+1(a6)    ; is this a physical operation?
  424.     beq.s    .0        ; no, so go get unit from pun
  425.     subi.w    #10,d0        ; subtract number of floppy&ACSI units
  426.     bra.s    .1        ; and use that as the unit number
  427.  
  428. .0:    lea    pun,a2
  429.     move.b    (a2,d0.w),d0    ; get the physical unit number
  430.     andi.w    #3,d0        ; strip off the flags
  431.  
  432. .1:    move.w    d0,-(sp)
  433.     bsr    selSCSI        ; select the SCSI device
  434.     addq    #2,sp
  435.  
  436.   .if SCDMA
  437.     move.l    xbuf(a6),d0    ; set the DMA source/destination
  438. ;    move.b    d0,bSDMAPTR+6
  439.     lsr.l    #8,d0
  440. ;    move.b    d0,bSDMAPTR+4
  441.     lsr.l    #8,d0
  442. ;    move.b    d0,bSDMAPTR+2
  443.     lsr.l    #8,d0
  444. ;    move.b    d0,bSDMAPTR
  445.  
  446. ; set up the size of the transfer (in bytes, assume each sector = $0200 bytes)
  447.     clr.l    d0
  448.     move.w    xcount(a6),d0    ; get the count of sectors
  449.     .if (^^defined NOCNT)
  450. ;    move.b    #8,bSDMACNT+6    ; make sure the count is non-zero at end
  451.     .else  ;NOCNT
  452. ;    move.b    #0,bSDMACNT+6    ; lsb of byte cnt always 0
  453.     .endif ;NOCNT
  454.     lsl.l    #1,d0        ; *$200/$100
  455. ;    move.b    d0,bSDMACNT+4
  456.     lsr.l    #8,d0
  457. ;    move.b    d0,bSDMACNT+2
  458.     lsr.l    #8,d0
  459. ;    move.b    d0,bSDMACNT
  460.   .endif ;SCDMA
  461.  
  462.     clr.l    d1
  463.     move.w    xrecno(a6),d1    ; get the record number
  464.     cmpi.w    #-1,d1        ; is recno==-1
  465.     bne.s    .11        ; if not, then use it
  466.     move.l    xlrecno(a6),d1    ; if so, then it implies the long form
  467. .11:    btst    #3,xrw+1(a6)    ; is it a physical operation?
  468.     bne.s    .15        ; yes, so don't change record number
  469.     move.w    xdev(a6),d2    ; get the logical unit number again
  470.     lsl.w    #2,d2        ; make it a long word index
  471.     lea    start,a2    ; and a pointer to the offset table
  472.     add.l    (a2,d2.w),d1    ; add the starting offset to specified record
  473. .15:
  474.   .if VERBOSE
  475.     movem.l    d0-d3/a0-a3,-(sp)
  476.     move.l    d1,-(sp)
  477.     bsr    crlf
  478.     move.b    #'R',d0
  479.     btst    #0,xrw+1(a6)
  480.     beq.s    .100
  481.     move.b    #'W',d0
  482. .100:    bsr    putc
  483.     move.w    retrycnt,d0
  484.     bsr    putnib
  485.     move.b    #':',d0
  486.     bsr    putc
  487.     move.w    xcount(a6),d0
  488.     bsr    putwor
  489.     move.b    #'#',d0
  490.     bsr    putc
  491.     move.l    (sp),d0
  492.     bsr    putlon
  493.     move.b    #'@',d0
  494.     bsr    putc
  495.     move.l    xbuf(a6),d0
  496.     bsr    putlon
  497.     move.l    (sp)+,d1
  498.     movem.l    (sp)+,d0-d3/a0-a3
  499.   .endif ;VERBOSE
  500.     move.b    #$28,d0        ; SCSI read extended command
  501.     btst    #0,xrw+1(a6)    ; read or write?
  502.     beq.s    .16
  503.     move.b    #$2A,d0        ; SCSI write extended command
  504. .16:    WSCSI    #2,#SREG3    ; assert c/d
  505.     WSCSI    #1,#SREG1    ; assert data bus
  506.     hshake    d0        ; write the command     -- 00 --
  507.     hshake    #0        ;                       -- 01 --
  508.     move.l    d1,d0        ; get the long block number
  509.     rol.l    #8,d0        ; send 4 bytes of block number
  510.     hshake    d0        ;                       -- 02 --
  511.     rol.l    #8,d0
  512.     hshake    d0        ;                       -- 03 --
  513.     rol.l    #8,d0
  514.     hshake    d0        ;                       -- 04 --
  515.     rol.l    #8,d0
  516.     hshake    d0        ;                       -- 05 --
  517.     hshake    #0        ; reserved byte         -- 06 --
  518.     move.w    xcount(a6),d0    ; word of count
  519.     rol.w    #8,d0
  520.     hshake    d0        ;                       -- 07 --
  521.     rol.w    #8,d0
  522.     hshake    d0        ;                       -- 08 --
  523.   .if 0
  524.     bra    .18        ; go send the control byte
  525.  
  526. ; send the SCSI command to the device
  527. .0:    move.b    #$08,d0        ; SCSI read command
  528.     btst    #0,xrw+1(a6)    ; only use lsb here, others reserved
  529.     beq.s    .1
  530.     move.b    #$0a,d0        ; SCSI write command
  531. .1:    WSCSI    #2,#SREG3    ; assert c/d
  532.     WSCSI    #1,#SREG1    ; assert data bus
  533.     hshake    d0        ; write the command     -- 00 --
  534.     hshake    #0        ; unfortunately rwabs only uses word block num
  535.     move.w    xrecno(a6),d0    ; get the specified block number
  536.     lsr.w    #8,d0
  537.     hshake    d0        ;                       -- 02 --
  538.     move.w    xrecno(a6),d0
  539.     hshake    d0        ;                       -- 03 --
  540.     move.w    xcount(a6),d0
  541.     hshake    d0        ;                       -- 04 --
  542.   .endif ;0
  543. .18:    hshake    #0        ; control byte always 0 -- 05 -- or -- 09 --
  544.  
  545.     btst    #0,xrw+1(a6)    ; only use lsb here, others reserved
  546.     beq.s    .25
  547.  
  548. ; write
  549.   .if SCDMA
  550.     WSCSI    #0,#SREG3        ; set data out phase
  551.     RSCSI    #SREG7,d0        ; clear potential interrupt
  552.     WSCSI    #2,#SREG2        ; enable DMA mode
  553.     WSCSI    #0,#SREG5        ; start the DMA
  554. ;    move.w    #DMAOUT,SDMACTL        ; set the DMAC direction
  555. ;    move.w    #DMAOUT+DMAENA,SDMACTL    ; turn on DMAC
  556.     bra.s    .26
  557.   .else ;SCDMA
  558.     WSCSI    #0,#SREG3        ; set data out phase
  559.     RSCSI    #SREG7,d0        ; clear potential interrupt
  560.     movea.l    xbuf(a6),a1        ; buffer pointer
  561.  
  562. .22:    RSCSI    #SREG4,d0
  563.     btst    #5,d0            ; wait for REQ
  564.     beq.s    .22
  565.     RSCSI    #SREG5,d0
  566.     btst    #3,d0            ; still in right phase
  567.     beq.s    .3            ; no, end of data out phase
  568.     move.b    (a1)+,(a0)        ; write the data byte
  569.  
  570.     RSCSI    #SREG1,d0
  571.     bset    #4,d0            ; assert ACK
  572.     WSCSI    d0,#SREG1
  573.  
  574. .23:    RSCSI    #SREG4,d0
  575.     btst    #5,d0            ; wait for REQ to go away
  576.     bne.s    .23
  577.  
  578.     RSCSI    #SREG1,d0
  579.     bclr    #4,d0            ; clear ACK
  580.     WSCSI    d0,#SREG1
  581.     bra.s    .22
  582.   .endif ;SCDMA
  583.  
  584. ; read
  585. .25:
  586.   .if SCDMA
  587.     WSCSI    #0,#SREG1        ; deassert the data bus
  588.     WSCSI    #1,#SREG3        ; set data in phase
  589.     RSCSI    #SREG7,d0        ; clear potential interrupt
  590.     WSCSI    #2,#SREG2        ; enable DMA mode
  591.     WSCSI    #0,#SREG7        ; start the DMA
  592. ;    move.w    #DMAIN,SDMACTL        ; set the DMAC direction
  593. ;    move.w    #DMAIN+DMAENA,SDMACTL    ; turn on DMAC
  594.  
  595. .26:
  596. ;    btst    #GPIP2SCSI,GPIP2    ; wait for 5380 to interrupt
  597.     bne.s    .261            ; active HIGH
  598. ;    btst    #5,GPIP2        ; or for DMAC to interrupt
  599.     bne.s    .26            ; active LOW
  600. ;    move.w    SDMACTL,d0        ; get the DMA status
  601.     andi.l    #$80,d0            ; ignore countout ints
  602.     beq.s    .26
  603.     neg.l    d0
  604.     move.l    d0,-(sp)
  605.     bsr    resetSCSI
  606.     move.l    (sp)+,d0
  607.     bra    .99
  608.  
  609. .261:    RSCSI    #SREG7,d0        ; clear potential interrupt
  610.  
  611. ; disable DMA
  612.     WSCSI    #0,#SREG2        ; disable DMA mode
  613.     WSCSI    #0,#SREG1        ; make sure data bus is not asserted
  614.   .else ;SCDMA
  615.     WSCSI    #1,#SREG3        ; set data in phase
  616.     RSCSI    #SREG7,d0        ; clear potential interrupt
  617.     movea.l    xbuf(a6),a1        ; buffer pointer
  618.  
  619. .27:    RSCSI    #SREG4,d0
  620.     btst    #5,d0            ; wait for REQ
  621.     beq.s    .27
  622.     RSCSI    #SREG5,d0
  623.     btst    #3,d0            ; still in right phase
  624.     beq.s    .3            ; no, end of data in phase
  625.     move.b    (a0),(a1)+        ; read the data byte
  626.  
  627.     RSCSI    #SREG1,d0
  628.     bset    #4,d0            ; assert ACK
  629.     WSCSI    d0,#SREG1
  630.  
  631. .28:    RSCSI    #SREG4,d0
  632.     btst    #5,d0            ; wait for REQ to go away
  633.     bne.s    .28
  634.  
  635.     RSCSI    #SREG1,d0
  636.     bclr    #4,d0            ; clear ACK
  637.     WSCSI    d0,#SREG1
  638.     bra.s    .27
  639.  
  640.   .endif ;SCDMA
  641.  
  642. .3:    WSCSI    #3,#SREG3        ; status in phase
  643.     RSCSI    #SREG7,d0        ; clear potential interrupt
  644.  
  645.     w4req                ; wait for status byte
  646.     clr.w    d0
  647.     RSCSI    #SREG0,d0
  648.     move.w    d0,-(sp)
  649.     doack
  650.  
  651.     w4req
  652.     RSCSI    #SREG0,d0        ; get and ignore message byte
  653.     doack
  654.  
  655.   .if VERBOSE
  656.     move.b    #'^',d0
  657.     bsr    putc
  658.     move.w    (sp),d0
  659.     bsr    putbyt
  660.   .endif ;VERBOSE
  661.  
  662. .9:    clr.l    d0
  663.  
  664.     move.w    (sp)+,d0    ; recall the status byte
  665.     beq.s    .99
  666.     neg.l    d0        ; errors are negative numbers
  667.     subq.w    #1,retrycnt    ; drop retry count and retry
  668.     bpl    scrw0        ; if there are still chances to win
  669.  
  670. .99:    bra    ahrw7
  671.  
  672. *+
  673. * VOID resetSCSI();
  674. *-
  675.  
  676. resetSCSI:
  677.     WSCSI    #$80,#SREG1
  678.  
  679.     movea.l    #_hz_200,a0
  680.     move.l    (a0),d0
  681.     addi.l    #51,d0        ; wait (at least) 250 mS
  682. .0:    cmp.l    (a0),d0
  683.     bne.s    .0
  684.  
  685.     WSCSI    #$00,#SREG1
  686.  
  687.     move.l    (a0),d0
  688.     addi.l    #201,d0        ; wait (at least) 1000 mS
  689. .1:    cmp.l    (a0),d0
  690.     bne.s    .1
  691.     rts
  692.  
  693. *+
  694. * BOOLEAN selSCSI(SCSIUnit) WORD SCSIUnit;
  695. *-
  696.  
  697. selSCSI:
  698. .0:    RSCSI    #SREG4,d0
  699.     btst    #6,d0            ; not STILL busy from last time?
  700.     bne.s    .0
  701.  
  702.     WSCSI    #0,#SREG3        ; data out phase
  703.     WSCSI    #0,#SREG4        ; no interrupt from selection
  704.     WSCSI    #$0C,#SREG1        ; assert BSY and SEL
  705. ; set dest SCSI IDs
  706.     clr.w    d0
  707.     move.w    4(sp),d1        ; get the SCSI unit desired
  708.     bset    d1,d0            ; set the appropriate bit
  709.     WSCSI    d0,#SREG0        ; (real code would set ours too)
  710.  
  711.     WSCSI    #$0d,#SREG1        ; assert BUSY, SEL and data bus
  712.  
  713.     RSCSI    #SREG2,d0
  714.     andi.b    #$FE,d0            ; clear arbitrate bit
  715.     WSCSI    d0,#SREG2
  716.     RSCSI    #SREG1,d0
  717.     andi.b    #$F7,d0            ; clear BUSY
  718.     WSCSI    d0,#SREG1
  719.     nop
  720.     nop
  721.  
  722. .1:    RSCSI    #SREG4,d0
  723.     btst    #6,d0            ; wait for bus to be busy
  724.     beq    .1
  725.  
  726.     WSCSI    #$0,#SREG1    ; clear SEL and data bus assertion
  727.     clr.w    d0        ; note lack of SCSI device timeout
  728.     rts
  729.  
  730.   .if VERBOSE
  731. ;
  732. ;    putlon - put d0.l as 8 hex digits
  733. ;    putwor - put d0.w as 4 hex digits
  734. ;    putbyt - put d0.b as 2 hex digits
  735. ;    putnib - put 4 lsbs as a hex digit
  736.  
  737. putlon:    move.l    d0,-(sp)
  738.     swap    d0
  739.     bsr    putwor
  740.     move.l    (sp)+,d0
  741. putwor:    move    d0,-(sp)
  742.     asr    #8,d0
  743.     bsr    putbyt
  744.     move    (sp)+,d0
  745. putbyt:    move    d0,-(sp)
  746.     asr    #4,d0
  747.     bsr    putnib
  748.     move    (sp)+,d0
  749. putnib:    andi.b    #$0f,d0
  750.     addi.b    #'0',d0
  751.     cmpi.b    #'9',d0
  752.     ble    putb2
  753.     addi.b    #7,d0
  754. putc:
  755. putb2:    tst.b    TSR
  756.     bpl.s    putb2
  757.     move.b    d0,UDR
  758.     rts
  759.  
  760. crlf:    move.l    #crlfmsg,-(sp)
  761.     bsr    puts
  762.     addq    #4,sp
  763.     rts
  764.  
  765. puts:    movea.l    4(sp),a0
  766. .1:    move.b    (a0)+,d0
  767.     beq.s    .9
  768.     bsr    putc
  769.     bra.s    .1
  770. .9:    rts
  771.  
  772. crlfmsg: dc.b    13,10,0
  773.     .even
  774.   .endif ;VERBOSE
  775. * page 
  776. *+
  777. * _do_rw - called to read/write no more than 128K to an even boundary
  778. *
  779. * Passed:    dev    $e(sp).W
  780. *        recno    $c(sp).W
  781. *        count    $a(sp).W
  782. *        buf    6(sp).L
  783. *        rw    4(sp).W        ; non-zero -> write
  784. *
  785. *-
  786.     .globl    _do_rw
  787. _do_rw:
  788.     move.w    d3,-(sp)        ; preserve d3
  789.  
  790. sasrw0:    move.w    _retries,retrycnt    ; setup retry counter
  791.  
  792.     move.w    6(sp),d3
  793.     btst    #2,d3            ; are retries disabled?
  794.     beq    sasrw1            ; no, act normally
  795.     move.w    #0,retrycnt        ; yes, so set retrycnt to zero
  796.  
  797. *
  798. * read sector(s),
  799. * delay .0005 to .001 seconds between driver calls
  800. *
  801. sasrw1:
  802.     move.l    lastrwtm,d0
  803. sasrw8:    cmp.l    _hz_200,d0        ; while (_hz_200 <= lastrwtm)
  804.     bcc    sasrw8            ;    just_wait;
  805.     move.l    _hz_200,d0        ; lastrwtm = _hz_200 + 1;
  806.     addq.l    #1,d0
  807.     move.l    d0,lastrwtm
  808.  
  809.     lea    2(sp),a1        ; frame pointer
  810.     moveq    #0,d0            ; coerce word to long, unsigned
  811.     move.w    $c(a1),d0        ; sect.L
  812.     move.w    4(a1),d3        ; rw
  813.  
  814.     btst    #3,d3            ; physical unit operation
  815.     beq    sasrw2            ; no, so do log->phys mapping
  816.  
  817.     move    $0e(a1),d2        ; get unit number
  818.     subq    #2,d2            ; subtract drive C offset
  819.     bra    sasrw3            ; and use that as the physical unit
  820.  
  821. sasrw2:    clr    d2            ; coerce byte to word
  822.     move.w    $e(a1),d1        ; get device
  823.     lea    pun,a2
  824.     move.b    0(a2,d1.w),d2        ; get physical unit number
  825. sasrw3:    move.w    d2,-(sp)        ; dev
  826.     move.l    6(a1),-(sp)        ; buf
  827.     move.w    $a(a1),-(sp)        ; count
  828.  
  829.     btst    #3,d3            ; physical operation?
  830.     bne    sasrw4            ; yes, so no offset
  831.  
  832.     asl.w    #2,d1            ; *4 to get index into long array
  833.     lea    start,a2
  834.     add.l    0(a2,d1.w),d0        ; adjust sector number
  835.  
  836. sasrw4:    move.l    d0,-(sp)        ; sect
  837.     btst    #0,d3            ; read or write?
  838.     bne    sasrw5            ; (write)
  839.     bsr    _hread            ; read sectors
  840.     bra    sasrw6
  841. sasrw5:    bsr    _hwrite            ; write sectors
  842. sasrw6:    add.w    #12,sp            ; (cleanup stack)
  843.     tst.l    d0            ; errors?
  844.     beq    sasrwr            ; no -- success
  845.     subq.w    #1,retrycnt        ; drop retry count and retry
  846.     bpl    sasrw1
  847.  
  848.     move    6(sp),d1        ; get r/w and flags word
  849.     move.l    #EREADF,d0        ; read error code
  850.     btst    #0,d1
  851.     beq    sasrw7
  852.     move.l    #EWRITF,d0        ; write error code
  853.  
  854. sasrw7:    btst    #2,d1            ; is this a "raw" operation?
  855.     bne    sasrwr            ; yes, so no critical error handler
  856.  
  857.     move.w    $10(sp),-(sp)        ; unit number
  858.     move.w    d0,-(sp)        ; error code (as a word, sic)
  859.     movea.l    etv_critic,a0
  860.     jsr    (a0)
  861.     addq    #4,sp
  862.     cmpi.l    #CRITRETRY,d0        ; is it the magic RETRY code?
  863.     beq    sasrw0
  864.  
  865. sasrwr:    move.w    (sp)+,d3        ; remember to restore d3
  866.     rts
  867.  
  868. *+
  869. * _sasi_mediach - see if hard disk media has changed (it never does)
  870. * Synopsis:    _sasi_mediach(dev)
  871. *        WORD dev;
  872. *
  873. * Returns:    0L
  874. *
  875. *-
  876.     .globl    _sasi_mediach
  877. _sasi_mediach:
  878.     clr.l    d0
  879.     rts
  880.  
  881.  
  882. * page 
  883. * ---------------- Low-level driver ----------------
  884.  
  885.  
  886. *----- Tunable:
  887. ltimeout        equ    450000        ; long-timeout (3 S)
  888. stimeout        equ    15000        ; short-timeout (100 mS)
  889.  
  890. *+
  891. * LONG _qdone() - Wait for command byte handshake
  892. * LONG _fdone() - Wait for operation complete
  893. * Passed:    nothing
  894. *
  895. * Returns:    EQ: no timeout
  896. *        MI: timeout condition
  897. *
  898. * Uses:        D0
  899. *
  900. * each pass through the loop takes 6.75 uS
  901. *-
  902.     .if    sermsg
  903.  
  904. _fdone:    move    d1,-(sp)
  905.     move    #1,d1
  906.     move.l    #ltimeout,tocount
  907.     bra    qd1
  908.  
  909. _qdone:
  910.     move    d1,-(sp)
  911.     move    #0,d1
  912.     move.l    #stimeout,tocount
  913. qd1:    subq.l    #1,tocount        ; drop timeout count
  914.     bmi    qdq            ; (i give up, return NE)
  915.     btst    #5,gpip            ; interrupt?
  916.     bne    qd1            ; (not yet)
  917.  
  918.     move    (sp)+,d1
  919.     moveq    #0,d0            ; return EQ (no timeout)
  920.     rts
  921.  
  922. qdq:    nop
  923.  
  924.     .if    1
  925.  
  926.     movem.l    d0-d3/a0-a4,-(sp)
  927.     lea    stmsg,a4
  928.     tst    d1
  929.     beq    qdq1
  930.     lea    ltmsg,a4
  931. qdq1:    move.b    (a4)+,d0
  932.     beq    qdq2
  933.     move    d0,-(sp)
  934.     move    #1,-(sp)
  935.     move    #3,-(sp)
  936.     trap    #13
  937.     addq    #6,sp
  938.     bra    qdq1
  939.  
  940. qdq2:    movem.l    (sp)+,d0-d3/a0-a4
  941.  
  942.     .endif
  943.  
  944.     move    (sp)+,d1
  945.     moveq    #-1,d0
  946.     rts
  947.  
  948. stmsg:    dc.b    'Short timeout',$0d,$0a,0
  949. ltmsg:    dc.b    'Long timeout',$0d,$0a,0
  950. drmsg:    dc.b    $0d,$0a,'Drive ',0
  951.     even
  952.  
  953.     .endif
  954.  
  955.     .if    sermsg=0
  956.  
  957. _fdone:    move.l    #ltimeout,tocount
  958.     bra    qd1
  959.  
  960. _qdone:
  961.     move.l    #stimeout,tocount
  962. qd1:    subq.l    #1,tocount        ; drop timeout count
  963.     bmi    qdq            ; (i give up, return NE)
  964.     btst    #5,gpip            ; interrupt?
  965.     bne    qd1            ; (not yet)
  966.  
  967.     moveq    #0,d0            ; return EQ (no timeout)
  968.     rts
  969.  
  970. qdq:    moveq    #-1,d0
  971.     rts
  972.  
  973.     .endif
  974.  
  975. *+
  976. * WORD _endcmd()
  977. * Wait for end of SASI command
  978. * Passed:    d0 value to be written to wdl
  979. *
  980. * Returns:    EQ: success (error code in D0.W)
  981. *        MI: timeout
  982. *        NE: failure (SASI error code in D0.W)
  983. *
  984. * Uses:        d0,d1
  985. *-
  986. _endcmd: move    d0,d1            ; preserve wdl value
  987.  
  988.     bsr    _fdone            ; wait for operation complete
  989.     bmi    endce            ; (timed-out, so complain)
  990.  
  991.     move.w    d1,wdl
  992.     nop
  993.     move.w    wdc,d0            ; get the result
  994.     and.w    #$00ff,d0        ; (clean it up), if non-zero should
  995.  
  996. endce:    rts                ;  do a ReadSense command to learn more
  997.  
  998. *-
  999. * _hread(sectno, count, buf, dev)
  1000. * LONG sectno;         4(sp)
  1001. * WORD count;         8(sp)
  1002. * LONG buf;        $a(sp)    $b=high, $c=mid, $d=low
  1003. * WORD dev;        $e(sp)
  1004. *
  1005. * Returns:    -1 on timeout
  1006. *        0 on success
  1007. *        nonzero on error
  1008. *
  1009. *-
  1010.     .globl    _hread
  1011. _hread:
  1012.     movea.l    #wdc,a0            ; pointer to DMA chip
  1013.     st    flock            ; lock FIFO
  1014.  
  1015.     move    #$88,xwdl(a0)
  1016.     clr.l    d0
  1017.     move.w    $0e(sp),d0        ; get unit number
  1018.     lsl.w    #5,d0
  1019.     swap    d0
  1020.     ori.l    #$0008008a,d0        ; 08 wdc, 8a wdl
  1021.     move.l    d0,(a0) ; wdcwdl
  1022.  
  1023.     move.l    $a(sp),-(sp)        ; set DMA address
  1024.     bsr    _setdma
  1025.     addq    #4,sp
  1026.  
  1027.     bsr    _setss            ; set sector and size
  1028.     bmi    _hto
  1029.  
  1030.     move.w    #$190,xwdl(a0)
  1031.     nop
  1032.     move.w    #$90,xwdl(a0)
  1033.     nop
  1034.     move.w    8(sp),(a0) ;wdc        ; write sector count to DMA chip
  1035.     nop
  1036.     move.w    #$8a,xwdl(a0)
  1037.     nop
  1038.     move.l    #$00000000,(a0) ; wdcwdl; control byte  0 wdc 0 wdl
  1039.  
  1040.     move.w    #$8a,d0
  1041.     bsr    _endcmd
  1042.  
  1043. hrx:    bra    _hdone            ; cleanup after IRQ
  1044.  
  1045.  
  1046. *-
  1047. * _hwrite(sectno, count, buf, dev)
  1048. * LONG sectno;         4(sp)
  1049. * WORD count;         8(sp)
  1050. * LONG buf;        $a(sp)    $b=high, $c=mid, $d=low
  1051. * WORD dev;        $e(sp)
  1052. *
  1053. *-
  1054.     .globl    _hwrite
  1055. _hwrite:
  1056.     movea.l    #wdc,a0            ; pointer to DMA chip
  1057.     st    flock            ; lock FIFO
  1058.  
  1059.     move.l    $a(sp),-(sp)        ; set DMA address
  1060.     bsr    _setdma
  1061.     addq    #4,sp
  1062.  
  1063.     move.w    #$88,xwdl(a0)
  1064.     clr.l    d0
  1065.     move.w    $0e(sp),d0        ; get unit number
  1066.     lsl.w    #5,d0
  1067.     swap    d0
  1068.     ori.l    #$000a008a,d0        ; 0a wdc 8a wdl
  1069.     move.l    d0,(a0) ; wdcwdl
  1070.  
  1071.     bsr    _setss
  1072.     bmi    _hto
  1073.  
  1074.     move.w    #$90,xwdl(a0)
  1075.     nop
  1076.     move.w    #$190,xwdl(a0)
  1077.     nop
  1078.     move.w    8(sp),(a0) ;wdc        ; sector count for DMA chip's benefit
  1079.     nop
  1080.     move.w    #$18a,xwdl(a0)
  1081.     nop
  1082.     move.l    #$00000100,(a0) ; wdcwdl
  1083.  
  1084.     move.w    #$18a,d0
  1085.     bsr    _endcmd
  1086.  
  1087. hwx:    bra    _hdone            ; cleanup after IRQ
  1088.  
  1089.  
  1090. *+
  1091. * void _setdma(addr)
  1092. * LONG addr;
  1093. *-
  1094. _setdma:
  1095.     move.b    7(sp),dmalow
  1096.     move.b    6(sp),dmamid
  1097.     move.b    5(sp),dmahi
  1098.     rts
  1099.  
  1100. *+
  1101. * WORD _setss  -- set sector number and number of sectors
  1102. *-
  1103.  
  1104. _setss:    move.w    #$8a,xwdl(a0)
  1105.  
  1106.     bsr    _qdone            ; wait for controller to take command
  1107.     bmi    setsse
  1108.  
  1109.     move.b    9(sp),d0        ; construct sector#
  1110.     swap    d0
  1111.     move.w    #$008a,d0
  1112.     move.l    d0,(a0) ; wdcwdl    ; write MSB sector# + devno
  1113.     bsr    _qdone
  1114.     bmi    setsse
  1115.  
  1116.     move.b    10(sp),d0        ; write MidSB sector#
  1117.     swap    d0
  1118.     move.w    #$008a,d0
  1119.     move.l    d0,(a0) ; wdcwdl
  1120.     bsr    _qdone
  1121.     bmi    setsse
  1122.  
  1123.     move.b    11(sp),d0        ; write LSB sector#
  1124.     swap    d0
  1125.     move.w    #$008a,d0
  1126.     move.l    d0,(a0) ; wdcwdl
  1127.     bsr    _qdone
  1128.     bmi    setsse
  1129.  
  1130.     move.w    12(sp),d0        ; write sector count
  1131.     swap    d0
  1132.     move.w    #$008a,d0
  1133.     move.l    d0,(a0) ; wdcwdl
  1134.     bsr    _qdone
  1135.  
  1136. setsse:    rts
  1137.  
  1138. _hto:    moveq    #-1,d0        ; indicate timeout
  1139. _hdone:    move.w    #$80,wdl    ; Landon's code seems to presume we
  1140.     nop            ;  put this back to $80
  1141.     tst.w    wdc
  1142.     clr    flock        ; NOW, signal that we are done
  1143.     rts
  1144.  
  1145. isasi5:
  1146.     move.l    d0,-(sp)    ; preserve the number of bytes we need
  1147.  
  1148.     tst.w    bootloaded    ; if bootloaded, then already in super mode
  1149.     bne    nboot1        ; (already there)
  1150.     move.l    savssp,-(sp)    ; become a mild mannered user process
  1151.     move.w    #$20,-(sp)    ; Super(savssp)
  1152.     trap    #1
  1153.     addq    #6,sp
  1154.  
  1155. nboot1:    move.l    (sp)+,d0    ; compute value for Ptermres() or Mshrink
  1156.     add.l    #((i_sasi1-i_sasi)+$0100),d0
  1157.  
  1158.     tst.w    bootloaded    ; exit to GEMDOS?
  1159.     beq    nboot2        ; (yes -- not boot loaded)
  1160.  
  1161. *
  1162. *  Return to TOS ROMs
  1163. *    - set default boot device to C:
  1164. *    - Print silly message
  1165. *    - Mshrink() memory that was alloc'd to us
  1166. *    - set magic# in D7 for TOS ROMs
  1167. *    - RTS back to ROMs
  1168. *
  1169.     move.l    d0,-(sp)    ; save D0
  1170.     pea    msg_loaded(pc)    ; print announcement
  1171.     move.w    #9,-(sp)
  1172.     trap    #1
  1173.     addq    #6,sp
  1174.  
  1175.   .if (^^defined HWDBUG)|(^^defined NOCNT)
  1176.     move.w    #1,-(sp)    ; get char from stdin
  1177.     trap    #1        ; (and ignore it)
  1178.     addq    #2,sp
  1179.   .endif
  1180.  
  1181.     move.l    (sp)+,d0
  1182.  
  1183.     move.w    #2,_bootdev    ; set default boot device to C: (devno=2)
  1184.     move.l    d0,-(sp)
  1185.     move.l    baseaddr,-(sp)
  1186.     clr.w    -(sp)
  1187.     move.w    #$4a,-(sp)    ; Mshrink(...)
  1188.     trap    #1
  1189.     add.w    #12,sp        ; (cleanup stack)
  1190.  
  1191.  
  1192. exec_os        equ    $4fe
  1193.  
  1194. *+
  1195. *  Bring up the AES:
  1196. *    do autoexec;
  1197. *    construct an enviroment string;
  1198. *    create a basepage for the AES;
  1199. *    exec the AES.
  1200. *
  1201. *-
  1202. st_1:
  1203.     bsr    findpackages        ; find bootable RAM packages
  1204.     bsr    _auto            ; do auto-exec
  1205.  
  1206.     pea    orig_env        ; push address of enviroment string
  1207.     pea    nullenv(pc)        ; no arguments
  1208.     pea    nullenv(pc)        ; null shell name (in ROM, after all)
  1209.     move.w    #5,-(sp)        ; createPSP flavor of exec
  1210.     move.w    #$4b,-(sp)        ; exec function#
  1211.     trap    #1            ; get pointer to PSP
  1212.     add.w    #14,sp            ; (clean up cruft)
  1213.     move.l    d0,a0            ; a0 -> PSP
  1214.     move.l    exec_os,8(a0)        ; stuff saddr of GEM in PSP
  1215.  
  1216.     move.l    a0,-(sp)        ; push addr of PSP
  1217.     pea    nullenv(pc)        ; null filename
  1218.     move.w    #4,-(sp)        ; just-go
  1219.  
  1220. st_x:    move.w    #$4b,-(sp)        ; function = exec
  1221.     trap    #1            ; do it
  1222.     add.w    #14,sp            ; cleanup stack
  1223.  
  1224. *+
  1225. * When startup fails (or if the exec returns,
  1226. * which "cannot happen") fake a system reset:
  1227. *-
  1228.     move.l    4,a0            ; get RESET vector
  1229.     jmp    (a0)            ; and do it
  1230.  
  1231.  
  1232.  
  1233. *+
  1234. * Default enviroment string
  1235. *
  1236. *-
  1237. orig_env:
  1238.     dc.b    "PATH=",0        ; default pathname
  1239.     dc.b    "C:\\",0        ; is the boot device
  1240.     dc.b    0            ; terminate env string
  1241.  
  1242.  
  1243. gemname: dc.b    "GEM.PRG"        ; desktop name
  1244. nullenv: dc.b    0,0            ; null string (and enviroment)
  1245.     even
  1246.  
  1247.  
  1248. *+
  1249. *  Auto path for hard disks (C:)
  1250. *
  1251. *-
  1252. autopath:    dc.b    'C:\\AUTO\\'
  1253. autofile:    dc.b    '*.PRG',0
  1254.         dc.w    $1234,$5678,$9abc,$def0
  1255.     even
  1256.  
  1257.  
  1258. *+
  1259. * _auto - exec auto-startup files in the appropriate subdirectory
  1260. * _auto1 - exec (with filename args)
  1261. *
  1262. * Passed:    a0 -> full filespec (pathname)
  1263. *        a1 -> filename part of filespec
  1264. *
  1265. * Returns:    nothing
  1266. *
  1267. * Uses:        everything
  1268. *-
  1269.     .globl    _auto            ; for debugging
  1270. _auto:    lea    autopath(pc),a0        ; -> path
  1271.     lea    autofile(pc),a1        ; -> filename
  1272.  
  1273. _auto1:    move.l    (sp)+,autoret        ; copy return addr (used by execlr)
  1274.     move.l    sp,origstk        ; (save original stack)
  1275.     move.l    a0,pathname        ; setup filename/pathname ptrs
  1276.     move.l    a1,filename
  1277.  
  1278.     lea    nullenv(pc),a3        ; a0 -> \0\0
  1279.     move.l    a3,-(sp)        ; null enviroment
  1280.     move.l    a3,-(sp)        ; null command tail
  1281.     move.l    a3,-(sp)        ; null shell name
  1282.     move.w    #5,-(sp)        ; Create-PSP subfunction
  1283.     move.w    #$4b,-(sp)        ; exec function#
  1284.     trap    #1            ; do DOS call
  1285.     add.w    #16,sp
  1286.  
  1287.     move.l    d0,a0            ; a0 -> PSP
  1288.     move.l    #fauto,8(a0)        ; initial PC -> autoexec prog
  1289.  
  1290.     move.l    a3,-(sp)        ; null enviroment
  1291.     move.l    d0,-(sp)        ; -> PSP
  1292.     move.l    a3,-(sp)        ; null shell name
  1293.     move.w    #4,-(sp)        ; just-go
  1294.     move.w    #$4b,-(sp)        ; function = exec
  1295.     trap    #1            ; do it
  1296.     add.w    #16,sp            ; cleanup stack & goodbye
  1297. autoq:    move.l    autoret,-(sp)
  1298.     rts
  1299.  
  1300.  
  1301.  
  1302. *+
  1303. *  fauto - exec'd by _auto to do autostartup
  1304. *
  1305. *  Passed:    pathname -> path part of filespec
  1306. *        filename -> file part of filespec
  1307. *
  1308. *-
  1309. fauto:
  1310.     move.w    #2,-(sp)        ; Dsetdrv(2)
  1311.     move.w    #$e,-(sp)
  1312.     trap    #1
  1313.     addq    #4,sp
  1314.  
  1315.     clr.l    -(sp)            ; get into super mode
  1316.     move.w    #$20,-(sp)
  1317.     trap    #1
  1318.     addq    #6,sp            ; cleanup
  1319.     move.l    d0,a4            ; a4 -> saved super stack
  1320.  
  1321. *--- free up some memory:
  1322.     move.l    4(a7),a5        ; a5 -> base page
  1323.     lea    $100(a5),sp        ; sp -> new, safer addr
  1324.     move.l    #$100,-(sp)        ; keep $100 (just the basepage)
  1325.     move.l    a5,-(sp)        ; -> start of mem to keep
  1326.     clr.w    -(sp)            ; junk word
  1327.     move.w    #$4a,-(sp)        ; setblock(...)
  1328.     trap    #1
  1329.     addq    #6,sp
  1330.     tst.w    d0
  1331.     bne    au_dn            ; punt on error
  1332.  
  1333.     move.w    #$0007,-(sp)        ; find r/o+hidden+system files
  1334.     move.l    pathname,-(sp)        ; -> filename (on input)
  1335.     move.w    #$4e,-(sp)        ; searchFirst
  1336.  
  1337.     moveq    #8,d7            ; d7 = cleanup amount
  1338. au1:    pea    autodma            ; setup DTA (for search)
  1339.     move.w    #$1a,-(sp)
  1340.     trap    #1
  1341.     addq    #6,sp
  1342.  
  1343.     trap    #1            ; search first/search next
  1344.     add.w    d7,sp            ; cleanup stack
  1345.     tst.w    d0            ; test for match
  1346.     bne    au_dn            ; (no match -- quit)
  1347.  
  1348. *--- construct filename from path and the name we just found:
  1349.     move.l    pathname,a0        ; copy pathname
  1350.     move.l    filename,a2        ; a2 -> end+1 of pathname
  1351.     lea    autoname,a1
  1352. au3:    move.b    (a0)+,(a1)+        ; copy path part of name
  1353.     cmp.l    a0,a2            ; finished?
  1354.     bne    au3            ; (no)
  1355.     lea    autodma+30,a0        ; copy fname to end of pathname
  1356. au2:    move.b    (a0)+,(a1)+
  1357.     bne    au2
  1358.  
  1359.     pea    nullenv(pc)        ; null enviroment
  1360.     pea    nullenv(pc)        ; no command tail
  1361.     pea    autoname        ; -> file to exec
  1362.     clr.w    -(sp)            ; load-and-go
  1363.     move.w    #$4b,-(sp)        ; exec(...)
  1364.     trap    #1
  1365.     add.w    #16,sp
  1366.  
  1367.     moveq    #2,d7            ; reset cleanup amount
  1368.     move.w    #$4f,-(sp)        ; searchNext
  1369.     bra    au1
  1370.  
  1371. *+
  1372. * Search for a package, execute it.
  1373. *
  1374. *    +---------------+
  1375. *    |   $12123456    | base + 0, on a 512-byte boundary
  1376. *    |        |
  1377. *    +---------------+
  1378. *    |   -> base    | base + 4
  1379. *    |        |
  1380. *    +---------------+
  1381. *    |   (code)    | base + 8
  1382. *    /        /
  1383. *    /        /
  1384. *    |        |
  1385. *    +---------------+
  1386. *              base + 512
  1387. *
  1388. *    The entire 512-byte block should word-checksum to $5678.
  1389. *
  1390. *-
  1391. findpackages:
  1392.     move.l    phystop,a0        ; a0 -> top of memory
  1393. fpk_n:    sub.w    #512,a0            ; down 512 bytes
  1394.     cmp.l    #$400,a0        ; bottom of memory?
  1395.     beq    fpk_r            ; (yes -- punt)
  1396.     cmp.l    #$12123456,(a0)        ; check magic #
  1397.     bne    fpk_n            ; (no match, try next one)
  1398.     cmp.l    4(a0),a0        ; self-pointer?
  1399.     bne    fpk_n            ; (doesn't point to itself, retry)
  1400.  
  1401.     clr.w    d0            ; zero checksum reg
  1402.     move.l    a0,a1            ; a1 -> block to checksum
  1403.     move.w    #$ff,d1            ; do 256 words
  1404. fpk_1:    add.w    (a1)+,d0        ; sum a word
  1405.     dbra    d1,fpk_1        ;    ... until we're done
  1406.     cmp.w    #$5678,d0        ; magic number to exec()?
  1407.     bne    fpk_n            ; (no, retry)
  1408.     move.l    a0,-(sp)        ; save our precious package pointer
  1409.     jsr    8(a0)            ; call package's code
  1410.     move.l    (sp)+,a0        ; restore A0
  1411.     bra    fpk_n            ; (do more blocks)
  1412.  
  1413. fpk_r:    rts
  1414.  
  1415.  
  1416. *+
  1417. * The first GEMDOS process can never terminate.
  1418. * This is not a good feature.
  1419. * Kludge around it -- re-initialize the stack
  1420. * and return to the guy who called us to begin with.
  1421. *
  1422. *-
  1423. au_dn:    move.l    origstk,sp        ; restore original stack
  1424.     move.l    autoret,-(sp)        ; get return addr
  1425.     rts                ; just jump there ...
  1426.  
  1427.  
  1428. *--- "bss" for auto-exec:
  1429. autoret:    dc.l    0        ; -> _auto's caller (yeccch)
  1430. pathname:    dc.l    0        ; -> filespec's pathname
  1431. filename:    dc.l    0        ; -> filename part of path
  1432. origstk:    dc.l    0        ; =  original supervisor stack
  1433. autodma:    dcb.b    44,0        ; 44 bytes for directory search
  1434. autoname:    dcb.b    32,0        ; 32 bytes for path+filename
  1435.     even
  1436.  
  1437.  
  1438. *    move.b    #$100-$20,d7    ; return to TOS ROMs
  1439. *    rts
  1440.  
  1441. msg_loaded:
  1442.     dc.b    'Atari Sparrow SCSI Driver'
  1443.   .if !SCDMA
  1444.     dc.b    ' (NoDMA)'
  1445.   .endif ;SCDMA
  1446.   .if (^^defined HWDBUG)
  1447.     dc.b    '(Hardware Debug) '
  1448.   .endif ;HWDBUG
  1449.   .if (^^defined NOCNT)
  1450.     dc.b    '(NoByteCount) '
  1451.   .endif ;NOCNT
  1452.     dc.b    13,10
  1453.     dc.b    '  ('
  1454.     VERSION
  1455.     dc.b    ')',13,10
  1456.   .if (^^defined HWDBUG)|(^^defined NOCNT)
  1457.     dc.b    'Press any key to continue...'
  1458.   .endif
  1459.     dc.b    0
  1460.     even
  1461.  
  1462. *
  1463. *  Terminate and stay resident;
  1464. *  installed driver under GEMDOS.
  1465. *
  1466. nboot2:    
  1467.     move.l    d0,-(sp)    ; save D0
  1468.     pea    msg_loaded(pc)    ; print announcement
  1469.     move.w    #9,-(sp)
  1470.     trap    #1
  1471.     addq    #6,sp
  1472.     move.l    (sp)+,d0
  1473.  
  1474.     move.w    #0,-(sp)    ; exit code
  1475.     move.l    d0,-(sp)
  1476.     move.w    #$31,-(sp)    ; terminate and stay resident
  1477.     trap    #1        ; should never come back...
  1478.     illegal
  1479.  
  1480.  
  1481. * page 
  1482.  
  1483. BPBLEN    equ    18
  1484.     .globl    _puns
  1485. _puns:
  1486. puns:    dc.w    0
  1487.  
  1488.     .globl    _pun
  1489. _pun:
  1490. pun:    dcb.b    maxunits,0
  1491.     .globl    _partstart
  1492. _partstart:
  1493. start:    dcb.l    maxunits,0
  1494. bpbs:    dcb.b    maxunits*18,0
  1495.  
  1496. lastrwtm:    dc.l    0        ; ``_hz_200 + 1'' at last _do_rw()
  1497. tocount:    dc.l    1        ; timeout counter
  1498. retrycnt:    dc.w    1        ; retry counter
  1499.     .globl    _retries
  1500. _retries:    dc.w    nretries    ; number of retries to do
  1501.  
  1502. o_init:        dc.l    1
  1503. o_bpb:        dc.l    1
  1504. o_rw:        dc.l    1
  1505. o_mediach:    dc.l    1
  1506.  
  1507. * page 
  1508. * ---------------- Installer ----------------
  1509. i_sasi1: nop
  1510.  
  1511.     tst.w    bootloaded        ; if boot-loaded, don't Super()
  1512.     bne    nboot3
  1513.     clr.l    -(sp)            ; it's a bird...
  1514.     move.w    #$20,-(sp)        ;    ... it's a plane ...
  1515.     trap    #1            ;      ... no, its:
  1516.     addq    #6,sp            ; SOOUPERUSER!
  1517.     move.l    d0,savssp        ; "Faster than a prefetched opcode..."
  1518.  
  1519. nboot3:    move    #maxunits-1,d1
  1520.     moveq    #-1,d0            ; a bad pun
  1521.     lea    pun,a0
  1522. i_sasi2: move.b    d0,(a0)+
  1523.     dbra    d1,i_sasi2
  1524.  
  1525.   .if VERBOSE
  1526.     andi.b    #($FF-$1E),IERA    ; turn off MFP serial interrupts
  1527.     andi.b    #($FF-$1E),IMRA    ; turn off MFP serial interrupts
  1528.  
  1529.     bsr    crlf
  1530.     move.l    #msg_loaded,-(sp)
  1531.     bsr    puts
  1532.     addq    #4,sp
  1533.   .endif ;VERBOSE
  1534.  
  1535.     bsr    resetSCSI    ; reset the SCSI bus
  1536.  
  1537.     move    #2,clun            ; current logical unit number
  1538.     move.l    #4,cdbit        ; current drive bit
  1539.     move    #0,cpun            ; current physical unit number
  1540.     move    #0,installed        ; none installed yet
  1541.     move    #0,puns            ; no physical units found
  1542.  
  1543. i_sasi3:
  1544.     move.w    cpun,-(sp)        ; pread(sectno, cnt, buf, physunit)
  1545.     move.l    #pbuf,-(sp)
  1546.     move.w    #1,-(sp)        ; 1 sector
  1547.     move.l    #0,-(sp)        ; sectno = 0
  1548.     bsr    pread            ; try to read root sector
  1549.     adda    #12,sp
  1550.  
  1551.     tst.w    d0
  1552.     bne    i_sasi4            ; no controller/disk of that ACSI unit
  1553.  
  1554.     addq    #1,puns            ; found a physical unit
  1555.  
  1556.     bsr    ppu
  1557.  
  1558.     addq    #1,cpun
  1559.     cmpi    #8,cpun
  1560.     bne    i_sasi3
  1561.  
  1562. i_sasi4:
  1563. ; hack in a SCSI partition
  1564.     move.w    #1,puns
  1565.     move.w    #1,installed
  1566.     move.b    #$40,pun+2
  1567.     move.l    #2,start+(2*4)
  1568.     ori.l    #4,_drvbits
  1569.  
  1570.     movea.l    #bpbs+(2*BPBLEN),a2
  1571.     lea    thebpb,a1
  1572.     move    #BPBLEN-1,d0
  1573. .4:    move.b    (a1)+,(a2)+
  1574.     dbra    d0,.4
  1575.  
  1576.     tst    puns            ; any drives found?
  1577.     beq    isase            ; nope, so just terminate
  1578.  
  1579.     clr.l    a5            ; zeropage ptr
  1580.     move.l    hdv_bpb(a5),o_bpb    ; save old vectors
  1581.     move.l    hdv_rw(a5),o_rw
  1582.     move.l    hdv_mediach(a5),o_mediach
  1583.  
  1584.     move.l    #hbpb,hdv_bpb(a5)    ; install our new ones
  1585.     move.l    #hrw,hdv_rw(a5)
  1586.     move.l    #hmediach,hdv_mediach(a5)
  1587.     move.l    #_puns,pun_ptr(a5)
  1588.  
  1589.     bra    isasi5        ; must get back into resident part
  1590.  
  1591. isase:    tst.w    bootloaded    ; if bootloaded, free block and punt
  1592.     bne    isaseb
  1593.     move.l    savssp,-(sp)    ; become a mild mannered user process
  1594.     move.w    #$20,-(sp)    ; Super(savssp)
  1595.     trap    #1
  1596.     addq    #6,sp
  1597.  
  1598.     move.w    #-1,-(sp)    ; exit code
  1599.     move.w    #$4C,-(sp)    ; terminate
  1600.     trap    #1        ; should never come back...
  1601.     illegal
  1602.  
  1603. *
  1604. *  Couldn't install driver, return to boot code
  1605. *
  1606. isaseb:    move.l    baseaddr,-(sp)    ; Mfree(baseaddr)
  1607.     move.w    #$49,-(sp)
  1608.     trap    #1
  1609.     addq.l    #6,sp
  1610.     move.b    #$100-$20,d7    ; return to TOS ROMs
  1611.     rts
  1612.  
  1613.  
  1614. * page 
  1615. *+
  1616. * pread(sectno, cnt, buf, physunit)
  1617. * LONG sectno;
  1618. * BYTE *buf; (word aligned)
  1619. * WORD cnt,physunit;
  1620. *
  1621. * Passed:    dev.w        $a(a0)    $e(sp)
  1622. *        &buf.l        $6(a0)    $a(sp)
  1623. *        cnt.w        $4(a0)    $8(sp)
  1624. *        sectno.l    $0(a0)    $4(sp)
  1625. *
  1626. * Returns:    -1 if we could not read it
  1627. *            (may not exist)
  1628. *-
  1629.     .globl    _pread
  1630. _pread:
  1631. pread:    move    _retries,retrycnt
  1632. pread1:    lea    4(sp),a0        ; frame pointer
  1633.     move.w    $a(a0),-(sp)        ; push physical unit number
  1634.     move.l    $6(a0),-(sp)        ; buffer address
  1635.     move.w    $4(a0),-(sp)        ; number to read
  1636.     move.l    (a0),-(sp)        ; sector number
  1637.     bsr    _hread
  1638.     adda    #12,sp
  1639.     tst    d0
  1640.     beq    pread9            ; no problems
  1641.     bmi    pread8            ; timeout, does not exist
  1642.     subq    #1,retrycnt        ; read error, try try again
  1643.     bpl    pread1
  1644. pread8:    moveq    #-1,d0
  1645.     rts
  1646.  
  1647. pread9:    move    #$8000,d0        ; delay for completion byte
  1648. preada:    subq    #1,d0
  1649.     bne    preada
  1650.     clr.l    d0            ; flag no errors
  1651.     rts
  1652.  
  1653. * page 
  1654. *+
  1655. * ppu
  1656. * Partition physical unit
  1657. *
  1658. *-
  1659. ppu:    move    #0,npart        ; number of partitions we have found
  1660.     movea.l    #pbuf+hd_siz,a0
  1661.     tst.l    (a0)+
  1662.     beq    ppu3            ; if 0, must not be valid
  1663.  
  1664.     moveq    #4-1,d1            ; maximum number of partitions/unit
  1665. ppu1:    movem.l    d1/a0,-(sp)
  1666.     tst.b    (a0)+            ; check the valid partition flag
  1667.     beq    ppu2            ; if 0, not a valid parition
  1668.  
  1669.     addq    #1,npart        ; number of partitions this unit
  1670.  
  1671.     cmpi.b    #'G',(a0)+        ; must find GEM as type
  1672.     bne    ppu2
  1673.     cmpi.b    #'E',(a0)+
  1674.     bne    ppu2
  1675.     cmpi.b    #'M',(a0)+
  1676.     bne    ppu2
  1677.  
  1678.     tst.l    4(a0)            ; is the size 0?
  1679.     beq    ppu2            ; then not a valid partition
  1680.  
  1681.     move.l    (a0),-(sp)        ; save start sector
  1682.  
  1683.     bsr    nxtdrv
  1684.  
  1685.     move.l    (sp)+,d1        ; recall start sector
  1686.  
  1687.     tst    d0            ; valid unit?
  1688.     bmi    ppu2
  1689.  
  1690.     movem.l    d1/a0-a1,-(sp)
  1691.  
  1692.     move.l    d1,-(sp)        ; getbpb(partition_start)
  1693.     bsr    getbpb            ; build bpb and put it in place
  1694.     addq    #4,sp
  1695.  
  1696.     movem.l    (sp)+,d1/a0-a1
  1697.  
  1698.     tst    d0
  1699.     bne    ppu2
  1700.  
  1701.     move.w    cpun,d0
  1702.     move.b    d0,(a0)
  1703.  
  1704.     move.l    d1,(a1)            ; start of partition
  1705.  
  1706.     addq    #1,clun
  1707.     addq    #1,installed        ; actually installed a hard disk
  1708.  
  1709. ppu2:    movem.l    (sp)+,d1/a0
  1710.     adda    #12,a0
  1711.     dbra    d1,ppu1
  1712.  
  1713.     tst    npart            ; did we find any?
  1714.     bne    ppu9
  1715.  
  1716. ppu3:    bsr    nxtdrv            ; no valid partitions found, assume
  1717.     move    cpun,d0            ;  whole thing is one big GEM disk
  1718.     move.b    d0,(a0)
  1719.     move.w    #0,(a1)            ; starts at 0
  1720.     lea    thebpb,a1
  1721.     move    #BPBLEN-1,d0
  1722. ppu4:    move.b    (a1)+,(a2)+
  1723.     dbra    d0,ppu4
  1724.  
  1725.     addq    #1,clun
  1726.     addq    #1,installed
  1727.  
  1728. ppu9:    rts
  1729.  
  1730. * page 
  1731. *+
  1732. * nxtdrv    (of clun, cdbit)
  1733. *    returns d0 = clun, or negative if error
  1734. *        a0 -> pun(clun)
  1735. *        a1 -> start(clun)
  1736. *        a2 -> bpbs(clun)
  1737. *-
  1738.  
  1739. nxtdrv:    cmpi    #maxunits,clun        ; have we already hit maximum?
  1740.     bge    nxtd9            ; yes, so signal error
  1741.  
  1742.     move.l    cdbit,d1        ; get the next bit to turn on
  1743.     move.l    _drvbits,d0        ; tell TOS we have the drive
  1744.     or.l    d1,d0
  1745.     move.l    d0,_drvbits
  1746.  
  1747.     asl.l    #1,d1
  1748.     move.l    d1,cdbit
  1749.     move    clun,d0
  1750.     lea    pun,a0
  1751.     adda    d0,a0
  1752.     lea    start,a1
  1753.     move    d0,d1
  1754.     asl    #2,d1            ; *4 for index into table of longs
  1755.     adda    d1,a1
  1756.     lea    bpbs,a2
  1757.     move    d0,d1
  1758.     mulu    #BPBLEN,d1
  1759.     adda    d1,a2
  1760.     rts
  1761.  
  1762. nxtd9:    moveq    #-1,d0
  1763.     rts
  1764.  
  1765. * page 
  1766. *+
  1767. * getbpb(sectorno)
  1768. * LONG sectorno;
  1769. *-
  1770.  
  1771. getbpb:    move.l    a2,-(sp)
  1772.  
  1773.     move.w    cpun,-(sp)        ; try to read this partition's
  1774.     move.l    #lbuf,-(sp)        ; boot sector
  1775.     move.w    #1,-(sp)        ; number of sectors
  1776.     move.l    16(sp),-(sp)        ; sectorno
  1777.     bsr    pread            ; pread(sectno, cnt, buf, physunit)
  1778.     adda    #12,sp
  1779.  
  1780.     movea.l    (sp)+,a2
  1781.  
  1782.     tst    d0            ; any trouble reading?
  1783.     bmi    getb9            ; bummer
  1784.  
  1785.     lea    lbuf,a3            ; pointer to boot sector
  1786.  
  1787.     move    #$0b,d0
  1788.     bsr    getlhw
  1789.     move    d0,(a2)+        ; =byt/sec
  1790.     move    d0,d1
  1791.  
  1792.     clr.w    d0
  1793.     move.b    $d(a3),d0
  1794.     move    d0,(a2)+        ; =sec/cluster
  1795.  
  1796.     mulu    d1,d0
  1797.     move    d0,(a2)+        ; =byt/cluster
  1798.  
  1799.     move    #$11,d0
  1800.     bsr    getlhw            ; number of directory entries
  1801.     mulu    #32,d0            ; size of each entry
  1802.     divu    d1,d0            ; number of sectors required
  1803.     move.l    d0,d1
  1804.     swap    d1
  1805.     tst    d1
  1806.     beq    getb1
  1807.     addq    #1,d0            ; round up
  1808. getb1:    move    d0,(a2)+        ; =rdlen
  1809.     move    d0,d2
  1810.  
  1811.     move    #$16,d0
  1812.     bsr    getlhw
  1813.     move    d0,(a2)+        ; =FATsize
  1814.     move    d0,d1
  1815.  
  1816.     move    #$e,d0
  1817.     bsr    getlhw            ; number of reserved sectors
  1818.     add    d1,d0
  1819.     move    d0,(a2)+        ; =2nd FAT start
  1820.  
  1821.     add    d1,d0            ; plus size of second fat
  1822.     add    d2,d0            ; plus rdlen
  1823.     move    d0,(a2)+        ; = data start
  1824.     move    d0,d2            ; save start of data
  1825.  
  1826.     move    #$13,d0
  1827.     bsr    getlhw            ; number of sectors on media
  1828.     sub    d2,d0            ; subtract number used by FATs,dir,boot
  1829.     clr.l    d1
  1830.     move    d0,d1
  1831.     clr    d0
  1832.     move.b    $d(a3),d0        ; number of sectors/cluster
  1833.     divu    d0,d1            ; rounding down
  1834.     move    d1,(a2)+        ; =number of clusters
  1835.     move    #1,(a2)            ; =flags, 16 bit fats
  1836.     clr.l    d0            ; no errors
  1837. getb9:    rts
  1838.  
  1839. *+
  1840. * WORD getlhw(d0=offset)
  1841. * returns word (low,high) from 0(D0,A3)
  1842. *-
  1843.  
  1844. getlhw:    move    d1,-(sp)        ; preserve d1
  1845.     move.b    1(a3,d0.w),d1
  1846.     lsl.w    #8,d1
  1847.     move.b    0(a3,d0.w),d1
  1848.     move    d1,d0
  1849.     move    (sp)+,d1
  1850.     rts
  1851.  
  1852. * page 
  1853. *+
  1854. * BPB for 11MB Syquest partition
  1855. *-
  1856. thebpb:    dc.w    512            ; #bytes/sector
  1857.     dc.w    2            ; #sectors/cluster
  1858.     dc.w    1024            ; #bytes/cluster
  1859.     dc.w    17            ; rdlen (512 root files) (in sectors)
  1860.     dc.w    43            ; FATsiz (20736 FAT entries) (sectors)
  1861.     dc.w    44            ; 2nd FAT start
  1862.     dc.w    104            ; data start (in sectors)
  1863.     dc.w    10837            ; #clusters (approximate here)
  1864.     dc.w    1            ; flags (16-bit FATs)
  1865.  
  1866.     .even
  1867.  
  1868.     bss
  1869. savssp:    ds.l    1            ; (saved SSP)
  1870. clun:    ds.w    1
  1871. cpun:    ds.w    1
  1872. cdbit:    ds.l    1
  1873. npart:    ds.w    1            ; number of partitions found this pun
  1874. installed: ds.w    1            ; number hard disk partitions installed
  1875.  
  1876. hd_siz    equ    $1c2            ; offset into pbuf for partition info
  1877. pbuf:    ds.b    512
  1878. lbuf:    ds.b    512
  1879.  
  1880.     end
  1881.  -> filename part of path
  1882. origstk:    dc.l    0        ; =  original supervisor stack
  1883. autodma:    dcb.b    44,0        ; 44
  1884.