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 / KAYPRO / KPNUROM.LBR / KDSKDRV.ZQ0 / KDSKDRV.Z80
Text File  |  2000-06-30  |  22KB  |  841 lines

  1. title    Kaypro 4-83 Resident Software Package
  2. subttl    Disk Equate and Parameters
  3. ;
  4. ; ################################################################
  5. ; ##                                ##
  6. ; ##    Disk support routines                    ##
  7. ; ##                                ##
  8. ; ################################################################
  9. ; ##    Last Update:06/08/82        [001]            ##
  10. ; ################################################################
  11. ; #    Revised to KPRO4, 3 Mar. 1984, C.B. Falconer        ##
  12. ; ################################################################
  13. ; ## Revised for integral data segment with Z80ASM  85/6/15 cbf ##
  14. ; ## General purpose disk routines, reduced Ram use.  Avoid use ##
  15. ; ## of AF' register (reserved for other uses).  Added use of   ##
  16. ; ## register E for drive sensing, per CPM standards.  Added    ##
  17. ; ## provision for disabling write checking.  Re-organized.     ##
  18. ; ## The "home" routine now returns a pointer to a data area.   ##
  19. ; ## Note the unmodified Kaypro returns a pointer in page zero, ##
  20. ; ## so software can tell them apart.                ##
  21. ; ################################################################
  22. ; ## 85/6/18 cbf. Added disk error messages, corrected summary  ##
  23. ; ## reset on any cold boot via diskinit.  Reduced error retrys ##
  24. ; ################################################################
  25. ;
  26.     extrn    bitport, bankbit;    bank selection
  27.     extrn    .thnsd;            delay
  28.     extrn    .print, .vidout;    for error system
  29. ;
  30. ; linkage to deblocking system
  31.     extrn    erflag, unacnt
  32.     extrn    hstact, hstbuf, hstdsk
  33.     extrn    hstsec, hsttrk, hstwrt
  34. ;
  35.     entry    home, seldsk, settrk, setsec
  36.     entry    sectran
  37.     entry    diskinit, datainit, diskon, diskoff
  38.     entry    readhst, writehst
  39. ;
  40. ; Public data areas (for deblocking area)
  41.     entry    sekdsk, seksec, sektrk
  42.     entry    denflag
  43. ;
  44. ; Entries to installed routines in data segment
  45.     entry    move, rd, wrt
  46. ;
  47. ; ---------------------------------------------------------
  48. ;
  49. drvmask    equ    0FCH;        drive select mask
  50. denmask    equ    0DFH;        density bit mask
  51. ddbit    equ    00H;        double density bit
  52. sdbit    equ    20H;        single density bit
  53. sidebit    equ    4;
  54. mtroff    equ    40h
  55. ;
  56. ; Disk controller ports
  57. control    equ    10H;        I/O port of disk controller
  58. status    equ    control+0;    status register
  59. cmnd    equ    control+0;    command register
  60. track    equ    control+1;    track register
  61. sector    equ    control+2;    sector register
  62. data    equ    control+3;    data register
  63. ;
  64. ; Controller commands (selected)
  65. ficmd    equ    11010000B;    force interrupt (Abort current command)
  66. rdcmd    equ    10001000B;    read command
  67. wrtcmd    equ    10101100B;    write command
  68. seekcmd    equ    00010000B;    seek command
  69. rstcmd    equ    00000000B;    home (restore) command
  70. adrcmd    equ    11000100B;    read track address
  71. rdmask    equ    10011100B;    read status mask
  72. wrtmask    equ    11111100B;    write status mask
  73. ;
  74. ; retry control
  75. tries1    equ    3;        re-home on bad sector # of tries+1
  76. tries2    equ    6;        re-read/write # of retries+1
  77. ;
  78. ; Miscellaneous
  79. retcod    equ    0C9H;        return op code
  80. nmivec    equ    0066H;        non-maskable interupt vector
  81. esc    equ    01bh;        for error message positioning
  82. ;
  83. subttl Physical disk routines
  84. ;
  85.     cseg
  86. ;
  87. ; enter here on system boot to initialize
  88. ; a,f,b,c,d,e,h,l
  89. diskinit:
  90.     ld    hl,ioimage;    move rd/wrt/dphs routines into RAM
  91.     ld    de,move
  92.     ld    bc,imaglen
  93.     ldir
  94. ;
  95.     xor    a;        0 to accumulator
  96.     ld    (hstact),a;    host buffer inactive
  97.     ld    (unacnt),a;    clear unalloc count
  98.     ld    a,ddbit;    set double density flag
  99.     ld    (denflag),a
  100.     ld    a,255;        set track numbers to 255
  101.     ld    (dsk),a;    clear disk number
  102.     ld    (tracka),a
  103.     ld    (trackb),a
  104.     ret
  105. ;
  106. ; called on cold start to initialize error counts etc
  107. ; f,b,c,d,e,h,l
  108. datainit:
  109.     ld    hl,.ckwrt
  110.     ld    de,chkwrt
  111.     ld    bc,.ckend-.ckwrt
  112.     ldir
  113.     ret
  114.  
  115. ;
  116. ; perform logical to physical sector translation.
  117. ; logical sector number in BC, table address in DE
  118. ; return physical sector number in HL
  119. ; a,f,d,e,h,l
  120. sectran:
  121.     ld    a,d;        table address 0?
  122.     or    e
  123.     ld    h,b;        if so no xlate
  124.     ld    l,c
  125.     ret    z
  126.     ex    de,hl;        table address in hl
  127.     add    hl,bc;        index by logical sector number
  128.     ld    l,(hl)
  129.     ld    h,0
  130.     ret
  131. ;
  132. ; set sector given by register c 
  133. ; a,f
  134. setsec:    ld    a,c
  135.     ld    (seksec),a;    sector to seek
  136.     ld    a,(denflag)
  137.     or     a
  138.     ret    z;        single density
  139. ;    "    "
  140. ; select sector #, BC=Sector # (double density)
  141. ; a,f
  142. secset:    in    a,(bitport);    single or double sided?
  143.     and    sidebit
  144.     ld    a,c;        move sector number to A
  145.     jp    z,secst1;    pure sector no in single sided
  146.     add    a,10
  147. secst1:    out    (sector),a;    to controller register
  148.     ret
  149. ;
  150. ; Set track
  151. settrk:    ld    h,b
  152.     ld    l,c
  153.     ld    (sektrk),hl;    set track given by registers BC
  154.     ld    a,(denflag)
  155.     or     a
  156.     ret    z;        single density
  157. ;    "    "
  158. ; seek track #, BC=Track # (double density)
  159. trkset:    call    ready;        make sure drive is on and ready
  160.     ld    a,(sidflg);                    {}
  161.     or    a
  162.     jp    z,tkset3;    single sided, select side 0
  163.     ld    a,c;        else double sided drive
  164.     rra;            trk no divided /2
  165.     ld    c,a;        for actual selection
  166.     in    a,(bitport)
  167.     jp    c,tkset1;    and select side 0 for even track
  168.     and    not sidebit;    else select side 1
  169.     jp    tkset2
  170. tkset1:    or    sidebit
  171. tkset2:    out    (bitport),a;    select side
  172. tkset3:    ld    a,c;        get physical track number
  173.     ld    (ctrack),a
  174.     out    (data),a;    track # to seek to
  175.     ld    a,seekcmd;    seek command
  176.     out    (cmnd),a;    issue command
  177. ;    "    "
  178. ; check status of controller, wait for command to finish executing
  179. ; a,f
  180. busy:    ld    a,(nmivec)
  181.     push    af
  182.     ld    a,retcod
  183.     ld    (nmivec),a
  184.     halt;            wait for command done
  185.     pop    af
  186.     ld    (nmivec),a
  187. busy1:    in    a,(status);    now wait for not busy
  188.     bit    0,a;        preserve code to return
  189.     jp    nz,busy1
  190.     ret
  191. ;
  192. ; home disk
  193. ; a,f,h,l
  194. home:    ld    a,(denflag)
  195.     or     a
  196.     jp    nz,dohome;    double density
  197.     ld    a,(hstwrt);    patch by DRI
  198.     or    a
  199.     jp    nz,dohome
  200.     ld    (hstact),a
  201. ;    "    "
  202. ; home disk head
  203. dohome:    call    ready;        make sure drive is on and ready
  204.     in    a,(bitport)
  205.     and    not sidebit
  206.     out    (bitport),a;    select side 0
  207.     xor    a
  208.     ld    (ctrack),a;    reset current track number
  209.     ld    a,rstcmd;    restore command
  210.     out    (cmnd),a;    issue command
  211.     call    busy;        test and wait for not busy
  212.     ld    hl,chkwrt
  213.     ret
  214. ;
  215. ; select disk
  216. seldsk:    ld    a,c;        selected disk number
  217.     ld    (sekdsk),a;    seek disk number
  218. ;    "    "
  219. ; Physical disk drive select, C=drive number 0=A:, 1=B:
  220. ; return HL=dph for selected drive, or HL=0 for non-existent drive
  221. ; Set up density for ddrive selected
  222. dsksel:    ld    hl,0;        hl = 0 for non-existent drive
  223.     ld    a,c
  224.     cp    2
  225.     ret    nc;        drive number >B:
  226.     or    a;        z flag set => A: drive else B: drive
  227.     ld    a,e;        Save the CPM flag momentarily
  228.     ld    de,tracka;    find propert track(x) and..
  229.     ld    hl,dpha;    select proper dph for drive
  230.     jp    z,sel0
  231.     ld    de,trackb
  232.     ld    hl,dphb
  233. sel0:    push    hl;        save dph of disk to be selected
  234.     and    1
  235.     ld    a,(dsk)
  236.     jp    nz,sel0a;    Previously selected to CPM
  237.     ld    a,255
  238.     ld    (de),a;        Mark for sensing
  239.     xor    a
  240.     ld    (unacnt),a;    home will reset hstact on sense
  241.     ld    a,(dsk)
  242.     cp    c
  243.     jp    z,selnot;    reselecting the current disk
  244. sel0a:    cp    c;        selecting disk already selected?
  245.     jp    z,selx;        yes, no further action needed
  246.     ld    a,c;        save new disk number
  247.     ld    (dsk),a
  248.     or    a;        set zero flag if A: drive
  249.     ld    hl,ctrack
  250.     ld    de,trackb;    now find proper track(x)
  251.     jp    z,sel1
  252.     ld    de,tracka
  253. sel1:    ld    a,(de);        have we been on disk we're "leaving"
  254.     cp    255;        if not do not update tracks
  255.     jp    z,selnot
  256.     push    bc
  257.     ld    bc,3
  258.     ldir;            save old table
  259.     pop    bc
  260. selnot:    ld    de,ctrack;    now to update main table  {}
  261.     ld    a,c;        set z flag if A: drive
  262.     or    a 
  263.     ld    hl,tracka
  264.     jp    z,sel2
  265.     ld    hl,trackb
  266. sel2:    ld    a,(hl)
  267.     cp    255;        first time for this drive?
  268.     jp    z,density;    if so, go set it up
  269.     ld    bc,3
  270.     ldir;            init table for density
  271.     ld    bc,15;        dparm size
  272.     ld    de,dpbd;    dparm addr
  273.     ld    hl,.dpbd;    single sided table
  274.     ld    a,(sidflg)
  275.     or    a
  276.     jp    z,sel2a
  277.     ld    hl,.dsdd;    double sided table
  278. sel2a:    ldir;            move in dparm for this drive
  279.     ld    a,(ctrack)
  280.     out    (track),a
  281. selx:    pop    hl;        adr of dph for disk we are selecting
  282.     ret
  283. ;
  284. density:
  285.     ld    a,ddbit
  286.     ld    (denflag),a
  287.     call    ready;        physical disk select
  288.     call    home;        seek track 0, side 0
  289.     pop    hl
  290.     call    dcheck;        see if we can read address
  291.     jp    z,dend;        if so, density is double
  292.     ld    a,sdbit
  293.     ld    (denflag),a
  294.     call    ready;        try single density
  295.     call     dcheck
  296.     ret    nz;        can't read, so don't change
  297. ;    "    "
  298. ; set up for single density operations
  299.     push    hl;        (* single density *)   hl^ to dph
  300.     push    de
  301.     ld    de,tbl1;    single density sector xlate table
  302.     ld    (hl),e;        store table^ into dph
  303.     inc    hl
  304.     ld    (hl),d
  305.     ld    de,9;        move foward in dph to dpb pointer
  306.     add    hl,de
  307.     ld    de,dpbs;    single density dpb
  308.     ld    (hl),e
  309.     inc    hl
  310.     ld    (hl),d;                    {}
  311.     jp    den1
  312. ;
  313. ; set up for double density operations
  314. dend:    push    hl;        (* double density *)   hl^ to dph
  315.     push    de
  316.     ld    de,0;        no xlate table (done by FORMAT prog)
  317.     ld    (hl),e;        store table^ into dph
  318.     inc    hl
  319.     ld    (hl),d
  320.     ld    de,9;        move forward in dph to dpb pointer
  321.     add    hl,de
  322.     ld    de,dpbd;    double density dpb
  323.     ld    (hl),e
  324.     inc    hl
  325.     ld    (hl),d
  326.     in    a,(bitport);    now try side 1 (double sided?)
  327.     or    sidebit
  328.     out    (bitport),a;    select side 1
  329.     call    dcheck;        try to read it
  330.     ld    bc,15
  331.     ld    de,dpbd
  332.     ld    hl,.dpbd;    source, single sided dparm
  333.     ld    a,0;        single sided flag (dont chg flags)
  334.     jp    nz,selsid;    single sided if not zero.
  335.     ld    a,(dsksns+2);    is sector # > 9
  336.     cp    10;         (it must be for valid dbl sided op)
  337.     ld    a,0;         (if not, single sided drives)
  338.     jp    c,selsid;    select single sided
  339.     ld    hl,.dsdd;    source double sided dparm
  340.     ld    a,255;        proper sidflg
  341. selsid:    ld    (sidflg),a;    set up double density dparm    {}
  342.     ldir
  343.     in    a,(bitport);    return to size zero
  344.     and    not sidebit
  345.     out    (bitport),a 
  346. ;    "    "        exit
  347. den1:    ld    hl,ctrack
  348.     ld    de,tracka
  349.     ld    a,(dsk)
  350.     or    a
  351.     jp    z,dskupd;    update dsk trk, side, etc. table
  352.     ld    de,trackb
  353. dskupd:    push    bc
  354.     ld    bc,3
  355.     ldir
  356.     pop    bc
  357.     pop    de;        restore pointer to dph
  358.     pop    hl;        pointer to track(x) bios register
  359.     ret
  360. ;
  361. ; check disk legible at current format. z flag if so
  362. ; a,f
  363. dcheck:    push    hl
  364.     push    bc
  365.     ld    hl,dsksns
  366.     ld    bc,6*256+data;    6 bytes from adr. header via "data"
  367.     ld    a,(nmivec)
  368.     push    af
  369.     ld    a,retcod
  370.     ld    (nmivec),a
  371.     ld    a,adrcmd;    get address command
  372.     out    (cmnd),a;    issue command to controller
  373. dchk1:    halt;            await interrupt from controller
  374.     ini
  375.     jp    nz,dchk1
  376.     pop    af
  377.     ld    (nmivec),a
  378.     call    busy;        wait for command done
  379.     and    10h;        record not found flag
  380.     pop    bc
  381.     pop    hl
  382.     ret;            return status
  383. ;
  384. ; ready disk drive, perform physical disk select, set density bit
  385. ; a,f
  386. ready:    push    hl;        save hl
  387.     push    de;        and de
  388.     push    bc
  389.     ld    a,ficmd;    abort any controller action
  390.     out    (cmnd),a
  391.     call    diskon;        turn drive motor on
  392.     ld    a,(dsk);    A=drive #
  393.     ld    e,a;        save drive # in E
  394.     in    a,(bitport);    A=bit port
  395.     and    drvmask and denmask;    strip drive/density bits
  396.     or    e;        or in requested drive
  397.     inc    a;        bump, 01=A:    10=B:
  398.     ld    hl,denflag;    hl^ to density bit for this drive
  399.     or    (hl)
  400.     out    (bitport),a;    to bit port
  401.     pop    bc
  402.     pop    de
  403.     pop    hl
  404.     ret
  405. ;
  406. ; turn disk motor on, delay for drive speed
  407. ; a,f,b        (because .thnsd protected)
  408. diskon:    in    a,(bitport);    get current drive motor status
  409.     bit    6,a;        is motor on? (save other bits)
  410.     ret    z;        motor on, do nothing
  411.     and    not mtroff;    motor on bit
  412.     out    (bitport),a;    turn motor on
  413.     ld    b,50;        delay 1/2 second & exit
  414.     jp    .thnsd
  415. ;
  416. ; turn disk motor off
  417. ; a,f
  418. diskoff:
  419.     in    a,(bitport)
  420.     or    mtroff;        motor off bit
  421.     out    (bitport),a
  422.     ret
  423. ;
  424. subttl Writehst and Readhst logical to Physical routines
  425. ;*    WRITEHST performs the physical write to      *;
  426. ;*    the host disk, READHST reads the physical    *;
  427. ;*    disk.                         *;
  428. ;
  429. ; hstdsk = host disk #, hsttrk = host track #,
  430. ; hstsec = host sect #. write "hstsiz" bytes
  431. ; from hstbuf and return error flag in erflag.
  432. ; return erflag non-zero if error
  433. writehst:
  434.     ld    l,3;        readback retries
  435. wthst0:    ld    a,(rtry1)
  436.     ld    d,a;        reseek tries
  437. wthst1:    ld    a,(rtry2)
  438.     ld    e,a;        retry error counts
  439. wthst2:    push    hl
  440.     push    de;        save error counts
  441.     call    hstcom;        set track and sector
  442.     ld    de,hstbuf
  443.     ld    b,4;        record sector
  444.     call    wrt;        write sector into hstbuf
  445.     pop    de;        restore error flags
  446.     pop    hl
  447.     jp    z,wtchk;    good op
  448.     dec    e;        retry count
  449.     jp    nz,wthst2;    try again
  450.     dec    d;        home and reseek count
  451.     jp     z,wtchk3;    can't recover
  452.     push    hl
  453.     call    dohome;        re seek
  454.     pop    hl
  455.     jp    wthst1;        reset retry count
  456. ;
  457. ; Read back the sector to check CRC for a good write
  458. wtchk:    ld    a,(chkwrt)
  459.     or    a
  460.     ret    z;        write checking disabled
  461.     ld    b,0
  462.     in    a,(nmivec)
  463.     push    af
  464.     ld    a,retcod
  465.     ld    (nmivec),a
  466.     ld    a,rdcmd;    read it back to check CRC
  467.     out    (cmnd),a
  468. wtchk1:    halt
  469.     in    a,(data)
  470.     djnz    wtchk1
  471. wtchk2:    halt
  472.     in    a,(data)
  473.     djnz    wtchk2
  474.     pop    af
  475.     ld    (nmivec),a
  476.     call    busy
  477.     and     rdmask
  478.     call    nz,saverr;    record any soft errors
  479. wtchk3:    ld    (erflag),a
  480.     call    errmsg;        saves regs/flags, msg if a <> 0
  481.     ret    z;        either good or entry from wthst
  482.     dec    l
  483.     jp    nz,wthst0;    try again
  484.     ret;            with hardware error flags
  485. ;
  486. ; hstdsk = host disk #, hsttrk = host track #,
  487. ; hstsec = host sect #. read "hstsiz" bytes
  488. ; into hstbuf and return error flag in erflag.
  489. readhst:
  490.     ld    a,(rtry1)
  491.     ld    d,a
  492. rdhst1:    ld    a,(rtry2)
  493.     ld    e,a;        retry error counts
  494. rdhst2:    push    de;        save error counts
  495.     call    hstcom;        set track and sector
  496.     ld    de,hstbuf
  497.     ld    b,4;        record sector
  498.     call    rd;        read sector into hostbuf
  499.     ld    (erflag),a;    error return flag
  500.     pop    de;        restore error flags
  501.     ret    z;        good op
  502.     dec    e;        retry count
  503.     jp    nz,rdhst2;    try again
  504.     dec    d;        home and reseek count
  505.     call    z,errmsg;    saves regs/flags, message if a<>0
  506.     ret    z;        can't recover
  507.     call    dohome;        re seek
  508.     jp    rdhst1;        reset retry count
  509. ;
  510. hstcom:    ld    a,(hstdsk);    select disk
  511.     ld    c,a
  512.     ld    e,1;        NOT a CPM call, dont force sensing
  513.     call    dsksel
  514.     ld    hl,(hsttrk);    set track to hsttrk
  515.     ld    b,h;         one byte more than "ld bc,", and
  516.     ld    c,l;         easily tracked with ddt etc.
  517.     call    trkset;        physical seek
  518.     ld    a,(hstsec);    set physical sector
  519.     ld    c,a;        c=sector
  520.     jp    secset;        and exit
  521. ;
  522. ; show error details if a <> 0
  523. errmsg:    push    af
  524.     or    a
  525.     jp    z,errmsgx;    all well
  526. ;    "    "
  527. ; Show disk, track, sector, error kind.
  528. ; Must save and restore cursor position.
  529. ; This can foul the screen if it occurs in the midst of
  530. ; an escape sequence from the application program.
  531.     push    bc
  532.     push    de
  533.     push    hl
  534.     ld    c,esc
  535.     call    .vidout;    separate, to get orig. cursor
  536.     push    hl;        save cursor
  537.     ld    de,posn
  538.     call    .print;        position to error msg location
  539. ;    "    "
  540. ; all positioned, now we can write the error details
  541.     ld    a,(dsk)
  542.     add    'A'
  543.     ld    c,a
  544.     call    .vidout
  545.     ld    de,part2
  546.     call    .print
  547.     ld    a,(hsttrk)
  548.     call    decout
  549.     ld    de,part3
  550.     call    .print
  551.     ld    a,(hstsec)
  552.     call    decout
  553.     ld    a,(erflag)
  554.     ld    hl,errids-5
  555.     ld    de,5
  556. erm1:    add    hl,de;        at least one bit must be set
  557.     rlca
  558.     jp    nc,erm1;    find appropriate message
  559.     ex    de,hl
  560.     call    .print
  561. ;    "    "
  562. ; restore the original cursor position
  563.     ld    c,esc
  564.     call    .vidout
  565.     ld    c,'='
  566.     call    .vidout
  567.     pop    hl
  568.     push    hl
  569.     ld    c,h;        the original "y"
  570.     call    .vidout
  571.     pop    bc;        and the original "x"
  572.     call    .vidout
  573.     pop    hl
  574.     pop    de
  575.     pop    bc
  576. errmsgx:
  577.     pop    af
  578.     ret
  579. ;
  580. posn:    db    '=', 23+' ', 64+' ',0;    leaving 16 char msg space
  581. part2:    db    ': T',0
  582. part3:    db    ', S',0
  583. errids:    db    ' NRY',0;    bit 7 - not ready
  584.     db    ' WPR',0;        6 - write protect
  585.     db    ' WFT',0;        5 - write fault
  586.     db    ' RNF',0;        4 - record not found
  587.     db    ' CRC',0;        3 - CRC error
  588.     db    ' LDA',0;        2 - data overrun
  589.     db    ' DRQ',0;        1 - data not supplied
  590.     db    ' BSY',0;    bit 0 - not ready
  591. ;
  592. ; output (a) as 2 digit decimal no.
  593. ; a,f,c,h,l
  594. decout:    ld    c,'0'-1
  595. dco1:    inc    c
  596.     sub    10
  597.     jp    nc,dco1
  598.     push    af
  599.     ld    a,'0'
  600.     cp    c
  601.     call    nz,.vidout;    suppress leading zero
  602.     pop    af
  603.     add    '0'+10
  604.     ld    c,a
  605.     jp    .vidout
  606. ;
  607. ; save and record soft error counts. Save regs.
  608. saverr:    push    hl
  609.     push    af;        the error
  610.     ld    a,(dsk)
  611.     ld    hl,aerr
  612.     or    a
  613.     jp    z,saver1;    a drive
  614.     inc    hl
  615.     inc    hl;        b drive, advance pointer
  616.     inc    hl
  617. saver1:    pop    af
  618.     push    af
  619.     ld    (hl),a
  620.     inc    hl
  621.     inc    (hl);        count the error
  622.     jp    nz,saver2;    no carry
  623.     inc    hl
  624.     inc    (hl)
  625. saver2:    pop    af
  626.     pop    hl
  627.     ret
  628. ;
  629. subttl Physical disk I/O, RAM image
  630. ;
  631. ioimage:
  632. ; This area is moved to memory for execution.
  633. ; All jumps must be relative for position independance
  634. ;
  635. ; block memory move, turn rom on/off
  636. .move:    in    a,(bitport);    turn rom off
  637.     and    not bankbit
  638.     out    (bitport),a
  639.     ldir;            move logical sector from hstbuf
  640.     in    a,(bitport);    turn rom back on
  641.     or    bankbit
  642.     out    (bitport),a
  643.     ret;            back to rom
  644. ;
  645. ; read a sector into de^
  646. ; return    A=0 for no errors,
  647. ;        A=1 for non-recoverable error
  648. ; if b=1 128, b=2 256, b=3 384, b=4 512   bytes/sector
  649. .rd:    ld    hl,rdmask*256+rdcmd;    d=read status mask
  650.     jr    action;            e=read command
  651. ;
  652. ; write a sector from de^
  653. ; return as per read from de^.
  654. ; b is sector length in 128 byte records
  655. .wrt:    ld    hl,wrtmask*256+wrtcmd;    d=status mask, 
  656. ;    "    "            e=write command
  657. ;    "    "
  658. action:    ex    de,hl
  659.     call    ready;        make sure drive is on and ready
  660.     di;            no interrupts during disk I/O
  661.     in    a,(bitport);    turn rom off
  662.     and    not bankbit
  663.     out    (bitport),a
  664.     ld    a,(nmivec)
  665.     push    af
  666.     ld    a,retcod
  667.     ld    (nmivec),a;    set up nmi vector
  668.     ld    a,b;        sector multiple
  669.     ld    bc,128*256+data; b=sector length, c=data port
  670.     bit    0,a;        if 0 then 256 or 512 bytes/sector
  671.     jr    nz,actn;    b set for 128 or 384 bytes/sector
  672.     ld    b,0;        b set for 256 or 512 bytes/sector
  673. actn:    cp    1;        compute entry point 1st or 2nd loop
  674.     push    psw;        save as Z flag
  675.     ld    a,e;        i/o command
  676.     cp    wrtcmd;        a write?
  677.     jr    z,wstart;    start write command
  678. ;    "    "
  679.     out    (cmnd),a;    fall through to read loop
  680.     pop    psw
  681.     jr    z,rl2
  682. rl1:    halt;            wait for controller
  683.     ini
  684.     jr    nz,rl1
  685. rl2:    halt
  686.     ini
  687.     jr    nz,rl2
  688.     jr    done;        read loop done, exit
  689. ;
  690. wstart:    out    (cmnd),a;    write loop
  691.     pop    psw
  692.     jr    z,wl2
  693. wl1:    halt
  694.     outi
  695.     jr    nz,wl1
  696. wl2:    halt
  697.     outi
  698.     jr    nz,wl2
  699. ;     "     "
  700. done:    pop    af;        byte at nmi vector address
  701.     ld    (nmivec),a;    restore it
  702.     in    a,(bitport);    turn rom back on
  703.     or    bankbit
  704.     out    (bitport),a
  705.     ei;            turn interrupts on
  706.     call    busy;        get status when contoller not busy
  707.     and    d;        status mask
  708.     jp    nz,saverr;    If soft error record it & exit
  709.     ret;            with any non-zero error code
  710. ;
  711. ; This section defines the disk parameters
  712. ; (dph's are images moved to RAM)
  713. .dpha:    dw    0,0,0,0;    dph for unit A:
  714.     dw    dirbuf,dpbd;    directory buffer, Disk Param. Block
  715.     dw    csva, alva;    check sum pointer, alloc. map ptr
  716.     db    ddbit;        density flag for this drive
  717. ;
  718. .dphb:    dw    0,0,0,0;    dph for unit B:
  719.     dw    dirbuf,dpbd;    directory buffer, Disk Param. Block
  720.     dw    csvb, alvb;    check sum pointer, alloc. map ptr.
  721.     db    ddbit;        density flag for this drive
  722. ;
  723. ; ( single density );
  724. .dpbs:    dw    18;        (spt) sectors per track
  725.     db    3;        (bsh) block shift factor
  726.     db    7;        (blm) block mask
  727.     db    0;        (exm) extent mask
  728.     dw    82;        (dsm) max logical block #
  729.     dw    31;        (drm) max directory #
  730.     db    80H;        (al0) directory allocation map
  731.     db    00H;        (al1)
  732.     dw    8;        (cks) size of dir. check vector
  733.     dw    3;        (off) reserved tracks
  734. ;
  735. ; ( single sided/double density ) moved in as needed
  736. .dpbd:    dw    40;        (spt) sectors per track
  737.     db    3;        (bsh) block shift factor
  738.     db    7;        (blm) block mask
  739.     db    0;        (exm) extent mask
  740.     dw    194;        (dsm) max logical block #
  741.     dw    63;        (drm) max directory #
  742.     db    0F0H;        (al0) dir. alloc. map/BIOS space
  743.     db    00H;        (al1)
  744.     dw    16;        (cks) size of directory check vector
  745.     dw    1;        (off) reserved tracks
  746. ;
  747. ; sector interleave table  ( single density ). Kept in RAM
  748. .tbl1:    db    1,6,11,16
  749.     db    3,8,13,18
  750.     db    5,10,15,2
  751.     db    7,12,17,4
  752.     db    9,14
  753. ;
  754. .imgend:
  755. imaglen    equ    .imgend-ioimage;    length of this image
  756. ;
  757. ; Following only initialized on cold boot (power on)
  758. .ckwrt:    db    0ffh;        initializer, check for good writes
  759. .rtry1:    db    tries1;            (0th table entry special)
  760. .rtry2:    db    tries2;            initial error retry counts
  761. .adata:    db    0,0,0;        last error and soft error counts
  762. .bdata:    db    0,0,0;        and the same for the "b" drive
  763. .ckend:
  764. ;
  765. ; ( double sided/double density). Moved in as needed
  766. .dsdd:    dw    40;        (spt) sectors per track
  767.     db    4;        (bsh) block shift factor
  768.     db    0fh;        (blm) block mask
  769.     db    1;        (exm) extent mask
  770.     dw    196;        (dsm) max logical block
  771.     dw    63;        (drm) max directory #
  772.     db    0c0h;        (al0) dir. alloc. map & bios space
  773.     db    0;        (al1)
  774.     dw    16;        (cks) size of directory check vector
  775.     dw    1;        (off) reserved tracks
  776. ;
  777. ; ----------------------------------------------------------
  778. ; NOTE: the data segment is placed after the code segment 
  779. ; because storage lengths depend on the code to be moved in
  780. ; ----------------------------------------------------------
  781.     dseg
  782. ;
  783. ;
  784. ; Disk operations - requested values
  785. sekdsk:    ds    1;    disk requested
  786. sektrk:    ds    2;    track number
  787. seksec:    ds    1;    sector number
  788. ;
  789. dsk:    ds    1;    current disk drive
  790. ctrack: ds    1;    track number (real) for current drive
  791. denflag: ds    1;    density flag for current drive
  792. sidflg:    ds    1
  793. tracka:    ds    3;    Drive A track (255 means density unknown)
  794. trackb:    ds    3;    Drive B track (255 means density unknown)
  795. csva:    ds    16;    Drive A directory check
  796. alva:    ds    26;    Drive A allocation map
  797. csvb:    ds    16;    Drive B directory check
  798. alvb:    ds    26;    Drive B allocation map
  799. ;
  800. ;    Routines inserted on power-on start
  801. ; ** THIS AREA MUST MATCH THE CODE ABOVE, moved in **
  802. ;
  803. move:    ds    .rd-.move;    move mem blocks, callable from rom
  804. rd:    ds    .wrt-.rd;    read physical sector size b, to de^
  805. wrt:    ds    .dpha-.wrt;    write physical sect size b from de^
  806. ;    END of installed routines
  807. ;
  808. ; Disk drive stuff, initialized on power-on start
  809. ;
  810. ; Disk paramater blocks etc
  811. dpha:    ds    .dphb-.dpha;    dph for A
  812. dphb:    ds    .dpbs-.dphb;    dph for B
  813. dpbs:    ds    .dpbd-.dpbs;    single density disk param blk
  814. dpbd:    ds    .tbl1-.dpbd;    double density disk param blk
  815. tbl1:    ds    .imgend-.tbl1;    single density skew table
  816. ;
  817. ; Any disk error parameters follow CHKWRT.  HOME returns a pointer
  818. ; to chkwrt (in hl), to allow external systems to modify. 
  819. ; An unmodified Kaypro returns a pointer to page 0, so we can
  820. ; tell them apart.
  821. ; MAKE SURE these agree with declaration from .chkwrt on in code
  822. chkwrt:    ds    1;        init true, check for good writes
  823. rtry1:    ds    1
  824. rtry2:    ds    1
  825. ;
  826. ; Following counts etc measured from last cold start time
  827. aerr:    ds    1;        last soft error on "a"
  828. aerrct:    ds    2;        count of soft errors on "a"
  829. berr:    ds    1;        last soft error on "b"
  830. berrct:    ds    2;        count of soft errors on "b"
  831. ; Can add further disk drives here.  Use only for this structure
  832. ;
  833. ; ** ------- END of moved in area --------- **
  834. ;
  835. ; Storage
  836. dsksns:    ds    6;    buffer for disk trk/adr data
  837. ;
  838. dirbuf:    ds    128;    CP/m directory buffer
  839. ;
  840.     end
  841.