home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / emulation / qlsource / romsrc / flp / flp2_asm < prev   
Encoding:
Text File  |  1998-01-11  |  66.4 KB  |  3,670 lines

  1. */beginfile FLP2_asm
  2.  
  3. ; --------------------------------------------------------------
  4. ; FLP2_asm - FLP Physical I/O - Amiga specific disk access
  5. ;      - last modified 11/01/98
  6.  
  7. ; Amiga-QDOS sources by Rainer Kowallik
  8. ;    ...latest changes by Mark J Swift
  9. ; --------------------------------------------------------------
  10.  
  11. ;  Version message
  12.  
  13. BANNER:
  14.     dc.b    0,34,'Amiga-QDOS FLP physical I/O v1.30',$A
  15.  
  16. ; -------------------------------------------------------------
  17. ;    Set up Basic procedures
  18.  
  19. user_ini:
  20.     movem.l    d1-d3/a0-a5,-(a7)
  21.  
  22.     lea    BANNER(pc),a1    ; start of message
  23.     suba.l    a0,a0        ; output channel 0
  24.     move.w    UT.MTEXT,a2
  25.     jsr    (a2)        ; print it
  26.  
  27. ; link in additional BASIC commands
  28.  
  29.     lea    PROC_DEF(pc),a1
  30.     suba.l    a2,a2
  31.     move.w    $110,a2
  32.     jsr    (a2)
  33.  
  34. ; allocate memory for disk variables
  35.  
  36.     move.l    #FV_LEN,d1
  37.     moveq    #MT.ALCHP,d0
  38.     moveq    #0,d2
  39.     trap    #1
  40.     move.l    a0,AV.DSKV
  41.  
  42. ;  allow disk DMA.
  43.  
  44.     move.w    #%1000000000010000,DMACON ; enable disk DMA
  45.  
  46. ; clear all the variables
  47.  
  48.     move.l    AV.DSKV,a3    ; address of disk vars ->a3
  49.     moveq    #((FV_LEN>>1)-1),d0
  50.  
  51. CLRV_LUP1:
  52.     clr.w    (a3)+
  53.     dbra    d0,CLRV_LUP1
  54.  
  55. ;  set up disk flags for:
  56. ;  Disable disk operation via index interrupt.
  57. ;  Write operation. Index on write. No index on read
  58. ;  WORDSYNC on. No retry on read error.
  59.  
  60.     move.l    AV.DSKV,a3    ; address of disk vars ->a3
  61.     move.w    #%0110100000100000,FV.FLAGS(a3)
  62.  
  63. ; link in polled routine to control switching off the motor
  64.  
  65.     lea    POLSERV(pc),a1    ; address of routine
  66.     move.l    AV.DSKV,a0
  67.     lea    FV.POLLLink(a0),a0
  68.     move.l    a1,4(a0)
  69.     moveq    #MT.LPOLL,d0
  70.     trap    #1
  71.  
  72. ; check availability of external drive(s)
  73.  
  74.     move.l    AV.DSKV,a3    ; address of disk vars ->a3
  75.     lea    FV.DRVVArs(a3),a4 ; address of drive vars->a4
  76.  
  77.     moveq    #2,d3        ; 3 drives to check
  78.  
  79. AVAIL_LUP:
  80.     moveq    #3,d0
  81.     sub.w    d3,d0
  82.     bsr    hw_DRV_TYP
  83.     beq.s    NODRV
  84.  
  85.     lea    DV_LEN(a4),a4
  86.     move.l    d0,DV.TYPE(a4)
  87.  
  88.     dbra    d3,AVAIL_LUP
  89.  
  90. NODRV    addq.w    #1,d3
  91.     moveq    #3,d0
  92.     sub.w    d3,d0
  93.     move.w    d0,FV.MAXDRive(a3)
  94.  
  95. ; mount each and every drive
  96.  
  97.     move.w    d0,d3
  98.  
  99. MOUNT_LUP:
  100.     move.w    d3,d0
  101.     bsr.s    MOUNT        ; mount drive
  102.  
  103.     dbra    d3,MOUNT_LUP    ; continue with next drive
  104.  
  105. INI_RTS:
  106.     movem.l    (a7)+,d1-d3/a0-a5
  107.     moveq    #0,d0
  108.     rts
  109.  
  110. ; -------------------------------------------------------------
  111. ; initialise and set the individual drive variables
  112.  
  113. MOUNT:
  114.     movem.l    d3/a3-a5,-(a7)
  115.  
  116.     move.w    d0,d3        ; drive number to d3
  117.  
  118.     move.l    AV.DSKV,a3    ; address of disk vars ->a3
  119.     lea    FV.DRVVArs(a3),a4 ; address of drive vars->a4
  120.  
  121.     mulu.w    #DV_LEN,d3
  122.     lea    0(a4,d3.w),a4    ; relevant drive vars
  123.  
  124.     move.w    d0,d3        ; drive number to d3
  125.  
  126. ; initialise and set the individual drive variables
  127.  
  128.     clr.w    DV.TIMEOut(a4)    ; timeout
  129.     clr.w    DV.SIDE(a4)    ; side
  130.     clr.w    DV.TRACK(a4)    ; track
  131.  
  132. ; allocate some room for drives buffer variables
  133.  
  134. ALOCBUF:
  135.     move.l    DV.SIDE0buff(a4),d0
  136.     bne.s    MOUNTOK        ; already defined
  137.  
  138.     movem.l    d1-d3/a1-a4,-(a7)
  139.     move.l    #(2*AB.BUFENd),d1
  140.     moveq    #MT.ALCHP,d0
  141.     moveq    #0,d2
  142.     trap    #1
  143.     movem.l    (a7)+,d1-d3/a1-a4
  144.  
  145.     tst.l    d0
  146.     bne.s    MOUNTX        ; exit on error
  147.  
  148.     move.l    a0,a5
  149.  
  150.     move.l    a5,DV.SIDE0buff(a4) ; addrs buffer vars, side 0
  151.     move.w    d3,AB.DRIVE(a5)    ; set disk #
  152.     clr.w    AB.SIDE(a5)    ; set first side
  153.     clr.w    AB.TRACK(a5)    ; set first track
  154.     clr.w    AB.PENDWflag(a5)    ; clear pending write
  155.     move.w    #511,AB.BADFLag(a5) ; sectors all bad
  156.  
  157.     lea    AB.BUFENd(a5),a5
  158.  
  159.     move.l    a5,DV.SIDE1buff(a4) ; addrs buffer vars, side 1
  160.     move.w    d3,AB.DRIVE(a5)    ; set disk #
  161.     move.w    #1,AB.SIDE(a5)    ; set second side
  162.     clr.w    AB.TRACK(a5)    ; set first track
  163.     clr.w    AB.PENDWflag(a5)    ; clear pending write
  164.     move.w    #511,AB.BADFLag(a5) ; sectors all bad
  165.  
  166. ; initialise drive status
  167.  
  168.     move.w    d3,d0
  169.  
  170.     bset    d0,FV.CNGFLag(a3) ; set disk changed
  171.     bclr    d0,FV.RDYFLag(a3) ; set drive not ready
  172.  
  173.     bsr    hw_GO_TK0
  174.  
  175. MOUNTOK:
  176.     moveq    #0,d0
  177.  
  178.     cmp.w    FV.MAXDRive(a3),d3
  179.     ble.s    MOUNTX
  180.     move.w    d3,FV.MAXDRive(a3)
  181.  
  182. MOUNTX:
  183.     movem.l    (a7)+,d3/a3-a5
  184.  
  185.     rts
  186.  
  187. ; -------------------------------------------------------------
  188. ;    interfacing to the CST floppy controller body
  189.  
  190. fd_read:
  191.     movem.l    d0/d3-d4/a3,-(a7)
  192.  
  193.     ifd    debug
  194.     movem.l    d0/a0,-(a7)    ; temporary aberration
  195.     move.l    #0,a0
  196.     move.l    #$00020000+'RD',d0
  197.     bsr    IOD0
  198.     move.l    #0,a0
  199.     move.l    d1,d0
  200.     bsr    HEX08
  201.     movem.l    (a7)+,d0/a0
  202.     endc
  203.  
  204.     moveq    #0,d3
  205.     move.w    fdd_rbeg(a3),d3    ; get no of bytes to skip
  206.     moveq    #0,d4
  207.     move.w    fdd_rend(a3),d4    ; get no of bytes to leave
  208.  
  209.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  210.  
  211. fd_readl:
  212.     bsr    RQSEC
  213.  
  214.     move.w    d0,d2        ; error return in d2 !
  215.     movem.l    (a7)+,d0/d3-d4/a3
  216.     rts
  217.  
  218. ; -------------------------------------------------------------
  219. fd_ftrack:
  220.     movem.l    a3,-(a7)
  221.  
  222.     ifd    debug
  223.     movem.l    d0/a0,-(a7)    ; temporary aberration
  224.     move.l    #0,a0
  225.     move.l    #$00020000+'FT',d0
  226.     bsr    IOD0
  227.     movem.l    (a7)+,d0/a0
  228.     endc
  229.  
  230.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  231.  
  232. fd_ftrackl:
  233.     bsr    FTRACK
  234.  
  235.     movem.l     (a7)+,a3
  236.     rts
  237.  
  238. ; -------------------------------------------------------------
  239. fd_write:
  240.     movem.l    d0/a3,-(a7)
  241.  
  242.     ifd    debug
  243.     movem.l    d0/a0,-(a7)    ; temporary aberration
  244.     move.l    #0,a0
  245.     move.l    #$00020000+'WR',d0
  246.     bsr    IOD0
  247.     move.l    #0,a0
  248.     move.l    d1,d0
  249.     bsr    HEX08
  250.     movem.l    (a7)+,d0/a0
  251.     endc
  252.  
  253.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  254.  
  255. fd_writel:
  256.     bsr    WQSEC
  257.  
  258.     move.w    d0,d2        ; error return in d2 !
  259.     movem.l    (a7)+,d0/a3
  260.     rts
  261.  
  262. ; -------------------------------------------------------------
  263. fd_side:
  264.     movem.l    d0-d1/a3,-(a7)
  265.  
  266.     ifd    debug
  267.     movem.l    d0/a0,-(a7)    ; temporary aberration
  268.     move.l    #0,a0
  269.     move.l    #$00020000+'SD',d0
  270.     bsr    IOD0
  271.     move.l    #0,a0
  272.     move.l    d1,d0
  273.     bsr    HEX08
  274.     movem.l    (a7)+,d0/a0
  275.     endc
  276.  
  277.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  278.  
  279. fd_sidel:
  280.     moveq    #0,d0
  281.     move.b    d1,d0
  282.     bsr    SEL_SIDE
  283.  
  284.     movem.l    (a7)+,d0-d1/a3
  285.     rts
  286.  
  287. ; -------------------------------------------------------------
  288. fd_select:
  289.     movem.l    d0-d1/a3,-(a7)
  290.  
  291.     ifd    debug
  292.     movem.l    d0/a0,-(a7)    ; temporary aberration
  293.     move.l    #0,a0
  294.     move.l    #$00020000+'SL',d0
  295.     bsr    IOD0
  296.     move.l    #0,a0
  297.     move.l    d1,d0
  298.     bsr    HEX08
  299.     movem.l    (a7)+,d0/a0
  300.     endc
  301.  
  302.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  303.  
  304. fd_selctl:
  305.     cmp.b    #4,d1        ; drive within range ?
  306.     bgt.s    fd_slctx
  307.  
  308.     moveq    #0,d0
  309.     move.b    d1,d0
  310.     subq.b    #1,d0
  311.     ext.w    d0
  312.     bsr    SEL_DRV
  313.  
  314. fd_slctx
  315.     movem.l    (a7)+,d0-d1/a3
  316.     rts
  317.  
  318. ; -------------------------------------------------------------
  319. fd_seek:
  320.     movem.l    d0-d1/a3,-(a7)
  321.  
  322.     ifd    debug
  323.     movem.l    d0/a0,-(a7)    ; temporary aberration
  324.     move.l    #0,a0
  325.     move.l    #$00020000+'SK',d0
  326.     bsr    IOD0
  327.     move.l    #0,a0
  328.     move.l    d1,d0
  329.     bsr    HEX08
  330.     movem.l    (a7)+,d0/a0
  331.     endc
  332.  
  333.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  334.  
  335. fd_seekl:
  336.     moveq    #0,d0
  337.     move.b    d1,d0
  338.     bsr    GO_TRACK
  339.  
  340.     movem.l    (a7)+,d0-d1/a3
  341.     rts
  342.  
  343. ; -------------------------------------------------------------
  344. fd_restore:
  345.     movem.l    a3,-(a7)
  346.  
  347.     ifd    debug
  348.     movem.l    d0/a0,-(a7)    ; temporary aberration
  349.     move.l    #0,a0
  350.     move.l    #$00020000+'RS',d0
  351.     bsr    IOD0
  352.     movem.l    (a7)+,d0/a0
  353.     endc
  354.  
  355.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  356.  
  357. fd_restrl:
  358.     moveq    #0,d0
  359.     bsr    GO_TRACK
  360.  
  361.     movem.l    (a7)+,a3
  362.     rts
  363.  
  364. ; -------------------------------------------------------------
  365. fd_wpro:
  366.     movem.l    a3,-(a7)
  367.  
  368.     ifd    debug
  369.     movem.l    d0/a0,-(a7)    ; temporary aberration
  370.     move.l    #0,a0
  371.     move.l    #$00020000+'WP',d0
  372.     bsr    IOD0
  373.     movem.l    (a7)+,d0/a0
  374.     endc
  375.  
  376.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  377.  
  378. fd_wprol:
  379.     bsr    WPRO
  380.  
  381.     ifd    debug
  382.     movem.l    d0/a0,-(a7)    ; temporary aberration
  383.     move.l    #0,a0
  384.     bsr    HEX08
  385.     movem.l    (a7)+,d0/a0
  386.     endc
  387.  
  388.     movem.l    (a7)+,a3
  389.     rts
  390.  
  391. ; -------------------------------------------------------------
  392. fd_chng:
  393.     movem.l    a3,-(a7)
  394.  
  395.     ifd    debug
  396.     movem.l    d0/a0,-(a7)    ; temporary aberration
  397.     move.l    #0,a0
  398.     move.l    #$00020000+'CG',d0
  399.     bsr    IOD0
  400.     movem.l    (a7)+,d0/a0
  401.     endc
  402.  
  403.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  404.  
  405. fd_chngl:
  406.     bsr    CHNG
  407.  
  408.     ifd    debug
  409.     movem.l    d0/a0,-(a7)    ; temporary aberration
  410.     move.l    #0,a0
  411.     bsr    HEX08
  412.     movem.l    (a7)+,d0/a0
  413.     endc
  414.  
  415.     movem.l    (a7)+,a3
  416.     rts
  417.  
  418. ; -------------------------------------------------------------
  419. fd_ckrdy:
  420.     movem.l    a3,-(a7)
  421.  
  422.     ifd    debug
  423.     movem.l    d0/a0,-(a7)    ; temporary aberration
  424.     move.l    #0,a0
  425.     move.l    #$00020000+'CK',d0
  426.     bsr    IOD0
  427.     movem.l    (a7)+,d0/a0
  428.     endc
  429.  
  430.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  431.  
  432. fd_ckrdyl:
  433.     bsr    CKRDY
  434.  
  435.     ifd    debug
  436.     movem.l    d0/a0,-(a7)    ; temporary aberration
  437.     move.l    #0,a0
  438.     bsr    HEX08
  439.     movem.l    (a7)+,d0/a0
  440.     endc
  441.  
  442.     movem.l    (a7)+,a3
  443.     rts
  444.  
  445. ; -------------------------------------------------------------
  446. fd_raddr:
  447.     movem.l    d2/a0/a3-a5,-(a7)
  448.  
  449.     ifd    debug
  450.     movem.l    d0/a0,-(a7)    ; temporary aberration
  451.     move.l    #0,a0
  452.     move.l    #$00020000+'RA',d0
  453.     bsr    IOD0
  454.     movem.l    (a7)+,d0/a0
  455.     endc
  456.  
  457.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  458.  
  459. fd_raddrl:
  460.     move.w    FV.REQDRive(a3),d0 ; Required drive in d0
  461.     and.w    #$3,d0        ; Only drives 0-3.
  462.  
  463.     move.w    d0,d2        ; Address of drive vars for
  464.     mulu.w    #DV_LEN,d2    ; required drive in a4
  465.     lea    FV.DRVVArs(a3,d2.w),a4
  466.  
  467.     move.w    DV.TRACK(a4),d1
  468.  
  469.     movem.l    (a7)+,d2/a0/a3-a5
  470.     moveq    #0,d0
  471.     rts
  472.  
  473. ; -------------------------------------------------------------
  474. fd_dskcng:
  475.     movem.l    d0/a3,-(a7)
  476.  
  477.     ifd    debug
  478.     movem.l    d0/a0,-(a7)    ; temporary aberration
  479.     move.l    #0,a0
  480.     move.l    #$00020000+'CD',d0
  481.     bsr    IOD0
  482.     movem.l    (a7)+,d0/a0
  483.     endc
  484.  
  485.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  486.  
  487. fd_dscngl:
  488.     move.w    FV.REQDRive(a3),d0
  489.  
  490.     bsr    DSKCNG
  491.  
  492.     movem.l    (a7)+,d0/a3
  493.     rts
  494.  
  495. ; -------------------------------------------------------------
  496. ;  Flush ASCII buffer for drive d0.w, only if it is truely
  497. ;  owned by that drive. Called before motor is switched off
  498. ;  Error returned in d0.
  499. ; -------------------------------------------------------------
  500. FLUSH_BUFF:
  501.     movem.l    d1-d2,-(a7)
  502.  
  503.     move.w    FV.REQDRive(a3),d2 ; save old required drive
  504.     move.w    d0,FV.REQDRive(a3) ; select this drive
  505.     bsr    WQDISK        ; write the buffer out
  506.     move.w    d2,FV.REQDRive(a3) ; restore old drive
  507.  
  508. FLUSH_BUFX:
  509.     tst.b    d0
  510.     movem.l    (a7)+,d1-d2
  511.     rts
  512.  
  513. ; -------------------------------------------------------------
  514. ;  Free ASCII buffer for drive d0.w by flushing contents,
  515. ;  irrespective of the owner. Called before new data is
  516. ;  loaded into the buffer. Error returned in d0.
  517. ; -------------------------------------------------------------
  518. FREE_BUFF:
  519.     movem.l    d2/a3-a5,-(a7)
  520.  
  521.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  522.  
  523.     and.w    #$3,d0        ; Only drives 0-3.
  524.  
  525.     move.w    d0,d2        ; Address of drive vars for
  526.     mulu.w    #DV_LEN,d2    ; required drive in a4
  527.     lea    FV.DRVVArs(a3,d2.w),a4
  528.  
  529.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  530.     lsl.w    #2,d2        ; for required side in a5
  531.     move.l    DV.SIDE0buff(a4,d2.w),a5
  532.  
  533.     moveq    #0,d0
  534.     tst.w    AB.PENDWflag(a5)    ; any pending writes ?
  535.     beq.s    FREE_BUFX    ; no !
  536.  
  537.     move.w    FV.REQDRive(a3),d2 ; save old required drive
  538.     move.w    AB.DRIVE(a5),FV.REQDRive(a3)
  539.     bsr    WQDISK        ; write the buffer out
  540.     move.w    d2,FV.REQDRive(a3) ; restore old drive
  541.  
  542. FREE_BUFX:
  543.     tst.b    d0
  544.     movem.l    (a7)+,d2/a3-a5
  545.     rts
  546.  
  547. ; -------------------------------------------------------------
  548. ;  Format current track for drive FV.REQDRive then verify track.
  549. ;  Error returned in d0.
  550. ; -------------------------------------------------------------
  551. FTRACK:
  552.     movem.l    d2/a3-a5,-(a7)
  553.  
  554.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  555.  
  556.     move.w    FV.REQDRive(a3),d0
  557.     and.w    #$3,d0        ; only drives 0-3
  558.  
  559.     move.w    d0,d2        ; Address of drive vars for
  560.     mulu.w    #DV_LEN,d2    ; required drive in a4
  561.     lea    FV.DRVVArs(a3,d2.w),a4
  562.  
  563.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  564.     lsl.w    #2,d2        ; for required side in a5
  565.     move.l    DV.SIDE0buff(a4,d2.w),a5
  566.  
  567.     move.w    #511,AB.PENDWflag(a5); indicate a write pending
  568.     move.w    #511,AB.BADFLag(a5) ; and all sectors bad
  569.     move.w    d0,AB.DRIVE(a5)
  570.     move.w    d0,d2        ; save drive number
  571.     bsr    WQDISK        ; write track to disk
  572.  
  573.     clr.w    AB.BADFLag(a5)
  574.     bset    d2,FV.CNGFLag(a3) ; signal disk change so as
  575.     bclr    d2,FV.RDYFLag(a3) ; to force a track read
  576.  
  577. FTRACKX:
  578.     tst.l    d0
  579.  
  580.     movem.l    (a7)+,d2/a3-a5
  581.     rts
  582.  
  583. ; -------------------------------------------------------------
  584. ;  Write one Track:
  585. ;  If the writeflag is not set, then skip this operation
  586. ;  Now prepare this Track and code it to MFM, write it to Disk,
  587. ;  and reset the writeflag. Error returned in d0.
  588. ; -------------------------------------------------------------
  589. WQDISK:
  590.     movem.l    d1-d2/d4-d5/a0-a1/a3-a5,-(a7)
  591.  
  592.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  593.  
  594.     move.w    FV.REQDRive(a3),d0
  595.     and.w    #$3,d0        ; only drives 0-3
  596.  
  597.     move.w    d0,d2        ; Address of drive vars for
  598.     mulu.w    #DV_LEN,d2    ; required drive in a4
  599.     lea    FV.DRVVArs(a3,d2.w),a4
  600.  
  601.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  602.     lsl.w    #2,d2        ; for required side in a5
  603.     move.l    DV.SIDE0buff(a4,d2.w),a5
  604.  
  605.     tst.w    AB.PENDWflag(a5)    ; any pending writes ?
  606.     beq    WQABORT_OK    ; no !
  607.  
  608.     cmp.w    AB.DRIVE(a5),d0 ; does buffer belong to me?
  609.     bne    WQABORT_OK    ; no !
  610.  
  611. ; check write protect status before trying to write
  612.  
  613.     bsr    WPRO
  614.     tst.b    d0
  615.     bne    WQABORT_WP
  616.  
  617. ; make sure drive is switched on
  618.     move.w    FV.REQDRive(a3),d0
  619.     bsr    SEL_DRV        ; check and switch on drive
  620.     bne    WQABORT_NF    ; drive not found
  621.  
  622. WQDSK1:
  623.     move.l    #MFMBUFFER,a1    ; address of MFM buffer, a1
  624.  
  625.     clr.w    FV.LASTBit(a3)    ; new MFM calculation
  626.  
  627. ; Now write 9 sectors in QDOS format
  628.  
  629.     moveq    #0,d4        ; initialise sector count
  630.  
  631. ; make some room between index mark and first header
  632.  
  633.     moveq    #91,d1        ; counter for 92 words
  634. WQROOMLP:
  635.     moveq    #$4E,d0        ; byte to write is $4E
  636.     bsr    ASCMFMD0
  637.     move.w    d0,(a1)+
  638.     dbra    d1,WQROOMLP
  639.  
  640. WQDSKLP:
  641.  
  642. ; preamble
  643.  
  644.     moveq    #83,d1        ; counter for 24+60 words
  645. WQPRELP:
  646.     moveq    #$4E,d0        ; byte to write is $4E
  647.     bsr    ASCMFMD0
  648.     move.w    d0,(a1)+
  649.     dbra    d1,WQPRELP
  650.  
  651. ; syncron 1
  652.  
  653.     moveq    #11,d1        ; counter for 12 words
  654. WQSYNLP1:
  655.     moveq    #0,d0        ; byte to write is 0
  656.     bsr    ASCMFMD0
  657.     move.w    d0,(a1)+
  658.     dbra    d1,WQSYNLP1
  659.  
  660. ; header block
  661.  
  662.     move.l    #$44894489,(a1)+    ; write 3 MFM sync words
  663.     move.l    #$44895554,(a1)+    ; and header block ID
  664.  
  665.     move.w    #$A1FE,FV.LASTBit(a3) ; set last bit variable
  666.  
  667. ; create an ASCII header block for this sector
  668.  
  669.     lea    6(a1),a0     ; a reasonably safe place
  670.  
  671.     move.w    DV.TRACK(a4),d0
  672.     move.b    d0,(a0)+     ; track 0-79
  673.     move.w    DV.SIDE(a4),d0
  674.     move.b    d0,(a0)+     ; side 0/1
  675.     move.b    d4,(a0)
  676.     addq.b    #1,(a0)+     ; sector 1-9
  677.     move.b    #2,(a0)+     ; bytes/sector, 2=512
  678.  
  679.     lea    -4(a0),a0    ; start of ASCII header
  680.     moveq    #4,d1        ; bytes in CRC calculation
  681.     move.w    #$B230,d0    ; initialise CRC
  682.     bsr    CALCCRC
  683.     move.w    d0,4(a0)     ; write ASCII CRC
  684.  
  685.     moveq    #$5,d1        ; count for 6 ASCII bytes
  686.  
  687. WQHEDLP:
  688.     move.b    (a0)+,d0
  689.     bsr    ASCMFMD0
  690.     move.w    d0,(a1)+
  691.     dbra    d1,WQHEDLP
  692.  
  693. ; trailer 1
  694.  
  695.     moveq    #21,d1        ; count for 22 MFM words
  696.  
  697. WQTRLLP1:
  698.     moveq    #$4E,d0        ; byte to write is $4E
  699.     bsr    ASCMFMD0
  700.     move.w    d0,(a1)+
  701.     dbra    d1,WQTRLLP1
  702.  
  703. ; syncron 2
  704.  
  705.     moveq    #11,d1        ; count for 12 MFM words
  706.  
  707. WQSYNLP2:
  708.     moveq    #0,d0        ; byte to write is 0
  709.     bsr    ASCMFMD0
  710.     move.w    d0,(a1)+
  711.     dbra    d1,WQSYNLP2
  712.  
  713. ; data block
  714.  
  715.     move.l    #$44894489,(a1)+    ; write 3 MFM sync words
  716.     move.l    #$44895545,(a1)+    ; and data block ID
  717.  
  718.     move.w    #$A1FB,FV.LASTBit(a3) ; set last bit variable
  719.  
  720.     move.w    AB.BADFLag(a5),d0
  721.     btst    d4,d0        ; check if sector is OK
  722.     beq.s    WQDSK2
  723.  
  724. ; sector is bad or undefined so create one from scratch
  725.  
  726.     move.l    #$252AA52A,(a1)+    ; initialise with 512 MFM
  727.     move.w    #254,d1        ; words. The MFM equivalent
  728.                 ; of $30.
  729. WQINILP:
  730.     move.l    #$A52AA52A,(a1)+
  731.     dbra    d1,WQINILP
  732.  
  733.     move.l    #$44952551,(a1)+    ; write MFM of CRC word
  734.  
  735.     move.w    #$A73D,FV.LASTBit(a3) ; set last bit variable
  736.  
  737.     bra    WQDSK3
  738.  
  739. ; sector is OK so use proper ASCII buffer
  740.  
  741. WQDSK2:
  742.     move.l    d4,d0        ; sector number-1
  743.     lsl.w    #2,d0        ; find offset
  744.     move.l    AB.SCTR1(a5,d0.w),a0 ; ASCII buffer address
  745.  
  746.     move.w    #513,d1        ; 514 ASCII bytes
  747.  
  748. WQDATLP:
  749.     move.b    (a0)+,d0
  750.     bsr    ASCMFMD0
  751.     move.w    d0,(a1)+
  752.     dbra    d1,WQDATLP
  753.  
  754. WQDSK3:
  755.     addq    #1,d4
  756.     cmpi.b    #8,d4
  757.     ble    WQDSKLP
  758.  
  759. ; write excess bytes
  760.  
  761.     move.w    #(WLEN/2-(92+9*(24+60+12+10+22+12+518))),d1
  762.  
  763. WQXESLP:
  764.     moveq    #$4E,d0        ; byte to write is $4E
  765.     bsr    ASCMFMD0
  766.     move.w    d0,(a1)+
  767.     dbra    d1,WQXESLP
  768.  
  769. ; now write MFM track
  770.  
  771.     move.w    AB.DRIVE(a5),d0
  772.     move.w    DV.SIDE(a4),d1
  773.     move.w    DV.TRACK(a4),d2
  774.     move.l    #MFMBUFFER,a0    ; start of track image
  775.  
  776.     ifd    debug
  777.  
  778.     movem.l    d0/a0,-(a7)    ; temporary aberration
  779.     suba.l    a0,a0
  780.     move.w    AB.DRIVE(a5),d0
  781.     bsr    HEX08
  782.     move.w    DV.SIDE(a4),d0
  783.     bsr    HEX08
  784.     move.w    DV.TRACK(a4),d0
  785.     bsr    HEX08
  786.     movem.l    (a7)+,d0/a0
  787.  
  788.     movem.l    d0/a0,-(a7)    ; temporary aberration
  789.     suba.l    a0,a0
  790.     move.l    #$00020000+'of',d0
  791.     bsr    IOD0
  792.     movem.l    (a7)+,d0/a0
  793.  
  794.     endc
  795.  
  796.     bsr    SCR_OFF
  797.  
  798.     ifd    debug
  799.  
  800.     movem.l    d0/a0,-(a7)    ; temporary aberration
  801.     suba.l    a0,a0
  802.     move.l    #$00020000+'=o',d0
  803.     bsr    IOD0
  804.     movem.l    (a7)+,d0/a0
  805.  
  806.     endc
  807.  
  808.     bsr    hw_WR_DSK    ; write buffer to disk
  809.  
  810. ; make flags right
  811.  
  812.     clr.w    AB.PENDWflag(a5)
  813.  
  814.     bclr    d0,FV.CNGFLag(a3)
  815.  
  816. ; invalidate mfm buffer
  817.  
  818.     move.l    #MFMBUFFER,a1    ; address of MFM buffer, a1
  819.     lea    184(a1),a1
  820.     moveq    #8,d0        ; loop 9 times
  821.  
  822. WQSCRUB:
  823.     lea    198(a1),a1
  824.     clr.w    (a1)
  825.     lea    88(a1),a1
  826.     clr.w    (a1)
  827.     lea    1030(a1),a1
  828.     dbra    d0,WQSCRUB
  829.  
  830. WQABORT_OK:
  831.     moveq    #0,d0
  832.     bra.s    WQDISKX
  833.  
  834. WQABORT_WP:
  835.     moveq    #-20,d0        ; signal writeprotect
  836.     bra.s    WQDISKX
  837.  
  838. WQABORT_NF:
  839.     moveq    #-7,d0        ; signal drive not found
  840.  
  841. WQDISKX:
  842.     tst.b    d0
  843.     movem.l    (a7)+,d1-d2/d4-d5/a0-a1/a3-a5
  844.     rts
  845.  
  846. ; -------------------------------------------------------------
  847. ; The following section uses a slightly different conventions
  848. ; in order to adopt it to the CST floppy controller software.
  849. ; The sector is passed in D1, the I/O buffer address in A1
  850. ; -------------------------------------------------------------
  851.  
  852. ; -------------------------------------------------------------
  853. ;  Read one Track:
  854. ;  If the Track in the Buffer has the Writeflag set, then write
  855. ;  this track !
  856. ;  Now read a track, and decode it according to MFM conventions
  857. ; -------------------------------------------------------------
  858. RQDISK:
  859.     movem.l    d1-d3/a0-a5,-(a7)
  860.  
  861.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  862.  
  863.     move.w    FV.REQDRive(a3),d0
  864.     and.w    #$3,d0        ; only drives 0-3
  865.  
  866.     move.w    d0,d2        ; Address of drive vars for
  867.     mulu.w    #DV_LEN,d2    ; required drive in a4
  868.     lea    FV.DRVVArs(a3,d2.w),a4
  869.  
  870.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  871.     lsl.w    #2,d2        ; for required side in a5
  872.     move.l    DV.SIDE0buff(a4,d2.w),a5
  873.  
  874. ; first check if buffer already contains correct info
  875.  
  876.     cmp.w    AB.DRIVE(a5),d0
  877.     bne.s    RQDISK1
  878.  
  879.     move.w    DV.SIDE(a4),d1
  880.     cmp.w    AB.SIDE(a5),d1
  881.     bne.s    RQDISK1
  882.  
  883.     move.w    DV.TRACK(a4),d1
  884.     cmp.w    AB.TRACK(a5),d1
  885.     bne.s    RQDISK1
  886.  
  887. ; disk changed?
  888.  
  889.     bsr    CHNG
  890.     tst.b    d0
  891.     beq    RQABORT_OK    ; quit if disk not changed
  892.  
  893. ; now check for pending write operations
  894.  
  895. RQDISK1:
  896.  
  897.     bsr    FREE_BUFF
  898.     bne    RQDISKX        ; cannot free buffer
  899.  
  900. ; make sure drive is switched on
  901.  
  902.     move.w    FV.REQDRive(a3),d0
  903.     bsr    SEL_DRV        ; check and switch on drive
  904.     bne    RQABORT_NF    ; drive not found
  905.  
  906. ; indicate new owner of this buffer
  907.  
  908.     move.w    FV.REQDRive(a3),AB.DRIVE(a5)
  909.     move.w    DV.SIDE(a4),AB.SIDE(a5)
  910.     move.w    DV.TRACK(a4),AB.TRACK(a5)
  911.  
  912. ; currently no changes to sectors
  913.  
  914.     clr.w    AB.PENDWflag(a5)
  915.  
  916. ; currently no good sectors at all
  917.  
  918.     move.w    #511,AB.BADFLag(a5)
  919.  
  920.     move.w    FV.FLAGS(a3),d3
  921.     and.w    #%0000000000100000,d3 ; number of retries
  922.     lsr.w    #3,d3
  923.  
  924. RQTRYLOOP:
  925.     lea    AB.BUFBEg(a5),a0    ; address to put ASCII
  926.     movem.l    a0,-(a7)     ; save for later
  927.  
  928.  
  929. ;  now read MFM track
  930.  
  931.     move.w    AB.DRIVE(a5),d0
  932.     move.w    DV.SIDE(a4),d1
  933.     move.w    DV.TRACK(a4),d2
  934.     move.l    #MFMBUFFER,a0    ; start of track image
  935.  
  936.     ifd    debug
  937.  
  938.     movem.l    d0/a0,-(a7)    ; temporary aberration
  939.     suba.l    a0,a0
  940.     move.w    AB.DRIVE(a5),d0
  941.     bsr    HEX08
  942.     move.w    DV.SIDE(a4),d0
  943.     bsr    HEX08
  944.     move.w    DV.TRACK(a4),d0
  945.     bsr    HEX08
  946.     movem.l    (a7)+,d0/a0
  947.  
  948.     movem.l    d0/a0,-(a7)    ; temporary aberration
  949.     suba.l    a0,a0
  950.     move.l    #$00020000+'of',d0
  951.     bsr    IOD0
  952.     movem.l    (a7)+,d0/a0
  953.  
  954.     endc
  955.  
  956.     bsr    SCR_OFF
  957.  
  958.     ifd    debug
  959.  
  960.     movem.l    d0/a0,-(a7)    ; temporary aberration
  961.     suba.l    a0,a0
  962.     move.l    #$00020000+'=i',d0
  963.     bsr    IOD0
  964.     movem.l    (a7)+,d0/a0
  965.  
  966.     endc
  967.  
  968.     bsr    hw_RD_DSK
  969.  
  970.     movem.l    (a7)+,a0     ; ASCII buffer -> a0
  971.  
  972.     bne    RQRETRY
  973.  
  974. ; signal disk has not changed
  975.  
  976.     bclr    d0,FV.CNGFLag(a3)
  977.  
  978. ; begin MFM translation
  979.  
  980.     move.l    #MFMBUFFER,a1    ; track image -> a1
  981.     lea    $4000(a1),a2    ; end of track image
  982.  
  983. ; first search for header block in track image
  984.  
  985. RQDSKLP2:
  986.     cmpi.w    #$4489,(a1)+    ; find sync pattern
  987.     beq.s    RQDSK1
  988.     cmpa.l    a2,a1
  989.     blt.s    RQDSKLP2
  990.     bra    RQRETRY
  991.  
  992. RQDSK1:
  993.     cmpi.w    #$4489,(a1)    ; skip over sync
  994.     bne.s    RQDSK2
  995.     addq.l    #2,a1
  996.     bra.s    RQDSK1
  997.  
  998. RQDSK2:
  999.     cmp.w    #$5554,(a1)    ; find header block marker
  1000.     bne    RQDSKLP2
  1001.  
  1002. ; header block found OK
  1003.  
  1004.     clr.w    (a1)+        ; make sure its not re-used
  1005.     moveq    #0,d1        ; counter for 6 ASCII bytes
  1006.  
  1007. RQDSKLP3:
  1008.     move.w    (a1)+,d0
  1009.     cmp.w    #$4489,d0    ; drop out if sync found
  1010.     beq    RQDSK1
  1011.     bsr    MFMASCD0
  1012.     move.b    d0,0(a0,d1.w)    ; store header as ASCII
  1013.     addq.w    #1,d1
  1014.     cmp.w    #6,d1
  1015.     blt.s    RQDSKLP3
  1016.  
  1017.     moveq    #4,d1
  1018.     move.w    #$B230,d0    ; initialise CRC
  1019.     bsr    CALCCRC        ; calculate CRC for header
  1020.  
  1021.     move.w    4(a0),d1     ; get CRC read from disk
  1022.     cmp.w    d0,d1        ; compare with calculated
  1023.     beq    RQDSK3        ; continue if OK
  1024.  
  1025.     ifd    debug
  1026.  
  1027.     movem.l    d0/a0,-(a7)    ; temporary aberration
  1028.     move.l    #0,a0
  1029.     move.l    #$00020000+'-h',d0
  1030.     bsr    IOD0
  1031.     move.l    #0,a0
  1032.     move.l    #$00020000+'??',d0
  1033.     bsr    IOD0
  1034.     movem.l    (a7)+,d0/a0
  1035.  
  1036.     endc
  1037.  
  1038.     lea    -12(a1),a1    ; otherwise search for
  1039.     bra    RQDSKLP2     ; another header sync
  1040.  
  1041. RQDSK3:
  1042.     move.w    AB.DRIVE(a5),d0
  1043.     moveq    #0,d2
  1044.     move.b    (a0),d2        ; check track
  1045.     sub.w    DV.TRACK(a4),d2
  1046.     beq.s    RQDSK3A
  1047.  
  1048.     bgt.s    RQDSKL2
  1049.  
  1050. RQDSKL1:
  1051.     bsr    hw_STEP_IN    ; increase track
  1052.     addq.w    #1,d2
  1053.     blt.s    RQDSKL1
  1054.  
  1055.     bra    RQRETRY
  1056.  
  1057. RQDSKL2:
  1058.     bsr    hw_STEP_OUT    ; decrease track
  1059.     subq.w    #1,d2
  1060.     bgt.s    RQDSKL2
  1061.  
  1062.     bra    RQRETRY
  1063.  
  1064. RQDSK3A:
  1065.     move.w    DV.SIDE(a4),d1
  1066.     cmp.b    1(a0),d1     ; check side
  1067.     beq.s    RQDSK3B
  1068.  
  1069.     bsr    hw_SEL_SIDE
  1070.     bra    RQRETRY
  1071.  
  1072. RQDSK3B:
  1073.     moveq    #0,d2
  1074.     move.b    2(a0),d2     ; get sector number
  1075.     subq    #1,d2
  1076.  
  1077.     ifd    debug
  1078.  
  1079.     movem.l    d0/a0,-(a7)    ; temporary aberration
  1080.     move.l    #0,a0
  1081.     move.l    #$00020000+'+h',d0
  1082.     bsr    IOD0
  1083.     move.l    #0,a0
  1084.     move.l    d2,d0
  1085.     bsr    HEX08
  1086.     movem.l    (a7)+,d0/a0
  1087.  
  1088.     endc
  1089.  
  1090.     move.w    AB.BADFLag(a5),d0
  1091.     btst    d2,d0
  1092.     beq    RQDSKLP2
  1093.  
  1094. ; CRC for header block was OK, now search for data block
  1095.  
  1096. RQDSK4:
  1097.     cmpi.w    #$4489,(a1)+    ; find sync pattern
  1098.     beq.s    RQDSK5
  1099.     cmpa.l    a2,a1
  1100.     blt.s    RQDSK4
  1101.     bra    RQRETRY
  1102.  
  1103. RQDSK5:
  1104.     cmpi.w    #$4489,(a1)    ; skip over sync
  1105.     bne.s    RQDSK6
  1106.     addq.l    #2,a1
  1107.     bra.s    RQDSK5
  1108.  
  1109. RQDSK6:
  1110.     cmp.w    #$5545,(a1)    ; find data block marker
  1111.     bne    RQDSK2        ; data block was not found
  1112.  
  1113. ; data block found OK
  1114.  
  1115. RQDSK7:
  1116.     clr.w    (a1)+        ; make sure its not re-used
  1117.     moveq    #0,d1        ; counter for 514 bytes
  1118.  
  1119. RQDSKLP4:
  1120.     move.w    (a1)+,d0
  1121.     cmp.w    #$4489,d0    ; drop out if sync found
  1122.     beq    RQDSK1
  1123.     bsr    MFMASCD0
  1124.     move.b    d0,0(a0,d1.w)
  1125.     addq.w    #1,d1
  1126.     cmp.w    #$202,d1
  1127.     blt.s    RQDSKLP4
  1128.  
  1129.     move.w    #$200,d1
  1130.     move.w    #$E295,d0    ; initialise CRC
  1131.     bsr    CALCCRC        ; calculate CRC for data
  1132.  
  1133.     move.w    $200(a0),d1    ; get CRC read from disk
  1134.     cmp.w    d0,d1        ; compare with calculated
  1135.     beq    RQDSK8        ; and continue if OK
  1136.  
  1137.     ifd    debug
  1138.  
  1139.     movem.l    d0/a0,-(a7)    ; temporary aberration
  1140.     move.l    #0,a0
  1141.     move.l    #$00020000+'-d',d0
  1142.     bsr    IOD0
  1143.     move.l    #0,a0
  1144.     move.l    d2,d0
  1145.     bsr    HEX08
  1146.     movem.l    (a7)+,d0/a0
  1147.  
  1148.     endc
  1149.  
  1150.     lea    -$404(a1),a1    ; otherwise search for
  1151.     bra    RQDSKLP2     ; another header sync
  1152.  
  1153. ; CRC for data block was OK
  1154.  
  1155. RQDSK8:
  1156.     ifd    debug
  1157.  
  1158.     movem.l    d0/a0,-(a7)    ; temporary aberration
  1159.     move.l    #0,a0
  1160.     move.l    #$00020000+'+d',d0
  1161.     bsr    IOD0
  1162.     move.l    #0,a0
  1163.     move.l    d2,d0
  1164.     bsr    HEX08
  1165.     movem.l    (a7)+,d0/a0
  1166.  
  1167.     endc
  1168.  
  1169.     move.w    d2,d0
  1170.     lsl.w    #2,d0
  1171.     move.l    a0,AB.SCTR1(a5,d0.w) ; store data address
  1172.  
  1173.     lea    $202(a0),a0    ; skip over data, 512 bytes
  1174.  
  1175.     move.w    AB.BADFLag(a5),d0
  1176.     bclr    d2,d0
  1177.     move.w    d0,AB.BADFLag(a5)
  1178.  
  1179.     bne    RQDSKLP2
  1180.  
  1181. RQABORT_OK:
  1182.     moveq    #0,d0
  1183.     bra.s    RQDISKX
  1184.  
  1185. RQRETRY:
  1186.     dbra    d3,RQTRYLOOP
  1187.  
  1188. RQABORT_BM:
  1189.     moveq    #ERR.FE,d0    ; bad or changed medium
  1190.     bra.s    RQDISKX
  1191.  
  1192. RQABORT_NF:
  1193.     moveq    #ERR.NF,d0    ; signal drive not found
  1194.  
  1195. RQDISKX:
  1196.     tst.b    d0
  1197.     movem.l    (a7)+,d1-d3/a0-a5
  1198.     rts
  1199.  
  1200. ; -------------------------------------------------------------
  1201. ;  Write one sector (D1) from buffer (A1)
  1202. ;  If the actual parameters are not the same as for the track in
  1203. ;  the track buffer, then call RQDISK.
  1204. ;  Copy (A1) to Track buffer
  1205. ;  set writeflag !
  1206. ; -------------------------------------------------------------
  1207. WQSEC:
  1208.     movem.l    d1-d2/a0-a5,-(a7)
  1209.  
  1210.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1211.  
  1212.     move.w    FV.REQDRive(a3),d0
  1213.     and.w    #$3,d0        ; only drives 0-3
  1214.  
  1215.     cmp.w    FV.MAXDRive(a3),d0
  1216.     bgt.s    WQSEC_BM
  1217.  
  1218.     move.w    d0,d2        ; Address of drive vars for
  1219.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1220.     lea    FV.DRVVArs(a3,d2.w),a4
  1221.  
  1222.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  1223.     lsl.w    #2,d2        ; for required side in a5
  1224.     move.l    DV.SIDE0buff(a4,d2.w),a5
  1225.  
  1226. ; first check if buffers contain correct info
  1227.  
  1228.     cmp.w    AB.DRIVE(a5),d0
  1229.     bne.s    WQSEC1
  1230.  
  1231.     move.w    DV.SIDE(a4),d2
  1232.     cmp.w    AB.SIDE(a5),d2
  1233.     bne.s    WQSEC1
  1234.  
  1235.     move.w    DV.TRACK(a4),d2
  1236.     cmp.w    AB.TRACK(a5),d2
  1237.     bne.s    WQSEC1
  1238.  
  1239. ; disk changed?
  1240.  
  1241.     bsr    CHNG
  1242.     tst.b    d0
  1243.     beq.s    WQSEC2
  1244.  
  1245. ; if so, read correct track into buffers
  1246.  
  1247. WQSEC1    move.w    FV.REQDRive(a3),d0
  1248.     bsr    RQDISK
  1249.     bne    WQSECX
  1250.  
  1251. ; determine position of sector
  1252.  
  1253. WQSEC2:
  1254.     moveq    #0,d0
  1255.     move.b    d1,d0
  1256.     lsl.w    #2,d0
  1257.     move.l    AB.SCTR1(a5,d0.w),a0 ; address of ASCII data
  1258.  
  1259.     move.w    #511,d0        ; load counter
  1260.  
  1261. WQSEC3:
  1262.     move.b    (a1)+,(a0)+    ; copy 512 bytes
  1263.     dbra    d0,WQSEC3
  1264.  
  1265.     lea    -512(a0),a0    ; start of ASCII data
  1266.     move.w    #512,d1        ; count of bytes
  1267.     move.w    #$E295,d0    ; initialise CRC
  1268.     bsr    CALCCRC
  1269.     move.w    d0,512(a0)    ; write ASCII CRC for data
  1270.  
  1271.     bset.w    d1,AB.PENDWflag(a5)    ; mark sector for write
  1272.     bclr.w    d1,AB.BADFLag(a5) ; mark sector as OK
  1273.  
  1274.     moveq    #0,d0
  1275.  
  1276.     move.w    #200,DV.TIMEOut(a4)
  1277.  
  1278.     bra    WQSECX
  1279.  
  1280. WQSEC_BM:
  1281.     moveq    #-16,d0        ; bad or changed medium
  1282.  
  1283. WQSECX:
  1284.     tst.b    d0
  1285.     movem.l    (a7)+,d1-d2/a0-a5
  1286.     rts
  1287.  
  1288. ; -------------------------------------------------------------
  1289. ;  Read one Sector (D1) to buffer (A1) , (A1 points to the end)
  1290. ;  skip (D3) bytes, and leave (D4) at the end
  1291. ;
  1292. ;  call RQDISK and copy sector from Track buffer to (A1)
  1293. ; -------------------------------------------------------------
  1294. RQSEC:
  1295.     movem.l    d1-d2/a0/a2-a5,-(a7)
  1296.  
  1297.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1298.  
  1299.     move.w    FV.REQDRive(a3),d0
  1300.     and.w    #$3,d0        ; only drives 0-3
  1301.  
  1302.     cmp.w    FV.MAXDRive(a3),d0
  1303.     bgt    RQSEC_BM
  1304.  
  1305.     move.w    d0,d2        ; Address of drive vars for
  1306.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1307.     lea    FV.DRVVArs(a3,d2.w),a4
  1308.  
  1309.     move.w    DV.SIDE(a4),d2    ; Address of buffer vars
  1310.     lsl.w    #2,d2        ; for required side in a5
  1311.     move.l    DV.SIDE0buff(a4,d2.w),a5
  1312.  
  1313. ; first check if buffer already contains correct info
  1314.  
  1315.     cmp.w    AB.DRIVE(a5),d0
  1316.     bne.s    RQSEC1
  1317.  
  1318.     move.w    DV.SIDE(a4),d2
  1319.     cmp.w    AB.SIDE(a5),d2
  1320.     bne.s    RQSEC1
  1321.  
  1322.     move.w    DV.TRACK(a4),d2
  1323.     cmp.w    AB.TRACK(a5),d2
  1324.     bne.s    RQSEC1
  1325.  
  1326. ; disk changed?
  1327.  
  1328.     bsr    CHNG
  1329.     tst.b    d0
  1330.     bne.s    RQSEC1        ; read again if changed
  1331.  
  1332. ; sector data bad?
  1333.  
  1334.     move.w    AB.BADFLag(a5),d2
  1335.     btst    d1,d2
  1336.     beq.s    RQSEC2        ; sector data OK
  1337.  
  1338. RQSEC1:
  1339.  
  1340.     bsr    RQDISK
  1341.  
  1342.     move.w    AB.BADFLag(a5),d2
  1343.     btst    d1,d2
  1344.     bne    RQSEC_BM
  1345.  
  1346. ; determine position of sector
  1347.  
  1348. RQSEC2:
  1349.     moveq    #0,d0
  1350.     move.b    d1,d0
  1351.     lsl.w    #2,d0
  1352.     move.l    AB.SCTR1(a5,d0.w),a0 ; address of ASCII
  1353.  
  1354.     and.l    #$1FF,d3     ; maximum bytes to skip
  1355.     add.l    d3,a0        ; subtract bytes to skip
  1356.     move.w    #511,d0        ; load counter
  1357.     sub.w    d3,d0        ; subtract bytes to skip
  1358.     sub.w    d4,d0        ; subtract bytes to leave
  1359.  
  1360. RQSEC3    move.b    (a0)+,(a1)+    ; copy 512 bytes
  1361.     dbra    d0,RQSEC3
  1362.  
  1363. RQSEC_OK:
  1364.     moveq    #0,d0
  1365.     bra.s    RQSECX
  1366.  
  1367. RQSEC_BM:
  1368.     moveq    #-16,d0        ; bad or changed medium
  1369.  
  1370. RQSECX:
  1371.     tst.b    d0
  1372.     movem.l    (a7)+,d1-d2/a0/a2-a5
  1373.     rts
  1374.  
  1375. ; -------------------------------------------------------------
  1376. ;  calculate the Cyclic Redundancy Check for d1 bytes at (a0)
  1377. ;  Initial CRC is passed in d0, modified CRC is returned in d0
  1378. ; -------------------------------------------------------------
  1379. CALCCRC:
  1380.     movem.l    d1-d3/a0,-(a7)
  1381.     bra.s    CRCNEXT
  1382.  
  1383. CRCLOOP:
  1384.     move.b    (a0)+,d3
  1385.     move.w    d0,d2
  1386.     lsr.w    #8,d0
  1387.     eor.b    d3,d0
  1388.     move.w    d0,d3
  1389.     lsr.w    #4,d0
  1390.     eor.w    d3,d0
  1391.     move.w    d0,d3
  1392.     lsl.w    #4,d0
  1393.     eor.w    d2,d0
  1394.     lsl.w    #3,d0
  1395.     eor.w    d3,d0
  1396.     lsl.w    #5,d0
  1397.     eor.w    d3,d0
  1398.  
  1399. CRCNEXT:
  1400.     dbra    d1,CRCLOOP
  1401.     movem.l    (a7)+,d1-d3/a0
  1402.     rts
  1403.  
  1404. ; --------------------------------------------------------------
  1405. ;  Convert d0.w from MFM to ASCII. Return value in d0.b
  1406. ; --------------------------------------------------------------
  1407. MFMASCD0:
  1408.     movem.l    d1/a0,-(a7)
  1409.  
  1410.     andi.w    #%0101010101010101,d0
  1411.     move.b    d0,d1
  1412.     lsr.w    #7,d0
  1413.     or.b    d1,d0
  1414.     lea    MFMASCTB(pc),a0
  1415.     move.b    0(a0,d0.w),d0
  1416.  
  1417.     movem.l    (a7)+,d1/a0
  1418.     rts
  1419.  
  1420. ; MFM to ASCII table
  1421.  
  1422. MFMASCTB:
  1423.    DC.B $00,$01,$10,$11,$02,$03,$12,$13,$20,$21,$30,$31,$22,$23,$32,$33
  1424.    DC.B $04,$05,$14,$15,$06,$07,$16,$17,$24,$25,$34,$35,$26,$27,$36,$37
  1425.    DC.B $40,$41,$50,$51,$42,$43,$52,$53,$60,$61,$70,$71,$62,$63,$72,$73
  1426.    DC.B $44,$45,$54,$55,$46,$47,$56,$57,$64,$65,$74,$75,$66,$67,$76,$77
  1427.    DC.B $08,$09,$18,$19,$0A,$0B,$1A,$1B,$28,$29,$38,$39,$2A,$2B,$3A,$3B
  1428.    DC.B $0C,$0D,$1C,$1D,$0E,$0F,$1E,$1F,$2C,$2D,$3C,$3D,$2E,$2F,$3E,$3F
  1429.    DC.B $48,$49,$58,$59,$4A,$4B,$5A,$5B,$68,$69,$78,$79,$6A,$6B,$7A,$7B
  1430.    DC.B $4C,$4D,$5C,$5D,$4E,$4F,$5E,$5F,$6C,$6D,$7C,$7D,$6E,$6F,$7E,$7F
  1431.    DC.B $80,$81,$90,$91,$82,$83,$92,$93,$A0,$A1,$B0,$B1,$A2,$A3,$B2,$B3
  1432.    DC.B $84,$85,$94,$95,$86,$87,$96,$97,$A4,$A5,$B4,$B5,$A6,$A7,$B6,$B7
  1433.    DC.B $C0,$C1,$D0,$D1,$C2,$C3,$D2,$D3,$E0,$E1,$F0,$F1,$E2,$E3,$F2,$F3
  1434.    DC.B $C4,$C5,$D4,$D5,$C6,$C7,$D6,$D7,$E4,$E5,$F4,$F5,$E6,$E7,$F6,$F7
  1435.    DC.B $88,$89,$98,$99,$8A,$8B,$9A,$9B,$A8,$A9,$B8,$B9,$AA,$AB,$BA,$BB
  1436.    DC.B $8C,$8D,$9C,$9D,$8E,$8F,$9E,$9F,$AC,$AD,$BC,$BD,$AE,$AF,$BE,$BF
  1437.    DC.B $C8,$C9,$D8,$D9,$CA,$CB,$DA,$DB,$E8,$E9,$F8,$F9,$EA,$EB,$FA,$FB
  1438.    DC.B $CC,$CD,$DC,$DD,$CE,$CF,$DE,$DF,$EC,$ED,$FC,$FD,$EE,$EF,$FE,$FF
  1439.  
  1440. ; --------------------------------------------------------------
  1441. ;  Convert byte d0.b, from ASCII to MFM. Return value in d0.w
  1442. ; --------------------------------------------------------------
  1443. ASCMFMD0:
  1444.     movem.l    d1/a0,-(a7)
  1445.  
  1446.     move.l    AV.DSKV,a0
  1447.     move.w    FV.LASTBit(a0),d1
  1448.     lsl.w    #8,d1
  1449.     move.b    d0,d1
  1450.     move.w    d1,FV.LASTBit(a0)
  1451.  
  1452.     lea    ASCMFMTB(pc),a0
  1453.     lsr.w    #4,d1
  1454.     andi.w    #$1F,d1
  1455.     move.b    0(a0,d1.w),d1
  1456.     lsl.w    #8,d1
  1457.     andi.w    #$1F,d0
  1458.     move.b    0(a0,d0.w),d1
  1459.     move.w    d1,d0
  1460.  
  1461.     movem.l    (a7)+,d1/a0
  1462.     rts
  1463.  
  1464. ; ASCII to MFM table
  1465.  
  1466. ASCMFMTB:
  1467.    DC.B $AA,$A9,$A4,$A5,$92,$91,$94,$95,$4A,$49,$44,$45,$52,$51,$54,$55
  1468.    DC.B $2A,$29,$24,$25,$12,$11,$14,$15,$4A,$49,$44,$45,$52,$51,$54,$55
  1469.  
  1470. ; --------------------------------------------------------------
  1471. ;  Select drive d0.w and switch on motor
  1472. ;  eq = no errors, ne = drive error (held in d0)
  1473. ; --------------------------------------------------------------
  1474. SEL_DRV:
  1475.     movem.l    d2/a3-a4,-(a7)
  1476.  
  1477.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1478.  
  1479.     and.w    #$3,d0        ; Only drives 0-3.
  1480.  
  1481.     move.w    d0,d2        ; Address of drive vars for
  1482.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1483.     lea    FV.DRVVArs(a3,d2.w),a4
  1484.  
  1485.     bclr    d0,FV.RDYFLag(a3) ; set drive not ready
  1486.  
  1487. ; switch to this drive
  1488.  
  1489.     move.w    d0,FV.REQDRive(a3) ; switch drives
  1490.  
  1491. ; check if motor already running
  1492.  
  1493.     tst.w    DV.TIMEOut(a4)
  1494.     bne.s    SEL_CK_CHG
  1495.  
  1496. ; select new drive
  1497.  
  1498.     bsr    hw_MTR_ON
  1499.  
  1500. ; check if drive motor can reach speed
  1501.  
  1502.     bsr    hw_IS_DRVRDY
  1503. ;     bne     SEL_DRV_NF     ; drive no good
  1504.  
  1505. SEL_CK_CHG:
  1506.  
  1507. ; check for disk change
  1508.  
  1509.     bsr    hw_IS_CHG
  1510.     bne.s    SEL_CHG_NO
  1511.  
  1512.     bset    d0,FV.CNGFLag(a3) ; indicate disk not changed
  1513.  
  1514. SEL_CHG_NO:
  1515.  
  1516. ; check if there's a disk in the drive
  1517.  
  1518.     bsr    hw_IS_CHG
  1519.     beq.s    SEL_DRV_NF
  1520.  
  1521. ; select correct side for this drive
  1522.  
  1523. SEL_DRV_OK:
  1524.     move.w    DV.SIDE(a4),d1
  1525.     bsr    hw_SEL_SIDE
  1526.  
  1527.     move.w    FV.REQDRive(a3),d0
  1528.     bset    d0,FV.RDYFLag(a3) ; set drive ready
  1529.  
  1530.     moveq    #0,d0        ; reset error number
  1531.     bra.s    SEL_DRVX
  1532.  
  1533. SEL_DRV_NF:
  1534.     bclr    d0,FV.RDYFLag(a3) ; set not drive ready
  1535.     moveq    #-7,d0        ; not found
  1536.  
  1537. ; set pending motor off for specified drive to 4 seconds
  1538.  
  1539. SEL_DRVX:
  1540.     move.w    #200,DV.TIMEOut(a4)
  1541.  
  1542.     tst.b    d0
  1543.     movem.l    (a7)+,d2/a3-a4
  1544.     rts
  1545.  
  1546. ; -------------------------------------------------------------
  1547. ;  Select side d0.w
  1548. ;  eq = no errors, ne = drive error (held in d0)
  1549. ; -------------------------------------------------------------
  1550. SEL_SIDE:
  1551.     movem.l    d1-d2/a3-a4,-(a7)
  1552.  
  1553.     move.w    d0,d1        ; save side to set
  1554.  
  1555.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1556.  
  1557.     move.w    FV.REQDRive(a3),d0
  1558.     and.w    #$3,d0        ; only drives 0-3
  1559.  
  1560.     move.w    d0,d2        ; Address of drive vars for
  1561.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1562.     lea    FV.DRVVArs(a3,d2.w),a4
  1563.  
  1564.     cmp.w    DV.SIDE(a4),d1    ; Same side?
  1565.     beq.s    SELSIDE1
  1566.  
  1567.     bsr    FLUSH_BUFF    ; flush buffer
  1568.     bne.s    SELSIDEX
  1569.  
  1570. SELSIDE1:
  1571.     move.w    d1,DV.SIDE(a4)
  1572.     move.w    FV.REQDRive(a3),d0
  1573.     bsr    hw_SEL_SIDE
  1574.  
  1575. SELSIDE_OK:
  1576.     moveq    #0,d0
  1577.  
  1578. SELSIDEX:
  1579.     tst.b    d0
  1580.     movem.l    (a7)+,d1-d2/a3-a4
  1581.     rts
  1582.  
  1583. ; -------------------------------------------------------------
  1584. ;  Go to track d0.w
  1585. ;  eq = no errors, ne = drive error (held in d0)
  1586. ; -------------------------------------------------------------
  1587. GO_TRACK:
  1588.     movem.l    d1-d2/a3-a4,-(a7)
  1589.  
  1590.     move.w    d0,d1        ; save track
  1591.  
  1592.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1593.  
  1594.     move.w    FV.REQDRive(a3),d0
  1595.     and.w    #$3,d0        ; only drives 0-3
  1596.  
  1597.     move.w    d0,d2        ; Address of drive vars for
  1598.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1599.     lea    FV.DRVVArs(a3,d2.w),a4
  1600.  
  1601.     cmp.w    DV.TRACK(a4),d1    ; Same track?
  1602.     beq.s    GO_TRACK1
  1603.  
  1604.     bsr    FLUSH_BUFF    ; flush buffer
  1605.     bne.s    GO_TRACKX
  1606.  
  1607. GO_TRACK1:
  1608.     move.w    FV.REQDRive(a3),d0
  1609.     bclr    d0,FV.CNGFLag(a3) ; clear disk change flag
  1610.  
  1611.     tst.b    d1        ; Track 0 ?
  1612.     bne.s    ANYTRACK
  1613.  
  1614.     bsr    hw_GO_TK0
  1615.     clr.w    DV.TRACK(a4)
  1616.  
  1617.     bra.s    GO_TRACK_OK
  1618.  
  1619. ANYTRACK:
  1620.     move.w    DV.TRACK(a4),d2
  1621.     cmp.b    d2,d1
  1622.     bgt.s    SI_TRACK
  1623.     blt.s    SO_TRACK
  1624.  
  1625. GO_TRACK_OK:
  1626.     moveq    #0,d0
  1627.  
  1628. GO_TRACKX:
  1629.     tst.b    d0
  1630.     movem.l    (a7)+,d1-d2/a3-a4
  1631.     rts
  1632.  
  1633. SI_TRACK:
  1634.     bsr    hw_STEP_IN
  1635.     addq.w    #1,DV.TRACK(a4)
  1636.     bra.s    ANYTRACK
  1637.  
  1638. SO_TRACK:
  1639.     bsr    hw_STEP_OUT
  1640.     subq.w    #1,DV.TRACK(a4)
  1641.     bra.s    ANYTRACK
  1642.  
  1643. ; -------------------------------------------------------------
  1644. ;     Check if drive FV.REQDRive is ready. Return status in d0.l
  1645. ; -------------------------------------------------------------
  1646. CKRDY:
  1647.     movem.l    d1/a3,-(a7)
  1648.  
  1649.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1650.  
  1651.     move.w    FV.REQDRive(a3),d0
  1652.     btst    d0,FV.CNGFLag(a3)
  1653.     bne.s    CKRDYTST
  1654.  
  1655.     btst    d0,FV.RDYFLag(a3)
  1656.     bne.s    CKRDYOK
  1657.  
  1658. CKRDYTST:
  1659.     bsr    SEL_DRV
  1660.     beq.s    CKRDYOK
  1661.  
  1662. CKRDYNOT:
  1663.     moveq    #-1,d0
  1664.  
  1665.     movem.l    (a7)+,d1/a3
  1666.     rts
  1667.  
  1668. CKRDYOK:
  1669.     moveq    #0,d0
  1670.  
  1671.     movem.l    (a7)+,d1/a3
  1672.     rts
  1673.  
  1674. ; -------------------------------------------------------------
  1675. ;  return status of writeprotect signal in d0.l for FV.REQDRive
  1676. ; -------------------------------------------------------------
  1677. WPRO:
  1678.     movem.l    a3,-(a7)
  1679.  
  1680.     move.l    AV.DSKV,a3    ; address of disk vars, a3
  1681.  
  1682.     move.w    FV.REQDRive(a3),d0
  1683.     bsr    hw_IS_PRO
  1684.  
  1685.     beq.s    WPRO_YES
  1686.  
  1687. WPRO_NO:
  1688.     moveq    #0,d0
  1689.     bra.s    WPRO_X
  1690.  
  1691. WPRO_YES:
  1692.     moveq    #1,d0
  1693.  
  1694. WPRO_X:
  1695.     movem.l    (a7)+,a3
  1696.     rts
  1697.  
  1698. ; -------------------------------------------------------------
  1699. ;  return status of diskchange signal in d0.l for FV.REQDRive
  1700. ; -------------------------------------------------------------
  1701. CHNG:
  1702.     movem.l    d2/a3-a5,-(a7)
  1703.  
  1704.     move.l    AV.DSKV,a3    ; address of disk vars, a3
  1705.  
  1706.     move.w    FV.REQDRive(a3),d0
  1707.     and.w    #$3,d0        ; only drives 0-3
  1708.  
  1709.     btst    d0,FV.CNGFLag(a3)
  1710.     bne.s    CHNG_YES
  1711.  
  1712.     bsr    hw_IS_CHG
  1713.     beq.s    CHNG_YES
  1714.  
  1715. CHNG_NO:
  1716.     bclr    d0,FV.CNGFLag(a3) ; indicate disk not changed
  1717.     moveq    #0,d0
  1718.     movem.l    (a7)+,d2/a3-a5
  1719.     rts
  1720.  
  1721. CHNG_YES:
  1722.     move.w    d0,d2        ; Address of drive vars for
  1723.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1724.     lea    FV.DRVVArs(a3,d2.w),a4
  1725.  
  1726.     bsr    CHNG_IT
  1727.  
  1728.     moveq    #1,d0
  1729.     movem.l    (a7)+,d2/a3-a5
  1730.     rts
  1731.  
  1732. ; -------------------------------------------------------------
  1733. ;  provide Diskchange signal for non standard drive d0
  1734. ; -------------------------------------------------------------
  1735. DSKCNG:
  1736.     movem.l    d0/d2/a3-a5,-(a7)
  1737.  
  1738.     move.l    AV.DSKV,a3    ; address of disk vars, a3
  1739.  
  1740.     and.w    #$3,d0        ; Only drives 0-3.
  1741.  
  1742.     move.w    d0,d2        ; Address of drive vars for
  1743.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1744.     lea    FV.DRVVArs(a3,d2.w),a4
  1745.  
  1746.     move.w    d0,-(a7)
  1747.     bsr    FLUSH_BUFF    ; just in case
  1748.     move.w    (a7)+,d0
  1749.  
  1750.     bsr    CHNG_IT
  1751.  
  1752.     movem.l    (a7)+,d0/d2/a3-a5
  1753.     rts
  1754.  
  1755. CHNG_IT:
  1756.     move.l    DV.SIDE0buff(a4),a5 ; address of vars, side 0
  1757.     cmp.w    AB.DRIVE(a5),d0 ; is buffer owned by drive?
  1758.     bne.s    DSKCNG2        ; no it isn't!
  1759.  
  1760.     move.w    #-1,AB.DRIVE(a5) ; set impossible disk
  1761.     move.w    #-1,AB.SIDE(a5) ; set impossible side
  1762.     move.w    #-1,AB.TRACK(a5) ; set impossible track
  1763.     clr.w    AB.PENDWflag(a5)    ; clear pending write
  1764.     move.w    #511,AB.BADFLag(a5) ; sectors all bad
  1765.  
  1766. DSKCNG2:
  1767.     move.l    DV.SIDE1buff(a4),a5 ; address of vars, side 1
  1768.     cmp.w    AB.DRIVE(a5),d0 ; is buffer owned by drive?
  1769.     bne.s    DSKCNG3        ; no it isn't!
  1770.  
  1771.     move.w    #-1,AB.DRIVE(a5) ; set impossible disk
  1772.     move.w    #-1,AB.SIDE(a5) ; set impossible side
  1773.     move.w    #-1,AB.TRACK(a5) ; set impossible track
  1774.     clr.w    AB.PENDWflag(a5)    ; clear pending write
  1775.     move.w    #511,AB.BADFLag(a5) ; sectors all bad
  1776.  
  1777. DSKCNG3:
  1778.     bset    d0,FV.CNGFLag(a3) ; set disk changed
  1779.     bclr    d0,FV.RDYFLag(a3) ; set drive not ready
  1780.  
  1781.     bsr    hw_DRV_TYP
  1782.     move.l    d0,DV.TYPE(a4)
  1783.  
  1784.     rts
  1785.  
  1786. ; -------------------------------------------------------------
  1787. ;  50 Hz interrupt server           (now changed to polled task)
  1788. ;  switch off motor if requested
  1789. ;  Flush writebuffer before motor_off
  1790. ; -------------------------------------------------------------
  1791. POLSERV:
  1792.     movem.l    d0/d2/a3-a5,-(a7)
  1793.  
  1794.     move.l    AV.DSKV,a3    ; Address of disk vars, a3
  1795.  
  1796. POLSERV1:
  1797.     bset.b    #7,FV.POLLActiv(a3) ; schedular already active?
  1798.     bne.s    POLX        ; if so, then ignore
  1799.  
  1800.     move.w    FV.MAXDRive(a3),d0 ; check timeout, all drives
  1801.  
  1802. STPFLPLP:
  1803.     bsr    TESTSTOP
  1804.     dbra    d0,STPFLPLP
  1805.  
  1806.     bclr.b    #7,FV.POLLActiv(a3) ; mark schedular inactive
  1807.  
  1808. POLX:
  1809.     movem.l    (a7)+,d0/d2/a3-a5
  1810.     rts
  1811.  
  1812. TESTSTOP:
  1813.     move.w    d0,d2        ; Address of drive vars for
  1814.     mulu.w    #DV_LEN,d2    ; required drive in a4
  1815.     lea    FV.DRVVArs(a3,d2.w),a4
  1816.  
  1817.     move.w    DV.TIMEOut(a4),d2 ; anything to do?
  1818.     beq.s    INTEX
  1819.  
  1820.     subq.w    #1,d2
  1821.     move.w    d2,DV.TIMEOut(a4)
  1822.     tst.w    d2
  1823.     bne    INTEX
  1824.  
  1825.     move.w    d0,d2
  1826.     bsr    FLUSH_BUFF
  1827.     move.w    d2,d0
  1828.  
  1829. INTEX1:
  1830.     bsr    hw_MTR_OFF
  1831.  
  1832. INTEX:
  1833.     rts
  1834.  
  1835. ; -------------------------------------------------------------
  1836. FLUSHALL:
  1837.     movem.l    d0/d2,-(a7)
  1838.  
  1839.     move.w    FV.MAXDRive(a3),d0
  1840.  
  1841. FLSHALLLP:
  1842.     move.w    d0,d2
  1843.     bsr    FLUSH_BUFF
  1844.     move.w    d2,d0
  1845.     dbra    d0,FLSHALLLP
  1846.  
  1847.     movem.l    (a7)+,d0/d2
  1848.     rts
  1849.  
  1850. ; -------------------------------------------------------------
  1851. ;  wait for no blitter activity, or a maximum of 40ms.
  1852. ; -------------------------------------------------------------
  1853. SCR_OFF:
  1854.     movem.l    d0-d1,-(a7)
  1855.  
  1856.     move.l    #39,d1        ; set count for 40 ms
  1857.  
  1858. sof_LUP1:
  1859.     bsr    hw_BEG_TIMING
  1860.  
  1861. sof_LUP2:
  1862.     btst.b    #6,DMACONR    ; wait blitter not busy
  1863.     beq.s    sof_X
  1864.  
  1865.     bsr    hw_IS_TIMING
  1866.     beq.s    sof_LUP2
  1867.  
  1868.     dbra    d1,sof_LUP1
  1869.  
  1870. sof_X:
  1871.     movem.l    (a7)+,d0-d1
  1872.     rts
  1873.  
  1874. ; -------------------------------------------------------------
  1875. ;  ROUTINES THAT HIT THE HARDWARE DIRECTLY
  1876. ; -------------------------------------------------------------
  1877.  
  1878. DISKCOPY:
  1879.     movem.l    d1-d3/d7/a0/a3,-(a7)
  1880.  
  1881.     moveq    #1,d0        ; drive 1
  1882.     bsr    hw_IS_PRO
  1883.     bne.s    DC_CONT
  1884.  
  1885.     moveq    #ERR.RO,d3
  1886.     bra    DC_EXIT
  1887.  
  1888. DC_CONT:
  1889.     trap    #0
  1890.     or.w    #$0700,sr    ; disable interrupts
  1891.  
  1892.     bsr    SCR_OFF        ; wait for blitter
  1893.  
  1894.     move.l    AV.DSKV,a3
  1895.     move.w    FV.FLAGS(a3),d7    ; save FV.FLAGS
  1896.     move.w    #%0011000000000000,FV.FLAGS(a3) ; indx R&W, no SYNC
  1897.  
  1898.     moveq    #0,d0        ; drive 0
  1899.     bsr    hw_GO_TK0
  1900.  
  1901.     bsr    hw_MTR_ON
  1902.     bsr    hw_IS_DRVRDY
  1903.     beq.s    DC_CONT1
  1904.  
  1905.     moveq    #ERR.NF,d3
  1906.     bra.s    DC_X0
  1907.  
  1908. DC_CONT1:
  1909.     moveq    #1,d0        ; drive 1
  1910.     bsr    hw_GO_TK0
  1911.  
  1912.     bsr    hw_MTR_ON
  1913.     bsr    hw_IS_DRVRDY
  1914.     beq.s    DC_CONT2
  1915.  
  1916.     moveq    #ERR.NF,d3
  1917.     bra.s    DC_X1
  1918.  
  1919. DC_CONT2:
  1920.     lea    MFMBUFFER,a0    ; buffer address
  1921.  
  1922. ; start in earnest
  1923.  
  1924.     moveq    #0,d2        ; track number
  1925.  
  1926. DC_CPY_LUP:
  1927.     moveq    #0,d0        ; drive 0
  1928.     moveq    #0,d1        ; side number
  1929.     bsr    hw_RD_DSK    ; read track
  1930.  
  1931.     moveq    #1,d0        ; drive 1
  1932.     bsr    hw_WR_DSK    ; write track
  1933.  
  1934.     moveq    #0,d0        ; drive 0
  1935.     moveq    #1,d1        ; side number
  1936.     bsr    hw_RD_DSK    ; read track
  1937.  
  1938.     bsr    hw_STEP_IN
  1939.  
  1940.     moveq    #1,d0        ; drive 1
  1941.     bsr    hw_WR_DSK    ; write track
  1942.  
  1943.     bsr    hw_STEP_IN
  1944.  
  1945.     addq    #1,d2
  1946.     cmpi.b    #80,d2
  1947.     bne.s    DC_CPY_LUP
  1948.  
  1949.     moveq    #ERR.OK,d3
  1950. DC_X1:
  1951.     moveq    #1,d0        ; drive 1
  1952.     bsr    hw_GO_TK0
  1953.     bsr    hw_MTR_OFF
  1954.     bsr    DSKCNG
  1955. DC_X0:
  1956.     moveq    #0,d0        ; drive 0
  1957.     bsr    hw_GO_TK0
  1958.     bsr    hw_MTR_OFF
  1959.     bsr    DSKCNG
  1960.  
  1961.     move.w    d7,FV.FLAGS(a3)
  1962.  
  1963.     move.w    (sp)+,sr
  1964.  
  1965. DC_EXIT:
  1966.     move.l    d3,d0
  1967.     movem.l    (a7)+,d1-d3/d7/a0/a3
  1968.     rts
  1969.  
  1970. ; -------------------------------------------------------------
  1971. ;  Wait for d0 x 1000th of a second
  1972. ; -------------------------------------------------------------
  1973. hw_TIMER:
  1974.     movem.l    d0,-(a7)
  1975.  
  1976.     bra.s    hw_TIMER3
  1977.  
  1978. hw_TIMER1:
  1979.     bsr    hw_BEG_TIMING
  1980.  
  1981. hw_TIMER2:
  1982.     bsr    hw_IS_TIMING
  1983.     beq.s    hw_TIMER2
  1984.  
  1985. hw_TIMER3:
  1986.     dbra    d0,hw_TIMER1
  1987.  
  1988.     movem.l    (a7)+,d0
  1989.     rts
  1990.  
  1991. ; -------------------------------------------------------------
  1992. ;  Set timer A for one 1000th of a second
  1993. ; -------------------------------------------------------------
  1994. hw_BEG_TIMING:
  1995.     move.b    #$CC,CIAB_TALO    ; and set counter to 716
  1996.     move.b    #$02,CIAB_TAHI
  1997.     move.b    #9,CIAB_CRA    ; set timer to OneShot &
  1998.     ; set the start bit
  1999.  
  2000.     rts
  2001.  
  2002. ; -------------------------------------------------------------
  2003. ;  Check if timer A is still going
  2004. ;  eq = still timing, ne = run down
  2005. ; -------------------------------------------------------------
  2006. hw_IS_TIMING:
  2007.     movem.l    d0-d1,-(a7)
  2008.  
  2009.     move.b    CIAB_CRA,d0
  2010.     eor.b    #1,d0
  2011.     and.b    #1,d0
  2012.  
  2013.     movem.l    (a7)+,d0-d1
  2014.     rts
  2015.  
  2016. ; -------------------------------------------------------------
  2017. ;  Wait until an INDEX interrupt is requested, or for 2 seconds
  2018. ;  ne = INDEX found, eq = no INDEX found
  2019. ; -------------------------------------------------------------
  2020. hw_WTIDX:
  2021.     movem.l    d0-d1,-(a7)
  2022.  
  2023.     move.b    CIAB_ICR,d0    ; read & reset int flg
  2024.     or.b    AV.CIAB_ICR,d0
  2025.     bclr    #4,d0        ; clear previous indx int
  2026.     move.b    d0,AV.CIAB_ICR    ; store for another program
  2027.  
  2028.     move.l    #1999,d1     ; set count for 2000 ms
  2029.  
  2030. hw_WTIDX_LUP1:
  2031.     bsr    hw_BEG_TIMING
  2032.  
  2033. hw_WTIDX_LUP2:
  2034.     move.b    CIAB_ICR,d0    ; read CIA-B ICR
  2035.     or.b    AV.CIAB_ICR,d0
  2036.     move.b    d0,AV.CIAB_ICR    ; store for another program
  2037.  
  2038.     bclr    #4,d0        ; was it index ?
  2039.     bne    hw_WTIDX_X    ; ...yes
  2040.  
  2041. hw_WTIDX_CONT:
  2042.     bsr    hw_IS_TIMING
  2043.     beq.s    hw_WTIDX_LUP2
  2044.  
  2045.     dbra    d1,hw_WTIDX_LUP1
  2046.  
  2047. hw_WTIDX_X:
  2048.     addq.w    #1,d1        ; set flags
  2049.     tst.w    d1
  2050.  
  2051.     movem.l    (a7)+,d0-d1
  2052.  
  2053.     rts
  2054.  
  2055. ; -------------------------------------------------------------
  2056. ;  Wait from disk DMA finished signal or for 0.5 seconds
  2057. ;  ne = DMA finished, eq = DMA not complete
  2058. ; -------------------------------------------------------------
  2059. hw_WTDSKDMA:
  2060.     movem.l    d0-d1,-(a7)
  2061.  
  2062.  
  2063.     move.l    #499,d1            ; set count for 500 ms
  2064.  
  2065. hw_WTDMA_LUP1:
  2066.     bsr    hw_BEG_TIMING
  2067.  
  2068. hw_WTDMA_LUP2:
  2069.     move.w    INTREQR,d0
  2070.     btst    #1,d0        ; is disk DMA finished?
  2071.     bne.s    hw_WTDSKDMA_X
  2072.  
  2073.     bsr    hw_IS_TIMING
  2074.     beq.s    hw_WTDMA_LUP2
  2075.  
  2076.     dbra    d1,hw_WTDMA_LUP1
  2077.  
  2078. hw_WTDSKDMA_X:
  2079.     move.w    #$4000,DSKLEN    ; stop disk DMA
  2080.  
  2081.     move.w    #$0002,INTREQ    ; clear interrupt flag
  2082.  
  2083.     addq.w    #1,d1        ; set flags
  2084.     tst.w    d1
  2085.  
  2086.     movem.l    (a7)+,d0-d1
  2087.  
  2088.     rts
  2089.  
  2090. ; --------------------------------------------------------------
  2091. ;  Read MFM track from disk to buffer at a0.l
  2092. ;  Pass drive number in d0.w, side in d1.w, track number in d2.w
  2093. ;  eq = Track read OK, ne = disk error
  2094. ; --------------------------------------------------------------
  2095. hw_RD_DSK:
  2096.     movem.l    d0-d3/a3,-(a7)
  2097.  
  2098.     moveq    #ERR.NF,d3
  2099.  
  2100.     bsr    hw_MTR_ON
  2101. ;     bsr     hw_IS_DRVRDY
  2102. ;     bne     hw_RD_DSK5
  2103.  
  2104.     bsr    hw_SEL_SIDE    ; select correct side
  2105.     bsr    hw_SEL_DRV    ; select drive
  2106.  
  2107.     move.w    #$4000,DSKLEN    ; stop disk DMA
  2108.     move.w    #$8010,DMACON    ; enable disk DMA
  2109.     move.l    a0,DSKPTH    ; start of buffer
  2110.     move.w    #$6600,ADKCON    ; PRECOMP=0, GCR SYNC off, WORDSYNC off
  2111.     move.w    #$9100,ADKCON    ; MFMPREC for MFM, 2°s/bit
  2112.  
  2113.     cmp.w    #40,d2        ; if it is a high track,
  2114.     blt.s    hw_RD_DSK1    ; we need a
  2115.     move.w    #$A000,ADKCON    ; 140 ns precompensation
  2116.  
  2117. hw_RD_DSK1:
  2118.     move.l    AV.DSKV,a3
  2119.     move.w    FV.FLAGS(a3),d2
  2120.  
  2121.     move.w    #(((TLEN+1324)>>1)&$3FFF)|$8000,d1
  2122.  
  2123.     btst    #12,d2        ; branch if index enabled
  2124.     bne.s    hw_RD_DSK2
  2125.  
  2126.     btst    #11,d2        ; branch if word SYNC disabled
  2127.     beq.s    hw_RD_DSK4
  2128.  
  2129.     move.w    #$8400,ADKCON    ; SYNC on
  2130.     move.w    #$4489,DSKSYNC    ; sync word
  2131.  
  2132.     bra.s    hw_RD_DSK4
  2133.  
  2134. ;  do disk read via index interrupt
  2135.  
  2136. hw_RD_DSK2:
  2137.     move.w    #((TLEN>>1)&$3FFF)|$8000,d1
  2138.  
  2139.     btst    #11,d2        ; branch if word SYNC disabled
  2140.     beq.s    hw_RD_DSK3
  2141.  
  2142.     move.w    #$8400,ADKCON    ; SYNC on
  2143.     move.w    #$4489,DSKSYNC    ; sync word
  2144.     move.w    #(((TLEN-376)>>1)&$3FFF)|$8000,d1
  2145.  
  2146. hw_RD_DSK3:
  2147.  
  2148.     bsr    hw_WTIDX     ; wait for index
  2149.     beq.s    hw_RD_DSK5    ; branch on error
  2150.  
  2151. ;  do disk read
  2152.  
  2153. hw_RD_DSK4:
  2154.     move.w    d1,DSKLEN    ; initiate disk operation
  2155.     move.w    d1,DSKLEN
  2156.  
  2157.     move.w    #$0002,INTREQ    ; clear previous interrupt
  2158.                 ; requests from disk DMA
  2159.  
  2160. ;  wait for operation to finish, then exit
  2161.  
  2162.     bsr    hw_WTDSKDMA    ; wait, until disk written
  2163.     beq.s    hw_RD_DSK5    ; branch on error
  2164.  
  2165.     moveq    #ERR.OK,d3    ; signal read error
  2166.  
  2167. hw_RD_DSK5:
  2168.     bsr    hw_DESEL_DRV    ; deselect drive
  2169.  
  2170.     tst.l    d3        ; set flags
  2171.  
  2172.     movem.l    (a7)+,d0-d3/a3
  2173.     rts
  2174.  
  2175. ; -------------------------------------------------------------
  2176. ;  Write MFM track to disk from buffer at a0.l
  2177. ;  Pass drive number in d0.w, track number in d1.w
  2178. ;  Requires you to have set up an interrupt server that acts
  2179. ;  on the index pulse and begins the actual disk write and DMA
  2180. ; -------------------------------------------------------------
  2181. hw_WR_DSK:
  2182.     movem.l    d0-d3/a3,-(a7)
  2183.  
  2184.     move.w    sr,-(a7)
  2185.     ori.w    #$0700,sr
  2186.  
  2187.     moveq    #ERR.NF,d3
  2188.  
  2189.     bsr    hw_MTR_ON
  2190. ;     bsr     hw_IS_DRVRDY
  2191. ;     bne     hw_WR_DSK4
  2192.  
  2193.     bsr    hw_SEL_SIDE    ; select side
  2194.     bsr    hw_SEL_DRV    ; select drive
  2195.  
  2196.     move.w    #$4000,DSKLEN    ; stop disk DMA
  2197.     move.w    #$8010,DMACON    ; enable disk DMA
  2198.     move.l    a0,DSKPTH    ; start of buffer
  2199.     move.w    #$6600,ADKCON    ; PRECOMP=0, MFM , no SYNC
  2200.     move.w    #$9100,ADKCON    ; MFMPREC for MFM, 2°s/bit
  2201.  
  2202.     cmp.w    #40,d2        ; if it is a high track,
  2203.     blt.s    hw_WR_DSK1    ; we need a
  2204.     move.w    #$A000,ADKCON    ; 140 ns precompensation
  2205.  
  2206. hw_WR_DSK1:
  2207.     move.l    AV.DSKV,a3
  2208.     move.w    FV.FLAGS(a3),d1
  2209.  
  2210.     btst    #13,d1        ; branch if index disabled
  2211.     beq    hw_WR_DSK2
  2212.  
  2213. ;  do disk write via index interrupt
  2214.  
  2215.     bsr    hw_WTIDX     ; wait for index
  2216.     beq.s    hw_WR_DSK4    ; branch on error
  2217.  
  2218. ;  do disk write
  2219.  
  2220. hw_WR_DSK2:
  2221.     move.w    #((WLEN>>1)&$3FFF)|$C000,d1
  2222.  
  2223.     move.w    d1,DSKLEN    ; initiate disk operation
  2224.     move.w    d1,DSKLEN
  2225.  
  2226.     move.w    #$0002,INTREQ    ; clear previous interrupt
  2227.                 ; requests from disk DMA
  2228.  
  2229. ;  wait for operation to finish, then exit
  2230.  
  2231. hw_WR_DSK3:
  2232.     bsr    hw_WTDSKDMA    ; wait, until disk written
  2233.     beq.s    hw_WR_DSK4    ; branch on error
  2234.  
  2235.     moveq    #ERR.OK,d3
  2236.  
  2237. hw_WR_DSK4:
  2238.     bsr    hw_DESEL_DRV    ; deselect drive
  2239.  
  2240.     tst.l    d3
  2241.  
  2242.     move.w    (a7)+,sr
  2243.  
  2244.     movem.l    (a7)+,d0-d3/a3
  2245.     rts
  2246.  
  2247. ; -------------------------------------------------------------
  2248. ;  deselect all drives
  2249. ; -------------------------------------------------------------
  2250. hw_DESEL_ALL:
  2251.     or.b    #%01111000,CIAB_PRB ; deselect all drives
  2252.  
  2253.     rts
  2254.  
  2255. ; -------------------------------------------------------------
  2256. ;  Select disk d0.b
  2257. ; -------------------------------------------------------------
  2258. hw_SEL_DRV:
  2259.     and.w    #$3,d0        ; Only drives 0-3.
  2260.  
  2261.     movem.l    d0,-(a7)
  2262.  
  2263.     addq.b    #3,d0
  2264.     bclr.b    d0,CIAB_PRB    ; select drive
  2265.  
  2266.     movem.l    (a7)+,d0
  2267.     rts
  2268.  
  2269. ; -------------------------------------------------------------
  2270. ;  Deselect disk d0.b
  2271. ; -------------------------------------------------------------
  2272. hw_DESEL_DRV:
  2273.     and.w    #$3,d0        ; Only drives 0-3.
  2274.  
  2275.     movem.l    d0,-(a7)
  2276.  
  2277.     addq.b    #3,d0
  2278.     bset.b    d0,CIAB_PRB    ; deselect drive
  2279.  
  2280.     movem.l    (a7)+,d0
  2281.     rts
  2282.  
  2283. ; -------------------------------------------------------------
  2284. ;  switch on motor for drive d0.w
  2285. ; -------------------------------------------------------------
  2286. hw_MTR_ON:
  2287.     and.w    #$3,d0        ; Only drives 0-3.
  2288.  
  2289.     bsr    hw_DESEL_ALL
  2290.     bclr    #7,CIAB_PRB    ; switch on motor
  2291.     bsr    hw_SEL_DRV
  2292.     bsr    hw_DESEL_DRV
  2293.  
  2294.     rts
  2295.  
  2296. ; -------------------------------------------------------------
  2297. ;  switch off motor for drive d0.w
  2298. ; -------------------------------------------------------------
  2299. hw_MTR_OFF:
  2300.     and.w    #$3,d0        ; Only drives 0-3.
  2301.  
  2302.     bsr    hw_DESEL_ALL
  2303.     bset    #7,CIAB_PRB    ; switch off motor
  2304.     bsr    hw_SEL_DRV
  2305.     bsr    hw_DESEL_DRV
  2306.  
  2307.     rts
  2308. ; -------------------------------------------------------------
  2309. ;  select side d1.b for drive d0.w
  2310. ; -------------------------------------------------------------
  2311. hw_SEL_SIDE:
  2312.     and.w    #$3,d0        ; Only drives 0-3.
  2313.     bsr    hw_DESEL_ALL
  2314.  
  2315.     btst.b    #0,d1
  2316.     beq.s    hw_SEL_SID0
  2317.  
  2318. hw_SEL_SID1:
  2319.     bclr    #2,CIAB_PRB    ; select side 1
  2320.     bra.s    hw_SEL_SIDX
  2321.  
  2322. hw_SEL_SID0:
  2323.     bset    #2,CIAB_PRB    ; select side 0
  2324.  
  2325. hw_SEL_SIDX:
  2326.     bsr    hw_SEL_DRV
  2327.     bsr    hw_DESEL_DRV
  2328.  
  2329.     rts
  2330.  
  2331. ; -------------------------------------------------------------
  2332. ;  Step in one track (increase track number) on drive d0.w
  2333. ; -------------------------------------------------------------
  2334. hw_STEP_IN:
  2335.     movem.l    d1,-(a7)
  2336.  
  2337.     and.w    #$3,d0        ; Only drives 0-3.
  2338.     bsr    hw_DESEL_ALL
  2339.  
  2340.     bsr    hw_SEL_DRV
  2341.  
  2342.     bclr    #1,CIAB_PRB    ; reset direction bit
  2343.  
  2344.     bset    #0,CIAB_PRB    ; set diskstep bit
  2345.     bclr    #0,CIAB_PRB    ; reset diskstep bit
  2346.     bset    #0,CIAB_PRB    ; set diskstep bit
  2347.  
  2348.     bsr    hw_DESEL_DRV
  2349.  
  2350.     moveq    #4,d1        ; set count for 5ms
  2351.  
  2352. hw_SI_LUP1:
  2353.     bsr    hw_BEG_TIMING
  2354.  
  2355. hw_SI_LUP2:
  2356.     bsr    hw_IS_TIMING
  2357.     beq.s    hw_SI_LUP2
  2358.  
  2359.     dbra    d1,hw_SI_LUP1
  2360.  
  2361. hw_SI_X:
  2362.     movem.l    (a7)+,d1
  2363.     rts
  2364.  
  2365. ; -------------------------------------------------------------
  2366. ;  Step out one track (decrease track number) on drive d0.w
  2367. ; -------------------------------------------------------------
  2368. hw_STEP_OUT:
  2369.     movem.l    d1,-(a7)
  2370.  
  2371.     and.w    #$3,d0        ; Only drives 0-3.
  2372.     bsr    hw_DESEL_ALL
  2373.  
  2374.     bsr    hw_SEL_DRV
  2375.  
  2376.     bset    #1,CIAB_PRB    ; set direction bit
  2377.  
  2378.     bset    #0,CIAB_PRB    ; set diskstep bit
  2379.     bclr    #0,CIAB_PRB    ; reset diskstep bit
  2380.     bset    #0,CIAB_PRB    ; set diskstep bit
  2381.  
  2382.     bsr    hw_DESEL_DRV
  2383.  
  2384.     moveq    #4,d1        ; set count for 5ms
  2385.  
  2386. hw_SO_LUP1:
  2387.     bsr    hw_BEG_TIMING
  2388.  
  2389. hw_SO_LUP2:
  2390.     bsr    hw_IS_TIMING
  2391.     beq.s    hw_SO_LUP2
  2392.  
  2393.     dbra    d1,hw_SO_LUP1
  2394.  
  2395. hw_SO_X:
  2396.     movem.l    (a7)+,d1
  2397.     rts
  2398.  
  2399. ; -------------------------------------------------------------
  2400. ;  Find track zero on drive d0.w
  2401. ; -------------------------------------------------------------
  2402. hw_GO_TK0:
  2403.     movem.l    d1,-(a7)
  2404.  
  2405.     moveq    #84,d1        ; maximum 84 tracks to step
  2406. hw_GT0_LUP:
  2407.     bsr    hw_IS_TK0    ; already track 0?
  2408.     beq.s    hw_GT0_X
  2409.     bsr    hw_STEP_OUT    ; step a little closer
  2410.     dbra    d1,hw_GT0_LUP
  2411.  
  2412. hw_GT0_X:
  2413.     movem.l    (a7)+,d1
  2414.     rts
  2415.  
  2416. ; -------------------------------------------------------------
  2417. ;  return whether drive d0.w is at track zero
  2418. ;  eq = is at track zero, ne = is not at track zero
  2419. ; -------------------------------------------------------------
  2420. hw_IS_TK0:
  2421.     movem.l    d0-d1,-(a7)
  2422.  
  2423.     and.w    #$3,d0        ; Only drives 0-3.
  2424.     bsr    hw_DESEL_ALL
  2425.  
  2426.     bsr    hw_SEL_DRV
  2427.     move.b    CIAA_PRA,d1
  2428.     bsr    hw_DESEL_DRV
  2429.  
  2430.     andi.b    #16,d1
  2431.  
  2432.     movem.l    (a7)+,d0-d1
  2433.     rts
  2434.  
  2435. ; -------------------------------------------------------------
  2436. ;  wait until drive has reached speed, or for a maximum of
  2437. ;  500 milliseconds.
  2438. ;  eq = drive has reached speed, ne = drive is duff
  2439. ; -------------------------------------------------------------
  2440. hw_IS_DRVRDY:
  2441.     movem.l    d0-d1,-(a7)
  2442.  
  2443. ; wait for motor to reach speed
  2444.  
  2445.     move.w    #500,d1        ; set counter for 500ms
  2446.  
  2447. hw_IS_DRVRDY1:
  2448.     bsr    hw_BEG_TIMING
  2449.  
  2450. hw_IS_DRVRDY2:
  2451. ;     bsr     hw_IS_RDY
  2452. ;     beq.s     hw_IS_DRVRDY3
  2453.  
  2454.     bsr    hw_IS_TIMING
  2455.     beq.s    hw_IS_DRVRDY2
  2456.  
  2457.     dbra    d1,hw_IS_DRVRDY1
  2458.  
  2459. ;     bsr     hw_MTR_OFF
  2460.  
  2461. ;     moveq     #-1,d0
  2462. ;     bra.s     hw_IS_DRVRDYX
  2463.  
  2464. hw_IS_DRVRDY3:
  2465.     moveq    #0,d0
  2466.  
  2467. hw_IS_DRVRDYX:
  2468.     movem.l    (a7)+,d0-d1
  2469.     rts
  2470.  
  2471. ; -------------------------------------------------------------
  2472. ;  return motor ready signal for drive d0.w in zero flag
  2473. ;  eq = motor ready, ne = motor not ready
  2474. ; -------------------------------------------------------------
  2475. hw_IS_RDY:
  2476.     movem.l    d0-d1,-(a7)
  2477.  
  2478.     and.w    #$3,d0        ; Only drives 0-3.
  2479.     bsr    hw_DESEL_ALL
  2480.  
  2481.     bsr    hw_SEL_DRV
  2482.     move.b    CIAA_PRA,d1
  2483.     bsr    hw_DESEL_DRV
  2484.  
  2485.     and.b    #32,d1
  2486.  
  2487.     movem.l    (a7)+,d0-d1
  2488.  
  2489.     rts
  2490.  
  2491. ; -------------------------------------------------------------
  2492. ;  return status of writeprotect signal for drive d0.w
  2493. ;  eq = protected, ne = not protected
  2494. ; -------------------------------------------------------------
  2495. hw_IS_PRO:
  2496.     movem.l    d0-d1,-(a7)
  2497.  
  2498.     and.w    #$3,d0        ; Only drives 0-3.
  2499.     bsr    hw_DESEL_ALL
  2500.  
  2501.     bsr    hw_SEL_DRV
  2502.     move.b    CIAA_PRA,d1
  2503.     bsr    hw_DESEL_DRV
  2504.  
  2505.     and.b    #8,d1
  2506.  
  2507.     movem.l    (a7)+,d0-d1
  2508.     rts
  2509.  
  2510. ; -------------------------------------------------------------
  2511. ;  return status of diskchange signal for drive d0.w
  2512. ;  eq = changed, ne = not changed
  2513. ; -------------------------------------------------------------
  2514. hw_IS_CHG:
  2515.     movem.l    d0-d1,-(a7)
  2516.  
  2517.     and.w    #$3,d0        ; Only drives 0-3.
  2518.     bsr    hw_DESEL_ALL
  2519.  
  2520.     bsr    hw_SEL_DRV
  2521.     move.b    CIAA_PRA,d1
  2522.     bsr    hw_DESEL_DRV
  2523.  
  2524.     andi.b    #4,d1
  2525.     bne.s    hw_IS_CHGX
  2526.  
  2527.     bsr    hw_STEP_IN    ; clear change signal
  2528.     bsr    hw_STEP_OUT
  2529.  
  2530.     tst.b    d1
  2531.  
  2532. hw_IS_CHGX:
  2533.     movem.l    (a7)+,d0-d1
  2534.     rts
  2535.  
  2536. ; -------------------------------------------------------------
  2537. ;  Return drive type for drive d0.w in d0.l
  2538. ; -------------------------------------------------------------
  2539. hw_DRV_TYP:
  2540.     movem.l    d1-d3/a0,-(a7)
  2541.  
  2542.     addq.b    #3,d0
  2543.     moveq    #1,d3
  2544.     asl.b    d0,d3
  2545.  
  2546. L0F8F616:
  2547.     not.b     d3
  2548.     lea     CIAB_PRB,a0
  2549.     move.b     #$7F,d0
  2550.     move.b     d0,(a0)
  2551.     and.b     d3,d0
  2552.     move.b     d0,(a0)
  2553.     move.b     #$FF,(a0)
  2554.     move.b     d3,(a0)
  2555.     move.b     #$FF,(a0)
  2556.     moveq     #$1F,d1
  2557.     moveq     #$0,d0
  2558. L0F8F636:
  2559.     lsl.l     #1,d0
  2560.     move.b     d3,(a0)
  2561.     btst     #$5,CIAA_PRA
  2562.     bne.s     L0F8F648    ;*/modify beq.s L0F8F648
  2563.     bset     #$0,d0
  2564. L0F8F648:
  2565.     move.b     #$FF,(a0)
  2566.     dbra     d1,L0F8F636
  2567. L0F8F650:
  2568.  
  2569.     movem.l    (a7)+,d1-d3/a0
  2570.     rts
  2571.  
  2572. ; -------------------------------------------------------------
  2573. ;  BASIC functions and procedures
  2574. ; -------------------------------------------------------------
  2575. PROC_DEF:
  2576.     ifnd    extras
  2577.     dc.w    4
  2578.     endc
  2579.  
  2580.     ifd    extras
  2581.     ifnd    extras2
  2582.     dc.w    4
  2583.     endc
  2584.     ifd    extras2
  2585.     dc.w    22
  2586.     endc
  2587.     endc
  2588.  
  2589.     dc.w    B_DISKCOPY-*
  2590.     dc.b    8,'DISKCOPY',0
  2591.     dc.w    B_MOUNT-*
  2592.     dc.b    5,'MOUNT'
  2593.     dc.w    B_DSKCNG-*
  2594.     dc.b    6,'DskCng',0
  2595.  
  2596.     ifd    extras
  2597.     dc.w    B_hw_SEL_SIDE-*
  2598.     dc.b    11,'hw_SEL_SIDE'
  2599.     dc.w    B_hw_STEP_OUT-*
  2600.     dc.b    11,'hw_STEP_OUT'
  2601.     dc.w    B_hw_STEP_IN-*
  2602.     dc.b    10,'hw_STEP_IN',0
  2603.     dc.w    B_hw_GO_TK0-*
  2604.     dc.b    9,'hw_GO_TK0'
  2605.     dc.w    B_hw_MTR_OFF-*
  2606.     dc.b    10,'hw_MTR_OFF',0
  2607.     dc.w    B_hw_MTR_ON-*
  2608.     dc.b    9,'hw_MTR_ON'
  2609.     dc.w    B_hw_WR_DSK-*
  2610.     dc.b    9,'hw_WR_DSK'
  2611.     dc.w    B_hw_RD_DSK-*
  2612.     dc.b    9,'hw_RD_DSK'
  2613.     dc.w    B_hw_TIMER-*
  2614.     dc.b    8,'hw_TIMER'
  2615.  
  2616.     ifd    extras2
  2617.     dc.w    B_W_INDEX-*
  2618.     dc.b    7,'W_INDEX'
  2619.     dc.w    B_R_INDEX-*
  2620.     dc.b    7,'R_INDEX'
  2621.     dc.w    B_FLUSH_BUFF-*
  2622.     dc.b    10,'Flush_BUFF',0
  2623.     dc.w    B_FREE_BUFF-*
  2624.     dc.b    9,'Free_BUFF'
  2625.     dc.w    B_FTRACK-*
  2626.     dc.b    6,'FTrack',0
  2627.     dc.w    B_WQDISK-*
  2628.     dc.b    6,'WQDisk',0
  2629.     dc.w    B_RQDISK-*
  2630.     dc.b    6,'RQDisk',0
  2631.     dc.w    B_WQSEC-*
  2632.     dc.b    5,'WQSec'
  2633.     dc.w    B_RQSEC-*
  2634.     dc.b    5,'RQSec'
  2635.     dc.w    B_SEL_DRV-*
  2636.     dc.b    7,'SEL_DRV'
  2637.     dc.w    B_SEL_SIDE-*
  2638.     dc.b    8,'SEL_SIDE',0
  2639.     dc.w    B_GO_TRACK-*
  2640.     dc.b    8,'GO_TRACK',0
  2641.     endc
  2642.     endc
  2643.  
  2644.     dc.w    0
  2645.  
  2646.     ifnd    extras
  2647.     dc.w    4
  2648.     endc
  2649.  
  2650.     ifd    extras
  2651.     ifnd    extras2
  2652.     dc.w    8
  2653.     endc
  2654.     ifd    extras2
  2655.     dc.w    14
  2656.     endc
  2657.     endc
  2658.  
  2659.     dc.w    B_hw_DRV_TYP-*
  2660.     dc.b    10,'hw_DRV_TYP',0
  2661.  
  2662.     ifd    extras
  2663.     dc.w    B_hw_IS_CHG-*
  2664.     dc.b    9,'hw_IS_CHG'
  2665.     dc.w    B_hw_IS_PRO-*
  2666.     dc.b    9,'hw_IS_PRO'
  2667.     dc.w    B_hw_IS_RDY-*
  2668.     dc.b    9,'hw_IS_RDY'
  2669.     dc.w    B_hw_IS_TK0-*
  2670.     dc.b    9,'hw_IS_TK0'
  2671.  
  2672.     ifd    extras2
  2673.     dc.w    B_CRC-*
  2674.     dc.b    3,'CRC'
  2675.     dc.w    B_ASCMFM-*
  2676.     dc.b    6,'ASCMFM',0
  2677.     dc.w    B_MFMASC-*
  2678.     dc.b    6,'MFMASC',0
  2679.     dc.w    B_CHNG-*
  2680.     dc.b    4,'Chng',0
  2681.     dc.w    B_WPRO-*
  2682.     dc.b    4,'WPro',0
  2683.     dc.w    B_CKRDY-*
  2684.     dc.b    5,'CkRdy'
  2685.     endc
  2686.     endc
  2687.  
  2688.     dc.w    0
  2689.  
  2690. ; -------------------------------------------------------------
  2691. ;    BASIC adaptions to M-Code procs
  2692. ; -------------------------------------------------------------
  2693. B_MOUNT:
  2694.     bsr    FETCH_W        ; get disk number
  2695.     bne    B_MOUNTX
  2696.     move.l    d1,d0
  2697.  
  2698.     cmp.l    a3,a5
  2699.     bne    RPRT_BP
  2700.  
  2701.     bsr    MOUNT
  2702.  
  2703. B_MOUNTX:
  2704.     rts
  2705.  
  2706. ; -------------------------------------------------------------
  2707. B_DSKCNG:
  2708.     bsr    FETCH_W        ; get drive number
  2709.     bne    B_DSKCNGX
  2710.     move.l    d1,d0
  2711.  
  2712.     cmp.l    a3,a5
  2713.     bne    RPRT_BP
  2714.  
  2715.     bsr    DSKCNG
  2716.  
  2717.     moveq    #0,d0        ; no errors
  2718.  
  2719. B_DSKCNGX:
  2720.     rts
  2721.  
  2722.     ifd    extras2
  2723. ; -------------------------------------------------------------
  2724. B_W_INDEX
  2725.     bsr    FETCH_W        ; get flag word
  2726.     bne    B_W_INDEXX
  2727.  
  2728.     cmp.l    a3,a5
  2729.     bne    RPRT_BP
  2730.  
  2731.     movem.l    a3,-(a7)
  2732.     move.l    AV.DSKV,a3
  2733.  
  2734.     tst.l    d1
  2735.     bne.s    B_W_IDX1
  2736.  
  2737.     move.w    FV.FLAGS(a3),d0
  2738.     bclr    #13,d0
  2739.  
  2740.     bra.s    B_W_IDX2
  2741.  
  2742. B_W_IDX1:
  2743.     move.w    FV.FLAGS(a3),d0
  2744.     bset    #13,d0
  2745.  
  2746. B_W_IDX2:
  2747.     move.w    d0,FV.FLAGS(a3)
  2748.  
  2749.     movem.l    (a7)+,a3
  2750.     moveq    #0,d0
  2751.  
  2752. B_W_INDEXX:
  2753.     rts
  2754.  
  2755. ; -------------------------------------------------------------
  2756. B_R_INDEX:
  2757.     bsr    FETCH_W        ; get flag word
  2758.     bne    B_R_INDEXX
  2759.  
  2760.     cmp.l    a3,a5
  2761.     bne    RPRT_BP
  2762.  
  2763.     movem.l    a3,-(a7)
  2764.     move.l    AV.DSKV,a3
  2765.  
  2766.     tst.l    d1
  2767.     bne.s    B_R_IDX1
  2768.  
  2769.     move.w    FV.FLAGS(a3),d0
  2770.     bclr    #12,d0
  2771.  
  2772.     bra.s    B_R_IDX2
  2773.  
  2774. B_R_IDX1:
  2775.     move.w    FV.FLAGS(a3),d0
  2776.     bset    #12,d0
  2777.  
  2778. B_R_IDX2:
  2779.     move.w    d0,FV.FLAGS(a3)
  2780.  
  2781.     movem.l    (a7)+,a3
  2782.     moveq    #0,d0
  2783.  
  2784. B_R_INDEXX:
  2785.     rts
  2786.  
  2787. ; -------------------------------------------------------------
  2788. B_CRC:
  2789.     bsr    FETCH_L        ; get address of data
  2790.     bne    B_FLUSH_BUFFX
  2791.     move.l    d1,d3
  2792.  
  2793.     bsr    FETCH_L        ; get length of data
  2794.     bne    B_FLUSH_BUFFX
  2795.     move.l    d1,d2
  2796.  
  2797.     bsr    FETCH_L        ; get previous CRC
  2798.     bne    B_FLUSH_BUFFX
  2799.  
  2800.     cmp.l    a3,a5
  2801.     bne    RPRT_BP
  2802.  
  2803.     move.l    d1,d0
  2804.     move.l    d2,d1
  2805.     move.l    d3,a0
  2806.     bsr    CALCCRC
  2807.     bra    RET_W
  2808.  
  2809. ; -------------------------------------------------------------
  2810. B_ASCMFM:
  2811.     bsr    FETCH_W        ; get ASCII byte
  2812.     bne    B_FLUSH_BUFFX
  2813.     move.l    d1,d0
  2814.  
  2815.     cmp.l    a3,a5
  2816.     bne    RPRT_BP
  2817.  
  2818.     bsr    ASCMFMD0
  2819.     bra    RET_W
  2820.  
  2821. ; -------------------------------------------------------------
  2822. B_MFMASC:
  2823.     bsr    FETCH_W        ; get MFM word
  2824.     bne    B_FLUSH_BUFFX
  2825.     move.l    d1,d0
  2826.  
  2827.     cmp.l    a3,a5
  2828.     bne    RPRT_BP
  2829.  
  2830.     bsr    MFMASCD0
  2831.     bra    RET_W
  2832.  
  2833. ; -------------------------------------------------------------
  2834. B_FLUSH_BUFF:
  2835.     bsr    FETCH_W        ; get disk number
  2836.     bne    B_FLUSH_BUFFX
  2837.     move.l    d1,d0
  2838.  
  2839.     cmp.l    a3,a5
  2840.     bne    RPRT_BP
  2841.  
  2842.     bsr    FLUSH_BUFF
  2843.  
  2844. B_FLUSH_BUFFX:
  2845.     rts
  2846.  
  2847. ; -------------------------------------------------------------
  2848. B_FREE_BUFF:
  2849.     bsr    FETCH_W        ; get disk number
  2850.     bne    B_FREE_BUFFX
  2851.     move.l    d1,d0
  2852.  
  2853.     cmp.l    a3,a5
  2854.     bne    RPRT_BP
  2855.  
  2856.     bsr    FREE_BUFF
  2857.  
  2858. B_FREE_BUFFX:
  2859.     rts
  2860.  
  2861. ; -------------------------------------------------------------
  2862. B_FTRACK:
  2863.     bsr    FETCH_W        ; get disk number
  2864.     bne    B_FTRACKX
  2865.     move.l    d1,d4
  2866.  
  2867.     bsr    FETCH_W        ; get side
  2868.     bne    B_FTRACKX
  2869.     move.l    d1,d3
  2870.  
  2871.     bsr    FETCH_W        ; get track number
  2872.     bne    B_FTRACKX
  2873.     move.l    d1,d2
  2874.  
  2875.     cmp.l    a3,a5
  2876.     bne    RPRT_BP
  2877.  
  2878.     move.l    d4,d0
  2879.     bsr    SEL_DRV
  2880.  
  2881.     move.l    d3,d0
  2882.     bsr    SEL_SIDE
  2883.  
  2884.     move.l    d2,d0
  2885.     bsr    GO_TRACK
  2886.  
  2887.     bsr    FTRACK
  2888.  
  2889. B_FTRACKX:
  2890.     rts
  2891.  
  2892. ; -------------------------------------------------------------
  2893. B_WQDISK:
  2894.     bsr    FETCH_W        ; get disk number
  2895.     bne    B_WQDISKX
  2896.     move.l    d1,d4
  2897.  
  2898.     bsr    FETCH_W        ; get side
  2899.     bne    B_WQDISKX
  2900.     move.l    d1,d3
  2901.  
  2902.     bsr    FETCH_W        ; get track number
  2903.     bne    B_WQDISKX
  2904.     move.l    d1,d2
  2905.  
  2906.     cmp.l    a3,a5
  2907.     bne    RPRT_BP
  2908.  
  2909.     move.l    d4,d0
  2910.     bsr    SEL_DRV
  2911.  
  2912.     move.l    d3,d0
  2913.     bsr    SEL_SIDE
  2914.  
  2915.     move.l    d2,d0
  2916.     bsr    GO_TRACK
  2917.  
  2918.     bsr    WQDISK
  2919.  
  2920. B_WQDISKX:
  2921.     rts
  2922.  
  2923. ; -------------------------------------------------------------
  2924. B_RQDISK:
  2925.     bsr    FETCH_W        ; get disk number
  2926.     bne    B_RQDISKX
  2927.     move.l    d1,d4
  2928.  
  2929.     bsr    FETCH_W        ; get side
  2930.     bne    B_RQDISKX
  2931.     move.l    d1,d3
  2932.  
  2933.     bsr    FETCH_W        ; get track number
  2934.     bne    B_RQDISKX
  2935.     move.l    d1,d2
  2936.  
  2937.     cmp.l    a3,a5
  2938.     bne    RPRT_BP
  2939.  
  2940.     move.l    d4,d0
  2941.     bsr    SEL_DRV
  2942.  
  2943.     move.l    d3,d0
  2944.     bsr    SEL_SIDE
  2945.  
  2946.     move.l    d2,d0
  2947.     bsr    GO_TRACK
  2948.  
  2949.     bsr    RQDISK
  2950.  
  2951. B_RQDISKX:
  2952.     rts
  2953.  
  2954. ; -------------------------------------------------------------
  2955. B_WQSEC:
  2956.     bsr    FETCH_L        ; output buffer address
  2957.     bne    B_WQSECX
  2958.     move.l    d1,d5
  2959.  
  2960.     bsr    FETCH_W        ; get disk number
  2961.     bne    B_WQSECX
  2962.     move.l    d1,d4
  2963.  
  2964.     bsr    FETCH_W        ; get side
  2965.     bne    B_WQSECX
  2966.     move.l    d1,d3
  2967.  
  2968.     bsr    FETCH_W        ; get track number
  2969.     bne    B_WQSECX
  2970.     move.l    d1,d2
  2971.  
  2972.     bsr    FETCH_W        ; get sector number
  2973.     bne    B_WQSECX
  2974.  
  2975.     cmp.l    a3,a5
  2976.     bne    RPRT_BP
  2977.  
  2978.     move.l    d4,d0
  2979.     bsr    SEL_DRV
  2980.  
  2981.     move.l    d3,d0
  2982.     bsr    SEL_SIDE
  2983.  
  2984.     move.l    d2,d0
  2985.     bsr    GO_TRACK
  2986.                 ; sector number in d1
  2987.     move.l    d5,a1        ; output buffer address
  2988.     bsr    WQSEC
  2989.  
  2990. B_WQSECX:
  2991.     rts
  2992.  
  2993. ; -------------------------------------------------------------
  2994. B_RQSEC:
  2995.     bsr    FETCH_L        ; output buffer address
  2996.     bne    B_RQSECX
  2997.  
  2998.     move.l    d1,d5
  2999.  
  3000.     bsr    FETCH_W        ; get disk number
  3001.     bne    B_RQSECX
  3002.     move.l    d1,d4
  3003.  
  3004.     bsr    FETCH_W        ; get side
  3005.     bne    B_RQSECX
  3006.     move.l    d1,d3
  3007.  
  3008.     bsr    FETCH_W        ; get track number
  3009.     bne    B_RQSECX
  3010.     move.l    d1,d2
  3011.  
  3012.     bsr    FETCH_W        ; get sector number
  3013.     bne    B_RQSECX
  3014.  
  3015.     cmp.l    a3,a5
  3016.     bne    RPRT_BP
  3017.  
  3018.     move.l    d4,d0
  3019.     bsr    SEL_DRV
  3020.  
  3021.     move.l    d3,d0
  3022.     bsr    SEL_SIDE
  3023.  
  3024.     move.l    d2,d0
  3025.     bsr    GO_TRACK
  3026.                 ; sector number in d1
  3027.     move.l    d5,a1        ; output buffer address
  3028.     moveq    #0,d3        ; no bytes to skip
  3029.     moveq    #0,d4        ; no bytes to leave
  3030.     bsr    RQSEC
  3031.  
  3032. B_RQSECX:
  3033.     rts
  3034.  
  3035. ; -------------------------------------------------------------
  3036. B_SEL_DRV:
  3037.     bsr    FETCH_W        ; get drive number
  3038.     bne    B_SEL_DRVX
  3039.     move.l    d1,d0
  3040.  
  3041.     cmp.l    a3,a5
  3042.     bne    RPRT_BP
  3043.  
  3044.     bsr    SEL_DRV
  3045.  
  3046. B_SEL_DRVX:
  3047.     rts
  3048.  
  3049. ; -------------------------------------------------------------
  3050. B_SEL_SIDE:
  3051.     bsr    FETCH_W        ; get side number
  3052.     bne    B_SEL_SIDEX
  3053.     move.l    d1,d0
  3054.  
  3055.     cmp.l    a3,a5
  3056.     bne    RPRT_BP
  3057.  
  3058.     bsr    SEL_SIDE
  3059.  
  3060. B_SEL_SIDEX:
  3061.     rts
  3062.  
  3063. ; -------------------------------------------------------------
  3064. B_GO_TRACK:
  3065.     bsr    FETCH_W        ; get track number
  3066.     bne    B_GO_TRACKX
  3067.     move.l    d1,d0
  3068.  
  3069.     cmp.l    a3,a5
  3070.     bne    RPRT_BP
  3071.  
  3072.     bsr    GO_TRACK
  3073.  
  3074. B_GO_TRACKX:
  3075.     rts
  3076.  
  3077. ; -------------------------------------------------------------
  3078. B_CHNG:
  3079.     bsr    CHNG        ; test for Disk change
  3080.     bra    RET_W
  3081.  
  3082. ; -------------------------------------------------------------
  3083. B_WPRO:
  3084.     bsr    WPRO        ; test for write protect
  3085.     bra    RET_W
  3086.  
  3087. ; -------------------------------------------------------------
  3088. B_CKRDY:
  3089.     bsr    CKRDY        ; check readiness of drive
  3090.     bra    RET_W
  3091.  
  3092.     endc
  3093.  
  3094. ; -------------------------------------------------------------
  3095. ;    BASIC routines that hit hit the hardware directly
  3096. ; -------------------------------------------------------------
  3097. B_DISKCOPY:
  3098.     moveq    #0,d1        ; default channel #
  3099.     bsr    GET_CH        ; get channel ID
  3100.  
  3101.     cmp.l    a3,a5
  3102.     bne    RPRT_BP
  3103.  
  3104.     move.l    AV.DSKV,a3
  3105.     cmp.w    #1,FV.MAXDRive(a3)
  3106.     bge.s    B_DC2
  3107.  
  3108.     lea    DRVMSG(pc),a1
  3109.     bsr    IOSTRG
  3110.     bra.s    B_DCOK
  3111.  
  3112. B_DC2:
  3113.     lea    CPYMSG(pc),a1
  3114.     bsr    IOSTRG
  3115.  
  3116. B_DCLUP:
  3117.     moveq    #IO.FBYTE,d0
  3118.     moveq    #-1,d3        ; infinite timeout
  3119.     trap    #3        ; fetch a byte
  3120.  
  3121.     tst.l    d0
  3122.     bne.s    B_DCX        ; exit on error
  3123.  
  3124.     cmp.b    #$0A,d1
  3125.     bne.s    B_DCLUP
  3126.  
  3127.     bsr    DISKCOPY     ; copy disk
  3128.     bne.s    B_DCX
  3129.  
  3130.     lea    DONMSG(pc),a1
  3131.     bsr    IOSTRG
  3132.  
  3133. B_DCOK:
  3134.     moveq    #0,d0
  3135.  
  3136. B_DCX:
  3137.     rts
  3138.  
  3139. ; -------------------------------------------------------------
  3140. B_hw_DRV_TYP:
  3141.     bsr    FETCH_W        ; get drive number
  3142.     bne    B_hw_DRV_TYPX
  3143.     move.l    d1,d0
  3144.  
  3145.     cmp.l    a3,a5
  3146.     bne    RPRT_BP
  3147.  
  3148.     bsr    hw_DRV_TYP    ; test drive type
  3149.     bra    RET_L
  3150.  
  3151. B_hw_DRV_TYPX:
  3152.  
  3153.     ifd    extras
  3154.  
  3155. ; -------------------------------------------------------------
  3156. B_hw_IS_CHG:
  3157.     bsr    FETCH_W        ; get drive number
  3158.     bne    B_hw_SEL_SIDX
  3159.     move.l    d1,d0
  3160.  
  3161.     cmp.l    a3,a5
  3162.     bne    RPRT_BP
  3163.  
  3164.     bsr    hw_IS_CHG    ; test for Disk change
  3165.     beq    RET_TRU
  3166.     bra    RET_FLS
  3167.  
  3168. ; -------------------------------------------------------------
  3169. B_hw_IS_PRO:
  3170.     bsr    FETCH_W        ; get drive number
  3171.     bne    B_hw_SEL_SIDX
  3172.     move.l    d1,d0
  3173.  
  3174.     cmp.l    a3,a5
  3175.     bne    RPRT_BP
  3176.  
  3177.     bsr    hw_IS_PRO    ; test for write protect
  3178.     beq    RET_TRU
  3179.     bra    RET_FLS
  3180.  
  3181. ; -------------------------------------------------------------
  3182. B_hw_IS_RDY:
  3183.     bsr    FETCH_W        ; get drive number
  3184.     bne    B_hw_SEL_SIDX
  3185.     move.l    d1,d0
  3186.  
  3187.     cmp.l    a3,a5
  3188.     bne    RPRT_BP
  3189.  
  3190.     bsr    hw_IS_RDY    ; check readiness of drive
  3191.     beq    RET_TRU
  3192.     bra    RET_FLS
  3193.  
  3194. ; -------------------------------------------------------------
  3195. B_hw_IS_TK0:
  3196.     bsr    FETCH_W        ; get drive number
  3197.     bne    B_hw_SEL_SIDX
  3198.     move.l    d1,d0
  3199.  
  3200.     cmp.l    a3,a5
  3201.     bne    RPRT_BP
  3202.  
  3203.     bsr    hw_IS_TK0    ; check if at track zero
  3204.     beq    RET_TRU
  3205.     bra    RET_FLS
  3206.  
  3207. ; -------------------------------------------------------------
  3208. B_hw_SEL_SIDE:
  3209.     bsr    FETCH_W        ; get drive number
  3210.     bne.s    B_hw_SEL_SIDX
  3211.     move.l    d1,d2
  3212.  
  3213.     bsr    FETCH_W        ; get drive side
  3214.     bne.s    B_hw_SEL_SIDX
  3215.  
  3216.     move.l    d2,d0        ; drive in d0, side in d1
  3217.  
  3218.     cmp.l    a3,a5
  3219.     bne    RPRT_BP
  3220.  
  3221.     bsr    hw_SEL_SIDE
  3222.     moveq    #0,d0
  3223.  
  3224. B_hw_SEL_SIDX:
  3225.     rts
  3226.  
  3227. ; -------------------------------------------------------------
  3228. B_hw_STEP_OUT:
  3229.     bsr    FETCH_W        ; get drive number
  3230.     bne.s    B_hw_STEP_OX
  3231.     move.l    d1,d0
  3232.  
  3233.     bsr    hw_STEP_OUT    ; increase track number
  3234.     moveq    #0,d0
  3235.  
  3236. B_hw_STEP_OX:
  3237.     rts
  3238.  
  3239. ; -------------------------------------------------------------
  3240. B_hw_STEP_IN:
  3241.     bsr    FETCH_W        ; get drive number
  3242.     bne.s    B_hw_STEP_IX
  3243.     move.l    d1,d0
  3244.  
  3245.     cmp.l    a3,a5
  3246.     bne    RPRT_BP
  3247.  
  3248.     bsr    hw_STEP_IN    ; decrease track number
  3249.     moveq    #0,d0
  3250.  
  3251. B_hw_STEP_IX:
  3252.     rts
  3253.  
  3254. ; -------------------------------------------------------------
  3255. B_hw_GO_TK0:
  3256.     bsr    hw_GO_TK0
  3257.     moveq    #0,d0
  3258.     rts
  3259.  
  3260. ; -------------------------------------------------------------
  3261. B_hw_MTR_OFF:
  3262.     bsr    FETCH_W        ; get drive number
  3263.     bne.s    B_hw_MTR_OFX
  3264.     move.l    d1,d0
  3265.  
  3266.     cmp.l    a3,a5
  3267.     bne    RPRT_BP
  3268.  
  3269.     bsr    hw_MTR_OFF    ; turn of drive motor
  3270.     moveq    #0,d0
  3271.  
  3272. B_hw_MTR_OFX:
  3273.     rts
  3274.  
  3275. ; -------------------------------------------------------------
  3276. B_hw_MTR_ON:
  3277.     bsr    FETCH_W        ; get drive number
  3278.     bne.s    B_hw_MTR_ONX
  3279.     move.l    d1,d0
  3280.  
  3281.     cmp.l    a3,a5
  3282.     bne.s    RPRT_BP
  3283.  
  3284.     bsr    hw_MTR_ON    ; turn on drive motor
  3285.     moveq    #0,d0
  3286.  
  3287. B_hw_MTR_ONX:
  3288.     rts
  3289.  
  3290. ; -------------------------------------------------------------
  3291. B_hw_WR_DSK:
  3292.     bsr    FETCH_L        ; address of buffer in a0
  3293.     bne.s    B_hw_WR_DSKX
  3294.     move.l    d1,a0
  3295.  
  3296.     bsr    FETCH_W        ; get drive number
  3297.     bne.s    B_hw_RD_DSKX
  3298.     move.l    d1,d3
  3299.  
  3300.     bsr    FETCH_W        ; get track number
  3301.     bne.s    B_hw_RD_DSKX
  3302.     move.l    d1,d2
  3303.  
  3304.     bsr    FETCH_W        ; get side number
  3305.     bne.s    B_hw_RD_DSKX
  3306.  
  3307.     move.l    d3,d0        ; drive in d0, side d1, track in d2
  3308.  
  3309.     cmp.l    a3,a5
  3310.     bne.s    RPRT_BP
  3311.  
  3312.     bsr    hw_WR_DSK    ; write buffer to drive
  3313.     moveq    #0,d0
  3314.  
  3315. B_hw_WR_DSKX:
  3316.     rts
  3317.  
  3318. ; -------------------------------------------------------------
  3319. B_hw_RD_DSK:
  3320.     bsr    FETCH_L        ; address of buffer in a0
  3321.     bne.s    B_hw_RD_DSKX
  3322.     move.l    d1,a0
  3323.  
  3324.     bsr    FETCH_W        ; get drive number
  3325.     bne.s    B_hw_RD_DSKX
  3326.     move.l    d1,d3
  3327.  
  3328.     bsr    FETCH_W        ; get track number
  3329.     bne.s    B_hw_RD_DSKX
  3330.     move.l    d1,d2
  3331.  
  3332.     bsr    FETCH_W        ; get side number
  3333.     bne.s    B_hw_RD_DSKX
  3334.  
  3335.     move.l    d3,d0        ; drive in d0, side d1, track in d2
  3336.  
  3337.     cmp.l    a3,a5
  3338.     bne.s    RPRT_BP
  3339.  
  3340.     bsr    hw_RD_DSK    ; read to buffer from drive
  3341.     moveq    #0,d0
  3342.  
  3343. B_hw_RD_DSKX:
  3344.     rts
  3345.  
  3346. ; -------------------------------------------------------------
  3347. B_hw_TIMER:
  3348.  
  3349.     bsr    FETCH_L        ; get count in ms
  3350.     bne.s    B_TIMERX
  3351.     move.l    d1,d0
  3352.  
  3353.     cmp.l    a3,a5
  3354.     bne.s    RPRT_BP
  3355.  
  3356.     bsr    hw_TIMER
  3357.     moveq    #0,d0
  3358.  
  3359. B_TIMERX:
  3360.     rts
  3361.  
  3362.     endc
  3363.  
  3364. ; -------------------------------------------------------------
  3365. RPRT_BP:
  3366.     moveq    #ERR.BP,d0
  3367.     rts
  3368.  
  3369. ; -------------------------------------------------------------
  3370. CPYMSG:
  3371.     dc.w    57
  3372.     dc.b    "Put SRC in flp1_ and DEST in flp2_"
  3373.     dc.b    " then press <ENTER>... ",0
  3374.  
  3375. DONMSG:
  3376.     dc.w    6
  3377.     dc.b    "done.",$0A
  3378.  
  3379. DRVMSG:
  3380.     dc.w    37
  3381.     dc.b    "Sorry, you need at least two drives.",$0A,0
  3382.  
  3383. ; -------------------------------------------------------------
  3384. ;    print string at (a1) to channel with id a0
  3385.  
  3386. IOSTRG:
  3387.     movem.l    d1-d3/a1-a2,-(a7)
  3388.  
  3389.     move.w    UT.MTEXT,a2
  3390.     jsr    (a2)
  3391.  
  3392.     movem.l    (a7)+,d1-d3/a1-a2
  3393.     rts
  3394.  
  3395.     ifd    debug
  3396.  
  3397. ; -------------------------------------------------------------
  3398. ;    print byte d0.l as HEX to channel with id a0
  3399.  
  3400. HEX20:
  3401.     swap    d0
  3402.     bsr    HEX10
  3403.     swap    d0
  3404.     bsr    HEX10
  3405.     rts
  3406.  
  3407. ; -------------------------------------------------------------
  3408. ;    print byte d0.w as HEX to channel with id a0
  3409.  
  3410. HEX10:
  3411.     ror.w    #8,d0
  3412.     bsr    HEX08
  3413.     rol.w    #8,d0
  3414.     bsr    HEX08
  3415.     rts
  3416.  
  3417. ; -------------------------------------------------------------
  3418. ;    print byte d0.b as HEX to channel with id a0
  3419.  
  3420. HEX08:
  3421.     movem.l    d0-d1,-(a7)
  3422.  
  3423.     moveq    #2,d1
  3424.  
  3425.     lsl.l    #8,d1
  3426.     move.b    d0,d1
  3427.     lsr.b    #4,d1
  3428.     and.b    #$F,d1
  3429.     add.b    #'0',d1
  3430.     cmp.b    #'9',d1
  3431.     ble.s    HEX081
  3432.     add.b    #7,d1
  3433.  
  3434. HEX081:
  3435.     lsl.l    #8,d1
  3436.     move.b    d0,d1
  3437.     and.b    #$F,d1
  3438.     add.b    #'0',d1
  3439.     cmp.b    #'9',d1
  3440.     ble.s    HEX082
  3441.     add.b    #7,d1
  3442.  
  3443. HEX082:
  3444.     move.l    d1,d0
  3445.     bsr    IOD0
  3446.  
  3447.     movem.l    (a7)+,d0-d1
  3448.     rts
  3449.  
  3450. IOD0:
  3451.     movem.l    a1,-(a7)
  3452.     move.l    d0,-(a7)
  3453.     move.l    a7,a1        ; address of string
  3454.     bsr    IOSTRG
  3455.     move.l    (a7)+,d0
  3456.     movem.l    (a7)+,a1
  3457.     rts
  3458.  
  3459.     endc
  3460.  
  3461. ; -------------------------------------------------------------
  3462. ; Entry: A3.L   pointer to first parameter
  3463. ;    A5.L   pointer to last parameter
  3464. ;
  3465. ; Exit:    A3.L   updated
  3466. ;    A5.L   updated
  3467. ;    D0.L...error code
  3468. ;    D1.W   result
  3469.  
  3470. FETCH_W:
  3471.     MOVEM.L    A1-A2,-(A7)
  3472.  
  3473.     MOVE.W    CA.GTINT,A2
  3474.     BSR.S    GET_ONE
  3475.     BNE.S    FETCH_WX
  3476.  
  3477.     MOVEQ    #0,D1
  3478.     MOVE.W    0(A6,A1.L),D1
  3479.     ADDQ.L    #2,A1
  3480.     MOVE.L    A1,BV_RIP(A6)
  3481.  
  3482. FETCH_WX:
  3483.     MOVEM.L    (A7)+,A1-A2
  3484.     TST.L    D0
  3485.     RTS
  3486.  
  3487. ; --------------------------------------------------------------
  3488. FETCH_L:
  3489.     MOVEM.L    A1-A2,-(A7)
  3490.  
  3491.     MOVE.W    CA.GTLIN,A2
  3492.     BSR.S    GET_ONE
  3493.     BNE.S    FETCH_LX
  3494.  
  3495.     MOVE.L    0(A6,A1.L),D1
  3496.     ADDQ.L    #4,A1
  3497.     MOVE.L    A1,BV_RIP(A6)
  3498.  
  3499. FETCH_LX:
  3500.     MOVEM.L    (A7)+,A1-A2
  3501.     TST.L    D0
  3502.     RTS
  3503.  
  3504. ; --------------------------------------------------------------
  3505. ;  This routine gets one parameter and returns it on the maths
  3506. ;  stack, pointed to by (A1).
  3507. ;
  3508. ; Entry: A2.L   routine to call (i.e. CA.GTINT)
  3509. ;    A3.L   pointer to first parameter
  3510. ;    A5.L   pointer to last parameter
  3511. ;
  3512. ; Exit:    A3.L   updated
  3513. ;    A5.L   updated
  3514. ;    A1.L   updated pointer to top of maths stack
  3515. ;    D0.L   error code
  3516.  
  3517. GET_ONE:
  3518.     MOVEM.L    D1-D6/A0/A2,-(A7)
  3519.  
  3520.     LEA    8(A3),A0
  3521.     CMP.L    A0,A5
  3522.     BLT.S    GET_ONEBp
  3523.  
  3524.     MOVE.L    BV_RIP(A6),A1
  3525.     MOVE.L    A5,-(A7)
  3526.     MOVE.L    A0,A5
  3527.     MOVE.L    A5,-(A7)
  3528.     JSR    (A2)
  3529.     MOVEM.L    (A7)+,A0/A5
  3530.  
  3531.     TST.L    D0
  3532.     BNE.S    GET_ONEX
  3533.  
  3534.     MOVE.L    A0,A3
  3535.     MOVE.L    A1,BV_RIP(A6)
  3536.  
  3537.     BRA.S    GET_ONEX
  3538.  
  3539. GET_ONEBp:
  3540.     MOVEQ    #ERR.BP,D0
  3541.  
  3542. GET_ONEX:
  3543.     MOVEM.L    (A7)+,D1-D6/A0/A2
  3544.     TST.L    D0
  3545.     RTS
  3546.  
  3547. ; --------------------------------------------------------------
  3548. ;  get channel parameter
  3549.  
  3550. ; Entry: A3.L   pointer to first parameter
  3551. ;    A5.L   pointer to last parameter
  3552.  
  3553. ; Exit:    A0.L   CH.ID (default d1)
  3554. ;    A2.L   CH.BASE
  3555. ;    A3.L   updated
  3556. ;    A5.L   updated
  3557. ;    D0.L   error code
  3558. ;    D1.L   default channel #
  3559.  
  3560. GET_CH:
  3561.     MOVEM.L    D1/D3/A1,-(A7)
  3562.  
  3563.     MOVE.L    BV_RIP(A6),A1
  3564.     CMP.L    A3,A5
  3565.     BEQ.S    GET_CH1
  3566.  
  3567.     BTST    #7,1(A6,A3.L)
  3568.     BEQ.S    GET_CH1
  3569.  
  3570.     BSR    FETCH_W
  3571.     BNE.S    GET_CHX
  3572.  
  3573. GET_CH1:
  3574.     MULU    #$28,D1
  3575.     ADD.L    BV_CHBAS(A6),D1
  3576.     CMP.L    BV_CHP(A6),D1
  3577.     BGE.S    GET_CHNO
  3578.  
  3579.     MOVE.L    D1,A2
  3580.     MOVE.L    0(A6,A2.L),A0
  3581.     MOVE.W    A0,D1
  3582.     BMI.S    GET_CHNO
  3583.  
  3584.     MOVEQ    #0,D0
  3585.     BRA.S    GET_CHX
  3586.  
  3587. GET_CHNO:
  3588.     MOVEQ.L    #ERR.NO,D0
  3589.  
  3590. GET_CHX:
  3591.     MOVEM.L    (A7)+,D1/D3/A1
  3592.     RTS
  3593.  
  3594. ; -------------------------------------------------------------
  3595. ;  return true or false back to BASIC
  3596.  
  3597. RET_FLS:
  3598.     moveq    #0,d0
  3599.     bra.s    RET_W
  3600.  
  3601. RET_TRU:
  3602.     moveq    #1,d0
  3603.  
  3604. ; --------------------------------------------------------------
  3605. ;  return word value to BASIC
  3606.  
  3607. RET_W:
  3608.     move.l    d0,d4
  3609.     moveq.l    #2,d1
  3610.     move.w    BV.CHRIX,a2
  3611.     jsr    (a2)
  3612.     move.l    d4,d0
  3613.  
  3614.     move.l    BV_RIP(a6),a1    ; Get arith stack pointer
  3615.     subq    #2,a1        ; room for 2 bytes
  3616.     move.l    a1,BV_RIP(a6)
  3617.     move.w    d0,0(a6,a1.l)    ; Put int number on stack
  3618.     moveq.l    #3,d4        ; set Integer type
  3619.     moveq.l    #0,d0        ; no errors
  3620.     rts
  3621.  
  3622. ; -------------------------------------------------------------
  3623. ;    return long Integer to BASIC
  3624.  
  3625. RET_L:
  3626.     move.l    d0,d4
  3627.     moveq.l    #6,d1
  3628.     move.w    BV.CHRIX,a2
  3629.     jsr    (a2)
  3630.     move.l    d4,d1
  3631.  
  3632.     BSR    CONV_L2F
  3633.     SUBQ.L    #6,BV_RIP(A6)
  3634.     MOVE.L    BV_RIP(A6),A1
  3635.     MOVE.W    D0,0(A6,A1.L)
  3636.     MOVE.L    D1,2(A6,A1.L)
  3637.     MOVEQ.L    #2,D4
  3638.     MOVEQ.L    #0,D0
  3639.     RTS
  3640.  
  3641. ; -------------------------------------------------------------
  3642. ;  convert long Integer to floating point form.
  3643. ;  Entry: d1.l = long int
  3644. ;  Exit:  d0.w = exponent
  3645. ;     d1.l = mantissa
  3646.  
  3647. CONV_L2F:
  3648.     MOVE.L    D1,D0
  3649.     BEQ.S    CONV_L2FX
  3650.  
  3651.     MOVE.W    #$81F,D0
  3652.     MOVE.L    D1,-(A7)
  3653.  
  3654. CONV_L2F1:
  3655.     ADD.L    D1,D1
  3656.     BVS.S    CONV_L2F2
  3657.  
  3658.     SUBQ.W    #1,D0
  3659.     MOVE.L    D1,(A7)
  3660.     BRA    CONV_L2F1
  3661.  
  3662. CONV_L2F2:
  3663.     MOVE.L    (A7)+,D1
  3664.  
  3665. CONV_L2FX:
  3666.     RTS
  3667.  
  3668. ; --------------------------------------------------------------
  3669. */endfile
  3670.