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 / CPM / PACKET / RLI120.ARK / CBIOS.MAC < prev    next >
Text File  |  1986-08-12  |  24KB  |  1,200 lines

  1. ; CBIOS.MAC - 3/9/86 The real BIOS for the Xerox.
  2. ; This loads itself using the SBIOS.
  3. ; It takes the place of the Xerox PROM code.
  4. ; Xerox CBIOS Version 10.6 (For MailBox/GateWay version 10.x).
  5. ; Thanks to k1bc, ke1g, ki4xo for help with the bios code.
  6. ; Bigboard I mods from n6fqr
  7.  
  8.     .z80
  9.     .xlist
  10.     maclib    TNC.LIB
  11.     timdef
  12.     asciictl
  13.     .list
  14.  
  15. false    equ    0
  16. true    equ    not false
  17.  
  18.     maclib    BIOSCPM.INC    ; CP/M addresses
  19.     maclib    BIOSDSKE.INC    ; Disk equates
  20.  
  21. ; Parallel keyboard port:
  22. ; Set keyreg to true to use a "normal" keyboard.
  23. ; Set to false and set keyxor if:
  24. ; the high order bit is set to one for control shift,
  25. ; then use ffh, if it is set to zero then use 7fh
  26.  
  27. keyreg    equ    true    ; I have funny keyboards.
  28. keyxor    equ    0ffh    ; 7fh for Sperry, 0ffh for Honeywell kbd
  29.  
  30. ; What to do with the PRINTER port.
  31. ; Set ONE of these tags to true.
  32.  
  33. pistnc    equ    true    ; Second TNC, 4800 baud, 8 bit, no parity.
  34. piscon    equ    false    ; Console, 9600 baud, 8 bit, no parity.
  35. pispr    equ    false    ; Printer, 9600 baud, 7 bit, even parity.
  36.  
  37. ; How to handshake the serial ports.
  38.  
  39. hdwhnd    equ    false    ; True if hdw handshake works
  40. xon    equ    dc1    ; dc1 or bs
  41. xoff    equ    dc3    ; dc3 or ' '
  42.  
  43. ; What to do with the parallel user port.
  44.  
  45. parlst    equ    true    ; True to use par port for list device.
  46.  
  47. clk4    equ    false    ; Set true if 4 Mhz system clock
  48.  
  49. ; Ram Allocation
  50.  
  51. ivec    equ    0ff00h    ; Interrupt vector page.
  52. defbuf    equ    80h    ; Default CPM Disk buffer area
  53. nmivec    equ    66h    ; Where Z80 traps on non-maskable interrupt
  54.  
  55. ; I/O ports:
  56.  
  57. ; COMM port (SIO A)
  58.  
  59. pu1st    equ    6
  60. pu1dat    equ    4
  61. pu1cts    equ    20h
  62. pu1dcd    equ    8
  63. pu1tbe    equ    4
  64. pu1spd    equ    0        ; Baud rate generator for channel A
  65. pu1buf    equ    bufbas        ; Must be on page boundary
  66. pu1siz    equ    256        ; Input buffer size
  67.  
  68. ; PRINTER port (SIO B)
  69.  
  70. pu2st    equ    7
  71. pu2dat    equ    5
  72. pu2cts    equ    20h
  73. pu2dcd    equ    8
  74. pu2tbe    equ    4
  75. pu2spd    equ    0ch        ; Baud rate generator for channel B
  76. pu2buf    equ    pu1buf+pu1siz    ; Must be on page boundary
  77. pu2siz    equ    256        ; Input buffer size
  78.  
  79. ; Keyboard port.
  80.  
  81. pu3dat    equ    1eh        ; Keyboard data port of PIO
  82. pu3st    equ    1fh        ; Keyboard control port of PIO
  83. pu3buf    equ    pu2buf+pu2siz    ; Must be on page boundary
  84. pu3siz    equ    16         ; Must be pwr of 2 and <= 256
  85.  
  86. ; Misc system ports.
  87.  
  88. pio.ad    equ    8    ; PIO channel A, Data port
  89. pio.as    equ    9    ; PIO channel A, Sts/Ctrl port
  90. pio.bd    equ    0ah    ; PIO channel B, Data port
  91. pio.bs    equ    0bh    ; PIO channel B, Sts/Ctrl port
  92.  
  93. fdc.cs    equ    10h    ; 1771 Disc Controller: Ctrl/Status
  94. fdc.tk    equ    11h    ; 1771 Disc Controller: Cylinder/track
  95. fdc.se    equ    12h    ; 1771 Disc Controller: Sector
  96. fdc.da    equ    13h    ; 1771 Disc Controller: Data
  97.  
  98. crt.sc    equ    14h    ; CRT Scroll control register
  99.  
  100. ctc.c0    equ    18h    ; Counter/Timer Chip Channel 0
  101. ctc.c1    equ    19h    ; Counter/Timer Chip Channel 1
  102. ctc.c2    equ    1ah    ; Counter/Timer Chip Channel 2
  103. ctc.c3    equ    1bh    ; Counter/Timer Chip Channel 3
  104.  
  105. pio.sd    equ    1ch    ; Data port of system PIO
  106. pio.sc    equ    1dh    ; Control port of system PIO
  107.  
  108. ; Bit numbers for bit, res,and set instructions
  109.  
  110. b0    equ    0
  111. b1    equ    1
  112. b2    equ    2
  113. b3    equ    3
  114. b4    equ    4
  115. b5    equ    5
  116. b6    equ    6
  117. b7    equ    7
  118.  
  119. ; This section is the loader code. It runs as a normal .COM file.
  120. ; It sets up the interrupt vectors, then moves the BIOS
  121. ; code to upper memory where it belongs.
  122.  
  123.     aseg
  124.     org    100h
  125.  
  126. ; Initialize the I/O devices.
  127.  
  128.     di            ; Start with interrupts off
  129.     ld    hl,inivio    ; Set up initial I/O variables
  130. initio:    ld    b,(hl)        ; Get count of I/O setup data bytes
  131.     inc    hl
  132.     ld    c,(hl)        ; To be stuffed into this I/O port
  133.     inc    hl        ; Point at data bytes
  134.     otir            ; Set up the I/O device
  135.     bit    b7,(hl)        ; Check for end of setup blocks
  136.     jr    z,initio    ; Loop over all I/O setups
  137.  
  138. ; Set the processor to proper interrupt state.
  139.  
  140.     ld    a,ivec shr 8    ; I/O vector page
  141.     ld    i,a        ; Set processor for vectored interrupts
  142.     im    2
  143.  
  144. ; Set up the interrupt vectors.
  145.  
  146.     ld    hl,livec    ; Point to local copy
  147.     ld    de,ivec        ; Point to where they go
  148.     ld    bc,livecl    ; How many bytes
  149.     ldir            ; Move them there
  150.  
  151. ; Move the BIOS code to its execution area.
  152.  
  153.     ld    hl,bsbgn
  154.     ld    de,bios
  155.     ld    bc,bslen
  156.     ldir
  157.     ei
  158.     jp    bios        ; Go do it.
  159.  
  160. ; I/O port initialization values.
  161. ; Organized for copying loop above, these are in the form:
  162. ; one byte count
  163. ; one byte port number
  164. ; n bytes of port initialization values
  165. ; followed by another block, or "FF" to mark the end of the list
  166.  
  167. inivio:
  168.     if    parlst
  169.     db    1,pio.as
  170.     db    0fh        ; Output mode on PIO port A
  171.     db    2,pio.bs
  172.     db    0cfh        ; BIT mode on PIO port B
  173.     db    0fh        ; BITS 7..4 outputs, BITS 3..0 inputs
  174.     db    1,pio.ad
  175.     db    0d0h        ; Strobe bit negated
  176.     endif
  177.  
  178.     db    3,pio.sc    ; PIO for system control port
  179.     db    0cfh,38h,40h    ; Change 38 to 18 for bell
  180.  
  181.     db    1,pio.sd
  182.     db    0        ; Init system control port data
  183.  
  184.     db    3,pu3st        ; PIO control for keyboard
  185.     db    4fh
  186.     db    ivkbd and 0ffh    ; Vector location
  187.     db    83h
  188.  
  189.     db    1,ctc.c0    ; Chan 0 of CTC
  190.     db    ivctc and 0ffh
  191.  
  192.     db    2,ctc.c2    ; Chan 2 of CTC
  193.     if    clk4
  194.     db    27h,168        ; Each tick = 10.752 Ms.
  195.     else
  196.     db    27h,105        ; Each tick = 10.752 Ms.
  197.     endif
  198.  
  199.     db    2,ctc.c3    ; Chan 3 of CTC
  200.     db    0c7h,93        ; Counts of ch 2 = 1 sec.
  201.  
  202. ; Baud rates for the SIO ports.
  203.  
  204.     db    1,pu1spd    ; SIO port A baud rate
  205.     db    12        ; 4800 baud for COMM port.
  206.     db    1,pu2spd    ; SIO port B baud rate
  207.     if    pistnc
  208.     db    12        ; 4800 baud for PRINTER port.
  209.     else
  210.     db    14        ; 9600 baud
  211.     endif
  212.  
  213. ; SIO port A (COMM port).
  214.  
  215.     db    pu1inl,pu1st    ; Count, port
  216. pu1ini:    db    18h        ; Reset
  217.     db    14h,44h        ; A reg 4 - x16, 1 stop, no par
  218.     db    13h,0c1h    ; A reg 3 - 8 bit, rx enable
  219.     db    15h,0eah    ; A reg 5 - DTR, RTS, 8 bit, tx enable
  220.     db    11h,19h    ; A reg 1 - rx int all char, external
  221. pu1inl    equ    $-pu1ini
  222.  
  223. ; SIO port B (PRINTER port).
  224.  
  225.     db    pu2inl,pu2st    ; Count, port
  226. pu2ini:
  227.     if    pispr
  228.     db    18h        ; Reset
  229.     db    14h,43h        ; B reg 4 - x16, 1 stop, even par
  230.     db    13h,40h        ; B reg 3 - 7 bit, no rx
  231.     db    15h,0aah    ; B reg 5 - DTR, RTS, 7 bit, tx enable
  232.     db    12h,(ivsio and 0ffh)    ; B reg 2 - Int addr
  233.     db    11h,5h    ; B reg 1 - rx off, ext, status affects vect
  234.     else
  235.     db    18h        ; Reset
  236.     db    14h,44h        ; B reg 4 - x16, 1 stop, no par
  237.     db    13h,0c1h    ; B reg 3 - 8 bit, rx enable
  238.     db    15h,0eah    ; B reg 5 - DTR, RTS, 8 bit, tx enable
  239.     db    12h,(ivsio and 0ffh)    ; B reg 2 - Int addr
  240.     db    11h,1dh    ; B reg 1 - rx all, ext, status affects vect
  241.     endif
  242. pu2inl    equ    $-pu2ini
  243.  
  244.     db    0ffh     ; End of I/O initializer list
  245.  
  246. ; Local copy of the interrupt vectors.
  247. ; Moved to the interrupt page at initialization time.
  248.  
  249. livec:
  250.  
  251. ; SIO vectors.
  252.  
  253. ivsio    equ    ivec+($-livec)
  254.     dw    0
  255.     dw    pu2ext
  256.     dw    pu2ihd
  257.     dw    pu2err
  258.     dw    0
  259.     dw    pu1ext
  260.     dw    pu1ihd
  261.     dw    pu1err
  262.  
  263. ; CTC interrupt vectors.
  264.  
  265. ivctc    equ    ivec+($-livec)
  266.     dw    0        ; CTC 0, not used.
  267.     dw    ctcint        ; Handler for timer (1 Ms ticks)
  268.     dw    0        ; CTC 2, prescale for clock.
  269.     dw    clkint        ; Handler for clock (seconds tick)
  270.  
  271. ; Keyboard PIO vectors.
  272.  
  273. ivkbd    equ    ivec+($-livec)
  274.     dw    pu3ihd        ; Handler for keyboard
  275.     dw    0
  276.     dw    0
  277.     dw    0
  278. livecl    equ    $-livec
  279.  
  280. ; Here is the bios code. It is moved to its real location
  281. ; by the loader code above.
  282.  
  283. bsbgn    equ    $        ; Start of BIOS code
  284.  
  285.     .phase    bios    ; Assemble correct addresses
  286.  
  287.     maclib    BIOSJMP.INC    ; Makes the BIOS jump table
  288.  
  289. ; Console.
  290. ; pu0 is keyboard/video + PRINTER, controled by pistnc/piscon/pispr
  291. ; pu1 is COMM port (SIO A)
  292. ; pu2 is PRINTER port (SIO B)
  293. ; pu3 is keyboard/video
  294. ; pu4 is parallel port on PIO
  295.  
  296. ; Console status
  297.  
  298. const:    ld    a,(3)    ; Iobyte
  299.     or    a
  300.     jr    z,pu0ist
  301.     dec    a
  302.     jr    z,pu1ist
  303.  
  304.     if    pistnc
  305.  
  306. pu2ist:    ld    a,(pu2ict)
  307.     or    a
  308.     jr    z,pu2isu
  309.     ld    a,0ffh
  310.     ret
  311. pu2isu:    ld    a,(pu2off)
  312.     or    a
  313.     ret    z        ; Not off
  314.     if    hdwhnd
  315.     di
  316.     ld    a,5
  317.     out    (pu2st),a
  318.     ld    a,0eah
  319.     out    (pu2st),a    ; Turn TNC on
  320.     else
  321.     push    bc
  322.     ld    c,xon
  323.     call    pu2ot        ; Send the xon to the tnc
  324.     pop    bc
  325.     di
  326.     endif
  327.     xor    a
  328.     ld    (pu2off),a
  329.     ei
  330.     ret            ; With zero set
  331.  
  332.     else
  333.  
  334. pu2ist:    ld    a,(pu2ict)
  335.     or    a
  336.     ret    z
  337.     ld    a,0ffh
  338.     ret
  339.  
  340.     endif
  341.  
  342. pu1ist:    ld    a,(pu1ict)
  343.     or    a
  344.     jr    z,pu1isu
  345.     ld    a,0ffh
  346.     ret
  347. pu1isu:    ld    a,(pu1off)
  348.     or    a
  349.     ret    z        ; Not off
  350.     if    hdwhnd
  351.     di
  352.     ld    a,5
  353.     out    (pu1st),a
  354.     ld    a,0eah
  355.     out    (pu1st),a    ; Turn TNC on
  356.     else
  357.     push    bc
  358.     ld    c,xon
  359.     call    pu1ot
  360.     pop    bc
  361.     di
  362.     endif
  363.     xor    a
  364.     ld    (pu1off),a
  365.     ei
  366.     ret
  367.  
  368. pu0ist:    if    piscon
  369.     call    pu2ist
  370.     ret    nz
  371.     endif
  372.  
  373. pu3ist:    ld    a,(pu3ict)    ; Anything in ring buffer?
  374.     or    a
  375.     ret    z        ; Return Z if not
  376.     ld    a,0ffh        ; Yes, return non-Z and A/ FF
  377.     ret
  378.  
  379. ; Console input
  380.  
  381. conin:    ld    a,(3)    ; Iobyte
  382.     or    a
  383.     jr    z,pu0inp
  384.     dec    a
  385.     jr    z,pu1inp
  386.  
  387. pu2inp:    call    pu2ist
  388.     jr    z,pu2inp
  389.     ld    hl,(pu2gpt)
  390.     ld    a,(hl)
  391.     inc    l
  392.     ld    (pu2gpt),hl
  393.     ld    hl,pu2ict
  394.     dec    (hl)
  395.     ret
  396.  
  397. pu1inp:    call    pu1ist
  398.     jr    z,pu1inp
  399.     ld    hl,(pu1gpt)
  400.     ld    a,(hl)
  401.     inc    l
  402.     ld    (pu1gpt),hl
  403.     ld    hl,pu1ict
  404.     dec    (hl)
  405.     ret
  406.  
  407. pu0inp:    if    piscon
  408.     call    pu2ist
  409.     jr    nz,pu2inp
  410.     endif
  411.     call    pu3ist
  412.     jr    z,pu0inp
  413.  
  414. ; Return character from keyboard. Wait if needed.
  415.  
  416. pu3inp:    call    pu3ist        ; Anything there yet?
  417.     jr    z,pu3inp    ; Wait if not
  418.     push    hl        ; Yes, save hl pair
  419.     ld    hl,pu3ict    ; One less char in ring
  420.     dec    (hl)
  421.     ld    hl,pu3gpt    ; Point at ring taker
  422.     call    pu3ibp        ; Get the char
  423.     pop    hl        ; Restore regs
  424.     ret            ; Return char in A
  425.  
  426. ; Console output
  427.  
  428. conout:    ld    a,(3)    ; Iobyte
  429.     or    a
  430.     jr    z,pu0ot
  431.     dec    a
  432.     jr    z,pu1ot
  433.  
  434.     if    pistnc
  435.  
  436. pu2ot:    in    a,(pu2st)
  437.     and    pu2dcd
  438.     ret    z        ; TNC is off
  439. pu2ota:    in    a,(pu2st)
  440.     and    pu2tbe
  441.     jr    z,pu2ota
  442. pu2otb:    in    a,(pu2st)
  443.     and    pu2cts
  444.     jr    z,pu2otb
  445.     ld    a,c
  446.     out    (pu2dat),a
  447.     ret
  448.  
  449.     else
  450.  
  451. pu2ot:    call    pu2ost
  452.     jr    z,pu2ot
  453.     ld    a,c
  454.     out    (pu2dat),a
  455.     ret
  456.  
  457. pu2ost:    in    a,(pu2st)
  458.     and    pu2tbe
  459.     ret    z
  460.     ld    a,0ffh
  461.     ret
  462.  
  463.     endif
  464.  
  465. pu1ot:    in    a,(pu1st)
  466.     and    pu1dcd
  467.     ret    z        ; TNC is off
  468. pu1ota:    in    a,(pu1st)
  469.     and    pu1tbe
  470.     jr    z,pu1ota
  471. pu1otb:    in    a,(pu1st)
  472.     and    pu1cts
  473.     jr    z,pu1otb
  474.     ld    a,c
  475.     out    (pu1dat),a
  476.     ret
  477.  
  478. pu0ot:    call    pu3ot
  479.     if    piscon
  480.     jr    pu2ot
  481.     else
  482.     ret
  483.     endif
  484.  
  485.     if    parlst
  486. pu4ot:    in    a,(pio.bd)    
  487.     and    2        
  488.     jr    nz,pu4ot    
  489.     ld    a,c        
  490.     out    (pio.ad),a    
  491.     push    af
  492.     di
  493.     in    a,(pio.bd)
  494.     res    4,a        
  495.     out    (pio.bd),a    
  496.     set    4,a        
  497.     out    (pio.bd),a
  498.     ei
  499.     pop    af
  500.     ret
  501.  
  502. pu4ost:    in    a,(pio.bd)    
  503.     and    2        
  504.     jr    nz,pu4osa    
  505.     ld    a,0ffh
  506.     or    a        
  507.     ret
  508. pu4osa:    xor    a
  509.     ret
  510.     endif
  511.  
  512. ; CP/M list device.
  513.  
  514.     if    pispr
  515. list    equ    pu2ot
  516. listst    equ    pu2ost
  517.     endif
  518.  
  519.     if    parlst
  520. list    equ    pu4ot
  521. listst    equ    pu4ost
  522.     endif
  523.  
  524.     if    (not pispr) and (not parlst)
  525. list    equ    pu0ot
  526. listst:    ld    a,0ffh        ; Return always ready
  527.     or    a
  528.     ret
  529.     endif
  530.  
  531. ; Punch and reader are not used.
  532.  
  533. punch    equ    conout
  534. reader    equ    conin
  535.  
  536. ; Increment pu3inp buffer pointer.
  537.  
  538. pu3ibp:    ld    a,(hl)        ; Pick up putter or taker low bits
  539.     inc    a        ; Step the pointer
  540.     and    pu3siz-1    ; Wrap within ring
  541.     ld    (hl),a        ; Update pointer
  542.     ld    hl,pu3buf    ; Now find the char it points to
  543.     add    a,l
  544.     ld    l,a
  545.     ld    a,(hl)        ; Pick up the character, for taker case
  546.     ret
  547.  
  548. ; The interrupt code.
  549.  
  550. pu1no:    ld    a,(pu1off)
  551.     or    a
  552.     ret    nz        ; Already off
  553.     cpl
  554.     ld    (pu1off),a
  555.     if    hdwhnd
  556.     ld    a,5
  557.     out    (pu1st),a
  558.     ld    a,0e8h
  559.     out    (pu1st),a
  560.     else
  561.     ld    c,xoff
  562.     call    pu1ot
  563.     endif
  564.     ret
  565.  
  566. pu2no:    ld    a,(pu2off)
  567.     or    a
  568.     ret    nz        ; Already off
  569.     cpl
  570.     ld    (pu2off),a
  571.     if    hdwhnd
  572.     ld    a,5
  573.     out    (pu2st),a
  574.     ld    a,0e8h
  575.     out    (pu2st),a
  576.     else
  577.     ld    c,xoff
  578.     call    pu2ot
  579.     endif
  580.     ret
  581.  
  582. pu1err:    ex    af,af'
  583.     in    a,(pu1dat)
  584.     ld    a,30h
  585.     jr    pu1xx
  586.  
  587. pu1ext:    ex    af,af'
  588.     in    a,(pu1st)
  589.     ld    a,10h
  590. pu1xx:    out    (pu1st),a
  591.     jr    iret2
  592.  
  593. pu1ihd:    ex    af,af'
  594.     exx
  595.     ld    hl,(pu1ppt)
  596.     in    a,(pu1dat)
  597.     ld    (hl),a
  598.     inc    l
  599.     ld    (pu1ppt),hl
  600.     ld    hl,pu1ict
  601.     inc    (hl)
  602.     ld    a,(hl)
  603.     cp    pu1siz-8
  604.     call    z,pu1no
  605.     jr    iret1
  606.  
  607. pu2err:    ex    af,af'
  608.     in    a,(pu2dat)
  609.     ld    a,30h
  610.     jr    pu2xx
  611.  
  612. pu2ext:    ex    af,af'
  613.     in    a,(pu2st)
  614.     ld    a,10h
  615. pu2xx:    out    (pu2st),a
  616.     jr    iret2
  617.  
  618. pu2ihd:    ex    af,af'
  619.     exx
  620.     ld    hl,(pu2ppt)
  621.     in    a,(pu2dat)
  622.     ld    (hl),a
  623.     inc    l
  624.     ld    (pu2ppt),hl
  625.     ld    hl,pu2ict
  626.     inc    (hl)
  627.     ld    a,(hl)
  628.     cp    pu2siz-8
  629.     call    z,pu2no
  630.     jr    iret1
  631.  
  632. ; Keyboard interrupt handler.
  633.  
  634. pu3ihd:    exx            ; Save registers
  635.     ex    af,af'
  636.     in    a,(pu3dat)    ; Get the keyboard data
  637.     if    keyreg
  638.     cpl            ; Invert inverted data
  639.     and    7fh        ; Bit 7 = 0
  640.     else
  641.  
  642. ; Fix for control chars from keyboard
  643.  
  644.     xor    keyxor
  645.     jp    p,xx
  646.     and    1fh
  647.     endif
  648. xx:    ld    c,a        ; Char to add to ring
  649.     ld    hl,pu3ict    ; Ring fullness count
  650.     ld    a,(hl)        ; Pick up count
  651.     inc    a        ; Add one more character
  652.     cp    pu3siz        ; Ring full?
  653.     jr    nc,iret1    ; Don't add another char, if full
  654.     ld    (hl),a        ; OK, add this one
  655.     ld    hl,pu3ppt    ; Point at ring putter
  656.     call    pu3ibp        ; Compute address and wrap
  657.     ld    (hl),c        ; Put char in ring
  658. iret1:    exx
  659. iret2:    ex    af,af'
  660.     ei
  661.     reti
  662.  
  663. pu1ppt:    dw    pu1buf
  664. pu1gpt:    dw    pu1buf
  665. pu1ict:    db    0
  666. pu1off:    db    0
  667.  
  668. pu2ppt:    dw    pu2buf
  669. pu2gpt:    dw    pu2buf
  670. pu2ict:    db    0
  671. pu2off:    db    0
  672.  
  673. pu3ppt:    db    0
  674. pu3gpt:    db    0
  675. pu3ict:    db    0
  676.  
  677. ; Disk handler.
  678.  
  679.     maclib    BIOSDPB.INC
  680.  
  681. ; Sector translate
  682.  
  683. sectrn:    ex    de,hl
  684.     add    hl,bc
  685.     ld    l,(hl)
  686.     ld    h,0
  687.     ret
  688.  
  689. ; Select drive
  690.  
  691. seldsk:    ld    hl,0        ; Assume bad staus
  692.     ld    a,c
  693.     cp    mxdrv
  694.     ret    nc        ; No such drive
  695.     ld    (drive),a
  696.     ld    l,c
  697.     add    hl,hl
  698.     add    hl,hl
  699.     add    hl,hl
  700.     add    hl,hl
  701.     ld    de,dpe0
  702.     add    hl,de
  703.     ret
  704.  
  705. ; Do the actual select.
  706.  
  707. select:    ld    a,(drive)    ; Get drive wanted
  708.     ld    hl,ldrive    ; Point at last drive used
  709.     cp    (hl)        ; Same one?
  710.     ret    z        ; Yes, do nothing.
  711.     cp    4        ; Is it 4 or more?
  712.     ret    nc        ; Return if so, no good.
  713.     ld    e,(hl)        ; Get the old one
  714.     ld    (hl),a        ; Save current, committed now
  715.     ld    c,a        ; Save a copy
  716.     ld    a,e        ; The previous drive.
  717.     cp    0ffh        ; was there really one?
  718.     jr    z,selec1    ; No, no need to save the track.
  719.     ld    hl,trkvec    ; Point at track slot
  720.  
  721.     if    xrxsds
  722.     ld    a,e
  723.     and    1        ; make the two sides of the same
  724.     ld    e,a        ; point to the same track save
  725.     endif
  726.  
  727.     ld    d,0
  728.     add    hl,de        ; for the old drive
  729.     in    a,(fdc.tk)    ; Read old track number
  730.     ld    (hl),a        ; Put it in vector for next use of drive
  731. selec1:    in    a,(pio.sd)    ; Turn off the drive/side select bits so that
  732.     and    0f8h        ;  first call to diskup will set them.
  733.     if    bigbrd
  734.     or    4        ; Deselct the drive
  735.     endif
  736.     out    (pio.sd),a
  737.     ld    hl,trkvec    ; Now get track of new drive
  738.  
  739.     if    xrxsds
  740.     ld    a,c
  741.     and    1        ; make the two sides of the same
  742.     ld    c,a        ;  point to the same track save
  743.     endif
  744.  
  745.     ld    b,0
  746.     add    hl,bc
  747.     ld    a,(hl)
  748.     cp    0ffh        ; If unknown, home this drive
  749.     jr    z,homea
  750.     out    (fdc.tk),a    ; Else tell 1771 where the head is
  751.     xor    a        ; Return Z, success
  752.     ret
  753.  
  754. ; Home the drive
  755.  
  756. home:    call    select
  757. homea:    call    diskup        ; Get the drive up to speed first
  758.     ret    nz        ; Return if can't
  759.     xor    a        ; OK, set cylinder to zero
  760.     ld    (track),a
  761. homeb:    ld    b,0ch        ; Set seek track 0 command
  762.     call    fdcsek        ; Go do it
  763.     xor    4        ; Set up error bits for return
  764.     and    9ch
  765.     ret
  766.  
  767. ; Set track.
  768.  
  769. settrk:    ld    a,c
  770.     ld    (track),a
  771.     ret
  772.  
  773. ; Set sector.
  774.  
  775. setsec:    ld    a,c
  776.     ld    (sect),a
  777.     ret
  778.  
  779. ; Set dma address.
  780.  
  781. setdma:    ld    (dmaadr),bc
  782.     ret
  783.  
  784. ; Read a sector.
  785.  
  786. read:    call    setup
  787.     call    z,rdsec
  788.     ret
  789.  
  790. ; Write a sector.
  791.  
  792. write:    call    setup
  793.     call    z,wtsec
  794.     ret
  795.  
  796. setup:
  797.     if    pistnc
  798.     call    pu2no
  799.     endif
  800.     call    pu1no
  801.     call    select
  802.     jp    seek
  803.  
  804. ; Reload CCP + BDOS.
  805.  
  806. ; Set up stuff in low memory for CP/M.
  807.  
  808. ; loadit is the entry point
  809.  
  810. lderrm:    db    ff,'Disk error loading DOS, type any character to retry.',0
  811. lderr:    ld    hl,lderrm
  812.     call    putstr
  813.     call    pu3inp        ; May want to be pu0inp
  814. loadit:    ld    a,0c3h
  815.     ld    (0),a
  816.     ld    (5),a
  817.     ld    hl,bios+3
  818.     ld    (1),hl
  819.     ld    hl,bdos+6
  820.     ld    (6),hl
  821.     xor    a
  822.     ld    (drive),a
  823. ;    ld    e,1        ; To force loggin of disk.
  824.     call    home
  825.     or    a        ; check for errors
  826.     jr    nz,lderr    ; woops!
  827.     ld    a,cpmsec
  828.     ld    (sect),a
  829.     ld    hl,ccp
  830.     ld    (dmaadr),hl
  831.     ld    b,44        ; # sectors to read.
  832. load:    push    bc
  833.     call    rdsec
  834.     pop    bc
  835.     or    a        ; check for errors
  836.     jr    nz,lderr    ; woops!
  837.     dec    b        ; Count sectors read
  838.     ret    z        ; Read em all, done
  839.     call    pokefd        ; Prevent motor timeout
  840.     ld    de,secsiz
  841.     ld    hl,(dmaadr)
  842.     add    hl,de
  843.     ld    (dmaadr),hl
  844.     ld    a,(sect)
  845.     inc    a
  846.     ld    (sect),a
  847.     sub    spt+1        ; Done with track?
  848.     jr    nz,load        ; No, continue reading
  849.     ld    a,1
  850.     ld    (sect),a
  851.     ld    hl,track
  852.     inc    (hl)
  853.     push    bc
  854.     call    seek
  855.     or    a        ; check for errors
  856.     jr    nz,lderr    ; woops!
  857.     pop    bc
  858.     jr    load
  859.  
  860. ; Do a warm boot.
  861.  
  862. bootw:    ld    sp,80h
  863.     call    loadit
  864.     ld    bc,80h
  865.     call    setdma
  866.     ld    a,(4)
  867.     ld    c,a
  868.     jp    ccp+3
  869.  
  870. ; Finish the cold boot.
  871.  
  872. bootc:    di
  873.     ld    sp,80h
  874.     call    loadit
  875.     ld    bc,80h
  876.     call    setdma
  877.     xor    a
  878.     ld    (yr),a        ; Flag for "no date entered"
  879.     ei
  880.  
  881. ; Print the id message.
  882.  
  883.     ld    hl,idmsg
  884.     call    putstr
  885.     jp    ccp
  886.  
  887. idmsg:    db    ff,'DOS 2.2 BIOS 10.6',0
  888.  
  889. putstr:    ld    c,(hl)
  890.     inc    hl
  891.     ld    a,c
  892.     or    a
  893.     ret    z
  894.     call    pu3ot        ; May want to be pu0ot
  895.     jr    putstr
  896.  
  897. mos:    db    31,28,31,30,31,30,31,31,30,31,30,31
  898. clkint:    exx            ; CTC chan 3 comes here once a second
  899.     ex    af,af'
  900. ; Tick the timer.
  901.     ld    hl,(timer)
  902.     dec    hl
  903.     ld    (timer),hl
  904.     ld    a,(sec)
  905.     inc    a
  906.     cp    60
  907.     jr    nz,tiksec
  908.     ld    a,(min)
  909.     inc    a
  910.     cp    60
  911.     jr    nz,tikmin
  912.     ld    a,(hr)
  913.     inc    a
  914.     cp    24
  915.     jr    nz,tikhr
  916.     ld    a,(day)
  917.     ld    hl,mo
  918.     ld    e,(hl)
  919.     dec    e        ; Months 0-11 to index table
  920.     ld    d,0
  921.     ld    hl,mos
  922.     add    hl,de
  923.     cp    (hl)
  924.     jr    nz,tikday    ; Not first day of new month
  925.     ld    a,(mo)
  926.     cp    12
  927.     jr    nz,tikmon    ; Not a new year
  928.     ld    hl,yr
  929.     inc    (hl)
  930.     xor    a
  931. tikmon:    inc    a
  932.     ld    (mo),a
  933.     xor    a
  934. tikday:    inc    a
  935.     ld    (day),a
  936.     xor    a
  937. tikhr:    ld    (hr),a
  938.     xor    a
  939. tikmin:    ld    (min),a
  940.     xor    a
  941. tiksec:    ld    (sec),a
  942.     ld    hl,fdrunt    ; Count down run time of floppy motor
  943.     dec    (hl)
  944.     jr    nz,tikdon    ; Time not up yet
  945.     in    a,(pio.sd)    ; Time up, deselect the drive
  946.     and    0f8h
  947.     if    bigbrd
  948.     or    44h        ; Turn off motor and deselect
  949.     endif
  950.     out    (pio.sd),a
  951. tikdon:    ex    af,af'
  952.     exx
  953.     ei
  954.     reti
  955.  
  956. ctcint:    exx            ; Channel 1 of CTC comes here
  957.     ex    af,af'
  958.     ld    hl,(dsktmr)
  959.     dec    hl
  960.     ld    (dsktmr),hl
  961.     ex    af,af'
  962.     exx
  963.     ei
  964.     reti
  965.  
  966.     maclib    BIOSVID.INC    ; Include video handler (pu3ot)
  967.  
  968. ; Seek to requested track.
  969.  
  970. seek:    call    diskup        ; Make sure disk is spinning
  971.     ret    nz        ; It won't. Fail.
  972.     ld    a,(track)    ; Desired track
  973.     cp    tracks        ; In range?
  974.     ret    nc        ; Fail if not.
  975.     out    (fdc.da),a    ; Tell the 1771 where to go
  976.     ld    b,1ch        ; Seek op
  977.     call    fdcsek        ; Plug in step rate and do it
  978.     and    98h        ; Check for any errors
  979.     ret    z        ; Done if OK
  980.     call    homeb        ; Seek failed. Try recalibrating
  981.     ret    nz        ; That failed too?
  982.     ld    a,(track)    ; Try the seek again if recal worked
  983.     out    (fdc.da),a
  984.     ld    b,1ch
  985.     call    fdcsek
  986.     and    98h         ; Return success or fail this time
  987.     ret
  988.  
  989. ; Sector Read and Write routines
  990.  
  991. wtsec:    call    fdcsts        ; See if disk is write locked
  992.     bit    b6,a
  993.     ret    nz        ; Don't try writing if locked
  994.     ld    b,0a8h        ; Write opcode
  995.     jr    rdsec1         ; Much like read from here on
  996.  
  997. rdsec:    ld    b,88h        ; Read opcode
  998. rdsec1:    ld    hl,fdop        ; Save the opcode in fdop
  999.     ld    (hl),b
  1000.     ld    hl,retryc    ; Point at retryc
  1001.     ld    (hl),11        ; Set initial retry count
  1002. again1:    di            ; Turn off interrupts during transfer
  1003.     ld    hl,nmivec    ; Use NMI mechanism for the data xfer
  1004.     ld    d,(hl)        ; Hold old contents of 0066H
  1005.     ld    (hl),0c9h    ; Put a "ret" there for now
  1006.     ld    b,secsiz    ; # bytes/sector set for ini/outi
  1007.     ld    c,fdc.da    ; I/O port for read and write data
  1008.     ld    hl,(dmaadr)    ; Memory address for the sector
  1009.     ld    a,(sect)    ; Tell it what sector we want
  1010.     out    (fdc.se),a
  1011.     call    fdcsts        ; Stop old op, get status
  1012.     bit    b5,a        ; Head loaded yet?
  1013.     ld    a,(fdop)    ; Pick up the read or write
  1014.     jr    nz,noload    ; Go if no need to load it
  1015.     or    4         ; Tell it to load head
  1016. noload:    call    fdcdo        ; Do the read or write
  1017.     bit    b5,a        ; Is this a read or a write?
  1018.     jr    nz,wrwait    ; Go handle write
  1019.  
  1020. rdwait:    halt            ; Wait for NMI
  1021.     ini            ; Read a byte
  1022.     jp    nz,rdwait    ; Loop if not done, JP not JR, faster
  1023.     call    fdcskw        ; Wait for it to finish CRC
  1024.     and    9ch        ; Error bits for read
  1025.     jr    rwwat1        ; Go clean up at end
  1026.  
  1027. wrwait:    halt            ; Wait for NMI, write case
  1028.     outi            ; Output a byte
  1029.     jp    nz,wrwait    ; Loop till sector done, JP not JR
  1030.     call    fdcskw        ; Wait for CRC to go out, get status
  1031.     and    0bch        ; Error bits for write case.
  1032. rwwat1:    ld    hl,nmivec    ; Restore the contents of 0066H
  1033.     ld    (hl),d
  1034.     ei            ; Allow interrupts again
  1035.     ret    z        ; Return if no errors
  1036.     ld    hl,retryc    ; Nuts, there were errors.
  1037.     dec    (hl)        ; Count the retries
  1038.     jr    nz,again    ; If some left, try it all again
  1039.     or    a        ; Else set NZ with error bits
  1040.     ret            ; and fail the read/write.
  1041.  
  1042. again:    call    seek
  1043.     jr    again1        ; And re-do the read or write.
  1044.  
  1045. fdcsek:    ld    a,stept        ; Pick up step rate bits
  1046.     or    b        ; Put in seek/home operation
  1047.     call    fdcdo        ; Hand it to the chip
  1048. fdcskw:    in    a,(fdc.cs)    ; Wait for it to finish
  1049.     bit    b0,a
  1050.     jr    nz,fdcskw
  1051.     ret
  1052.  
  1053. fdcdo:    out    (fdc.cs),a    ; Do the requested op in 1771
  1054.     call    fdcdow        ; And wait a little while
  1055. fdcdow:    ex    (sp),hl        ; since 1771 is a bit slow on 
  1056.     ex    (sp),hl        ; getting the status right
  1057.     ret
  1058.  
  1059. fdcsts:    ld    a,0d0h        ; Reset current op
  1060.     call    fdcdo        ; Do that and delay
  1061.     in    a,(fdc.cs)    ; See what status is
  1062.     ret
  1063.  
  1064. pokefd:    ld    a,whirtm    ; Restart motor timer at max
  1065.     ld    (fdrunt),a
  1066.     call    pokef1        ; A little delay
  1067.     in    a,(pio.sd)    ; Get system PIO for drive bits
  1068. pokef1:    ret
  1069.  
  1070. diskup:    call    pokefd        ; Restart timer, get drive bits
  1071.     ld    e,0        ; A success code in case allready up.
  1072.     if    xerox
  1073.     and    7
  1074.     jr    nz,dskupx    ; Return if one is selected
  1075.     endif
  1076.     if    bigbrd
  1077.     and    4
  1078.     jr    z,dskupx    ; Return if one is selected
  1079.     endif
  1080.     push    hl        ; Save two reg pairs
  1081.     push    bc
  1082.     ld    a,(ldrive)    ; Get desired drive
  1083.     ld    c,a        ; Make a copy
  1084.     if    xerox
  1085.     and    2        ; If 2 or 3 get a 2 to add to turn that 2 bit
  1086.     add    a,c        ;  into a 4 bit for side select.
  1087.     inc    a        ; If 0 or 4 turn on bit 1 to select drive A/C,
  1088.     ld    c,a        ;  if 1 or 5 turn that 1 bit to a 2 bit to
  1089.                 ;  select drive B/D.
  1090.     endif
  1091.     if    bigbrd
  1092.                 ; Nothing to do here
  1093.     endif
  1094.     in    a,(pio.sd)    ; Get other bits, we know that drive/side bits
  1095.     or    c        ;  are allready zero or we wouldn't be here,
  1096.     if    bigbrd
  1097.     and    0bbh        ; Turn on drive motor and select
  1098.     endif
  1099.     out    (pio.sd),a    ;  so we don't have to mask them.
  1100.     ld    a,87h        ; Tell CTC 1 to time us
  1101.     out    (ctc.c1),a
  1102.  
  1103.     if    clk4
  1104. tkpms    equ    250    ; processor clocks per ms / 16
  1105.     else
  1106. tkpms    equ    156
  1107.     endif
  1108.  
  1109.     ld    a,tkpms        ; for a while (1 Ms ticks).
  1110.     out    (ctc.c1),a
  1111.     ld    hl,2000        ; This many Ms. says disk doesn't turn
  1112.     ld    (dsktmr),hl
  1113.     call    fdcsts        ; See if index bit is on
  1114.     and    2
  1115.     ld    b,a
  1116.     call    idxwat        ; Wait for index bit to change
  1117.     jr    c,offlin    ; If it didn't, give up on drive
  1118. dskup2:    ld    hl,(dsktmr)    ; It changed. Now wait for up to speed
  1119.     call    idxwat
  1120.     jr    c,offlin    ; Go if failed
  1121.     call    idxwat        ; Wait for two half square-waves
  1122.     jr    c,offlin    ; Go if failed
  1123.     ld    de,(dsktmr)    ; Now see if it's fast enough
  1124.     sbc    hl,de
  1125.     ld    (idxtim),hl    ; Save rotation time
  1126.  
  1127.     ld    de,msprev
  1128.     or    a        ; Clear CY for sbc
  1129.     sbc    hl,de        ; Is it this fast yet?
  1130.     jr    nc,dskup2    ; If not, let it turn some more
  1131.     ld    e,0        ; Fast enough.Success code. Go accept it
  1132.     jr    oflin1
  1133.  
  1134. offlin:    in    a,(pio.sd)    ; Disconnect from this drive. It's bad
  1135.     and    0f8h
  1136.     if    bigbrd
  1137.     or    4        ; Deselect
  1138.     endif
  1139.     out    (pio.sd),a
  1140.     ld    e,80h         ; Failure code
  1141. oflin1:    ld    a,3        ; Through with this CTC channel
  1142.     di            ; Because of CTC chip bug
  1143.     out    (ctc.c1),a
  1144.     ei    
  1145.     pop    bc        ; Restore registers
  1146.     pop    hl
  1147. dskupx:    ld    a,e        ; Success/fail code
  1148.     or    a        ; Non-Z says OK
  1149.     ret
  1150.  
  1151. idxwat:    call    fdcsts        ; Get Index hole bit
  1152.     and    2 
  1153.     xor    b        ; Compare to old bit
  1154.     jr    nz,idxchg    ; Go when it changes
  1155.     ld    a,(dsktmr+1)    ; See if time to give up
  1156.     bit    b7,a
  1157.     jr    z,idxwat    ; No, keep waiting
  1158.     scf            ; Failed. This thing isn't turning
  1159.     ret
  1160.  
  1161. idxchg:    ld    a,b         ; Aha. It changed.
  1162.     xor    2        ; Remember the new Index value
  1163.     ld    b,a
  1164.     ret             ; Return from idxwat
  1165.  
  1166. drive:    ds    1    ; Drive wanted, 0-3
  1167. ldrive:    db    0ffh    ; Previous drive wanted, 0-3
  1168.  
  1169. track:    ds    1
  1170. trkvec:    db    0ffh,0ffh,0ffh,0ffh
  1171.  
  1172. sect:    ds    1
  1173. dmaadr:    ds    2
  1174.  
  1175. fdrunt:    db    whirtm    ; Seconds to let motor run.
  1176. fdop:    db    0    ; Opcode for current floppy op
  1177. retryc:    db    0    ; Retry count for read or write on floppy
  1178.  
  1179. dsktmr:    dw    0    ; Time counter for disk up to speed test
  1180. idxtim:    dw    0    ; Time for disk to turn
  1181.  
  1182. dirbuf:    ds    128
  1183. alv0:    ds    31
  1184. csv0:    ds    16
  1185.     if    mxdrv gt 1
  1186. alv1:    ds    31
  1187. csv1:    ds    16
  1188.     endif
  1189.     if    mxdrv gt 2
  1190. alv2:    ds    31
  1191. csv2:    ds    16
  1192.     endif
  1193.     if    mxdrv gt 3
  1194. alv3:    ds    31
  1195. csv3:    ds    16
  1196.     endif
  1197. bufbas    equ    256*(($ shr 8)+1)
  1198. bslen    equ    $-bios    ; Length of the bios load
  1199.     end
  1200.