home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ENTERPRS / CPM / UTILS / A / BIOSR4.ARC / CXDISK.ASM < prev    next >
Assembly Source File  |  1987-04-26  |  31KB  |  1,641 lines

  1. ; changes made to this module were to remove test for 
  2. ; disk status line (it is displayed all of the time now), and
  3. ; to remove unecessary disk definitions ( only A, B, and C now)
  4. ; The virtual drive E: has been removed,  and the 40 column disk status
  5. ; display has been removed (previously it was always running no matter
  6. ; what.
  7. ;
  8. ; compare with an original copy of CXDISK.ASM if you want to
  9. ; find what the changes were
  10. ;
  11. ;  User assumes _ALL_ liability for use of this module.  Original
  12. ;  copyright is still maintained by Commodore
  13. ;
  14. ;
  15. ;
  16. ;
  17. ;    *****************************************
  18. ;    *                    *
  19. ;    *    Commodore Disk    Controller    *
  20. ;    *    Module for CP/M 3.0 BIOS    *
  21. ;    *                    *
  22. ;    *****************************************
  23. ;
  24. ;
  25. ;
  26.     title 'CXDISK   Commodore C-128 Disk Controller    26 April 87'
  27.  
  28.  
  29.  
  30.  
  31. ; CP/M 3 Disk definition macros
  32.  
  33.     maclib    cpm3
  34.  
  35.     maclib    z80
  36.  
  37. ; C-128 system equates
  38.  
  39.     maclib    cxequ
  40.  
  41.     page
  42.  
  43. ; Disk drive dispatching tables for linked BIOS
  44.  
  45.     public    cmdsk0,cmdsk1,cmdsk2
  46.  
  47. ; System Control Block variables
  48.     extrn    @ermde        ; BDOS error mode
  49.  
  50. ; Utility routines in standard BIOS
  51.     extrn    ?wboot        ; warm boot vector
  52.     extrn    ?pmsg        ; print message @<HL> up to 00
  53.                 ; saves <BC> & <DE>
  54.     extrn    ?pdec        ; print binary number in <HL> from 0 to 65535
  55.     extrn    ?pderr        ; print BIOS disk error header
  56.     extrn    ?conin,?cono    ; con in and out
  57.     extrn    ?const        ; get console status
  58.     extrn    ?sctrn        ; sector translation routine
  59.     extrn    @covec
  60.  
  61. ;    status line calls
  62.  
  63.     extrn    ?save,?recov,?stat
  64.  
  65. ; System function call
  66.     extrn    ?kyscn
  67.     extrn    ?fun65
  68.     extrn    ?bank
  69.     extrn    ?di$int
  70.  
  71.     public    ?dskst
  72.     public    ?dkmov
  73.     extrn    ?stat
  74.  
  75.     page
  76. ;
  77. ; Initialization entry point.
  78. ; called for first time initialization.
  79. ;
  80.     DSEG
  81. init$154X:
  82.     xra    a
  83.     sta    fast
  84.     lxi    h,MFM$table
  85.     shld    MFM$tbl$ptr
  86.     ret
  87.  
  88.  
  89.     page
  90. ;
  91. ; This entry is called when a logical drive is about to
  92. ;  be logged into for the purpose of density and type determination.
  93. ;  It may adjust the parameters contained in the disk
  94. ;  parameter header pointed to by <DE>
  95. ;
  96.     DSEG
  97. ;
  98. ;    if disk type GCR or drive type 1541
  99. ;       if 1st sector has 'CBM' (1st 3 bytes)
  100. ;          if last byte = -1 (0FFh)
  101. ;             set C128 double sided
  102. ;          else
  103. ;             set C128 single sided
  104. ;          endif
  105. ;       else
  106. ;          set C64 type
  107. ;       endif
  108. ;    else (must be MFM)
  109. ;       TEST MFM
  110. ;    endif
  111. ;
  112. login$154X:
  113.     call    get$drv$info    ; set the drive to check (DPH$pointer set)
  114.  
  115.     mvi    a,vic$test
  116.     call    ?fun65
  117.     mov    b,a
  118.     ani    0ch
  119.     cpi    0ch
  120.     jrz    GCR$type    ; jump if not a 1571
  121.  
  122.     mov    a,b
  123.     rlc
  124.     jrc    MFM$type
  125.  
  126.     page
  127. ;
  128. ;
  129. ;
  130. GCR$type:
  131.     lhld    DPH$pointer
  132.     dcx    h
  133.     mvi    m,dsk$c64
  134.     lxi    d,dpb$c64$cpm    ; set DPB to C64
  135.     call    set$dpb$only
  136.  
  137.     xra    a
  138.     sta    vic$sect    ; set track 1 sector 0 (1st sector
  139.     inr    a        ; on the disk)
  140.     sta    vic$trk
  141.  
  142.     lxi    h,@buffer
  143.     shld    local$DMA    ; move DMA pointer to disk buffer
  144.     call    login$rd
  145.     ana    a        ; read error ?
  146.     rnz            ; yes, just return
  147.  
  148.     RCALL    FR$check$CBM
  149.     rnz            ; return if not 'CBM'
  150.                 ; A=0FFh if double sided
  151.     inr    a
  152.  
  153.     lhld    DPH$pointer
  154.     dcx    h        ; does not affect flags
  155.     mvi    m,dsk$c128
  156.  
  157.     lxi    d,dpb$c128$SS
  158.     jrnz    set$dpb$only
  159.  
  160.     lxi    d,dpb$c128$DS
  161.  
  162.     page
  163. ;
  164. ;
  165. ;
  166. set$dpb$only:
  167.     lxi    b,0        ; set sector translation to zero
  168. set$format:
  169.     lhld    DPH$pointer
  170.     mov    m,c
  171.     inx    h
  172.     mov    m,b        ; install sector translation
  173.     lxi    b,25-1        ; ofset to DPB
  174.     dad    b        ; HL points to DPB now
  175.     lxi    b,17        ; dpb size
  176.     xchg            ; move to DPB location
  177.     ldir
  178.     ret
  179.  
  180.  
  181.     page
  182. ;
  183. ;    TEST MFM()
  184. ;    save number bytes/sector
  185. ;       if double sided
  186. ;          mark two sided
  187. ;       endif
  188. ;       find start and end sector numbers
  189. ;       scan table of disk for match (if more then 1 match ask user) 
  190. ;
  191. MFM$type:
  192.     mvi    c,01100000b
  193.     ana    c            ; A = status(trk1) shifted left 1 
  194.     push    psw            ; save in case bad query
  195.     push    b            ; save BC
  196.  
  197.     call    get$max$num$B        ; used to set the pointer only
  198.     mov    b,m            ; get size, and disk lock flag
  199.     inx    h
  200.     mov    a,m
  201.     inx    h
  202.     mov    h,m            ; get last MFM$mactch$ptr
  203.     mov    l,a
  204.     mov    a,b            ; get lock flag in A
  205.     ani    80h            ; lock bit set ?
  206.     sta    lock$flag        ;   (save old lock status)
  207.     shld    last$match        ; save last match pointer
  208.     jrz    not$$locked$entry    ; yes, then set same disk type
  209. ; set$locked$entry
  210.     xra    a
  211.     sta    lock$flag
  212.     mvi    c,0B0h
  213.     lda    vic$data        ; get sector size info
  214.     ana    c
  215.     mov    b,a            ; save disk sector size info
  216.     xchg                ; save HL
  217.     lhld    DPH$pointer
  218.     dcx    h
  219.     mov    a,c
  220.     ana    m            ; get old disk sector size
  221.     cmp    b            ; are they the same?
  222.     jrnz    not$locked$entry    ; no, then unlock disk anyway
  223.  
  224.     xchg                ; get last match pointer (in DE)
  225.     pop    psw            ; yes, remove two data elements 
  226.     pop    psw            ; ..save on stack
  227.     jr    set$this$entry
  228.  
  229. not$locked$entry:
  230.     lxi    h,MFM$match$tbl        ; clear Match table
  231.     shld    MFM$cur$ptr
  232.     lxi    d,MFM$match$tbl+1
  233.     mvi    m,0
  234.     lxi    b,(MFM$tbl$entries*2)-1+1+1    ; table, offset and count
  235.     ldir
  236.     mvi    a,4
  237.     sta    vic$trk            ; do query on track 4
  238.     mvi    a,vic$query
  239.     call    ?fun65
  240.     pop    b            ; recover BC
  241.     ani    0eh            ; query error ?
  242.     jrnz    query$error        ; yes, use only bits 5 and 6 
  243.     lda    @buffer            ; get trk 4 status
  244.     mov    b,a            ; save in B
  245.     ani    0eh            ; trk 4 status error ?
  246.     jrnz    query$error        ; yes, use only bits 5 and 6
  247.     mov    a,b            ; recover B (trk 4 status)
  248.     add    a            ; shift left
  249.     ana    c            ; mask sector size bits
  250.     mov    b,a
  251.     pop    psw            ; get trk 1 sector size bits
  252.     cmp    b            ; same as trk 4 sector size?
  253.     mvi    c,01111111b
  254.     jrz    trk$1$trk$4        ; yes, (then test for mult format)
  255.     mvi    a,80h            ; set MSB to mean mult format
  256.     add    b            ; ..(track 0 different sector size
  257.                     ; ..then track 4) 
  258.     mov    b,a            ; save in B
  259.     mvi    c,11111111b
  260. trk$1$trk$4:
  261.     lda    @buffer+1        ; get number of sectors/track
  262.     sui    4            ; remove 4 to extend the range
  263.     add    a            ; shift    left
  264.     add    b            ; combine with rest of mask
  265.     mov    b,a            ; save in B for now
  266.  
  267.     lda    @buffer+3        ; minimum sector number
  268.     add    b            ; add in start sector #
  269.     push    psw            ; save on stack for a moment
  270.  
  271. query$error:
  272.     pop    psw            ; get value to match 
  273.     ana    c            ; test only those bits in the mask
  274.  
  275.     lhld    MFM$tbl$ptr
  276.     mvi    b,MFM$tbl$entries
  277. check$next:
  278.     push    b            ; save BC for a moment
  279.     mov    b,a            ; move compare value to 
  280.     mov    a,m            ; get type info
  281.     ana    c            ; test only the good info
  282.     cmp    b            ; match the current type byte
  283.     mov    a,b            ;   (recover A)
  284.     pop    b            ;   (recover BC)
  285.     jrnz    not$found        ; no, do not queue data
  286.                     ; yes queue table entry address
  287.  
  288.     xchg                ; save adr in DE
  289.     lhld    MFM$cur$ptr
  290.     mov    m,e
  291.     inx    h
  292.     mov    m,d
  293.     inx    h
  294.     shld    MFM$cur$ptr
  295.     lxi    h,MFM$count
  296.     inr    m            ; add one to counter
  297.     xchg
  298.  
  299.     page
  300. ;
  301. ;
  302. not$found:
  303.     lxi    d,32            ; table entry size
  304.     dad    d
  305.     djnz    check$next
  306.  
  307.     lda    MFM$count        ; number of matches in table 
  308.     ana    a            ; test for zero
  309.     jz    tell$user$no$entry    ; none, tell the user 
  310.  
  311.     dcr    a            ; only one ?
  312.     jrnz    user$select        ; no, go check with user (which one)
  313.     lhld    MFM$match$tbl        ; yes, use the only one found
  314.  
  315. ;
  316. ;    install data form pointer in HL
  317. ;
  318. set$this$entry:
  319.     push    h        ; save table pointer
  320.     inx    h
  321.     mov    a,m        ; get type info. 
  322.     xchg            ; save table address in DE
  323.     lhld    DPH$pointer
  324.     dcx    h
  325.     mov    m,a        ; save type code
  326.     xchg            ; get table adr to HL
  327.     inx    h        ; HL points to sector translation table 
  328.     mov    c,m        ; ..zero if none
  329.     inx    h
  330.     mov    b,m
  331.     inx    h        ; HL points to DPB
  332.     xchg            ; DE points to DPB (HL trash)
  333.     call    set$format
  334.     mov    b,m        ; get the number of sect/trk from MFM table
  335.     lda    lock$flag    ; get the current lock flag value
  336.     ora    b        ; combine with sect/trk
  337.     xchg            ; HL=to adr,  DE=from adr
  338.     mov    m,a        ; install sect/trk and lock flag
  339.     pop    d        ; recover table pointer
  340.     inx    h
  341.     mov    m,e
  342.     inx    h
  343.     mov    m,d        ; save MFM table pointer at end of DPH
  344.     ret
  345.  
  346.     page
  347. ;
  348. ;    let the user select the Disk type s/he wants
  349. ;
  350. user$select:
  351.     inr    a            ; number of entries to try to match
  352.     mov    b,a            ; set in B as loop count
  353.     lhld    last$match        ; get value to match with
  354.     mov    d,h
  355.     mov    e,l            ; last match pointer is in DE
  356.  
  357.     lxi    h,MFM$match$tbl
  358.     shld    MFM$cur$ptr
  359.     mvi    c,0            ; start offset at zero
  360.  
  361. try$next$format:
  362.     mov    a,e
  363.     cmp    m
  364.     inx    h
  365.     jrnz    not$last$match
  366.     mov    a,d
  367.     cmp    m
  368.     jrnz    not$last$match
  369. ;
  370. ; match, set pointer
  371. ;
  372.     mov    a,c            ; get offset in A
  373.     push    psw
  374.     call    save$dsk$window
  375.     pop    psw
  376.     jr    set$offset
  377.  
  378. not$last$match:
  379.     inx    h            ; each pointer uses two bytes 
  380.     inr    c            ; advance the index
  381.     djnz    try$next$format        ; test for more, loop if so
  382.  
  383.     call    save$dsk$window
  384.  
  385.     lhld    MFM$cur$ptr
  386. user$loop:
  387.     mov    e,m            ; HL=(MFM$cur$ptr)
  388.     inx    h
  389.     mov    d,m
  390.     lxi    h,22            ; offset to NAME field
  391.     dad    d            ; point to Disk name
  392.     call    dsk$window$old
  393.  
  394. dsk$user$sel$wait:
  395.     call    ?kyscn
  396.     inr    b            ; test for key pressed
  397.     jrz    dsk$user$sel$wait
  398.     dcr    b            ; adjust back
  399.     mov    a,b            ; move matrix position to A
  400.     cpi    SF$exit
  401.     jrnz    CK$dsk$user$rt
  402.  
  403.     mov    a,c
  404.     ani    4            ; control key down ?
  405.     jrz    no$cntr$key        ; no, don't lock this selection
  406.     mvi    a,80h            ; yes, lock disk type to this drive
  407. no$cntr$key:
  408.     sta    lock$flag        ;
  409.     call    dsk$window$remove
  410.     lhld    MFM$cur$ptr
  411.     mov    e,m
  412.     inx    h
  413.     mov    d,m
  414.     xchg
  415.     jr    set$this$entry
  416.  
  417.     page
  418. ;
  419. ;
  420. ;
  421. CK$dsk$user$rt:
  422.     cpi    SF$right        ;
  423.     jrnz    CK$dsk$user$lf
  424.  
  425. ; move window down
  426.     lda    MFM$count        ; get number of items in list
  427.     mov    b,a            ; save in B
  428.     lda    MFM$offset        ; get current position
  429.     inr    a            ; advance position
  430.     cmp    b            ; at last position ? (n-1+1 =count)
  431.     jrnz    set$offset        ; no, then use A as new position
  432.     xra    a            ; yes, move back to start
  433.     jr    set$offset
  434.     
  435. CK$dsk$user$lf:
  436.     cpi    SF$left            ;
  437.     jrnz    dsk$user$sel$wait
  438.  
  439. ; move window up
  440.     lda    MFM$offset
  441.     dcr    a            ; back up offset (under flow?)
  442.     jp    set$offset        ; result positive, jump
  443.     lda    MFM$count        ; get last item number
  444.     dcr    a            ; pointer is 0 to n-1 (not 1 to n)
  445. set$offset:
  446.     sta    MFM$offset        ; set new list offset
  447.     inr    a            ; add one to adjust for DCR below
  448.     lxi    h,MFM$match$tbl        ; set to the beginning
  449.  
  450. adjust$dsk$loop:
  451.     shld    MFM$cur$ptr        ; set pointer here !
  452.     dcr    a            ; at offset yet?
  453.     jrz    user$loop        ; yes, go display name
  454.     inx    h
  455.     inx    h
  456.     jr    adjust$dsk$loop
  457.  
  458.     page
  459. ;
  460. ;
  461. ;
  462. tell$user$no$entry:
  463.     lda    vic$data        ; get disk test status
  464.     ani    0b0h            ; save only sector size and MFM flag
  465.     lhld    DPH$pointer
  466.     dcx    h
  467.     mov    m,a            ; set disk size and Type0 (MFM)
  468.  
  469.     lxi    h,dsk$window*256+buff$pos
  470.     lxi    d,no$dsk$msg
  471. disp$msg$DE$HL:
  472.     call    dsk$window$new
  473. dsk$no$entry$wait:
  474.     call    ?kyscn
  475.     inr    b
  476.     jrz    dsk$no$entry$wait
  477.     dcr    b
  478.     mov    a,b
  479.     cpi    SF$exit
  480.     jrnz    dsk$no$entry$wait
  481. ;    jr    dsk$window$remove
  482.  
  483.     page
  484. ;
  485. ;
  486. ;
  487. dsk$window$remove:
  488.     lhld    window$info
  489.     mov    b,h
  490.     mov    c,l
  491.     jmp    ?recov
  492. ;
  493. ;
  494. ;
  495. save$dsk$window:
  496.     lxi    h,dsk$window*256+buff$pos    ; H=size l=pos
  497.     shld    window$info
  498.     mov    b,h
  499.     mov    c,l
  500.     jmp    ?save
  501. ;
  502. ;
  503. ;
  504. dsk$window$new:
  505.     shld    window$info
  506.     xchg
  507.     mov    b,d
  508.     mov    c,e
  509.     push    h
  510.     call    ?save
  511.     pop    h
  512.  
  513. dsk$window$old:
  514.     lda    window$info        ; get start index
  515.     inr    a
  516.     mov    c,a            ; place in C
  517.  
  518. dsk$out$next:
  519.     push    h
  520.     lhld    window$info
  521.     mov    a,h
  522.     add    l            ; compute max index (start+size)
  523.     dcr    a            ; ..less 1
  524.     pop    h
  525.     cmp    c
  526.     rz    
  527.     mov    b,m
  528.     call    dsk$B$out
  529.     inx    h
  530.     jr    dsk$out$next
  531.  
  532. ;
  533. ;
  534. ;
  535. dsk$B$out:
  536.     mvi    a,01000000b            ; set reverse video attr
  537.     push    b
  538.     push    h
  539.     call    ?stat                ; display space
  540.     pop    h
  541.     pop    b                ; recover count
  542.     inr    c
  543.     ret
  544.  
  545.     page
  546. ;
  547. ; disk READ and WRITE entry points.
  548. ; These entries are called with the following arguments:
  549. ;    relative drive number in @rdrv (8 bits)
  550. ;    absolute drive number in @adrv (8 bits)
  551. ;    disk transfer address in @dma (16 bits)
  552. ;    disk transfer bank    in @dbnk (8 bits)
  553. ;    disk track address    in @trk (16 bits)
  554. ;    disk sector address    in @sect (16 bits)
  555. ;    pointer to XDPH in <DE>
  556. ;
  557. ;   return with an error code in <A>
  558. ;     A=0    no errors
  559. ;     A=1    non-recoverable error
  560. ;    A=2    disk write protected
  561. ;    A=FF    media change detected
  562. ;
  563.     DSEG
  564. read$154X:
  565.     call    get$drv$info
  566.     jm    mfm$rd
  567.     call    set$up$GCR        ; compute effective track and sector
  568. login$rd:
  569.     lda    vic$drv
  570.     mov    b,a
  571.     lda    fast            ; get fast flags
  572.     ana    b            ; isolate fast bit for this drive
  573.     jrnz    rd$fast            ; go handle fast drive
  574. rd$slow:
  575.     mvi    a,vicrd            ; read a sector of data (A=1)
  576.     call    dsk$fun            ; a=0 if no errors
  577.     jnz    test$error        ; check for disk error or media change
  578. ;
  579. ;
  580. ;
  581. buf$move:
  582.     xra    a            ; set direction to read
  583.     call    ?dkmov            ; go move buffer to DMA
  584.     lda    sect$cnt
  585.     ana    a
  586.     rz                ; a=0 means not read errors
  587.     call    set$up$next
  588.     jr    rd$slow
  589.  
  590.     page
  591. ;
  592. ;    A=drive type info
  593. ;
  594. mfm$rd:
  595.     call    set$up$MFM
  596.  
  597. rd$fast:
  598.     mvi    a,vic$rd$f
  599.     call    dsk$fun            ; go read the disk
  600.  
  601.     ani    0eh            ; mask off error bits
  602.     jrnz    test$error
  603.  
  604.     call    get$sector$size
  605.     inr    d
  606.     inr    e            ; adjust count for pre-decrement
  607.  
  608.     call    ?di$int
  609.     lxi    b,0DD00h        ; D2PRA
  610.     inp    a            ; get current clock polarity 
  611.     xri    10h            ; toggle clk$bit
  612.     outp    a            ; to have status sent (extra clock
  613.                     ; supplied by rd$1571$data for multi
  614.                     ; sector transfers)
  615.     lda    vic$count
  616. rd$multi$sect:
  617.     push    psw
  618.     push    d        ; save the sector size
  619.     call    rd$1571$data    ; read disk data to DMA address
  620.     pop    d
  621.  
  622.     lda    vic$data
  623.     ani    0eh
  624.     jrnz    test$error$pop    ; A=0 if no errors
  625.     pop    psw
  626.     dcr    a
  627.     jrnz    rd$multi$sect
  628.     ei
  629.     lda    sect$cnt
  630.     ana    a        ; any sectors left to read
  631.     jrz    done$rd$1571
  632.  
  633.     call    set$up$next
  634.     jr    rd$fast
  635.  
  636. done$rd$1571:
  637.     lxi    b,0DD00h        ;   D2PRA
  638.     inp    a
  639.     ani    not(10h)        ; set clk$bit hi
  640.     outp    a
  641.     xra    a            ; A=0 for no errors
  642.     ret
  643.  
  644.  
  645.     page
  646. ;
  647. ;
  648. ;
  649. write$154X:
  650.     call    get$drv$info
  651.     jm    mfm$wr
  652.     call    set$up$GCR
  653.     lda    vic$drv
  654.     mov    b,a
  655.     lda    fast            ; get fast flags
  656.     ana    b            ; isolate fast bit for this drive
  657.     jrnz    wr$fast$drive        ; go handle fast drive
  658. wr$slow:
  659.     mvi    a,-1            ; set direction to write
  660.     call    ?dkmov            ; go move DMA to buffer
  661.  
  662.     mvi    a,vicwr            ; write a sector of data
  663.     call    dsk$fun            ; a=0 if no errors
  664.     ani    0eh
  665.     jrnz    test$error
  666.     lda    sect$cnt
  667.     ana    a
  668.     rz
  669.     call    set$up$next
  670.     jr    wr$slow
  671.  
  672. test$error$pop:
  673.     pop    psw
  674. test$error:
  675.     ei
  676.     lda    vic$data
  677.     ani    0fh            ; check for disk error or media change
  678.     cpi    0bh            ; disk change ?
  679.     jrz    change$error
  680.     cpi    08h            ; test for write protect error
  681.     jrz    write$prot$error
  682.  
  683.     mvi    a,1            ;  get general error flag
  684.     ret
  685.  
  686. ;
  687. ;
  688. write$prot$error:
  689.     mvi    a,2
  690.     ret
  691.  
  692. ;
  693. ;
  694. change$error:
  695.     mvi    a,-1
  696.     ret
  697.  
  698.     page
  699. ;
  700. ;
  701. ;
  702. mfm$wr:
  703.     call    set$up$MFM
  704. wr$fast$drive:
  705.     mvi    a,vic$wr$f
  706.     call    dsk$fun            ; go send the write command
  707.  
  708.     call    get$sector$size        ; setup DMA adr and transfer count
  709.     lda    vic$count
  710. wr$multi$sect:
  711.     push    psw
  712.     push    d            ; save sector size
  713.     call    wr$1571$data        ; write data to disk from DMA address
  714.     pop    d
  715.     ani    0eh
  716.     jrnz    test$error$pop
  717.     pop    psw
  718.     dcr    a
  719.     jrnz    wr$multi$sect
  720.  
  721.     ei
  722.     lda    sect$cnt
  723.     ana    a
  724.     rz                ; return if no errors (A=0)
  725.     call    set$up$next
  726.     jr    wr$fast$drive
  727.  
  728.     page
  729. ;
  730. ;
  731. ;
  732. get$drv$info:
  733.     lhld    @dma
  734.     shld    local$dma
  735.     xchg
  736.     shld    DPH$pointer
  737.  
  738.     lda    @adrv            ; get drive number (0 to F)
  739.     dcx    h            ; point at drive mask
  740.     dcx    h
  741.     mov    a,m            ; get drive mask
  742.     mov    b,a            ; save in B
  743.     sta    vic$drv            ; save vic drive # (values 1,2,4,8)
  744.  
  745.     inx    h            ; point at disk type
  746.     xra    a
  747.     sta    sect$cnt        ; clear the count
  748.     inr    a
  749.     sta    vic$count
  750.     mov    a,m            ; get disk type
  751.     ana    a
  752.     ret
  753.  
  754. ;
  755. ;    
  756. ;
  757. ;
  758. get$max$num$b:
  759.     lhld    DPH$pointer
  760.     lxi    b,42            ; offset to number of sectors on track
  761.     dad    b
  762.     mov    a,m            ; get number sectors/track/side
  763.     ani    1fh
  764.     mov    b,a
  765.     ret
  766. ;
  767. ;
  768. ;
  769. get$sector$size:
  770.     lhld    DPH$pointer
  771.     dcx    h
  772.     mov    a,m            ; disk type in B (bit 5,4 size info)
  773.     rrc                ; ..00 = 080h byte sectors
  774.     rrc                ; ..01 = 100h byte sectors
  775.     rrc                ; ..10 = 200h byte sectors
  776.     rrc                ; ..11 = 400h byte sectors
  777.     ani    3
  778.     jrz    set$128
  779.     jpo    not$3            ; jump if (A=) 01b or 10b
  780.     inr    a            ; make A = 4
  781. not$3:
  782.     mvi    e,0            ; set E to zero
  783.     mov    d,a            ; set sector size (1,2 or 4)
  784. get$DMA:
  785.     lhld    local$DMA        ; get the current DMA pointer
  786.     ret
  787.  
  788. set$128:
  789.     lxi    d,128
  790.     jr    get$DMA 
  791.  
  792.     page
  793. ;
  794. ;
  795. ;
  796.     DSEG
  797. set$up$GCR:
  798.     cpi    dsk$c128
  799.     jnz    tst$c64
  800.  
  801.     mvi    a,4
  802.     sta    sect$cnt
  803.     lxi    h,sect$buffer
  804.     shld    sect$buf$ptr
  805.  
  806.     lhld    @trk            ; 1 K sector pointer 
  807.     dad    h
  808.     dad    h            ; make 256 byte pointer
  809. ;
  810. ;    build a list of tracks and sectors
  811. ;
  812. next$sect:
  813.     shld    @trk
  814.     RCALL    FR$trk$sect
  815.     lhld    vic$trk            ; get trk(L) and sector(H) to HL
  816.     xchg
  817.     lhld    sect$buf$ptr
  818.     mov    m,e
  819.     inx    h
  820.     mov    m,d
  821.     inx    h
  822.     shld    sect$buf$ptr
  823.     lhld    @trk
  824.     inr    l            ; update saved above at next$sect
  825.     mov    a,l
  826.     ani    3
  827.     jrnz    next$sect
  828. ;
  829. ;    check list of trk-sectors for number of sectors on this trk
  830.     lxi    h,sect$buffer
  831.     shld    sect$buf$ptr
  832.     lda    vic$drv
  833.     mov    b,a
  834.     lda    fast
  835.     ana    b            ; drive type 1571
  836.     jrz    handle$1541        ; no, handle as 1541
  837.  
  838.     lda    sect$cnt        ; number of sectors to rd/wr
  839.     mov    b,a
  840.     inx    h
  841.     mov    a,m            ; get 1st sector #
  842.     sta    vic$sect
  843.     dcx    h
  844.     mov    a,m            ; get 1st track #
  845.     sta    vic$trk
  846.  
  847. try$next:
  848.     cmp    m            ; test for same trk #
  849.     jrnz    exit$no$match
  850.     inx    h
  851.     inx    h            ; advance to next trk
  852.     shld    sect$buf$ptr
  853.     djnz    try$next    
  854.  
  855. exit$no$match:
  856.     lda    sect$cnt        ; number of sectors to rd/wr
  857.     sub    b            ; remove number left
  858.                     ; (leaving number matched)
  859.     sta    vic$count        ; save number to read
  860.     mov    a,b            ; get remaining count
  861.     sta    sect$cnt        ; save remaining count
  862.     ret
  863.  
  864.  
  865. set$up$next:
  866.     lda    vic$count        ; get number of sectors read
  867.     lhld    local$DMA        ; get current DMA pointer
  868.     add    h            ; advance pointer by number of
  869.     mov    h,a            ; sectors read
  870.     shld    local$DMA
  871. handle$1541:
  872.     lhld    sect$buf$ptr
  873.     mov    a,m
  874.     sta    vic$trk
  875.     inx    h
  876.     mov    a,m
  877.     sta    vic$sect
  878.     inx    h
  879.     shld    sect$buf$ptr
  880.     lda    vic$drv
  881.     mov    b,a
  882.     lda    fast
  883.     ana    b
  884.     jrz    set$up$next$slow
  885.     lda    sect$cnt
  886.     sta    vic$count
  887.     xra    a            ; two reads max with fast drive
  888.     jr    set$up$next$exit
  889.  
  890. set$up$next$slow:
  891.     lda    sect$cnt
  892.     dcr    a
  893. set$up$next$exit:
  894.     sta    sect$cnt
  895.     ret
  896.  
  897. tst$c64:
  898.     cpi    dsk$c64    
  899.     jrnz    tst$none    ; compute adjusted track number
  900. ;
  901. ;    this routine will adjust the track number if necessary.
  902. ;    The C64 CP/M disk has the C64 directory in the center
  903. ;    of the disk. This routine checks and adds one to the track
  904. ;    number if we have reached or passed the directory track. 
  905. ;    An additional offset of is added to make the track number
  906. ;    range from 1 to N+1 instead of 0 to N.
  907. ;
  908. set$up$c64:
  909.     lda    @trk
  910.     inr    a
  911.     cpi    dir$track    ; carry=1 if A < dir$track
  912.     cmc            ; add one if dir$track or more (carry not set)
  913.     aci    0        ; add the carry bit in
  914.  
  915. set$up$cont:
  916.     sta    vic$trk
  917.     lda    @sect
  918.     sta    vic$sect
  919.     ret
  920. ;
  921. ;    This format is for direct track and sector addressing 
  922. ;
  923. tst$none:
  924. ;    cpi    dsk$none    ; don't test extras for now....??
  925. ;    rnz
  926. do$type$7:
  927.     lda    @trk
  928.     jr    set$up$cont
  929.  
  930.     page
  931. ;
  932. ;    A=dsk$info on entry
  933. ;
  934. set$up$MFM:
  935.     mvi    d,0        ; D=side # (0)
  936.     mov    e,a        ; save dsk$info in E
  937.     ani    TypeX        ; look at Type0 to Type7
  938.     jrz    do$type$0    ;
  939.     cpi    Type2
  940.     lda    @trk        ; used by Type1, Type2 and Type3
  941.     jrz    do$type$2
  942.     jrc    do$type$1
  943.  
  944. ;    cpi    Type6
  945. ;    jrz    do$type$6
  946. ;    jnc    do$type$7    ; MSB of sector(byte) set for 2nd side of disk
  947.  
  948.     cpi    Type7
  949.     jz    do$type$7    ; MSB of sector(byte) set for 2nd side of disk
  950. ;
  951. ;    only types 0 to 2 and 7 are currenty defined
  952. ;        Type3 to Type6 will do Type2
  953. ;do$type$3:
  954. ;do$type$6:
  955.  
  956. do$type$2:
  957.     mov    b,a        ; save a copy in B
  958.     sui    40
  959.     jrc    do$type$0    ; jump if still on side 0
  960.     mvi    a,79        ; on back side count 39,38,37,...,0
  961.     sub    b
  962. set$trk:
  963.     mvi    d,80h        ; D=side # (1)
  964.     sta    @trk
  965.     jr    do$type$0
  966.  
  967.     page
  968. ;
  969. ;    divide the track number by two and if Head=1
  970. ;        add #sect/side to @sect
  971. ;
  972. do$type$1:
  973.     cmc            ; carry was set clear it
  974.     rar            ; divide track by 2 (carry gets LSB)
  975.     sta    @trk
  976.     jrnc    do$type$0
  977.     call    get$max$num$b    ; HL and C changed
  978.     lda    @sect
  979.     add    b
  980.     sta    @sect
  981.  
  982. do$type$0:
  983.     lda    @trk
  984.     sta    vic$trk
  985.     call    get$max$num$b    ; B=number of sectors per track per side
  986.     lda    @sect        ; ..HL and C changed
  987.     cmp    b
  988.     jrc    is$side$0
  989.     mvi    d,80h        ; D=side # (1)
  990.     bit    C1$bit,e    ; dsk$info in E
  991.                 ; sector numbering continues on side 1 ?
  992.     jrnz    is$side$0    ; yes, do not remove side one bias
  993.     sub    b        ; no, remove side one bias
  994. is$side$0:
  995.     mov    c,a        ; hold @sect in C    
  996.     mov    a,e        ; get dsk$info to A
  997.     ani    S1        ; A=Starting  sector number (0 or 1)
  998.     add    c        ; add back @sect
  999.     ora    d        ; add in the side bit
  1000.     sta    vic$sect
  1001.     ret
  1002.  
  1003.     page
  1004. ;
  1005. ;    input:
  1006. ;        DE = number bytes to read
  1007. ;        HL = DMA address
  1008. ;
  1009.     CSEG
  1010. rd$1571$data:
  1011.     lda    @dbnk            ; get the disk DMA bank
  1012.     call    ?bank            ; set it
  1013.  
  1014.     lxi    b,0DC0Dh        ; D1ICR
  1015. rd$1571$stat$wait:
  1016.     inp    a
  1017.     ani    8            ; data ready bit set?
  1018.     jrz    rd$1571$stat$wait    ; no, loop
  1019.  
  1020.     mvi    c,0ch            ; D1SDR
  1021.     inp    a            ; read the status byte
  1022.     sta    vic$data        ; save it
  1023.     ani    0eh            ; any errors ?
  1024.     jrnz    rd$1571$exit        ; yes, exit
  1025.  
  1026.     lxi    b,0DD00h
  1027.     inp    a            ; get current clock polarity
  1028.  
  1029. rd$1571$next:
  1030.     lxi    b,0DD00h        ; D2PRA
  1031.     xri    10h            ; toggle clk$bit
  1032.     outp    a            ; clock the 1571 for a byte
  1033.  
  1034.     dcr    e            ; DE=count
  1035.     jnz    rd$1571$more        ; leave as normal jump to keep
  1036.     dcr    d            ; the transfer speed at it's max
  1037.     jrz    rd$1571$exit        ; ...
  1038.  
  1039. ;
  1040. rd$1571$more:
  1041.     dcr    b
  1042. rd$1571$wait:
  1043.     mvi    c,0dh            ; D1ICR (DC0Dh)
  1044.     inp    c
  1045.     bit    3,c
  1046.     jz    rd$1571$wait
  1047.     mvi    c,0ch            ; D1SDR
  1048.     ini                ; (hl) <- (bc) ; hl <- hl+1 ; b <- b-1
  1049.     jmp    rd$1571$next
  1050.  
  1051.  
  1052. rd$1571$exit:
  1053.     sta    bank$0            ; restore current mem config
  1054.     ret
  1055.  
  1056.     page
  1057.  
  1058. clk$in    equ    40h
  1059. ;
  1060. ;    input:
  1061. ;        DE = number of bytes to write
  1062. ;        HL = DMA address
  1063. ;
  1064. wr$1571$data:
  1065.     call    ?di$int
  1066. ; do spout inline
  1067.     lxi    b,mode$reg
  1068.     mvi    a,fast$wr$en
  1069.     sta    io$0
  1070.     outp    a            ; set data direction to output
  1071.     sta    bank$0
  1072.  
  1073.     lxi    b,0dc05h        ; low (D1T1h)
  1074.     xra    a
  1075.     outp    a
  1076.     dcr    c            ; low(D1T1l)
  1077.     mvi    a,3            ; clk = osc/3
  1078.     outp    a            ;
  1079.  
  1080.     mvi    c,0eh            ; D1CRA
  1081.     inp    a
  1082.     ani    80h
  1083.     ori    55h
  1084.     outp    a
  1085.     dcr    c            ; D1ICR
  1086.     inp    a
  1087.  
  1088.     lda    @dbnk            ; get the disk DMA bank
  1089.     call    ?bank            ; set it
  1090.  
  1091.     mvi    a,clk$in
  1092.     sta    cur$clk
  1093.  
  1094.     page
  1095. ;
  1096. ;
  1097. clk$wait:
  1098.     lxi    b,0dd00h        ; D2PRA
  1099.     inp    a
  1100.     inp    c            ; debounce
  1101.     cmp    c
  1102.     jrnz    clk$wait
  1103.  
  1104.     lda    cur$clk            ; get old clk value
  1105.     xra    c            ; check if changed 
  1106.     ani    clk$in            ; (only clock in bit)
  1107.     jrz    clk$wait        ; loop if not
  1108.  
  1109.     mov    a,c            ; 
  1110.     sta    cur$clk            ; make this the current clk value
  1111.     lxi    b,0dc0ch        ; D1SDR
  1112.     mov    a,m
  1113.     outp    a            ; send character to drive
  1114.     inx    h            ; advance pointer
  1115.     dcx    d            ; dec the char count
  1116.  
  1117.     inr    c            ; D1ICR
  1118. send$wait:
  1119.     inp    a
  1120.     ani    8
  1121.     jz    send$wait
  1122.  
  1123.     mov    a,d
  1124.     ora    e
  1125.     jnz    clk$wait        ; go send the next byte
  1126.  
  1127. ; do spin
  1128.     lxi    b,0DC0Eh        ; D1CRA
  1129.     inp    a
  1130.     ani    80h
  1131.     ori    8
  1132.     outp    a
  1133.     lxi    b,mode$reg
  1134.     mvi    a,fast$rd$en
  1135.     sta    io$0            ; enable the MMU
  1136.     outp    a            ; set data direction to input
  1137.     sta    bank$0            ; disable MMU
  1138. ; spin done
  1139.  
  1140.     page
  1141.  
  1142.     lxi    b,0DC0Dh        ; D1ICR
  1143.     inp    a            ; clear data pending flag
  1144.  
  1145.     lxi    b,0DD00h        ; D2PRA
  1146.     inp    a
  1147.     ori    10h            ; set clk$bit low (hardware inverted)
  1148.     outp    a            ; 
  1149.  
  1150.     lxi    b,0DC0Dh        ; D1ICR
  1151. wait$status:
  1152.     inp    a
  1153.     ani    8
  1154.     jrz    wait$status
  1155.  
  1156.     lxi    b,0DC0Ch        ; D1SDR
  1157.     inp    d
  1158.  
  1159.     lxi    b,0DD00h        ; D2PRA
  1160.     inp    a
  1161.     ani    not(10h)        ; set clk$bit hi (hardware inverted)
  1162.     outp    a            ; 
  1163.  
  1164.     mov    a,d            ; recover the status byte
  1165.     sta    vic$data
  1166.  
  1167.     ei
  1168.     ret
  1169.  
  1170.     page
  1171. ;
  1172. ;    This routine is used to move a sector of data
  1173. ;     to/from the sector buffer and the DMA pointer.
  1174. ;         A=0 for buffer to DMA  (disk read)
  1175. ;         A<>0 for DMA to buffer (disk write)
  1176. ;
  1177.     CSEG
  1178. ?dkmov:
  1179.     lhld    local$DMA    ; current DMA adr
  1180.     lxi    d,@buffer    ; location of disk read/write buffer
  1181.     lxi    b,256        ; sector size
  1182. ;
  1183. ;
  1184. dk$cont:
  1185.     ora    a
  1186.     jrnz    dsk$read    ; swap pointer for read
  1187.     xchg
  1188. ;
  1189. ;
  1190. dsk$read:
  1191.     lda    @dbnk        ; get the disk bank
  1192.     call    ?bank
  1193.     ldir            ; do the data move
  1194.     sta    bank$0        ; current bank will ALWAYS be 0
  1195.     ret
  1196.  
  1197. ;
  1198. ;
  1199. ;
  1200.     DSEG
  1201. dsk$fun:
  1202.     sta    vic$cmd
  1203.     call    disp$dsk$info        ; yes, go display disk info
  1204.     jmp    ?fun65+3        ; go do the function
  1205.  
  1206.     page
  1207. ;
  1208. ;*****************************************************************
  1209. ;
  1210.     DSEG
  1211. ?dskst:
  1212. disp$dsk$info:
  1213.     mvi    a,72            ; r/w in col 72 (col 0-79)
  1214.     sta    offset
  1215.     lda    vic$cmd
  1216.     mvi    b,'R'
  1217.     dcr    a            ; ?1 normal$rd
  1218.     jrz    out$cmd$rd
  1219.     dcr    a            ; ?2 normal$wr
  1220.     jrz    out$cmd$wr
  1221.     dcr    a            ; ?3 fast$rd
  1222.     jrz    out$cmd$rd
  1223.     dcr    a            ; ?4 fast$wr
  1224.     rnz
  1225. out$cmd$wr:
  1226.     mvi    b,'W'
  1227. out$cmd$rd:
  1228.     call    disp$B
  1229.     call    disp$space
  1230.     mvi    b,'A'-1
  1231.     lda    vic$drv
  1232. next$drv:
  1233.     inr    b
  1234.     rrc
  1235.     jrnc    next$drv
  1236.  
  1237.     call    disp$B
  1238.     lda    vic$trk
  1239.     call    disp$dec
  1240.     lda    vic$sect
  1241.     ani    80h
  1242.     cz    disp$space
  1243.     mvi    b,'-'
  1244.     cnz    disp$B
  1245.     lda    vic$sect    
  1246.     ani    7fh
  1247.  
  1248.     page
  1249. ;
  1250. ;
  1251. ;
  1252. disp$dec:
  1253.     mvi    b,'0'-1
  1254.  
  1255. conv$loop:
  1256.     inr    b
  1257.     sui    10
  1258.     jrnc    conv$loop
  1259.  
  1260.     adi    '0'+10
  1261.     push    psw
  1262.     call    disp$B
  1263.     pop    psw
  1264. disp$A:
  1265.     mov    b,a
  1266. disp$B:
  1267.     lda    offset
  1268.     mov    c,a            ; col # in C
  1269.     inr    a
  1270.     sta    offset            ; advance cursor position
  1271.     xra    a            ; no attribute to write
  1272.     call    ?stat
  1273.  
  1274.     xra    a
  1275.     ret
  1276.  
  1277. disp$space:
  1278.     mvi    b,' '
  1279.     jr    disp$B
  1280.  
  1281.     page
  1282.  
  1283. ;*****************************************************************
  1284. ;
  1285. ; Extended Disk Parameter Headers (XDPHs)
  1286. ;
  1287.     CSEG            ; place tables in common
  1288. ;
  1289. ;    1st disk drive on the system
  1290. ;
  1291.     dw    write$154X
  1292.     dw    read$154X
  1293.     dw    login$154X
  1294.     dw    init$154X
  1295.     db    1        ; bit 0 set (drive 0)
  1296.     db    dsk$c128    ; format type byte
  1297. cmdsk0:    
  1298.     dph    0,dpb$0
  1299.  
  1300. dpb$0:
  1301.     dpb    1024,1,1360,2048,128,0
  1302.     db    0        ; max sector number and lock flag
  1303.     dw    0        ; MFM table pointer
  1304.  
  1305.     page
  1306. ;
  1307. ;    2nd disk Drive on the system
  1308. ;
  1309.     dw    write$154X
  1310.     dw    read$154X
  1311.     dw    login$154X
  1312.     dw    init$154X
  1313.     db    2        ; bit 1 set (drive 1)
  1314.     db    dsk$c128    ; format type byte 
  1315. cmdsk1:
  1316.     dph    0,dpb$1
  1317.  
  1318. dpb$1:
  1319.     dpb    1024,1,1360,2048,128,0
  1320.     db    0        ; max sector number and lock flag
  1321.     dw    0        ; MFM table pointer
  1322.  
  1323.     page
  1324. ;
  1325. ;    3rd disk drive on the system
  1326. ;
  1327.     dw    write$154X
  1328.     dw    read$154X
  1329.     dw    login$154X
  1330.     dw    init$154X
  1331.     db    4        ; bit 2 set (drive 2)
  1332.     db    dsk$c128    ; format type byte
  1333. cmdsk2:    
  1334.     dph    0,dpb$2
  1335.  
  1336. dpb$2:
  1337.     dpb    1024,1,1360,2048,128,0
  1338.     db    0        ; max sector number and lock flag
  1339.     dw    0        ; MFM table pointer
  1340.  
  1341.     page
  1342. ;
  1343. ;    NOTE: The blocking factor for all of these formats is
  1344. ;        1K (2K for double sided), thus the fractional
  1345. ;        parts are unusable by CP/M.  They can be accessed
  1346. ;        by absolute sector addressing.
  1347. ;
  1348. ;    NOTE: 1571 and 1541 disk drives use track numbers
  1349. ;        of 1 to 35 and sector numbers of 0 to nn
  1350.  
  1351. ;
  1352. ;        The method used to access the full disk
  1353. ;        is to tell the system that there is 1 sector
  1354. ;        per track and then to use the track # as an
  1355. ;        absolute sector address and do conversion in BIOS.
  1356. ;
  1357. ; DPB FOR C128 CP/M 3.0 disk        ( 170K, 34K larger then C64 CP/M)
  1358. ;    256 byte sectors        ( 170.75K )
  1359. ;    1 sectors/track
  1360. ;        up to 21 physical sectors (0 to 16,17,18 or 20)
  1361. ;    680 tracks/disk (usable, 683 real)
  1362. ;        35 physical tracks (0 to 34)
  1363. ;    1K allocation blocks
  1364. ;    64 directory entries
  1365. ;    track offset of 2 (2 sectors) (handled by set$up$c128)
  1366. ;
  1367.     DSEG        ; these tables are moved to common when used
  1368. dpb$c128$SS:
  1369.     dpb    1024,1,170,1024,64,0
  1370.  
  1371.     page
  1372. ;
  1373. ; DPB FOR C128 CP/M 3.0 double sided disk    ( 340K )
  1374. ;    256 byte sectors            ( 341.5K )    
  1375. ;    1 sectors/track
  1376. ;        up to 21 physical sectors (0 to 16,17,18 or 20)
  1377. ;    1360 tracks/disk (usable, 1366 real)
  1378. ;        70 physical tracks (0 to 34 side 0, 35 to 69 side 1)
  1379. ;    2K allocation units
  1380. ;    128 directory entrys
  1381. ;    track offset of 1 (1 sectors) taken care of in set$up$c128
  1382. ;
  1383. dpb$c128$DS:
  1384.     dpb    1024,1,340,2048,128,0
  1385.  
  1386.     page
  1387. ;
  1388. ; DPB FOR C64 CP/M 2.2 disk --             ( 136K )
  1389. ;    256 byte sectors
  1390. ;    17 sectors / tracks    (sector numbering 0-16)
  1391. ;        sector 18 to n on the outer tracks are unused
  1392. ;    34 tracks / disk
  1393. ;        tracks track 2 to 16    (track numbering 0-34)
  1394. ;        track 17 is the C128 directory track (not counted)
  1395. ;        track 19 to 34
  1396. ;    1K allocation blocks
  1397. ;    64 directory entrys
  1398. ;    track offset of 2 (1st two tracks used for CP/M 2.2 boot)
  1399. ;
  1400. dpb$c64$cpm:
  1401.     dpb    256,17,34,1024,64,2
  1402.                 
  1403.     page
  1404. ;
  1405.     DSEG
  1406. MFM$table:
  1407.     db    S256*2+(16*2-8)+1    ; 256 byte sect, 16 sect/trk
  1408.     db    MFM+S256+Type0+C0+S1    ;     DSDD
  1409.     dw    0            ; start on track 4 sect 1 (2 alc)
  1410.     dpb    256,32,40,2048,128,2    ; sect# 1 to 16
  1411.     db    16            ; (top and bottom numbered the same)
  1412.     db    'Epson QX10'        ;1 Epson QX10
  1413.  
  1414.  
  1415.  
  1416.  
  1417.  
  1418.     db    80h+S512*2+(10*2-8)+1    ; 512 byte sect, 10 sect/trk
  1419. ;    db    S256*2            ; track 0 is 256 bytes/sector
  1420.     db    MFM+S512+Type0+C0+S1    ;    DSDD
  1421.     dw    0            ; start on track 2 sect 1 (2 alc)
  1422.     dpb    512,20,40,2048,128,2    ; sect# 1 to 10
  1423.     db    10            ; (top and bottom numbered the same)
  1424.     db    'Epson QX10'        ;2
  1425.  
  1426.     page
  1427.  
  1428.     db    S512*2+(8*2-8)+1    ; 512 byte sect 8 sect/trk
  1429.     db    MFM+S512+Type2+C0+S1    ;     SSDD
  1430.     dw    0            ; start on track 1 sector 1 (2 alc)
  1431.     dpb    512,8,40,1024,64,1    ; sect# 1 to 8
  1432.     db    8            ;
  1433.     db    ' IBM-8 SS '        ;3
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.     db    S512*2+(8*2-8)+1    ; 512 byte sect 8 sect/trk
  1440.     db    MFM+S512+Type2+C0+S1    ;     DSDD
  1441.     dw    0            ; start on track 1 sector 1 (1 alc)
  1442.     dpb    512,8,80,2048,64,1    ; sect# 1 to 8
  1443.     db    8            ; (top and bottom numbered the same)
  1444.     db    ' IBM-8 DS '        ;4
  1445.  
  1446.     page
  1447.  
  1448.     db    S512*2+(10*2-8)+0    ; 512 byte sector, 10 sect/trk
  1449.     db    MFM+S512+Type1+C1+S0    ;    DSDD
  1450.     dw    0            ; start on track 0 sector 10 (2 alc)
  1451.     dpb    512,10,80,2048,128,1    ; sect# 0 to 9 on top (even tracks)
  1452.     db    10            ; sect# 10 to 19 on bottom (odd tracks)
  1453.     db    'KayPro IV '        ;5
  1454.  
  1455.  
  1456.  
  1457.  
  1458.  
  1459.     db    S512*2+(10*2-8)+0    ; 512 byte sect, 10 sect/trk
  1460.     db    MFM+S512+Type0+C1+S0    ;     SSDD
  1461.     dw    0            ; start on track 1 sector 0 (4 alc)
  1462.     dpb    512,10,40,1024,64,1    ; sect# 0 to 9 
  1463.     db    10            ;
  1464.     db    'KayPro II '        ;6
  1465.  
  1466.     page
  1467.  
  1468.     db    S1024*2+(5*2-8)+1    ; 1024 byte sect, 5 sect/trk
  1469.     db    MFM+S1024+Type0+C0+S1    ;     SSDD
  1470.     dw    0            ; start on track 3 sector 1 (2 alc)
  1471.     dpb    1024,5,40,1024,64,3    ; sect# 1 to 5
  1472.     db    5            ;
  1473.     db    'Osborne DD'        ;7
  1474.  
  1475.  
  1476.  
  1477.  
  1478.     db    S512*2+(9*2-8)+1    ; 512 byte sect 9 sect/track (uses 8)
  1479.     db    MFM+S512+Type1+C0+S1    ;     DSDD
  1480.     dw    0            ; start on trk 0, sect 1, hd 1 (1 alc)
  1481.     dpb    512,8,80,2048,64,1    ; sect# 1 to 9
  1482.     db    8            ; (top and bottom numbered the same)
  1483.     db    '  Slicer  '        ;8
  1484.  
  1485.     page
  1486.  
  1487.     db    S256*2+(16*2-8)+1    ; 256 byte sect, 16 sect/trk
  1488.     db    MFM+S256+Type0+C0+S1    ;     DSDD
  1489.     dw    0            ; start on track 4 sect 1 (2 alc)
  1490.     dpb    256,32,40,2048,128,4    ; sect# 1 to 16
  1491.     db    16            ; (top and bottom numbered the same)
  1492.     db    'Epson Euro'        ;1 Epson European (MFCP/M ?)
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.     db    -1
  1499.     db    MFM            ; 
  1500.     dw    0            ; 
  1501.     dpb    512,20,40,2048,128,2    ; 
  1502.     db    8            ;
  1503.     db    '   None   '        ;10
  1504.  
  1505.     page
  1506.  
  1507.     db    -1
  1508.     db    MFM            ; 
  1509.     dw    0            ; 
  1510.     dpb    512,20,40,2048,128,2    ; 
  1511.     db    8            ;
  1512.     db    '   None   '        ;11
  1513.  
  1514.     db    -1
  1515.     db    MFM            ; 
  1516.     dw    0            ; 
  1517.     dpb    512,20,40,2048,128,2    ; 
  1518.     db    8            ;
  1519.     db    '   None   '        ;12
  1520.  
  1521.     page
  1522.  
  1523.     db    -1
  1524.     db    MFM            ; 
  1525.     dw    0            ; 
  1526.     dpb    512,20,40,2048,128,2    ; 
  1527.     db    8            ;
  1528.     db    '   None   '        ;13
  1529.  
  1530.     db    -1
  1531.     db    MFM            ; 
  1532.     dw    0            ; 
  1533.     dpb    512,20,40,2048,128,2    ; 
  1534.     db    8            ;
  1535.     db    '   None   '        ;14
  1536.  
  1537.     page
  1538.  
  1539.     db    -1
  1540.     db    MFM            ; 
  1541.     dw    0            ; 
  1542.     dpb    512,20,40,2048,128,2    ; 
  1543.     db    8            ;
  1544.     db    '   None   '        ;15
  1545.  
  1546.     db    -1
  1547.     db    MFM            ; 
  1548.     dw    0            ; 
  1549.     dpb    512,20,40,2048,128,2    ; 
  1550.     db    8            ;
  1551.     db    '   None   '        ;16
  1552.  
  1553.  
  1554.     page
  1555. ;
  1556. ;    not functional yet
  1557. ;
  1558.  
  1559. ;    db    S1024*2+(5*2-8)+1    ; 1024 byte sect 5 sect/track
  1560. ;    db    MFM+S1024+Type0+C0+S1    ;     SSDD
  1561. ;    dw    0            ; start on trk 2, sect 1 (2 alc)
  1562. ;    dpb    1024,5,40,2048,128,2    ; sect# 1 to 5
  1563. ;    db    5            ;
  1564. ;    db    'Morrow MD2'        ; 
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570. ;    db    S1024*2+(5*2-8)+1    ; 1024 byte sect  5 sect/trk
  1571. ;    db    MFM+S1024+Type0+C0+S1    ;     DSDD
  1572. ;    dw    0            ; start on trk 1, sect 1, hd 0 (3 alc)
  1573. ;    dpb    1024,10,40,2048,192,1    ; sect# 1 to 5
  1574. ;    db    5            ;
  1575. ;    db    'Morrow MD3'        ; 
  1576.  
  1577.  
  1578. MFM$tbl$entries    equ    ($-MFM$table)/32
  1579.  
  1580.     db    -1
  1581.     db    -1
  1582.  
  1583.     page
  1584.  
  1585.     cseg
  1586. cur$clk:    ds    1
  1587.  
  1588.     dseg
  1589. lock$flag    ds    1
  1590. last$match    ds    2
  1591. window$info:    ds    2
  1592.  
  1593. dsk$window    equ    12
  1594.  
  1595. no$dsk$msg:
  1596.         ;1234567890
  1597.     db    ' Missing  ' 
  1598.  
  1599.  
  1600. MFM$match$tbl:
  1601.     ds    2*MFM$tbl$entries    ; MFM$count MUST follow this parm
  1602. MFM$count:
  1603.     ds    1            ; MFM$offset MUST follow this parm
  1604. MFM$offset:
  1605.     ds    1
  1606.  
  1607. MFM$cur$ptr:
  1608.     ds    2
  1609.  
  1610. DPH$pointer:
  1611.     ds    2
  1612.  
  1613. sect$cnt:
  1614.     ds    1
  1615. sect$buf$ptr:
  1616.     ds    2
  1617. sect$buffer:
  1618.     ds    4*2
  1619.  
  1620. local$DMA:
  1621.     ds    2
  1622.  
  1623. status$atr    equ    0
  1624. offset:        db    0
  1625.  
  1626.     end
  1627.  
  1628. ct$cnt:
  1629.     ds    1
  1630. sect$buf$ptr:
  1631.     ds    2
  1632. sect$buffer:
  1633.     ds    4*2
  1634.  
  1635. local$DMA:
  1636.     ds    2
  1637.  
  1638. status$atr    equ    0
  1639. offse