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 / BIOS-R62.LZH / CXDISK.ASM < prev    next >
Assembly Source File  |  2000-06-30  |  34KB  |  1,740 lines

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