home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / cbios / acibs1k.ark / ACIBS1K.ASM next >
Assembly Source File  |  1989-10-21  |  60KB  |  2,287 lines

  1. PAGE 62
  2. ;P2BIOS.ASM aka ACIBS1K.ASM 
  3. ;ALSPA COMPUTER, INC.  Double Density Floppy Disk BIOS  P2DOS/CPM2.2
  4. ;******************************************************
  5. ;EDIT HISTORY
  6. ;    DATE:          REL:    MOD:
  7. ;01/11/82 - 02/01/82        1.8 ACIBS modified to 61K CPM, Blocking added
  8. ;02/01/82 - 02/02/82        Track mechanism fixed, side A:/B: code removed
  9. ;02/03/82 - 02/04/82        Diskswap fixed
  10. ;02/08/82 - 02/09/82    2.0 B: Logon fixed, sign-on 'glitch' fixed
  11. ;02/18/82 - 02/18/82        RCLOCK/WCLOCK timing fix, PIP/Density fixed
  12. ;02/25/82        2.1*SELDSK modified to delay disk change till R/W/SEEK
  13. ;03/02/82        2.2 Disk chg (dbl-sd PIP[V]) problem fixed
  14. ;03/05/82            D B: (rev A) problem fixed
  15. ;03/08/82            IBM format on B: option supported (rev xI)
  16. ;03/15/82            SYSFMT generated from IOBYTE, IOBYTE corrected
  17. ;03/16/82 - 03/25/82    2.3 Clock routines updated, IO routines re-done
  18. ;04/19/82 - 04/26/82        IOBYTE select, Coldboot in buffer, Autostart done.
  19. ;04/27/82 - 05/05/82    2.4 Add Motor on/off, User#/JumpTable saved in Wboot.
  20. ;05/07/82        2.5 System speed optimized.
  21. ;05/10/82        2.6 Wboot select error fixed.
  22. ;05/19/82 - 05/20/82        Select problem (when no Home after SELDSK) fixed.
  23. ;05/21/82        2.7*Select C:+ problem (drive# in Wboot) fixed.
  24. ;05/22/82        2.8*Tandon Motor-On speed mod.
  25. ;05/24/82        2.9 Motor-On mod improved (spindle-speed test added).
  26. ;08/23/82 - 08/25/82    3.0 1 Drive Side-select(B:dbl1/A:sngl0) bug fixed.
  27. ;10/27/82 - 11/02/82        Type-ahead buffer added (WordStar users rejoice).
  28. ;11/10/82            Density flag clear in HOME added (for JBS drives).
  29. ;11/10/82 - 11/11/82        Flush buffer on CONIN added.
  30. ;12/09/82 - 12/21/82        Autoswitch IOBYTE option added, Warmboot CCP only.
  31. ;12/21/82 - 01/17/83    3.1 Code for self-load of ACIDOS.COM file added.
  32. ;03/03/85 - 03/03/85    3.2%Added USER0 code
  33. ;09/18/87        3.3%Added USER0 warning (USER0 kills ZCPR3 & FCOPY)
  34. ;10/30/87 - 11/09/87        Added P2DOS support.
  35. ;11/10/87 - 11/12/87        made rev A code optional, to save a few bytes, 
  36. ;11/15/87            Added 2-drive only flag and p2dos time function.
  37. ;11/17/87            Added clear of mem above BIOS on coldboot.
  38. ;11/21/87            Added ZCPR3 definitions.
  39. ;11/24/87 - 11/26/87        Added ZCPR3/P2DOS overlays and data areas.
  40. ;11/28/87 - 11/29/87    3.4%Added fix for motor-on problem.
  41. ;01/12/88        3.5%Upgraded for P2DOS v. 23
  42. ;01/27/89        3.6%Added parallel printer status
  43. ;09/19/89 - 09/20/89    3.7%Modified to NOT use DIRBUF for scratch area.
  44. ; possible improvement - flush on nnnn*CONST (if no char is input)??
  45. ; * Unreleased/Limited Release versions
  46. ; % Special version - Custom by W.O.S. 
  47. ;******************************************************
  48. MO    EQU    09    ;LAST EDIT DATE
  49. DA    EQU    20
  50. YR    EQU    89
  51.  
  52. REVNO    EQU    37    ;REVISION #
  53.  
  54. TRUE    EQU    0FFFFH
  55. FALSE    EQU    NOT TRUE
  56.  
  57. VER36    EQU    FALSE    ;Version3.6 code option (for restore after testing 3.7)
  58. ;************************************************************
  59. ;* USER-SELECTED ASSEMBLY-TIME OPTIONS                *
  60. ;************************************************************
  61. IBMB    EQU    FALSE    ;Set to true if IBM disk compatibility is desired.
  62.             ;This will cause the system to use 'diskette' density
  63.             ;when reading Track 1 of disks B:,C:,... (i.e. not A:).
  64.             ;ALSPA disks always use double-density
  65.             ;on track 1 to hold the system, even if disk density
  66.             ;is single-d. Since the system on B: is not likely
  67.             ;to be read (except, maybe, by 'Disk Editor' utilities)
  68.             ;This should not affect normal operation. If an IBM-CPM
  69.             ;translation utility is used, this option MUST be
  70.             ;selected.
  71. LL    EQU    0    ;DEFAULT PRINTER OPTION:  (0,1,2,or 3)
  72.             ;0=Parallel printer interface
  73.             ;1=(console output)
  74.             ;2=Serial interface, ETX/ACK protocol
  75.             ;3=Serial interface, X-ON/X-OFF(or NO) protocol
  76. DD    EQU    2    ;# OF PHYSICAL FLOPPY DISK DRIVES: (1 or 2)
  77. AA    EQU    1    ;AUTOSWITCH OPTION: (0 OR 1)
  78.             ;0=Autoswitch enabled
  79.             ;1=Autoswitch disabled
  80.             ;The Autoswitch option runs the Modem and Console ports
  81.             ;in parallel, i.e. any character input from either
  82.             ;port is accepted as console input, and is echoed to
  83.             ;both Console and Modem output ports.
  84. SS    SET    0    ;AUTOSTART OPTION: (0 OR 1)
  85.             ;0=Autostart enabled  (both Cold/Warmboot)
  86.             ;1=Autostart disabled (Coldboot only)
  87.             ;The Autostart option allows the user to insert a
  88.             ;command in the CCP to be executed upon either coldboot
  89.             ;or warmboot. If the option is disabled, the command in
  90.             ;the CCP buffer will be ignored on warmboot, but 
  91.             ;executed upon coldboot(power-on or reset).
  92.             ;Autostart MUST be ENABLED for ZCPR3!
  93. QSIZE    EQU    25    ;Type-ahead buffer size (maximum: 255 characters)
  94. TYPEAHEAD EQU    TRUE    ;TYPE-AHEAD Option = TRUE or FALSE
  95. USER0    SET    FALSE    ;Add USER 0 = Public capability (patch CCP).
  96.             ;USER0 MUST be FALSE for ZCPR3!
  97. P2DOS    EQU    FALSE    ;TRUE if this is a P2DOS BIOS, FALSE for CP/M.
  98. ZCPR3    EQU    TRUE    ;TRUE if this BIOS is to be use with ZCPR3.
  99. DEBUG    EQU    FALSE    ;Add debugging code - watch ENDDISK parameter!
  100.             ;G = GoCPM    dnn = drive#    tnn = track#
  101.             ;snn = sector#    r = read    w = write
  102.             ;R = real read    W = real write    H = real home
  103.             ;* = warmboot    xnn = xlat sector
  104. NOREVA    EQU    TRUE    ;If true, BIOS handles Alspa rev B boards only.
  105. ONLY2    EQU    TRUE    ;TRUE for 2-drive only version (saves code space).
  106. ;*******************************************************************
  107.     if    ZCPR3
  108. SS    SET    0
  109. USER0    SET    FALSE
  110.     endif
  111.  
  112. MSIZE    EQU    61    ;MEMORY SIZE
  113.     if    not NOREVA
  114. REVA    EQU    'A'    ;VALUE OF CPU-BOARD=REV.A FLAG
  115. REVB    EQU    'B'    ;VALUE OF CPU-BOARD=REV.B FLAG
  116.     endif
  117.  
  118. ;SERIAL I/O PORTS (8251)
  119. MSTAT    EQU    5    ;MODEM STATUS PORT
  120. MDATA    EQU    4    ;MODEM DATA PORT
  121. CSTAT    EQU    3    ;CONSOLE STATUS PORT
  122. CDATA    EQU    2    ;CONSOLE DATA PORT
  123. LSTAT    EQU    1    ;LIST STATUS PORT
  124. LDATA    EQU    0    ;LIST DATA PORT
  125.  
  126. ;PARALLEL I/O PORTS (8255 - REV B ONLY)
  127. PPORTA    EQU    0D0H        ;8255 PORT A
  128. PPORTB    EQU    PPORTA+1    ;8255 PORT B
  129. PPORTC    EQU    PPORTA+2    ;8255 PORT C
  130. PPCMD    EQU    PPORTA+3    ;8255 COMMAND PORT
  131. PPINIT    EQU    91H    ;A MODE0 IN, C HI OUT; B MODE0 OUT, C LO IN
  132.  
  133. ;**********************************************************
  134. ;* SYSTEM CONFIGURATION:                  *
  135. ;* Both IOBYTE and SYSFMT are initialized from 'IOBYTA':  *
  136. ;*    IOBYTE=(IOBYTA AND IOBMSK) OR (DFTSY SHR 2 AND 1) *
  137. ;*    SYSFMT=(IOBYTA AND SYSMSK) OR DFTSY          *
  138. ;* This is done for continuity with earlier systems which *
  139. ;* used IOBYTE for all the system configuration functions.*
  140. ;**********************************************************
  141. IOBYTE    EQU    0003H    ;I/O BYTE: <llpprrcc>  (Reserved Memory location)
  142.     ;IOBYTE assignments: (Default = '*', optional defaults = '-')
  143.     ;------------------------------------------------
  144.     ;ll: prn protocol         pp: punch device 
  145.     ;-00 PARALLEL         TTY:    -00 PARALLEL PRN  TTY:
  146.     ;-01 (CONSOLE OUT)   CRT:    -01 (not used)    PUN:
  147.     ;-10 ETX/ACK         LPT:    *10 MODEM OUT     UP1:
  148.     ;*11 XON/XOFF(or NO) UL1:    -11 CLOCK WRITE   UP2:
  149.     ;   --------------------------------------
  150.     ;rr:  reader device         cc: console device
  151.     ;-00  (not used)     TTY:    *00 CONSOLE       TTY:
  152.     ; 01  (not used)     RDR:     01 CONSOLE/MODEM CRT: (autoswitch)
  153.     ;*10  MODEM IN       UR1:    -10 MODEM I/O     BAT:
  154.     ; 11  CLOCK READ     UR2:     11 CLOCK R/W     UC1:
  155.     ;------------------------------------------------
  156.     ;SYSFMT Sytem format byte: <---s-a-d>
  157.     ;s: autostart mode  a: autoswitch mode    d: #drives
  158.     ; 0 on (cold/warm)   0 on(modem&console)   0 2-drives
  159.     ;*1 off    (cold)        *1 off(console only)  *1 1-drive
  160.     ;------------------------------------------------
  161. SYSMSK    EQU    05H          ;(Mask for bits used in SYSFMT from IOBYTA)
  162. IOBMSK    EQU (NOT SYSMSK) AND 0FFH ;(Mask for bits used in IOBYTE from IOBYTA)
  163. DFTIO    EQU ((LL shl 6 or 28H) and iobmsk)        ;Default IOBYTE
  164. DFTSY    EQU (AA*4+(not (DD-1) and 1)+(SS*10H and 10H))    ;Default SYSFMT
  165. DFLTIOB    EQU    DFTIO or (DFTSY AND SYSMSK)        ;Default IOBYTA
  166. ;********************************************************
  167. CDISC    EQU    0004H    ;CP/M Reserved memory location - current disk
  168.  
  169. ;DOUBLE DENSITY TEST CODE FLAG
  170. ;NOTE: FOR A DISK TO BE CONSIDERED DOUBLE DENSITY
  171. ;CODE3 MUST BE ALREADY ON THE DISK AT TRACK 0
  172. ;SECTOR 1, BYTE 7F (LAST BYTE)
  173. ;CODE4 FOR DOUBLE DENSITY DOUBLE SIDE
  174. CODE3    EQU    0DDH
  175. CODE4    EQU    0D0H
  176. SINGL    EQU    2    ;LOGDEN VALUE FOR SINGLE DENS. DISK
  177.  
  178. ;BLOCKING/DEBLOCKING PARAMETERS
  179. WRALL    EQU    0    ;WRITE TO ALLOCATED SECTOR*BDOS
  180. WRDIR    EQU    1    ;WRITE TO DIRECTORY      *CONSTANTS
  181. WRUAL    EQU    2    ;WRITE TO UNALLOCATED SEC.*
  182. HSTSIZ    EQU    1024    ;PHYSICAL SECTOR SIZE
  183. HSTSPT    EQU    8    ;HOST SECTORS PER TRACK
  184. HSTBLK    EQU    HSTSIZ/128 ;CPM SECTORS/HOST SECTOR
  185.  
  186.  
  187. ;DISK IO PORTS
  188. DISK    EQU    0F8H    ;DISK BASE ADDRESS.
  189. DCOM    EQU    DISK    ;DISK COMMAND PORT.
  190. DSTAT    EQU    DISK    ;DISK STATUS PORT.
  191. TRACK    EQU    DISK+1    ;DISK TRACK PORT
  192. SECTP    EQU    DISK+2    ;DISK SECTOR PORT.
  193. DDATA    EQU    DISK+3    ;DISK DATA PORT.
  194. DSEL    EQU    DISK+5    ;DENSITY SELECT/MOTOR CONTROL PORT:
  195.                         ; CODE:     |       01/02       |      04/08       |
  196.             ;     |density=dble/single|motor=on/off(revB)|
  197. DCONT    EQU    DISK+4    ;DISK CONTROL PORT:
  198.             ; CODE:     |  01/02  |  04/08  |
  199.             ;REV B:  |disk=B/A |side=1/0 |
  200.             ;REV A:  |disk/side|   n/a   |
  201.  
  202. ;CPM PARAMETERS
  203. RTCNT    EQU    10    ;RETRY COUNT
  204. BIAS    EQU    (MSIZE-20)*1024 ;BIAS FOR LARGER THAN 17K.
  205. CCP    EQU    BIAS+3400H    ;START OF CPM.
  206. OFFSET    EQU    980H-CCP    ;OFFSET USED WITH DDT IN SYSTEM CONFIGURATION
  207. BDOS    EQU    CCP+806H    ;BASE OF BDOS
  208. BIOS    EQU    CCP+1600H    ;BASE OF BIOS
  209. CPML    EQU    BDOS-CCP    ;LENGTH OF CPM CCP (re-loaded in warmboot).
  210. NSECTS    EQU    (CPML+127)/128    ;NUMBER OF CPM SECTORS IN IT.
  211. NPSECTS    EQU    (HSTSIZ-1+NSECTS*128)/HSTSIZ    ;# OF PHYSICAL SECTORS    
  212. MAXDRV    EQU    1        ;DRIVES 0 - 1 VALID
  213. CCCONOT    EQU    CCP+8CH        ;CCP:    OUTPUT A TO CONSOLE
  214. CCGTUSR    EQU    CCP+113H    ;    GET USER NUMBER
  215. CCSTUSR    EQU    CCP+115H    ;    SET USER NUMBER
  216. CCOPFCB    EQU    CCP+0D0H    ;    CCP OPEN FILE (CPMFCB$)
  217. CCATTR    EQU    CCP+7D6H    ;    ATTRIBUTE FIELD IN CPMFCB$
  218. CCDSK    EQU    CCP+7F0H    ;    DISK GIVEN IN COMMAND STRING
  219. CCERR    EQU    CCP+76BH    ;    TYPE ERROR STRING
  220. CCLOAD    EQU    CCP+6DEH    ;    IF FILE OPENS, GO HERE
  221.  
  222. ;Character Equates
  223. CR    EQU    0DH
  224. LF    EQU    0AH
  225. ESC    EQU    1BH
  226. BELL    EQU    7
  227.  
  228. ;Z80 OPCODE EQUATES
  229. JR    EQU    18H    ;JR    XX
  230. JRNZ    EQU    20H    ;JR    NZ,XX
  231. JRZ    EQU    28H    ;JR    Z,XX
  232. JRNC    EQU    30H    ;JR    NC,XX
  233. JRC    EQU    38H    ;JR    C,XX
  234. RRCB    EQU    08CBH    ;RRC    B
  235. LDIR    EQU    0B0EDH    ;LDIR
  236. SRLA    EQU    2FCBH    ;SRL    A
  237. DJNZ    EQU    10H    ;DJNZ    XX
  238. PUSHIX    EQU    0E5DDH    ;PUSH    IX
  239. LDIX    EQU    21DDH    ;LD    IX,XXXX
  240. POPIX    EQU    0E1DDH    ;POP    IX
  241. INI    EQU    0A2EDH    ;INI
  242. JPIX    EQU    0E9DDH    ;JP    (IX)
  243. OUTI    EQU    0A3EDH    ;OUTI
  244. OUTCA    EQU    79EDH    ;OUT    (C),A
  245. INAC    EQU    78EDH    ;IN    A,(C)
  246. SBCHLDE    EQU    52EDH    ;SBC    HL,DE
  247. RES2HL    EQU    96CBH    ;RES    2,(HL)
  248. RES3HL    EQU    9ECBH    ;RES    3,(HL)
  249.  
  250. ;***********ACIDOS.COM PREFACE CODE****************
  251. ;This code allows the ACIDOS.COM to be executed. If run
  252. ;(by mistake), it merely brings up the new operating system.
  253.     ORG    0100H-OFFSET
  254.     LXI    H,CCP+OFFSET    ;COPY (image in ram from .COM file)
  255.     LXI    D,CCP        ;  TO (executable address)
  256.     LXI    B,ENDISK-CCP    ;     (# of bytes of image)
  257.     DW    LDIR
  258.     JMP    BIOS        ;COLDSTART (image at executable address)
  259.     DB    '  no copyright message here                            '
  260. ;***************************************************
  261.  
  262.     if    USER0
  263. ;***********USER0 PATCHES ON THE CCP****************
  264. ;This code patches the CCP to look first on the A: drive, then in USER 0
  265. ;for command files requested but not found in the current user number.
  266. ;It makes a call on a routine assembled intp the BIOS.
  267.     ORG    CCP+6DBH    ;Replace 'jz ccerr' with 'jz patch'
  268.     JZ    CCPATCH        ;Patch is called if file isn't found
  269.                 ;in current user.
  270.     ORG    CCP+7F2H    ;Patch is placed in area of CCP occupied
  271. CCPATCH:            ;by unused NOPs.
  272.     LXI    H,CCDSK        ;Get drive spec'd in command
  273.     ORA    M        ;If explicit drive given, look in USER0
  274.     JNZ    CHKUSR0        
  275.     INR    M        ;Else set A (was 0 on entry) to A:
  276.     LXI    D,CCATTR    ; and retry (re-enter CCP)
  277.     JMP    CCP+6CDH
  278. ;***************************************************
  279.     endif
  280.  
  281. ; I/O JUMP VECTOR
  282. ; THIS IS WHERE CPM CALLS WHENEVER IT NEEDS
  283. ; TO DO ANY INPUT/OUTPUT OPERATION.
  284. ; USER PROGRAMS MAY USE THESE ENTRY POINTS
  285.  
  286.     ORG    BIOS
  287.  
  288.     JMP    CBOOT    ;FROM COLD START LOADER.
  289. WBOOTE:    JMP    WBOOT
  290.     JMP    LCONST
  291.     JMP    LCONIN
  292.     JMP    LCONOUT
  293.     JMP    LLIST
  294.     JMP    LPUNCH
  295.     JMP    LREADER
  296.     JMP    HOME
  297.     JMP    SELDSK
  298.     JMP    SETTRK
  299.     JMP    SETSEC    ;SET SECTOR NUMBER.
  300.     JMP    SETDMA    ;SET DISK STARTING ADR.
  301.     JMP    READ    ;READ SELECTED RECORD
  302.     JMP    WRITE    ;WRITE SELECTED RECORD
  303.     JMP    LLISTST    ;RETURN LIST STATUS
  304.     JMP    SECTRAN    ;SECTOR TRANSLATE
  305. ; this must be after 17th JUMP address
  306. DFLAGS:    DB    0,0,0,0    ;DENSITY FLAGS        *do
  307.     CALL    BLDPTR    ;DENSITY SETTING ROUTINE*not
  308.     CALL    DENSITY    ;FOR FCOPY PROGRAM    *move
  309.     RET        ;            *or
  310. IOBYTA:    DB    DFLTIOB    ;DEFAULT I/O BYTE    *change
  311. SYSFMT:    DB    DFTSY and IOBMSK ;        *
  312.     if    not P2DOS
  313.     DB    'Reserve';FOR FUTURE USE    *
  314.     endif
  315.     if    P2DOS
  316.     JMP    BTIME    ;BIOS TIME ROUTINES    *
  317.     DB    'free'    ;FOR FUTURE USE        *
  318.     endif
  319. UARTT:    DB    0CEH    ;USART MODE SELECT    *
  320. UARTP:    DB    0CEH    ;CODES            *
  321. UARTM:    DB    0CEH    ;            *
  322.  
  323. ;FIXED DATA TABLES FOR TWO-DRIVE STANDARD
  324. ;IBM-COMPATIBLE 8" DISKS (MODIFIED IN 'DENSITY').
  325. ;    DISK PARAMETER HEADER FOR DISK 00 -SNGL D
  326. DPBASE:    DW    TRANS,0000H
  327.     DW    0000H,0000H
  328.     DW    DIRBF,DPSDBK
  329.     DW    CHK00,ALL00
  330. ;    DISK PARAMETER HEADER FOR DISK 01 -SNGL D
  331.     DW    TRANS,0000H
  332.     DW    0000H,0000H
  333.     DW    DIRBF,DPSDBK
  334.     DW    CHK01,ALL01
  335.  
  336. ;    SINGLE DENSITY SECTOR TRANSLATE VECTOR
  337. TRANS:    DB    1,7,13,19    ;SECTORS 1,2,3,4
  338.     DB    25,5,11,17    ;SECTORS 5,6,7,8
  339.     DB    23,3,9,15    ;SECTORS 9,10,11,12
  340.     DB    21,2,8,14    ;SECTORS 13,14,15,16
  341.     DB    20,26,6,12    ;SECTORS 17,18,19,20
  342.     DB    18,24,4,10    ;SECTORS 21,22,23,24
  343.     DB    16,22        ;SECTORS 25,26
  344.  
  345. ;    DOUBLE DENSITY SECTOR TRANSLATE VECTOR
  346. TRANSD:    EQU    0    ;NO SECTOR TRANSLATION
  347.  
  348. DPDDBK:        ;DOUBLE DENSITY PARAMETER BLOCK
  349.     DW    64    ;SECTORS PER TRACK - SPT
  350.     DB    4    ;BLOCK SHIFT FACTOR - BSH
  351.     DB    15    ;BLOCK MASK - BLM
  352.     DB    0    ;NULL MASK - EXM
  353.     DW    300-1    ;DISK SIZE IN BLOCKS - DSM
  354.     DW    128-1    ;DIRECTORY MAX ENTRIES - DLM
  355.     DB    0C0H    ;DIR. ALLOC. MASK - AL0
  356.     DB    0    ;DIR. ALLOC. MASK - AL1
  357.     DW    128/4    ;DIR. CHECK SIZE - CKS
  358.     DW    2    ;TRACK OFFSET - OFF
  359.     DB    16    ;BLOCKSIZE/128    ****************
  360.     DB    7    ;SECMASK    *BLOCKING PARMS*
  361.     DB    3+1    ;SECSHF        * DO NOT MOVE  *
  362.     DB    64    ;CPMSPT        ****************
  363. DPDDBK1:    ;DOUBLE DENSITY PARAMETER BLOCK (2 side)
  364.     DW    64    ;SECTORS PER TRACK - SPT
  365.     DB    5    ;BLOCK SHIFT FACTOR - BSH
  366.     DB    31    ;BLOCK MASK - BLM
  367.     DB    1    ;NULL MASK - EXM
  368.     DW    304-1    ;DISK SIZE IN BLOCKS - DSM
  369.     DW    128-1    ;DIRECTORY MAX ENTRIES - DLM
  370.     DB    80H    ;DIR. ALLOC. MASK - AL0
  371.     DB    0    ;DIR. ALLOC. MASK - AL1
  372.     DW    128/4    ;DIR. CHECK SIZE - CKS
  373.     DW    2    ;TRACK OFFSET - OFF
  374.     DB    32    ;BLOCKSIZE/128    *BLOCKING PARMS    *
  375.     DB    7    ;SECMASK    * =HSTSIZ/128-1    *
  376.     DB    3+1    ;SECSHF        *=LG2(SCMSK+1)+1*
  377.     DB    64    ;CPMSPT        *=HSTBLK*HSTSPT *
  378. DPSDBK:    ;DISK PARAMETER BLOCK, SINGLE DENSITY
  379.     DW    26    ;SECTORS PER TRACK
  380.     DB    3    ;BLOCK SHIFT FACTOR
  381.     DB    7    ;BLOCK MASK
  382.     DB    0    ;NULL MASK
  383.     DW    242    ;DISK SIZE-1
  384.     DW    63    ;DIRECTORY MAX
  385.     DB    192    ;ALLOC 0
  386.     DB    0    ;ALLOC 1
  387.     DW    16    ;CHECK SIZE
  388.     DW    2    ;TRACK OFFSET
  389.     DB    8    ;BLOCKSIZE/128    ****************
  390.     DB    0    ;SECMASK    *BLOCKING PARMS*
  391.     DB    0+1    ;SECSHF        * DO NOT MOVE  *
  392.     DB    26    ;CPMSPT        ****************
  393.  
  394. ;******** END OF FIXED TABLES **************************************
  395.  
  396. ;*******************
  397. ; COLDBOOT: STARTUP
  398. ;*******************
  399.     DB    MO,DA,YR;THIS MUST PRECEDE CBOOT
  400. CBOOT:    JMP    BOOT    ;BOOT CHANGES THIS TO WBOOT
  401.  
  402.  
  403. ;***************************************************************
  404. ; WARM-BOOT:  READ CCP AND PART OF BDOS BACK IN, THEN JUMP TO CCP.
  405. ;****************************************************************
  406. ;*** THIS CODE BYTE MUST BE ALWAYS BE THE BYTE BEFORE LABEL WBOOT: ***
  407.     DB    0DDH    ;*** DO NOT MOVE OR REMOVE ***
  408.  
  409. WBOOT:
  410.     if    DEBUG
  411.     MVI    A,'*'
  412.     CALL    CONOUTA
  413.     endif
  414.     LXI    SP,80H    ;SET STACK POINTER.
  415.     LDA    SEKDSK    ;SAVE DISK NUMBER.
  416.     PUSH    PSW    ;
  417.     XRA    A    ;CLEAR BLOCKING FLAGS
  418.     STA    HSTACT    ;  -HOSTBUFFER INACTIVE
  419.     STA    UNACNT    ;  -UNALLOC CT=0
  420.     STA    HSTWRT    ;  -NO PENDING WRITE
  421.     STA    SEKDSK    ;SET DISK=0 (A:)
  422.     CALL    CLRDFLGS;CLEAR DENSITY FLAGS
  423.     CALL    CHKSD    ;SELECT A:
  424.     MVI    A,1    ;
  425.     CALL    SEEK    ;SET TRACK=1
  426.     MVI    A,1    ;SECTOR=E=1
  427.     OUT    SECTP    ;
  428.     MOV    E,A    ;
  429.     LXI    H,CCP    ;HL -> CCP
  430.     MVI    C,DDATA    ;C -> DATAPORT(1793)
  431.     MVI    A,8CH    ;A=(READ W/15MS DELAY)COMMAND
  432. WBOOT2:    CALL    RLOOP    ;  READ SECTOR(E) => (HL)
  433.     IN    DSTAT    ;  IF (ERROR) THEN EXIT(RDERR)
  434.     ANI    9DH    ;
  435.     DB    JRNZ,BTERR-$-1
  436.     INR    E    ;  INCREMENT SECTOR
  437.     MOV    A,E    ;  IF (SECTOR=NPSECTS) THEN EXIT(DONE)
  438.     CPI    NPSECTS+1 ;
  439.     DB    JRZ,WBOOT3-$-1
  440.     OUT    SECTP    ;  SET SECTOR(E)
  441.     MVI    A,88H    ;  A=(READ W/NO DELAY)COMMAND
  442.     DB    JR,WBOOT2-$+0FFH    ;  END
  443.  
  444. WBOOT3:    POP    PSW    ;RESTORE DISK NUMBER.
  445.     STA    SEKDSK    ;
  446.     if    not P2DOS
  447.     LDA    SYSFMT    ;IF (AUTOSTART OFF) DISABLE CCP COMMAND
  448.     ANI    10H
  449.     DB    JRZ,GOCPM-$-1
  450.     XRA    A
  451.     STA    CCP+7
  452.     endif
  453.  
  454. GOCPM:    if    DEBUG
  455.     MVI    A,'G'
  456.     CALL    CONOUTA
  457.     endif
  458.     MVI    A,0C3H    ;PUT JMP TO WBOOT
  459.     STA    0    ;ADR AT ZERO.
  460.     LXI    H,WBOOTE
  461.     SHLD    1
  462.     STA    5
  463.     LXI    H,BDOS    ;PUT JUMP TO BDOS
  464.     SHLD    6    ;AT ADR 5,6,7.
  465.     LXI    H,80H    ;SET DEFAULT DMA ADR.
  466.     SHLD    DMAADD
  467.     LDA    SEKDSK    ;GET LAST REQUESTED DISK#
  468.     MOV    C,A
  469.     PUSH    B
  470.     CALL    CHKDS1    ;SET UP DRIVE
  471.     POP    B
  472.     LDA    CDISC
  473.     ANI    0F0H    ;GET USER# (if c:+ requested, cdisc is wrong)
  474.     ORA    C    ;GET (REAL) DRIVE #
  475.     MOV    C,A
  476.     if    P2DOS and ZCPR3
  477.     JMP    P2CWBT    ;Do extra ZCPR3 warmboot stuff (reinit Submit FCB).
  478.     endif
  479.     if    (not P2DOS) or (not ZCPR3)
  480.     JMP    CCP    ;JUMP TO CCP.
  481.     endif
  482.  
  483.  
  484. BTERR:    LXI    H,BTMSG    ;GET ADDRESS OF "BOOT ERROR".
  485.     CALL    ERMSG    ;PRINT IT.
  486.     CALL    LCONIN    ;READ A CHAR FROM CONSOLE.
  487.     JMP    WBOOT    ;DO A WARM BOOT.
  488.  
  489. CLRDFLGS:
  490.     LXI    H,0    ;CLEAR DENSITY FLAGS
  491.     SHLD    DFLAGS    ;
  492.     SHLD    DFLAGS+2;
  493.     RET
  494.  
  495. ;****************************************************************
  496. ;SELDSK: SELECT DISK NUMBER ACCORDING TO REGISTER C.
  497. ;BLDPTR: BUILD POINTER (IN HL) TO DISK PARM BLK HEADER
  498. ;****************************************************************
  499. SELDSK:
  500.     if    DEBUG
  501.     MVI    A,'d'
  502.     CALL    CONOUTA
  503.     MOV    A,C
  504.     CALL    PHEX
  505.     endif
  506.     LDA    SEKDSK    ;SAME AS  LAST DRIVE REQUESTED?
  507.     CMP    C    ;
  508.     DB    JRZ,BLDPTR-$-1; YES, JUST BUILD DRIVE HEADER POINTER.
  509.     MOV    A,C    ;
  510.     CPI    MAXDRV+1;SEE IF DRIVE NO. IS VALID
  511.     LXI    H,0    ;  (IF INVALID, RETURN HL=0)
  512.     RNC        ;ERROR - RETURN IF OUT OF RANGE
  513.     PUSH    PSW    ;IF WRITE PENDING THEN
  514.     CALL    FLUSH    ;  FLUSH BUFFER
  515.     POP    PSW    ;
  516.     STA    SEKDSK    ;SEKDSK=NEW DRIVE SELECTED
  517.     MOV    C,A    ;BUILD DPB HEADER POINTER
  518.     CALL    BLDPTR    ;
  519.     JMP    DENSITY    ;GET DENSITY PARMS
  520.  
  521. BLDPTR:            ;COMPUTE SEL. DRIVE HEADER VECTOR
  522.     MOV    L,C    ;DISK NO.
  523.     MVI    H,0    ;AS 16 BIT QTY.
  524.     DAD    H    ;*2 (BUILD 16-BYTE OFFSET)
  525.     DAD    H    ;*4
  526.     DAD    H    ;*8
  527.     DAD    H    ;*16
  528.     LXI    D,DPBASE;TABLE BASE
  529.     DAD    D    ;EFFECTIVE ADDRESS OF VECTOR
  530.     RET        ;
  531.  
  532. ;****************************************************
  533. ;CHKSD: CHECK THAT CURRENT DISK=SELECTED DISK &
  534. ;CHKDSK: CHECK THAT DISK (C) =SELECTED DISK &
  535. ;        & SELECT IF NOT
  536. ;****************************************************
  537. CHKSD:    LDA    SEKDSK    ;C=SEKDSK
  538. CHKDSA:    MOV    C,A
  539. CHKDSK:    LDA    CURDSK    ;A=CURDSK
  540.     CMP    C    ;IF (A=C) THEN RETURN(&TURN MOTORS ON)
  541.     JZ    MTRON    ;
  542. CHKDS1:            ;/******* ENTRY FOR BOOT (A=C=0)*******/
  543.             ;/*FROM HERE ON, C=DISK TO BE SELECTED*/
  544.     MOV    E,A    ;HL => TRACKTABLE(LASTDRIVE)
  545.     MVI    D,0    ;
  546.     LXI    H,TRTAB    ;
  547.     DAD    D    ;
  548.     IN    TRACK    ;A = 1793 TRACK REGISTER (ADJUSTED)
  549.     CALL    INTRK    ;
  550.     MOV    M,A    ;M(HL) = A
  551.     MOV    E,C    ;HL => TRACKTABLE(NEWDRIVE)
  552.     LXI    H,TRTAB    ;
  553.     DAD    D    ;
  554.     MOV    A,M    ;
  555.     CALL    OUTRK    ;
  556.     OUT    TRACK    ;1793 TRACK REG = TRKTBL(NWDR) (ADJUSTED)
  557.     if    not ONLY2
  558.     LDA    SYSFMT    ;IF (1 DRIVE SYSTEM) THEN DO
  559.     MOV    B,A    ;
  560.     RAR        ;
  561.     DB    JRNC,TWODR-$-1;SWAP DISKS:
  562.     PUSH    H        ;THE FOLLOWING IS  SINGLE DRIVE
  563.     PUSH    B        ;DISK SWAP CODE
  564.     LDA    CURDSK        ;
  565.     CMP    C        ;CHECK IF CHANGE IN DISK &
  566.     DB    JRZ,CHKDS2-$-1    ;
  567.     MOV    A,C        ;PUT DISK REFERENCE IN MESSAGE
  568.     ADI    'A'        ;
  569.     STA    SWDSK        ;
  570.     LXI    H,SWMSG        ;PROMPT FOR DISK SWAP
  571.     CALL    PMSG        ;
  572.     CALL    LCONIN        ;WAIT FOR KEY TO BE HIT
  573.     CALL    PCRLF        ;PRINT CRLF
  574. CHKDS2:    POP    B        ;
  575.     POP    H        ;
  576.     DB    JR,CHKDS4-$-1    ;
  577.     endif
  578. TWODR:    MOV    A,C    ;ELSE CHANGE DRIVE
  579.     INR    A    ;
  580.     CMA        ;
  581.     ANI    3    ;
  582.     OUT    DCONT    ;
  583. CHKDS4:    MOV    A,M    ;IF (TRACK=0FFH) DO
  584.     INR    A    ;
  585.     DB    JRNZ,CHKDS6-$-1
  586.     if    not NOREVA
  587.     LDA    CPUREV    ;  IF (REV.B) OR (REV.A AND 2DRIVE SYSTEM) DO
  588.     CPI    'B'
  589.     DB    JRZ,CHKDS5-$-1
  590.     MOV    A,B
  591.     RAR
  592.     DB    JRNC,CHKDS6-$-1
  593.     endif
  594. CHKDS5:    PUSH    B    ;        /*This is the 1st time this disk is*/
  595.     CALL    OUTRK    ;    SET SIDE 0    /*accessed. We don't know where the*/
  596.     OUT    TRACK    ;        /*head is, so we HOME it. */
  597.     CALL    HOME1    ;    HOME DRIVE
  598.     POP    B    ;    ENDIF
  599. CHKDS6:    CALL    MTRON    ;WAIT FOR DRIVE READY(TURN MOTOR ON, ALSO)
  600.     MOV    A,C    ;SET CURDSK=SELECTED DRIVE
  601.     STA    CURDSK    ;
  602.     CALL    BLDPTR    ;BUILD POINTER TO PARM. HDR.
  603.             ;SET DENSITY PARMS FOR DISK (C).
  604. ;***********************************************
  605. ;DENSITY: SET DRIVE PARMS FOR DRIVE # (C)
  606. ;    C:    DRIVE # (0-3)
  607. ;    HL:    -> DISK PARAMETER HEADER (IN DPBASE:)
  608. ;    KILLS:    A,BC,DE,FLAGS
  609. ;DETERMINE DENSITY OF NEW DISK, SELECT TRANSLATE TABLE
  610. ;AND DISK PARM BLOCK, IN DPBASE
  611. ;***********************************************
  612. DENSITY:
  613.     PUSH     H    ;SAVE DISKPARM HEADER PTR
  614.     LXI    H,DFLAGS;HL -> DENSITY FLAGS
  615.     MVI    B,0    ;
  616.     DAD    B    ;
  617.     MOV    A,M    ;
  618.     ORA    A    ;GET DENSITY FLAG(C)
  619.     JM    LOGED    ;SKIP IF LOGGED IN BEFORE
  620.     PUSH    H    ;  SAVE DENSITYFLAGPTR
  621.     CALL    CHKDSK    ;  CHECK IF SELECTED ALREADY, DO SO IF NOT.
  622.     IF    VER36
  623.     LDA    SEKSEC    ;  SAVE SECTOR
  624.     PUSH    PSW    ;
  625.     LHLD    DMAADD    ;  SAVE DMAADD
  626.     PUSH    H    ;
  627.     CALL    HOME1    ;  DENSITYFLAG=F(TRACK0,SECTOR1,BYTE7FH)
  628.     MVI    C,1
  629.     CALL    SETSEC
  630.     LXI    B,DIRBF
  631.     CALL    SETDMA
  632.     CALL    READ
  633.     POP    H    ;  RESTORE DMADD
  634.     SHLD    DMAADD
  635.     POP    PSW    ;  RESTORE SECTOR
  636.     STA    SEKSEC
  637.     POP    H    ;  RESTORE DENSITYFLAGPTR
  638.     LDA    DIRBF+07FH;(DENSITYFLAG BYTE)
  639.     ENDIF
  640.     IF    NOT VER36
  641.     CALL    HOME1
  642.     LXI    H,ERCNT
  643.     MVI    M,RTCNT
  644. DENS1:    MVI    A,0D0H    ;FORCE INTERRUPT
  645.     OUT    DCOM
  646.     XTHL        ;KILL TIME
  647.     XTHL
  648.     XTHL
  649.     XTHL
  650.     MVI    A,1    ;SET SECTOR
  651.     OUT    SECTP
  652.     IN    DSTAT    ;LOOK AT HEAD LOAD BIT
  653.     ANI    20H
  654.     MVI    A,8CH    ;READ WITH HEAD LOAD DELAY
  655.     DB    JRZ,DENS2-$-1
  656.     MVI    A,88H    ; READ WITH NO HEAD LOAD DELAY
  657. DENS2:    DW    PUSHIX
  658.     CALL    XRLOOP    ;READ SECTOR AND REATIN (ONLY) LAST BYTE
  659.     DW    POPIX        
  660.     MOV    B,A
  661.     IN    DSTAT    ;CHECK FOR ERRORS
  662.     ANI    9DH
  663.     DB    JRZ,DENS3-$-1    ;NONE FOUND
  664.     DCR    M    ;ERROR FOUND - DECREMENT ERRORCOUNT
  665.     DB    JRNZ,DENS1-$+0FFH    ;RETRY
  666.     CALL    ERMSG0    ;PRINT ERRMSGS (RETURNS 0 WHICH WE USE FOR SSSD) 
  667. DENS3:    POP    H    ;RESTORE PTR TO DENSITY FLAG
  668.     MOV    A,B
  669.     ENDIF
  670.     CPI    0DDH    ;CODE3
  671.     DB    JRZ,LOGDD-$-1
  672.     CPI    0D0H    ;CODE4
  673.     DB    JRZ,LOGD0-$-1
  674.  
  675. LOG00:    MVI    A,82H    ;LOGGED DISK IS SINGLE DENSITY
  676.     LXI    B,TRANS    ;
  677.     LXI    D,DPSDBK;
  678.     DB    JR,LOGDRV-$-1
  679.  
  680. LOGED:    CPI    081H    ;TEST PREVIOUSLY LOGGED DRIVE PARM
  681.     DB    JRZ,LOGDD-$-1    ;AND BRANCH APPROPRIATELY
  682.     CPI    085H    ;
  683.     DB    JRNZ,LOG00-$+0FFH
  684.  
  685. LOGD0:    MVI    A,85H    ;LOGGED DISK IS DBL SIDE, DBL DENSITY
  686.     LXI    B,TRANSD;
  687.     LXI    D,DPDDBK1;
  688.     DB    JR,LOGDRV-$-1
  689.  
  690. LOGDD:    MVI    A,81H    ;LOGGED DISK IS SNGL SIDE, DBL DENSITY
  691.     LXI    B,TRANSD;
  692.     LXI    D,DPDDBK;
  693.  
  694. LOGDRV:    MOV    M,A    ;SAVE DISKTYPE IN DENSITY FLAGS
  695.     ANI    3    ;STRIP OFF LOGGED IN BIT
  696.     STA    LOGDEN    ;SAVE DENSITY OF LOGGED IN DRIVE
  697.     OUT    DSEL    ;SET IT
  698.     POP    H    ;GET DISKPARMHDR PTR
  699.     PUSH     H    ;SAVE IT FOR RETURN
  700.     MOV    M,C    ;SET UP TRANSLATE TABLE PTR IN BLOCK
  701.     INX    H
  702.     MOV    M,B    ;
  703.     LXI    B,9    ;SET UP DISK PARM PTR IN BLOCK
  704.     DAD    B    ;
  705.     MOV    M,E    ;
  706.     INX    H    ;
  707.     MOV    M,D    ;
  708.     LXI    H,15    ;LET HL->BLOCKING PARMS    (SET BLKG PRMS FOR DISK)
  709.     DAD    D    ;
  710.     LXI    D,CPMSPB;LET DE->LOGGEDDRIVE BLOCKINGPARM AREA
  711.     LXI    B,4    ;LET BC=#ITEMS TO MOVE
  712.     DW    LDIR    ;(MOVE (HL)=>(DE),BC ITEMS)
  713.     POP    H    ;RETURN DISKPARMHDR POINTER
  714.     RET        ;
  715.  
  716. XRLOOP:    DW    LDIX,XRL1
  717.     OUT    DCOM
  718.     EI
  719. XRL1:    HLT        ;WAIT FOR F/D CONTROLLER TO START AGAIN...
  720.     IN    DDATA
  721.     EI
  722.     DW    JPIX
  723.  
  724. ;****************************************************************
  725. ; SET TRACK NUMBER TO REGISTER C.
  726. ;****************************************************************
  727. SETTRK:
  728.     if    DEBUG
  729.     MVI    A,'t'
  730.     CALL    CONOUTA
  731.     MOV    A,C
  732.     CALL    PHEX
  733.     endif
  734.     MVI    H,0    ;SAVE TRACK NUMBER
  735.     MOV    L,C
  736.     SHLD    SEKTRK
  737.     RET
  738.  
  739. ;****************************************************************
  740. ; SET DISK SECTOR NUMBER.
  741. ;****************************************************************
  742. SETSEC:    
  743.     if    DEBUG
  744.     MVI    A,'s'
  745.     CALL    CONOUTA
  746.     MOV    A,C
  747.     CALL    PHEX
  748.     endif
  749.     MOV    A,C    ;GET SECTOR NUMBER.
  750.     STA    SEKSEC
  751.     RET        ;RETURN FROM SETSEC.
  752.  
  753. ;****************************************************************
  754. ; SET DISK DMA ADDRESS.
  755. ;****************************************************************
  756. SETDMA:  MOV    H,B    ;MOVE B&C TO H&L.
  757.      MOV    L,C
  758.      SHLD    DMAADD    ;PUT AT DMA ADR ADDRESS.
  759.      RET        ;RETURN FROM SETDMA.
  760.  
  761. ;****************************************************************
  762. ;TRANSLATE SECTOR IN BC TO HL USING TABLE POINTED AT BY DE.
  763. ;****************************************************************
  764. SECTRAN:
  765.     if    DEBUG
  766.     MVI    A,'x'
  767.     CALL    CONOUTA
  768.     MOV    A,B
  769.     CALL    PHEX
  770.     MOV    A,C
  771.     CALL    PHEX
  772.     endif
  773.     MOV    A,E    ;TEST IF TABLE TRANSLATION IS REQUESTED
  774.     ORA    D    ;  (I.E. DE<>0)
  775.     DB    JRNZ,SECTR1-$-1    ;  YES, DO IT
  776.     MOV    L,C    ;  NO, LET HL=BC+1
  777.     MOV    H,B    ;
  778.     INX    H    ;
  779.     RET        ;
  780. SECTR1:    XCHG        ;GET TABLE ADDR IN HL
  781.     DAD    B    ;INDEX INTO TABLE
  782.     MOV    L,M    ;HL=M(BC+DE)
  783.     MVI    H,0    ;
  784.     RET        ;
  785.  
  786.  
  787. ;*****************************************************
  788. ;*    Read CPM sector (record) from SEKDSK,         *
  789. ;*    SEKTRK,SEKSEC, to M(DMAADD).                 *
  790. ;*****************************************************
  791. READ:
  792.     if    DEBUG
  793.     MVI    A,'r'
  794.     CALL    CONOUTA
  795.     endif
  796.     XRA    A
  797.     STA    UNACNT
  798.     INR    A
  799.     STA    READOP        ;read operation
  800.     STA    RSFLAG        ;must read data
  801.     MVI    A,WRUAL
  802.     STA    WRTYPE        ;treat as unalloc
  803.     DB    JR,RWOPER-$-1    ;to perform the read
  804.  
  805. ;*****************************************************
  806. ;*    Write CPM sector (record) from M(DMAADD)     *
  807. ;*    to SEKDSK,SEKTRK,SEKSEC.                     *
  808. ;*****************************************************
  809. WRITE:
  810.     if    DEBUG
  811.     MVI    A,'w'
  812.     CALL    CONOUTA
  813.     endif
  814.     XRA    A        ;0 to accumulator
  815.     STA    READOP        ;not a read operation
  816.     MOV    A,C        ;write type in c
  817.     STA    WRTYPE
  818.     LDA    LOGDEN        ;IF (SD), NEVER RD BEFORE WR
  819.     CPI    SINGL        ;
  820.     DB    JRZ,NOOVF-$-1    ;
  821.     MOV    A,C        ;
  822.     CPI    WRUAL        ;write unallocated?
  823.     DB    JRNZ,CHKUNA-$-1    ;check for unalloc
  824.                 ;write to unallocated, set parameters
  825.     LDA    CPMSPB        ;next unalloc recs
  826.     STA    UNACNT
  827.     LXI    H,SEKDSK    ;Copy SEEK parms to UNALLOC parms
  828.     LXI    D,UNADSK
  829.     LXI    B,5
  830.     DW    LDIR
  831. CHKUNA:                ;check for write to unallocated sector
  832.     LDA    UNACNT        ;any unalloc remain?
  833.     ORA    A
  834.     DB    JRZ,ALLOC-$-1    ;skip if not
  835.                 ;more unallocated records remain
  836.     DCR    A        ;unacnt = unacnt-1
  837.     STA    UNACNT
  838.     LDA    SEKDSK        ;same disk?
  839.     LXI    H,UNADSK
  840.     CMP    M        ;sekdsk = unadsk?
  841.     DB    JRNZ,ALLOC-$-1    ;skip if not
  842.                 ;disks are the same
  843.     LHLD    UNATRK
  844.     CALL    SEKTRKCMP    ;sektrk = unatrk?
  845.     DB    JRNZ,ALLOC-$-1    ;skip if not
  846.                 ;tracks are the same
  847.     LDA    SEKSEC        ;same sector?
  848.     LXI    H,UNASEC
  849.     CMP    M        ;seksec = unasec?
  850.     DB    JRNZ,ALLOC-$-1    ;skip if not
  851.                 ;match, move to next sector for future ref
  852.     INR    M        ;unasec = unasec+1
  853.     LDA    CPMSPT        ;end of track?
  854.     CMP    M        ;count CP/M sectors
  855.     DB    JRNC,NOOVF-$-1    ;skip if no overflow
  856.                 ;overflow to next track
  857.     MVI    M,1        ;unasec = 1
  858.     LHLD    UNATRK
  859.     INX    H
  860.     SHLD    UNATRK        ;unatrk = unatrk+1
  861. NOOVF:                ;match found, mark as unnecessary read
  862.     XRA    A
  863.     STA    RSFLAG        ;rsflag = 0
  864.     DB    JR,RWOPER-$-1    ;to perform the write
  865.  
  866. ALLOC:                ;not an unallocated record, requires pre-read
  867.     XRA    A
  868.     STA    UNACNT        ;unacnt = 0
  869.     INR    A
  870.     STA    RSFLAG        ;rsflag = 1
  871. ;*****************************************************
  872. ;*                                                   *
  873. ;*    Common code for READ and WRITE follows       *
  874. ;*                                                   *
  875. ;*****************************************************
  876. RWOPER:    if    TYPEAHEAD
  877.     CALL    TESTI    ;(TEST CONSOLE INPUT)
  878.     endif
  879.     LDA    SECSHF    ;COMPUTE HOST SECTOR
  880.     MOV    B,A
  881.     LDA    SEKSEC    ;HOSTSECTOR=((SEEKSECTOR)-1 SHR SEKSHF)+1
  882.     DCR    A
  883.     DB    JR,RWOPR2-$-1
  884. RWOPR1: DW    SRLA
  885. RWOPR2: DB    DJNZ,RWOPR1-$+0FFH
  886.     INR    A
  887.     STA    SEKHST        ;host sector to seek
  888.                 ;active host sector?
  889.     LXI    H,HSTACT    ;host active flag
  890.     MOV    A,M
  891.     MVI    M,1        ;always becomes 1
  892.     ORA    A        ;was it already?
  893.     DB    JRZ,FILHST-$-1    ;fill host if not
  894.             ;host buffer active, same as seek buffer?
  895.     LDA    SEKDSK    
  896.     LXI    H,HSTDSK
  897.     CMP    M        ;sekdsk = hstdsk?
  898.     DB    JRNZ,NOMATCH-$-1
  899.     LHLD    HSTTRK
  900.     CALL    SEKTRKCMP    ;sektrk = hsttrk?
  901.     DB    JRNZ,NOMATCH-$-1
  902.     LDA    SEKHST
  903.     LXI    H,HSTSEC    ;sekhst = hstsec?
  904.     CMP    M
  905.     DB    JRZ,MATCH-$-1    ;skip if match
  906. NOMATCH:        ;not correct sector
  907.     CALL    FLUSH        ;flush buffer
  908.     STA    ERFLAG        ;REPORT ANY ERRORS
  909. FILHST:            ;fill the host buffer
  910.     LXI    H,SEKDSK    ;Copy SEEK parms to HOSTBUFFER parms
  911.     LXI    D,HSTDSK
  912.     LXI    B,5
  913.     DW    LDIR
  914.     LDA    RSFLAG        ;need to read?
  915.     ORA    A
  916.     CNZ    READHST        ;yes, if 1
  917.     LXI    H,ERFLAG    ;REPORT ANY ERRORS
  918.     ORA    M
  919.     MOV    M,A
  920.     XRA    A
  921.     STA    HSTWRT        ;no pending write
  922. MATCH:            ;copy data to or from buffer
  923.     LDA    SEKSEC        ;mask buffer number
  924.     DCR    A        ;  HL=((SEKSEC-1) AND SECMSK) SHL 7
  925.     MOV    L,A
  926.     LDA    SECMSK
  927.     ANA    L
  928.     RAR
  929.     MOV    H,A
  930.     MVI    A,0
  931.     RAR
  932.     MOV    L,A    ; HL has relative host buffer address
  933.     LXI    D,HSTBUF
  934.     DAD    D    ;hl = host address
  935.     XCHG        ;now in DE
  936.     LHLD    DMAADD    ;get/put CP/M data
  937.     XCHG
  938.     LXI    B,128    ;length of move
  939.     LDA    READOP    ;which way?
  940.     ORA    A
  941.     DB    JRNZ,RWMOVE-$-1 ;skip if read
  942.             ;write operation, mark and switch direction
  943.     MVI    A,1
  944.     STA    HSTWRT    ;hstwrt = 1
  945.     XCHG        ;source/dest swap
  946. RWMOVE:    DW    LDIR    ;BC initially 128, HL is source, DE is dest
  947.             ;data has been moved to/from host buffer
  948.     LDA    WRTYPE    ;write type
  949.     CPI    WRDIR    ;to directory?
  950.     LDA    ERFLAG    ;IF NOT THEN EXIT WITH FLAG
  951.     RNZ
  952.             ;clear host buffer for directory write
  953.     ORA    A    ;errors?
  954.     CZ    WRITEHST;IF NOT, WRITE BUFFER
  955.     RET
  956.  
  957. ;*****************************************************
  958. ;*    Compare M(HL)=SEKTRK,  16-bit compare        *
  959. ;*****************************************************
  960. SEKTRKCMP:    ;HL = .unatrk or .hsttrk, compare with sektrk
  961.     XCHG
  962.     LHLD    SEKTRK
  963.     ORA    A    ;(clear carry)
  964.     DW    SBCHLDE    ;SBC HL,DE  set Z/NZ on compare
  965.     RET
  966.  
  967. ;****************************************************************
  968. ; READ THE SECTOR AT HSTSEC, HSTTRK, HSTDSK.
  969. ; USE HOSTBUFFER.
  970. ;****************************************************************
  971. READHST:
  972.     if    DEBUG
  973.     MVI    A,'R'
  974.     CALL    CONOUTA
  975.     endif
  976.     LDA    HSTDSK
  977.     CALL    CHKDSA    ;SELECT HOST DISK
  978.     CALL    CHKTRK    ;CHECK FOR CORRECT CURRENT TRACK, & MOVE
  979.     MVI    A,RTCNT    ;GET RETRY COUNT.
  980. RRETRY:    STA    ERCNT    ;STORE IN ERROR CTR.
  981.     if    TYPEAHEAD
  982.     CALL    TESTI
  983.     endif
  984.     LXI    H,HSTBUF;GET STARTING ADR.
  985.     MVI    A,0D0H    ;CAUSE INTERRUPT.
  986.     OUT    DCOM
  987.     XTHL        ;SOME DELAY.
  988.     XTHL
  989.     XTHL
  990.     XTHL
  991.     LDA    HSTSEC    ;GET SECTOR NUMBER.
  992.     OUT    SECTP    ;SET SECTOR INTO 1793.
  993.     IN    DSTAT    ;READ STATUS.
  994.     ANI    20H    ;LOOK AT HLD BIT.
  995.     MVI    A,8CH    ;READ WITH HEAD LOAD DELAY
  996.     DB    JRZ,READ3-$-1    ;HEAD NOT LOADED.
  997.     MVI    A,88H    ;CODE FOR READ W/O HD LD DELAY
  998. READ3:    MVI    C,DDATA    ;SEND COMMAND TO 1793
  999.     DW    PUSHIX
  1000.     CALL    RLOOP
  1001.     DW    POPIX
  1002.     IN    DSTAT    ;DONE: READ DISK STATUS.
  1003.     ANI    9DH    ;LOOK AT ERROR BITS.
  1004.     JZ    MTROFF    ;IF NO ERROR THEN RETURN (&TURN MOTOR OFF)
  1005.     CALL    ERCHK    ;CHECK FOR SEEK ERROR.
  1006.     LXI    H,RECNT    ;GET RD ERR COUNT ADDR.
  1007.     INR    M        ;ONE MORE ERROR.
  1008.     LDA    ERCNT    ;GET ERROR COUNT.
  1009.     DCR    A            ;DECREMENT COUNT.
  1010.     DB    JRNZ,RRETRY-$+0FFH    ;TRY TO READ AGAIN.
  1011. ERMSG0:    LXI    H,RDMSG    ;PRINT "READ ".
  1012. ERMSG:    CALL    PMSG    ;PRINT ORIGIN MESSAGE.
  1013. ERMSG1:
  1014.     MOV    A,D    ;GET ERROR BITS.
  1015.     RAL        ;IF BIT 7 HIGH,
  1016.     LXI    H,NRMSG    ;"NOT READY".
  1017.     DB    JRC,ERMSG2-$-1
  1018.     MOV    A,D    ;GET ERROR BITS.
  1019.     ANI    10H    ;IF BIT 4 IS HIGH,
  1020.     LXI    H,RNMSG    ;PRINT "RECORD NOT FOUND"
  1021.     CNZ    PMSG
  1022.     MOV    A,D    ;GET ERROR BITS.
  1023.     ANI    8H    ;IF BIT 3 IS HIGH,
  1024.     LXI    H,CRCMSG    ;PRINT "CRC ERROR".
  1025.     CNZ    PMSG
  1026.     MOV    A,D    ;GET ERROR BITS.
  1027.     ANI    4H    ;IF BIT 2 IS HIGH,
  1028.     LXI    H,LDMSG    ;PRINT "LOST DATA".
  1029.     CNZ    PMSG
  1030.     MOV    A,D    ;GET ERROR BITS.
  1031.     RAR        ;IF BIT 1 IS HIGH,
  1032.     LXI    H,BSYMSG;PRINT "BUSY".
  1033.     CC    PMSG
  1034. PERMSG:    LXI    H,ERRMSG    ;PRINT "ERROR."
  1035. ERMSG2:    CALL    PMSG
  1036.     MVI    A,1    ;SET FOR BDOS ERR.
  1037.     ORA    A
  1038.     JMP    MTROFF    ;TURN MOTOR OFF
  1039.  
  1040. RLOOP:    DW    LDIX,RL1
  1041.     OUT    DCOM    ;
  1042.     EI        ;
  1043. RL1:    HLT        ;
  1044.     DW    INI    ;
  1045.     EI        ;
  1046.     DW    JPIX    ;
  1047.  
  1048. ; ERCHK - CHECK FOR RECORD NOT FOUND ERROR.
  1049. ERCHK:    MOV    D,A    ;SAVE ERROR BITS IN D.
  1050.     ANI    10H    ;IF RECORD NOT FOUND,
  1051.     CNZ    CHKSK    ;DO A CHECK ON SEEK.
  1052.     MOV    A,D    ;RESTORE BITS
  1053.     ORA    A    ;SET FLAGS,
  1054.     RET        ;AND RETURN.
  1055.  
  1056. ;CHECK FOR SEEK TO CORRECT TRACK,
  1057. ;AND CHANGE IF NECESSARY.
  1058. CHKSK:    PUSH    H    ;
  1059.     MVI    A,0C4H    ;COMMAND TO READ ADDRESS
  1060.     MVI    C,DDATA    ;
  1061.     LXI    H,ADDRBF    ;
  1062.     DW    PUSHIX
  1063.     CALL    RLOOP    ;
  1064.     DW    POPIX
  1065.     LDA    ADDRBF    ;
  1066.     MOV    B,A    ;
  1067.     POP    H    ;DMAADD: TRK,SIDE,SECTOR,SECL,CRC,CRC
  1068. CHKS3:    IN    DSTAT    ;READ DISK STATUS.
  1069.     ORA    A    ;SET FLAGS.
  1070.     DB    JRZ,CHKS4-$-1    ;READ ADR OK IF 0.
  1071.     CALL    HOME1    ;OTHERWISE, HOME FIRST.
  1072.     DB    JR,CHKTRK-$-1
  1073. CHKS4:
  1074.     MOV    A,B    ;UPDATE TRACK REGISTER.
  1075.     CALL    OUTRK    ;ADJUST IF 2SIDE
  1076.     OUT    TRACK    ;
  1077. ;*********************************************
  1078. ;CHKTRK: IF CURRENT TRACK <> HOST TRACK, GOTO HOSTTRACK
  1079. ;*********************************************
  1080. CHKTRK:    IN    TRACK
  1081.     CALL    INTRK
  1082.     LXI    H,HSTTRK
  1083.     CMP    M
  1084.     RZ        ;TRACKS ARE THE SAME, RETURN
  1085.     MOV    A,M    ;TRACKS NOT SAME, CORRECT
  1086.     JMP    SEEK    ;
  1087.  
  1088. ;****************************************************************
  1089. ; FLUSH THE BUFFER IF A WRITE OPERATION IS PENDING
  1090. ;****************************************************************
  1091. FLUSH:    LDA    HSTWRT    ;
  1092.     ORA    A    ;
  1093.     RZ
  1094. ;****************************************************************
  1095. ; WRITE THE SECTOR AT HSTSEC, HSTTRK, HSTDSK.
  1096. ; USE HOST BUFFER.
  1097. ;****************************************************************
  1098. WRITEHST:
  1099.     if    DEBUG
  1100.     MVI    A,'W'
  1101.     CALL    CONOUTA
  1102.     endif
  1103.     LDA    HSTDSK    ;CHECK FOR CORRECT DISK, AND SELECT
  1104.     CALL    CHKDSA    ;
  1105.     CALL    CHKTRK    ;GO TO CORRECT TRACK
  1106.     MVI    A,RTCNT    ;GET RETRY COUNT.
  1107. WRETRY:    STA    ERCNT    ;STORE IN ERROR COUNTER.
  1108.     if    TYPEAHEAD
  1109.     CALL    TESTI
  1110.     endif
  1111.     LXI    H,HSTBUF ;GET STARTING ADR.
  1112.     MVI      A,0D0H    ;STATUS INTERUPT FOR 1793.
  1113.     OUT    DCOM    ;COMMAND 1793.
  1114.     XTHL
  1115.     XTHL
  1116.     XTHL
  1117.     XTHL
  1118.     LDA    HSTSEC    ;GET SECTOR NUMBER.
  1119.     OUT    SECTP    ;SET THE SECTOR INTO 1793.
  1120.     IN    DSTAT    ;GET 1793 STATUS.
  1121.     ANI    20H    ;CHECK FOR HEAD LOAD.
  1122.     MVI    A,0ACH    ;SET UP 1793 FOR WRITE.
  1123.     DB    JRZ,WRITE2-$-1    ;HEAD IS NOT LOADED.
  1124.     MVI    A,0A8H    ;CODE FOR WRITE W/O HD LD.
  1125. WRITE2:    MVI    C,DDATA
  1126.     DW    PUSHIX
  1127.     CALL    WLOOP
  1128.     DW    POPIX
  1129.     IN    DSTAT    ;DONE: READ DISK STATUS.
  1130.     ANI    0FDH    ;LOOK AT THESE BITS.
  1131.     STA    HSTWRT    ;CLEAR PENDINGWRITEFLAG IF NO ERROR
  1132.     JZ    MTROFF    ;RETURN IF NO ERROR (&TURN MOTOR OFF).
  1133.     CALL    ERCHK    ;CHECK/CORRECT SEEK ERR.
  1134.     LXI    H,WECNT    ;GET ADR OF WRITE ERR CTR.
  1135.     INR    M    ;ONE MORE WRITE ERROR.
  1136.     LDA    ERCNT    ;GET ERROR COUNT.
  1137.     DCR    A    ;DECREMENT COUNT.
  1138.     DB    JRNZ,WRETRY-$+0FFH    ;TRY TO WRITE AGAIN.
  1139.     LXI    H,WTMSG    ;PRINT "WRITE ".
  1140.     CALL    PMSG
  1141.     MOV    A,D    ;GET ERROR BITS.
  1142.     ANI    40H    ;LOOK AT BIT 6.
  1143.     LXI    H,WPMSG    ;PRINT "PROTECT ".
  1144.     CNZ    PMSG
  1145.     MOV    A,D    ;GET ERROR BITS.
  1146.     ANI    20H    ;LOOK AT BIT 5.
  1147.     LXI    H,WFMSG    ;PRINT "FAULT ".
  1148.     CNZ    PMSG
  1149.     JMP    ERMSG1    ;DO COMMON MESSAGES.
  1150.  
  1151. WLOOP:    DW    LDIX,WL1
  1152.     OUT    DCOM
  1153.     EI
  1154. WL1:    HLT
  1155.     DW    OUTI
  1156.     EI
  1157.     DW    JPIX
  1158.  
  1159. ;****************************************************************
  1160. ; HOME DISK DRIVE (RETURN TO TRACK 0)
  1161. ;****************************************************************
  1162. HOME:
  1163.     if    DEBUG
  1164.     MVI    A,'H'
  1165.     CALL    CONOUTA
  1166.     endif
  1167.     CALL    FLUSH    ;IF (BUFFER WRITE PENDING) THEN WRITE BUFFER
  1168.             ;    (SPEEDS UP SAVE & PIP)
  1169.     CALL    CLRDFLGS;CLEAR DENSITY FLAGS
  1170.     CALL    CHKSD    ;CHECK FOR SEKDSK AND SELECT IF NECESSARY
  1171. HOME1:    MVI    A,2
  1172.     OUT    DSEL    ;SINGLE DENSITY
  1173.     MVI    C,0
  1174.     CALL    SETTRK
  1175.     CALL    MTRON    ;TURN MOTOR ON
  1176.     XRA    A
  1177.     OUT    DDATA    ;TRACK # 0
  1178.     MVI    A,1CH    ;3MS SEEK W/ HEAD LOAD & VERIFY
  1179.     CALL    DCOMM
  1180.     IN    DSTAT    ;READ STATUS.
  1181.     ANI    91H    ;LOOK AT BITS.
  1182.     RZ        ;OK IF ZERO.
  1183.     MVI    A,9    ;6MS RESTORE W/BEGIN HEAD LOAD
  1184.     CALL    DCOMM    ;
  1185.     IN    DSTAT
  1186.     ANI    91H
  1187.     DB    JRZ,HOME2-$-1    ;IF NOT OK, SEEK TRACK 0
  1188.     XRA    A
  1189.     CALL    SEEK
  1190. HOME2:    JMP    MTROFF    ;RETURN (&TURN MOTOR OFF)
  1191.  
  1192. ;****************************************************************
  1193. ;SEEK: MOVE THE HEAD TO THE TRACK IN REGISTER A (= 0-153).
  1194. ;****************************************************************
  1195. SEEK:    PUSH    B    ;SAVE B&C.
  1196.     PUSH    PSW    ;
  1197.     CALL    MTRON    ;(TURN MOTOR ON)
  1198.     POP    PSW    ;
  1199.     MOV     B,A    ;SAVE DESTINATION TRACK.
  1200.     XRA    A    ;
  1201.     STA    SECNT    ;CLEAR SEEK ERROR CTR
  1202.     MOV    A,B    ;
  1203.     ORA    A    ;  IF (TK 0) THEN
  1204.     MVI    A,2    ;    SET UP FOR SINGLE DENS
  1205.     DB    JRZ,SEEK1-$-1
  1206.     MVI    A,1    ;  IF (TK 1) THEN
  1207.     CMP    B    ;    SET UP FOR DOUBLE DENSITY
  1208.     if    not IBMB
  1209.     DB    JRZ,SEEK1-$-1
  1210.     endif
  1211.     if    IBMB
  1212.     DB    JRNZ,SEEK0-$-1;    (UNLESS NOT A: AND IBM OPTION SELECTED)
  1213.     LDA    CURDSK    ;    (IN WHICH CASE, TRK1 DENSITY=LOGDEN)
  1214.     ORA    A    ;
  1215.     MVI    A,1    ;
  1216.     DB    JRZ,SEEK1-$-1
  1217. SEEK0:            ;
  1218.     endif
  1219.     LDA    LOGDEN    ;ELSE GET DENSITY OF LOGGED DRIVE.
  1220. SEEK1:    OUT    DSEL    ;SET DENSITY IN 1793
  1221.     MVI    A,RTCNT    ;GET RETRY COUNT.
  1222. SRETRY:    STA    SERCNT    ;STORE IN ERROR COUNTER.
  1223.     IN    TRACK    ;READ PRESENT TRACK NO.
  1224.     CALL    INTRK    ;ADJUST IF 2SIDE
  1225.     MOV    C,A    ;SAVE IN C. (CURR TK)
  1226.     CMP    B    ;SAME AS SEEK TRACK NO.? (A IS CURR TK)
  1227.     MOV    A,B    ;RESTORE A FROM B. (MAKE A DESIRED TK)
  1228.     DB    JRZ,THERE-$-1    ;IF (THERE) THEN EXIT
  1229.     MVI    A,0D0H    ;TERMINATE COMMAND AND/OR BUSY
  1230.     OUT    DCOM    ;
  1231.     XTHL        ;WASTE
  1232.     XTHL        ;TIME
  1233.     MOV    A,B    ;GET TRACK
  1234.     CALL    OUTRK    ;ADJUST FOR 2-SIDE
  1235.     OUT    DDATA    ;OUTPUT (SEEK TRACK #)
  1236.     MVI    A,1CH    ;3MS SEEK W/ HEAD LOAD & VERIFY
  1237.     CALL    DCOMM    ;
  1238.     IN    DSTAT    ;READ STATUS.
  1239.     ANI    91H    ;LOOK AT BITS.
  1240.     DB    JRZ,THERE-$-1    ;OK IF ZERO.
  1241.     MOV    B,A    ;SAVE STATUS IN B
  1242.     LDA    SECNT    ;
  1243.     INR    A    ;
  1244.     STA    SECNT    ;ADD 1 TO SEEK ERR CTR
  1245.     LDA    SERCNT    ;GET ERROR COUNT.
  1246.     DCR    A    ;DECREMENT COUNT.
  1247.     DB    JRNZ,SRETRY-$+0FFH    ;RETRY SEK.
  1248.     MOV    D,B    ;RESTORE STATUS TO D REG
  1249.     POP    B    ;RESTORE B&C.
  1250.     LXI    H,SKMSG    ;PRINT "SEEK ".
  1251.     JMP    ERMSG    ;DO COMMON ERR MESSAGES.
  1252.  
  1253. THERE:    POP    B
  1254.     RET
  1255.  
  1256.  
  1257. DCOMM:    OUT DCOM
  1258.     EI
  1259.     HLT        ;INTERUPT CAUSES RETURN
  1260.     RET        ;WHEN COMMAND COMPLETE
  1261.  
  1262. ;*****************************************************
  1263. ; INTRK/OUTRK ADJUST TRACK NUMBERS IF >77
  1264. ;*****************************************************
  1265. INTRK:    ;TRACK # IN A INCREASED BY 77 IF SIDEFLG NON-ZERO
  1266.     PUSH    PSW
  1267.     LDA    SIDEFLG
  1268.     ORA    A    ;Z:=(TRACK<77)
  1269.     DB    JRZ,INTRK1-$-1
  1270.     POP    PSW
  1271.     ADI    77
  1272.     RET
  1273.  
  1274. OUTRK:    ;TRACK # IN A REDUCED BY 77 IF >76 AND SET SIDEFLG NON-ZERO
  1275.     PUSH    PSW
  1276.     CPI    77
  1277.     if    not NOREVA
  1278.     LDA    CPUREV    ;A=CPU BD REV
  1279.     endif
  1280.     DB    JRC,OUTRK1-$-1
  1281.     if    not NOREVA
  1282.     CPI    REVB    ;  (>=T77)
  1283.     endif
  1284.     MVI    A,4    ;  (REV B)
  1285.     if    not NOREVA
  1286.     DB    JRZ,OUTRK0-$-1
  1287.     MVI    A,1    ;  (REV A)
  1288.     endif
  1289. OUTRK0:    STA    SIDEFLG
  1290.     OUT    DCONT
  1291.     POP    PSW
  1292.     SUI    77
  1293.     RET
  1294.  
  1295. OUTRK1:    if    not NOREVA
  1296.     CPI    REVB    ;  (<T77)
  1297.     endif
  1298.     MVI    A,8    ;  (REV B)
  1299.     if    not NOREVA
  1300.     DB    JRZ,OUTRK2-$-1
  1301.     LDA    SEKDSK    ;  (REV A) IF NOT(DRIVE A) THEN DON'T SET SIDE
  1302.     ORA    A    ;
  1303.     DB    JRNZ,OUTRK3-$-1
  1304.     MVI    A,2    ;  (REV A AND DRIVE A)
  1305.     endif
  1306. OUTRK2:    OUT    DCONT
  1307. OUTRK3:    XRA    A
  1308.     STA    SIDEFLG
  1309. INTRK1:    POP    PSW
  1310.     RET
  1311.  
  1312. ;****************************************
  1313. ; DRIVE MOTOR CONTROL    ON/OFF
  1314. ;****************************************
  1315. MTRON:
  1316.     IN    TRACK    ;SET SIDE 0
  1317.     CALL    OUTRK
  1318.     MVI    A,8    ;TURN DRIVE MOTOR ON
  1319.     OUT    DSEL
  1320.     MVI    A,0D0H    ;1793 FORCE INTERRUPT COMMAND
  1321.     OUT    DCOM
  1322.     IN    DSTAT    ;IF (READY) THEN RETURN
  1323.     RAL
  1324.     RNC
  1325. MTRON1:    IN    DSTAT    ;ELSE DO
  1326.     RAL        ;  REPEAT
  1327.     DB    JRC,MTRON1-$+0FFH;    UNTIL (READY)
  1328.     PUSH    H    ;  /*Check spindle speed*/
  1329.     PUSH    B
  1330.     CALL    SPIN
  1331.     POP    B
  1332.     POP    H
  1333.     RET
  1334.  
  1335. SPIN:    CALL    SPIN1    ;Check spindle speed twice
  1336. SPIN1:    LXI    B,-13544;  REPEAT
  1337. SPIN2:    LXI    H,0    ;    HL=0
  1338. SPIN3:                ;    REPEAT
  1339.     if    TYPEAHEAD
  1340.     CALL    TESTI
  1341.     endif
  1342.     IN    DSTAT
  1343.     ANI    2
  1344.     DB    JRZ,SPIN3-$+0FFH;     UNTIL (INDEX PULSE)
  1345. SPIN4:    IN    DSTAT    ;    REPEAT
  1346.     ANI    2
  1347.     DB    JRNZ,SPIN4-$+0FFH; UNTIL (NO INDEX PULSE)
  1348. SPIN5:  INX    H    ;    REPEAT
  1349.     MOV    A,H    ;      IF (HL++ == 0) start over
  1350.     ORA    L
  1351.     DB    JRZ,SPIN2-$+0FFH
  1352.     IN    DSTAT
  1353.     ANI    2
  1354.     JZ    SPIN5    ;      UNTIL (INDEX PULSE)
  1355.     DAD    B    ;    UNTIL (HL<13544)
  1356.     JC    SPIN2
  1357.     RET
  1358.  
  1359. MTROFF:
  1360.     PUSH    PSW    ;TURN DRIVE MOTOR OFF
  1361.     MVI    A,4    ;(DRIVE STOPS ~20 SECS AFTER COMMAND)
  1362.     OUT    DSEL
  1363.     POP    PSW
  1364.     RET
  1365.  
  1366. ;****************************************************************
  1367. ;      I/O Routines
  1368. ;****************************************************************
  1369.  
  1370. PCRLF:    LXI    H,CRLF    ;PRINT CRLF
  1371. PMSG:    MOV    A,M    ;GET A CHARACTER.
  1372.     CALL    CONOUTA    ;PRINT IT.
  1373.     ORA    M    ;GET AGAIN, SET FLAGS
  1374.     RM        ;IF MSB SET, RETURN
  1375.     INX    H    ;INCREMENT H&L, AND GET ANOTHER.
  1376.     DB    JR,PMSG-$+0FFH
  1377.  
  1378.     if    DEBUG
  1379. PHEX:    PUSH    PSW    ;Print ACC in Hex (destroys acc)
  1380.     RRC
  1381.     RRC
  1382.     RRC
  1383.     RRC
  1384.     CALL    PHEX1
  1385.     POP    PSW
  1386. PHEX1:    ANI    0FH
  1387.     ADI    90H
  1388.     DAA
  1389.     ACI    40H
  1390.     DAA
  1391.     ;fall through to CONOUTA
  1392.     endif
  1393.  
  1394. CONOUTA:    ;print acc
  1395.     PUSH    B
  1396.     ANI    7FH
  1397.     MOV    C,A
  1398.     CALL    LCONOUT
  1399.     POP    B
  1400.     RET
  1401.  
  1402.  
  1403. ;**************************************************
  1404. ;*        I/O DEVICE DRIVERS          *
  1405. ;* See IOBYTE description at beginning of listing *
  1406. ;**************************************************
  1407.  
  1408. LCONST:    PUSH    D    ;LOGICAL CONSOLE INPUT DEVICE STATUS
  1409.     CALL    DISPATCH0
  1410.     DW    CONST    ;00=Console
  1411.     DW    AUTST    ;01=Console & Modem in parallel (Autoswitch mode)
  1412.     DW    MODST    ;10=Modem
  1413.     DW    NULLRDY    ;11=Clock (Always ready)
  1414.  
  1415. LCONIN:    PUSH    D    ;LOGICAL CONSOLE INPUT DEVICE
  1416.     CALL    DISPATCH0
  1417.     DW    CONIN    ;00=Console
  1418.     DW    AUTIN    ;01=Console & Modem
  1419.     DW    MODEMIN    ;10=Modem
  1420.     DW    RCLOCK    ;11=Clock
  1421.  
  1422. LCONOUT:PUSH    D    ;LOGICAL CONSOLE OUTPUT DEVICE
  1423.     CALL    DISPATCH0
  1424.     DW    CONOUT    ;00=Console
  1425.     DW    AUTOUT    ;01=Console & Modem
  1426.     DW    MODEMO    ;10=Modem
  1427.     DW    WCLOCK    ;11=Clock
  1428.  
  1429. LREADER:PUSH    D    ;LOGICAL READER DEVICE
  1430.     MVI    E,2
  1431.     CALL    DISPATCH
  1432.     DW    NULLIN    ;00= not used
  1433.     DW    NULLIN    ;01= not used
  1434.     DW    MODEMIN    ;10=Modem
  1435.     DW    RCLOCK    ;11=Clock
  1436.  
  1437. LPUNCH:    PUSH    D    ;LOGICAL PUNCH DEVICE
  1438.     MVI    E,4
  1439.     CALL    DISPATCH
  1440.     DW    PLLPRN    ;00=Parallel printer
  1441.     DW    NULLOUT    ;01= not used
  1442.     DW    MODEMO    ;10=Modem
  1443.     DW    WCLOCK    ;11=Clock
  1444.  
  1445. LLISTST: PUSH    D    ;LOGICAL LIST DEVICE STATUS
  1446.     MVI    E,6
  1447.     CALL    DISPATCH
  1448.     DW    PLLRDY    ;00=Parallel printer
  1449.     DW    NULLRDY    ;01=Console
  1450.     DW    NULLRDY    ;10=Serial, ETX/ACK
  1451.     DW    NULLRDY    ;11=Serial, XON/XOFF
  1452. NULLRDY:XRA    A    ;RETURN STATUS (0 IF NOT-READY SEZ D.R.I.?)
  1453.     RET
  1454.  
  1455. LLIST:    PUSH    D    ;LOGICAL LIST DEVICE
  1456.     MVI    E,6
  1457.     CALL    DISPATCH
  1458.     DW    PLLPRN    ;00=Parallel printer
  1459.     DW    CONOUT    ;01=Console
  1460.     DW    ETXACK    ;10=Serial, ETX/ACK protocol
  1461.     DW    XONXOFF    ;11=Serial, XON/XOFF protocol
  1462.  
  1463. DISPATCH0:
  1464.     MVI    E,8
  1465. DISPATCH:
  1466.     LDA    IOBYTE    ;Get byte from IOBYTE
  1467. DISP1:    RRC        ;Rotate bits of interest into lsb
  1468.     DCR    E
  1469.     DB    JRNZ,DISP1-$+0FFH
  1470.     ANI    3    ;Mask for desired bits
  1471.     XTHL        ;Push HL, Pop (Table Address)
  1472.     MOV    E,A
  1473.     MVI    D,0    ;HL -> Table Item
  1474.     DAD    D
  1475.     DAD    D
  1476.     MOV    E,M    ;HL = Table Item
  1477.     INX    H
  1478.     MOV    D,M
  1479.     XCHG
  1480.     PUSH    B    ;Push B (TOS=Caller's HL,DE)
  1481.     LXI    D,DISP2    ;Push return address
  1482.     PUSH    D
  1483.     if    TYPEAHEAD
  1484.     CALL    TESTI    ;Test console input
  1485.     endif
  1486.     PCHL        ;GOTO TABLE ROUTINE
  1487. DISP2:    POP    B    ;Restore caller's regs (except psw)
  1488.     POP    H
  1489.     POP    D
  1490.     RET
  1491.  
  1492. CONST:            ;IF(CONSOLE RDY) THEN RETURN (NZ)
  1493.     if    TYPEAHEAD
  1494.     LDA    ICOUNT
  1495.     ORA    A
  1496.     endif
  1497.     if    not TYPEAHEAD
  1498.     IN    CSTAT    ;IF (RX CHAR RDY) DO
  1499.     ANI    2
  1500.     endif
  1501.     DB    JRNZ,CONST1-$-1
  1502.     RET
  1503.  
  1504. AUTST:    CALL    CONST
  1505.     RNZ
  1506. MODST:    IN    MSTAT    ;RETURN (MODEM STATUS)
  1507.     ANI    2
  1508.     RZ
  1509. CONST1:    ORI    0FFH
  1510.     RET
  1511.  
  1512. CONIN:    CALL    FLUSH    ;FLUSH BUFFER
  1513.     if    TYPEAHEAD
  1514.     CALL    TESTI
  1515.     LXI    H,ICOUNT    ;IF (CON CHAR NOT RDY) GOTO CONIN
  1516.     MOV    A,M
  1517.     ORA    A
  1518.     DB    JRZ,CONIN-$+0FFH
  1519.     DCR    M
  1520.     LXI    H,ICHARQ+1;  ELSE DO
  1521.     LXI    D,ICHARQ
  1522.     MOV    C,A
  1523.     MVI    B,0
  1524.     LDAX    D    ;  A=CHAR
  1525.     DW    LDIR    ;  DROP QUEUE
  1526.     endif
  1527.     if    not TYPEAHEAD
  1528.     IN    CSTAT    ;IF (CON CHAR NOT RDY) GOTO CONIN
  1529.     ANI    2
  1530.     DB    JRZ,CONIN-$+0FFH
  1531.     IN    CDATA    ;ELSE RETURN (A=CHAR AND 7FH)
  1532.     endif
  1533.     ANI    7FH
  1534.     RET
  1535.  
  1536.     if    TYPEAHEAD
  1537. TESTI:    IN    CSTAT    ;IF (RX CHAR RDY) DO
  1538.     ANI    2
  1539.     RZ
  1540.     LDA    ICOUNT    ;  IF (QUEUE<QSIZE) DO
  1541.     CPI    QSIZE
  1542.     RNC
  1543.     INR    A    ;    QUEUE.COUNT++
  1544.     STA    ICOUNT
  1545.     PUSH    H    ;    QUEUE||RX CHAR
  1546.     LXI    H,ICHARQ-1
  1547.     ADD    L
  1548.     MOV    L,A
  1549.     DB    JRNC,TEST0-$-1
  1550.     INR    H
  1551. TEST0:    IN    CDATA
  1552.     MOV    M,A
  1553.     POP    H
  1554.     RET
  1555.     endif
  1556.  
  1557. AUTIN:    CALL    FLUSH
  1558. AUTIN1:
  1559.     if    TYPEAHEAD
  1560.     CALL    TESTI
  1561.     endif
  1562.     CALL    CONST
  1563.     DB    JRNZ,CONIN-$+0FFH
  1564.     CALL    MODST
  1565.     DB    JRZ,AUTIN1-$+0FFH
  1566. MODEMIN:CALL    FLUSH
  1567.     IN    MSTAT
  1568.     ANI    02H
  1569.     DB    JRZ,MODEMIN-$+0FFH
  1570.     IN    MDATA
  1571.     RET
  1572.  
  1573. CONOUT:    IN    CSTAT    ;OUTPUT (C) TO CONSOLE
  1574.     RAR
  1575.     DB    JRNC,CONOUT-$+0FFH
  1576.     MOV    A,C
  1577.     OUT    CDATA
  1578.     RET
  1579.  
  1580. AUTOUT:    CALL    CONOUT
  1581. MODEMO:    IN    MSTAT    ;OUTPUT TO MODEM
  1582.     RAR
  1583.     DB    JRNC,MODEMO-$+0FFH
  1584.     MOV    A,C
  1585.     OUT    MDATA
  1586.     RET
  1587.  
  1588.  
  1589. XONXOFF:    ;START OF X-ON X-OFF
  1590.     IN    LDATA
  1591.     ANI    1FH    ;MASK MSB'S
  1592.     CPI    13H    ;CHECK FOR X-OFF
  1593.     DB    JRNZ,XONX2-$-1    ;IF NOT THEN OUTPUT CHAR
  1594. XONX1:            ;IF SENT THEN WAIT FOR X-ON
  1595.     IN    LDATA
  1596.     ANI    1FH    ;MASK MSB'S
  1597.     CPI    11H    ;X-ON CHAR ?
  1598.     DB    JRNZ,XONX1-$+0FFH;IF NOT GOBACK
  1599. XONX2:    IN    LSTAT
  1600.     ANI    81H    ;SEND CHAR
  1601.     CPI    81H
  1602.     DB    JRNZ,XONX2-$+0FFH
  1603.     MOV    A,C
  1604.     OUT    LDATA
  1605.     RET
  1606.  
  1607. PLLPRN:            ;PARALLEL PORT DRIVER
  1608.     MVI    A,81H
  1609.     OUT    0D3H        ;8255 CONTROL PORT
  1610. PLLP1:    CALL    PLLRDY
  1611.     DB    JRNZ,PLLP1-$+0FFH;LOOP UNTIL READY
  1612.     MOV    A,C
  1613.     OUT    0D1H        ;OUTPUT DATA TO PORT B
  1614.     MVI    A,0BH
  1615.     OUT    0D3H        ;STROBE
  1616.     DCR    A
  1617.     OUT    0D3H
  1618.     RET
  1619.  
  1620. PLLRDY:    IN    0D2H        ;Parallel Printer Ready
  1621.     ANI    4        ;04H==busy, 00=ready
  1622.     RZ            ;Return 0==ready
  1623.     ORI    0FFH
  1624.     RET            ;Return 0FFH==not ready
  1625.  
  1626. ETXACK:    IN    LSTAT
  1627.     RAR
  1628.     DB    JRNC,ETXACK-$+0FFH
  1629.     MOV    A,C
  1630.     OUT    LDATA
  1631.     LXI    H,PCOUNT
  1632.     DCR    M
  1633.     RP
  1634.     MVI    M,80H
  1635.     MVI    C,3
  1636.     CALL    ETXACK
  1637. ACKCHK: IN    LSTAT
  1638.     ANI    2
  1639.     DB    JRZ,ACKCHK-$+0FFH
  1640.     IN    LDATA
  1641.     ANI    7FH
  1642.     CPI    6
  1643.     DB    JRNZ,ACKCHK-$+0FFH
  1644.     RET
  1645.  
  1646. NULLIN:    MVI    A,1AH    ;NULL INPUT DEVICE - RETURN CONTROL-Z
  1647. NULLOUT:RET        ;NULL OUTPUT DEVICE
  1648.  
  1649.  
  1650.  
  1651. ;*****************************************************************
  1652. ;CLOCK READ/WRITE ROUTINES
  1653. ;*****************************************************************
  1654. RCLOCK:    LXI    H,PASSADD        
  1655.     DCR    M    ;DECREMENT PASS COUNTER(RANGE:15H-0-0FDH)
  1656.     MOV    A,M
  1657.     CPI    0DH    ;CHECK TO SEE IF AT BEGINNING
  1658.     JM    RCLOC1    
  1659.     MVI    A,' '    ;IF NOT, RET WITH A SPACE
  1660.     RET
  1661.  
  1662. RCLOC1:    ORA    A    ;CHECK TO SEE IF ALL PASSES    
  1663.     JP    RCLOC2    ;   COMPLETED
  1664.     CPI    0FEH
  1665.     MVI    A,' '    ;(RETURN {'.',' ',CR} AFTER STRING)
  1666.     RZ        ;  (2ND CHAR AFTER)
  1667.     MVI    A,'.'
  1668.     RNC        ;  (1ST CHAR AFTER)
  1669.     MVI    M,15H
  1670.     MVI    A,0DH    ;  (3RD CHAR AFTER)
  1671.     RET
  1672.  
  1673.  
  1674. RCLOC2:    MVI    A,40H        
  1675.     OUT    0CCH    ;TURN ON CLOCK
  1676.     MVI    B,78H
  1677. RCLOC3:    DB    DJNZ,RCLOC3-$+0FFH    ;WAIT
  1678.     MOV    A,M
  1679.             ;CONVERT PTR=(12-0) TO (10,9,8,7,12,11,6-0)
  1680.     CPI    7    ;THIS MAKES DATA ORDER=MMDDYYwHHMMSS
  1681.     DB    JRC,RCLOC4-$-1    ;MUCH MORE CONVENIENT TO USE
  1682.     SUI    2    ;
  1683.     CPI    7    ;
  1684.     DB    JRNC,RCLOC4-$-1
  1685.     ADI    6    ;
  1686. RCLOC4:    ORI    0C0H    ;CONVERT TO CLOCK CHIP I/O PORT#
  1687.     MOV    C,A    ;SET UP OUTPUT ADDRESS
  1688.     MVI    A,50H
  1689.     DW    OUTCA    ;TOGGLE CLOCK    
  1690.     DW    INAC
  1691.     CALL    SWAP    ;FLIP THE BITS
  1692.     ADI    30H
  1693.     PUSH    PSW
  1694.     XRA    A
  1695.     OUT    0C0H    ;RESET CLOCK
  1696.     POP    PSW    ;RETURN WITH DATA IN ACC.
  1697.     RET
  1698.  
  1699.  
  1700. WCLOCK:    LXI    H,CLKDIR
  1701.     MOV    A,C    ;IF (CHAR < '0') THEN RETURN
  1702.     ANI    07FH
  1703.     SUI    '0'
  1704.     RC    
  1705.     CPI    9+1+1    ;IF (CHAR < '9'+1) THEN DO
  1706.     DB    JRNC,WCLK2-$-1 ; (NOTE: '9'+1=':', NEEDED FOR 24 HR MODE SET)
  1707.     CALL    SWAP
  1708.     MOV    B,A
  1709.     MOV    A,M    ;IF ('DIRECTOR' < 'A') THEN RETURN
  1710.     CPI    'A'-40H    
  1711.     RC
  1712.     CPI    'M'+1-40H;IF ('DIRECTOR' > 'M') THEN RETURN
  1713.     RNC
  1714.     DCR    A
  1715.     CPI    6
  1716.     DB    JRNC,WCLOC0-$-1
  1717.     ADI    2
  1718.     CPI    6
  1719.     DB    JRC,WCLOC0-$-1
  1720.     SUI    6
  1721. WCLOC0:    INR    A
  1722.     MOV    C,A        
  1723.     MVI    A,40H
  1724.     OUT    0C0H    ;ISSUE HOLD COMMAND
  1725.     MVI    A,0BFH+14;PORT BASE ADDRESS 
  1726.     SUB    C    ;ADD ADDRESS TO BASE PORT
  1727.     MOV    C,A    ;('A'=13, 'M'=1)
  1728.     MOV    A,B
  1729.     MVI    B,62+6    ;HOLD 200uS (+10% MARGIN)
  1730. TIML1:    DB    DJNZ,TIML1-$+0FFH
  1731.     ADI    40H    ;SET UP ADDRESS
  1732.     DW    OUTCA    ;OUT (C),A
  1733.     XTHL
  1734.     XTHL        ;DELAY
  1735.     ORI    20H    ;TURN ON WRITE
  1736.     DW    OUTCA
  1737.     XTHL
  1738.     XTHL        ;DELAY
  1739.     ANI    4FH    ;TURN OFF WRITE
  1740.     DW    OUTCA
  1741.     XRA    A
  1742.     OUT    0C0H    ;TURN OFF CLOCK
  1743.     INR    M    ;RESET DIRECTOR
  1744.     RET
  1745.  
  1746. WCLK2:    CPI    'A'-'0'
  1747.     RC        ;RETURN IF < ASCII "A"
  1748.     CPI    'M'-'0'+1
  1749.     RNC        ;RETURN IF > ASCII "M"
  1750.     ANI    0FH    ;STRIP OFF ASCII
  1751.     MOV    M,A    ;STORE DIRECTOR
  1752.     RET
  1753.  
  1754. SWAP:    MOV    B,A
  1755.     XRA    A    ;SWAP BITS 0-4,1-3
  1756.     CALL    SWAP1
  1757. SWAP1:    DW    RRCB
  1758.     RAL
  1759.     DW    RRCB
  1760.     RAL
  1761.     RET
  1762.  
  1763.     if    P2DOS
  1764. ;Set Time    c==0FFH, de == &buffer:
  1765. ;        NDAYS:    DW    0    ;(binary count) #days since 1/1/1978
  1766. ;        HOURS:    DB    0    ;(in BCD)    0000H<=ndays<=0FFFFH,
  1767. ;        MINUTE:    DB    0    ;(in BCD)    i.e. only 1978-2157,
  1768. ;        SECOND:    DB    0    ;(in BCD)    179 years.
  1769. ;Get Time    c==00H; return hl == &buffer
  1770. ;Note: calls to rclock return mmddyyWhhmmss
  1771. ; pm: hx D2==1, 24: hx D3==1, leap: dx= D2==1
  1772. BTIME:    INR    C
  1773.     RC            ;Cannot set time (yet?)
  1774. GTIME:    MVI    A,0DH        ;synchronise rclock
  1775.     STA    PASSADD
  1776.     LXI    D,TBUFMO    ;read clock information into buffer
  1777.     MVI    B,13
  1778. GTIME2:    PUSH    B
  1779.     CALL    RCLOCK
  1780.     POP    B
  1781.     ANI    0FH
  1782.     STAX    D
  1783.     INX    D
  1784.     DB    djnz,GTIME2-$+0FFH
  1785. GTIME3:    MVI    A,15H        ;reset rclock
  1786.     STA    PASSADD
  1787.                 ;days = day_of_month-1;
  1788.     LXI    H,TBUFYR    ;for(yr -= 1978; yr>0; --y)
  1789.     CALL    PAKBIN        ;    days += 365 + leap(yr);
  1790.     SUI    78        ;(We assume 1900s here, subtract just 0078)
  1791.     MOV    B,A        ;(b = p2dos year)
  1792.     PUSH    B        ;(save b for later calculations)
  1793.     LXI    H,TBUFDY
  1794.     DW    res2hl        ;(clear "leap year" bit from clock chip)
  1795.     CALL    PAKBIN        ;(init hl = day of month - 1)
  1796.     DCX    H
  1797.     LXI    D,365
  1798. GTIME4:    DCR    B
  1799.     JM    GTIME5
  1800.     DAD    D
  1801.     CALL    LEAP
  1802.     DB    jrnz,GTIME4-$+0FFH
  1803.     INX    H
  1804.     DB    jr,GTIME4-$+0FFH
  1805. GTIME5:    POP    B        ;(restore b=year#)
  1806.     XCHG             ; m = mon-1; while (m-- > 0)
  1807.     LXI    H,TBUFMO    ;     day += md[m] + (m == 1 && leap (y));
  1808.     CALL    PAKBIN 
  1809.     DCR    A
  1810.     MOV    C,A        ;(b=year,c=month,de=day,hl->md[m])
  1811.     LXI    H,MD-1
  1812.     ADD    L
  1813.     MOV    L,A
  1814.     DB    jrnc,GTIME6-$-1
  1815.     INR    H
  1816. GTIME6:    DCR    C
  1817.     JM    GTIME9
  1818.     MOV    A,M
  1819.     DCX    H
  1820.     ADD    E
  1821.     MOV    E,A
  1822.     DB    jrnc,GTIME7-$-1
  1823.     INR    D
  1824. GTIME7: MOV    A,C        ;(is month == 1?)
  1825.     DCR    A
  1826.     DB    jrnz,GTIME6-$+0FFH
  1827.     CALL    LEAP        ;(yes, now is it a leap year?)
  1828.     DB    jrnz,GTIME6-$+0FFH
  1829.     INX    D        ;(yup, increment #days by 1)
  1830.     DB    jr,GTIME6-$+0FFH
  1831. GTIME9:            ;Save number of days since 1/1/1978
  1832.     XCHG
  1833.     SHLD    P2NDAY
  1834.  
  1835.     LXI    D,P2HR
  1836.     LXI    H,TBUFHR
  1837.     DW    res3hl
  1838.     DW    res2hl
  1839.     CALL    PAKBCD
  1840.     CALL    PAKBCD
  1841.     CALL    PAKBCD
  1842.     LXI    H,P2NDAY
  1843.     RET
  1844.  
  1845. PAKBCD: MOV    A,M    ;Pack two successive bcd bytes into bcd byte
  1846.     RLC
  1847.     RLC
  1848.     RLC
  1849.     RLC
  1850.     INX    H
  1851.     ADD    M
  1852.     INX    H
  1853.     STAX    D
  1854.     INX    D        
  1855.     RET
  1856.  
  1857. ;leap -    Return Z if p2dos year is a leap year, NZ otherwise. 
  1858. ;    year 1978 = p2dos year 0, and maximum p2dos year = 2157
  1859. LEAP:    MOV    A,B    ;B = years since 1978
  1860. ;    CPI    122    ; if (y = 122) return (NZ)    /*year 2100*/
  1861. ;    DB    jrz,LEAP1-$-1
  1862.     ADI    2    ;correction needed: year 2 is leap year, year 0 is not 
  1863. LEAP1:    ANI    3    ; return (y % 4)
  1864.     RET
  1865.  
  1866. MD:    DB    31,28,31,30,31,30,31,31,30,31,30    ;Don't need December
  1867.  
  1868. ;Pack two successive bytes into binary word
  1869. PAKBIN:    MOV    A,M
  1870.     RLC
  1871.     RLC
  1872.     ADD    M
  1873.     RLC
  1874.     INX    H
  1875.     ADD    M
  1876.     MOV    L,A
  1877.     MVI    H,0
  1878.     RET
  1879.     endif
  1880.  
  1881. ;*************************************************************
  1882. ;    End of I/O routines
  1883. ;*************************************************************
  1884.  
  1885. RNMSG:    DB    'ID NOT FOUN','D'+80H
  1886. CRCMSG:    DB    'CR','C'+80H
  1887. LDMSG:    DB    'LOST DAT','A'+80H
  1888. BSYMSG:    DB    'BUS','Y'+80H
  1889. WPMSG:    DB    'PROTEC','T'+80H
  1890. WFMSG:    DB    'FAUL','T'+80H
  1891.  
  1892. NRMSG:    DB    'READY'
  1893. ERRMSG:    DB    ' ERRO','R'+80H
  1894.  
  1895. BTMSG:    DB    'BOOT',' '+80H
  1896. RDMSG:    DB    0DH,0AH,'READ',' '+80H
  1897. WTMSG:    DB    0DH,0AH,'WRITE',' '+80H
  1898. SKMSG:    DB    0DH,0AH,'SEEK',' '+80H
  1899. HEMSG:    DB    0DH,0AH,'HOME',' '+80H
  1900.     if    not ONLY2
  1901. SWMSG:    DB    0DH,0AH,'insert '
  1902. SWDSK:    DB    '?: disk then key retur','n'+80H
  1903.     endif
  1904.  
  1905.  
  1906. ;********************************************************
  1907. ;PRE-INITIALIZED DATA VARIABLES:
  1908. ;    These items are set to initial values when loaded
  1909. ;    during cold-load.
  1910. ;********************************************************
  1911. ; Error counts.  These locations keep track of the number
  1912. ; of errors occurring during Read, Write, or Seek.
  1913. RECNT:    DB    0    ;READ ERROR COUNT.
  1914. WECNT:    DB    0    ;WRITE ERROR COUNT.
  1915. SECNT:    DB    0    ;SEEK ERROR COUNT.
  1916. ERFLAG:    DB    0    ;CPM BLOCKING ERROR FLAG
  1917.  
  1918. SIDEFLG: DB    0            ;HEAD 2 SELECT FLAG (0=SIDE 1, NZ=SIDE 2)
  1919. TRTAB:    DB    0FFH,0FFH,0FFH,0FFH ;TRACK TABLE: PRESENT HEAD POSITION
  1920.                     ;FOR FOUR DRIVES.
  1921.  
  1922. PASSADD:DB    15H    ;PASS COUNT & CLOCK REG PTR
  1923. CLKDIR:    DB    00H    ;CLOCK DIGIT 'DIRECTOR'
  1924.  
  1925. CURDSK:    DB    0    ;Currently Selected Disk (Init=A:)
  1926. UNACNT:    DB    0    ;Blocking    - Unallocated Record count
  1927. HSTACT:    DB    0    ;        - Hostbuffer Active flag
  1928. HSTWRT:    DB    0    ;        - Hostbuffer Write Pending flag
  1929.  
  1930.     if    TYPEAHEAD
  1931. ICOUNT:    DB    0    ;INPUT QUEUE - number of characters
  1932.     endif
  1933.     
  1934.     if    USER0
  1935. CHKUSR0: CALL    CCGTUSR    ;Get current user number
  1936.     ORA    A
  1937.     JZ    CCERR    ;If already 0, print error message
  1938.     MOV    E,A    ;Save user number
  1939.     PUSH    D
  1940.     MVI    E,0    ;Set user = 0
  1941.     CALL    CCSTUSR
  1942.     CALL    CCOPFCB    ;Try to open file
  1943.     POP    D    
  1944.     PUSH    PSW    ;Restore user number
  1945.     CALL    CCSTUSR
  1946.     POP    PSW
  1947.     JNZ    CCLOAD    ;If file found, get it
  1948.     JMP    CCERR    ;Else print error 
  1949.     endif
  1950.  
  1951. ;********************************************************
  1952. HSTBUF:    ;Start of Host-Buffer (For 1 physical sector)    *
  1953.     ;Reserve HSTSIZ bytes                *
  1954.     ;The Cold-Boot routine here will be overwritten    *
  1955. ;********************************************************
  1956. BOOT:    LXI    H,WBOOT    ;RE-DIRECT CBOOT TO WBOOT
  1957.     SHLD    CBOOT+1
  1958.     LXI    SP,7FH    ;SET STACK POINTER.
  1959.     MVI    A,0A6H    ;INIT 8251 I/O PORTS
  1960.     CALL    INITSIO
  1961.     MVI    A,40H
  1962.     CALL    INITSIO
  1963.     LDA    UARTT
  1964.     OUT    CSTAT
  1965.     LDA    UARTP
  1966.     OUT    LSTAT
  1967.     LDA    UARTM
  1968.     OUT    MSTAT
  1969.     MVI    A,27H
  1970.     CALL    INITSIO
  1971.     MVI    A,PPINIT;INIT 8255
  1972.     OUT    PPCMD
  1973.     if    not NOREVA
  1974.     MVI    A,41H    ;TEST IF 8255 IS PRESENT
  1975.     CALL    TESTB    ;IF SO, THIS IS REV B BOARD
  1976.     CMA        ;(TEST TWICE, TO BE SURE)
  1977.     CALL    TESTB    ;
  1978.     endif
  1979.     XRA    A    ;SET DISK SELECT TO A: & USER# TO 0
  1980.     STA    SEKDSK
  1981.     STA    CDISC
  1982.     LXI    H,SYSFMT;INIT IOBYTE &SYSFMT
  1983.     MOV    A,M
  1984.     ANI    4
  1985.     RAR
  1986.     RAR
  1987.     MOV    C,A
  1988.     LDA    IOBYTA
  1989.     MOV    B,A
  1990.     ANI    IOBMSK
  1991.     ORA    C
  1992.     STA    IOBYTE
  1993.     MOV    A,B
  1994.     ANI    SYSMSK
  1995.     ORA    M
  1996.     MOV    M,A
  1997.     LXI    H,SMSG    ;PRINT OPENING MESSAGE.
  1998.     CALL    PMSG
  1999.     LDA    07FH    ;DISK OPTIONS: (temp addr. of density flag)
  2000.     LXI    H,VDD    ;  DBL-D
  2001.     CPI    0DDH
  2002.     DB    JRZ,DEN1-$-1
  2003.     LXI    H,VDSD    ;  DBL-SD (always DBL-D)
  2004.     CPI    0D0H
  2005.     DB    JRZ,DEN1-$-1
  2006.     LXI    H,VSD    ;  SINGL-D
  2007. DEN1:    CALL    PMSG
  2008.     if    not ONLY2
  2009.     MOV    A,B
  2010.     ANI    1    ;DRIVE OPTIONS:
  2011.     endif
  2012.     LXI    H,V2D    ; 2DRIVE
  2013.     if    not ONLY2
  2014.     DB    JRZ,STAT2-$-1
  2015.     LXI    H,V1D    ; 1DRIVE
  2016.     endif
  2017. STAT2:    CALL    PMSG
  2018.     MOV    A,B    ;PRINTER OPTIONS:
  2019.     ANI    0C0H
  2020.     LXI    H,VPLL    ; PARALLEL
  2021.     DB    JRZ,STAT5-$-1
  2022.     CPI    80H
  2023.     LXI    H,VEA    ; ETX-ACK
  2024.     DB    JRZ,STAT6-$-1
  2025.     LXI    H,VXO    ; XON/XOFF OR NO
  2026.     DB    JRC,STAT7-$-1; CONSOLE, SAY NOTHING
  2027. STAT5:    CALL    PMSG
  2028.     LXI    H,PROTCL;'PRINTER PROTOCOL'
  2029. STAT6:    CALL    PMSG
  2030.     if    ZCPR3
  2031.     LXI    H,ENDISK-1    ;Clear rest of memory
  2032.     LXI    D,ENDISK
  2033.     LXI    B,0FFFFH-ENDISK+1
  2034.     DW    LDIR
  2035.     endif
  2036. STAT7:
  2037.     if    P2DOS and ZCPR3
  2038.     JMP    P2CBT        ;Do extra initialisation for P2DOS/ZCPR3
  2039.     endif
  2040.     if    (not P2DOS) or (not ZCPR3)
  2041.     JMP    GOCPM
  2042.     endif
  2043.  
  2044. INITSIO:
  2045.     OUT    CSTAT
  2046.     OUT    LSTAT
  2047.     OUT    MSTAT
  2048.     RET
  2049.  
  2050.     if    not NOREVA
  2051. TESTB:    MOV    B,A    ;TEST 8255 PORT B WITH BYTE IN A:
  2052.     OUT    PPORTB    ;  OUTPUT BYTE TO PORT.
  2053.     IN    PPORTB    ;  READ BACK IN.
  2054.     CMP    B    ;  IF SAME, TEST PASSES, RETURN.
  2055.     RZ        ;
  2056.     MVI    A,REVA    ;  ELSE CHANGE FLAG TO 'A' AND RETURN.
  2057.     STA    CPUREV    ;  (NOTE: FLAG IS IN SIGN-ON MESSAGE)
  2058.     RET
  2059.     endif
  2060.  
  2061. SMSG:    DB    CR, LF, LF, 'ACI  '
  2062.     DB    MSIZE/10+'0', MSIZE MOD 10 +'0', 'K '
  2063.     if    P2DOS
  2064.     DB    'P2DOS'
  2065.     endif
  2066.     if    not P2DOS
  2067.     DB    'CP/M'
  2068.     endif
  2069.     DB    '  v'
  2070.     DB    REVNO/10+'0', '.', REVNO MOD 10 +'0'
  2071.     if    not NOREVA
  2072. CPUREV:    DB    'B'
  2073.     endif
  2074.     if    IBMB
  2075.     DB    'I'
  2076.     endif
  2077.     if    USER0
  2078.     DB    'U'
  2079.     endif
  2080. CRLF:    DB    CR,LF+80H
  2081.  
  2082.  
  2083.     if    not ONLY2
  2084. V2D:    DB    '2 drive,',' '+80H        ;DRIVE OPTIONS
  2085. V1D:    DB    '1 drive,',' '+80H        ;
  2086.     endif
  2087.     if    ONLY2
  2088. V2D:    DB    '2 drive only,',' '+80H    ;
  2089.     endif
  2090. VPLL:    DB    'PARALLE','L'+80H        ;PRINTER OPTIONS
  2091. VXO:    DB    'XON/XOFF(or NO',')'+80H    ;
  2092. VEA:    DB    'ETX/ACK'            ;
  2093. PROTCL:    DB    ' printe','r'+80H    ;
  2094. VSD:    DB    'Single density,',' '+80H    ;DISK OPTIONS
  2095. VDD:    DB    'Double density,',' '+80H    ;
  2096. VDSD:    DB    'Double side,',' '+80H        ;
  2097.     if    ZCPR3
  2098.     DB    0                ;byte to clear mem to.
  2099.     endif
  2100. ENDISK:        ;End of CP/M image required to be stored on disk.
  2101. ;************************************************************************
  2102.     if    not ((HSTSIZ-($-HSTBUF)) SHR 15)*TRUE    ;If not enough    *
  2103.     DS    (HSTSIZ-($-HSTBUF))            ;space is used,    *
  2104.     endif                        ;reserve it    *
  2105. ;************************************************************************
  2106.  
  2107.  
  2108. ;****************************************************************
  2109. ;    THE REMAINDER OF THE CBIOS IS RESERVED UNINITIALIZED
  2110. ;    DATA AREA, AND DOES NOT NEED TO BE A PART OF THE
  2111. ;    SYSTEM MEMORY IMAGE (THE SPACE MUST BE AVAILABLE,
  2112. ;    HOWEVER AS SCRATCH RAM AREA FOR BDOS USE). INITIALIZATION
  2113. ;    IS DONE FOR 'CONVENIENCE', AND IS SET TO PROBABLY
  2114. ;    CORRECT VALUES (FOR SINGLE-DENSITY DISKS).
  2115. ;****************************************************************
  2116. ERCNT:    DB    0    ;ERROR COUNT FOR RETRIES.
  2117. SERCNT:    DB    0    ;SEEK RETRY COUNTER.
  2118.  
  2119.  
  2120. SEKDSK:    DB    0    ;CURRENTLY REQUESTED DISK.    *DON'T
  2121. SEKTRK:    DW    0    ;CURRENTLY REQUESTED TRACK.    *RE-ARRANGE
  2122. SEKHST:    DB    1    ;CURRENTLY REQUESTED HOST SECTOR*
  2123. SEKSEC:    DB    1    ;CURRENTLY REQUESTED SECTOR.    *
  2124.  
  2125. HSTDSK:    DB    0FFH    ;HOSTBUFFER DISK.        *DON'T
  2126. HSTTRK:    DW    0FFFFH    ;HOSTBUFFER TRACK.        *RE-ARRANGE
  2127. HSTSEC:    DB    0FFH    ;HOSTBUFFER SECTOR.        *
  2128.     DB    0FFH    ;not used, reserved        *
  2129.  
  2130. UNADSK:    DB    0    ;LAST UNALLOCATED DISK.        *DON'T
  2131. UNATRK:    DW    0    ;LAST UNALLOCATED TRACK.    *RE-ARRANGE
  2132.     DB    0    ;not used, reserved        *
  2133. UNASEC:    DB    0    ;LAST UNALLOCATED SECTOR.    *
  2134.  
  2135.  
  2136. CPMSPB:    DB    8    ;BLOCKSIZE/128        *******BLOCKING PARMS********
  2137. SECMSK:    DB    0    ;HSTSIZ/128-1        **    DON'T RE-ARRANGE     **
  2138. SECSHF:    DB    0+1    ;LOG2(HSTSIZ/128)+1 **PARMS ARE FOR LOGGED DISK**
  2139. CPMSPT:    DB    26    ;TRACKSIZE/128        *****************************
  2140. LOGDEN:    DB    2    ;DENSITY OF LOGGED DRIVE (2=SGL,1=DBL)
  2141.  
  2142. RSFLAG:    DB    0    ;READ SECTOR FLAG
  2143. READOP:    DB    0    ;READ OPERATION FLAG
  2144. WRTYPE:    DB    0    ;WRITE OPERATION TYPE
  2145.  
  2146. DMAADD:    DW    0080H    ;CURRENT READ/WRITE ADDRESS.
  2147.  
  2148. PCOUNT:    DB    80H    ;COUNTER FOR ETXACK:
  2149.  
  2150.     if    TYPEAHEAD
  2151. ICHARQ:    DS    QSIZE    ;INPUT CHARACTER QUEUE
  2152.     endif
  2153.  
  2154. DIRBF:    DS    128    ;SCRATCH DIRECTORY AREA
  2155. ALL00:    DS    39    ;ALLOCATION VECTOR 0
  2156. ALL01:    DS    39    ;ALLOCATION VECTOR 1
  2157. CHK00:    DS    128/4    ;CHECK VECTOR 0
  2158. CHK01:    DS    128/4    ;CHECK VECTOR 1
  2159.  
  2160. ADDRBF:    DS    7    ;READ ADDRESS BUFFER (1 EXTRA BYTE RESERVED)
  2161.  
  2162.     if    P2DOS
  2163. ;data buffer for P2DOS time function - doesn't need initialization
  2164. TBUFMO:    DB    0,1    ;month
  2165. TBUFDY:    DB    0,1    ;day
  2166. TBUFYR:    DB    7,8    ;year
  2167.     DB    0    ;day of week (Sunday)
  2168. TBUFHR:    DB    0,0    ;hours    12-1-11 am, 52-41-51 pm
  2169. TBUFMI:    DB    0,0    ;minutes
  2170. TBUFSC:    DB    0,0    ;seconds
  2171.  
  2172. P2NDAY:    DW    0    ;#days since 1/1/78
  2173. P2HR:    DB    0    ;bcd hours
  2174. P2MIN:    DB    0    ;bcd minutes
  2175. P2SEC:    DB    0    ;bcd seconds
  2176.     endif    ;P2DOS    
  2177.  
  2178.     if    ZCPR3
  2179.  
  2180. ;This area needs to be cleared to all zeros on coldboot, with exceptions
  2181. ;noted (and initialized by CBOOT. ZCPR3 must have these addresses defined
  2182. ;in Z3BASE.HDR, exactly as they appear here.
  2183.  
  2184. ;ZCPR3 Shell Stack
  2185. SHSTK:    DS    4*32
  2186.  
  2187. ;ZCPR3 Message Buffer
  2188. Z3MSG:    DS    80
  2189.  
  2190.  
  2191. ;80 byte command buffer for ZCPR3. Set Z3CL and Z3CLS (=80) in Z3BASE.HDR.
  2192. Z3CL:    DW    0    ;(Must be initialized to Z3BF by CBOOT)
  2193. Z3SIZ:    DB    0    ;(Must be initialized to 80 by CBOOT)
  2194. Z3CT:    DB    0
  2195. Z3BF:    DS    80
  2196.  
  2197. ;Named directory buffer for ZCPR3. Set Z3NDIR and Z3NDIRS (=14) in Z3BASE.
  2198. Z3NDIR:    DS    14*18 + 1
  2199.  
  2200. ;External Stack for ZCPR3. Set EXTSTK in Z3BASE. Always uses 48 bytes.
  2201. EXTSTK:    DS    48
  2202.  
  2203. ;External FCB for ZCPR3. Set EXTFCB in Z3BASe. Always uses 36 byes.
  2204. EXTFCB:    DS    36    ;(Could this be put in the end of P2DOS also?)
  2205.  
  2206.     endif    ;endif ZCPR3
  2207.  
  2208.     if    P2DOS
  2209. ;External Stack for P2DOS. Set P2STK in P2DOS.MAC. Uses 62 bytes (v23)
  2210. P2STK:    DS    62
  2211.     endif    ;endif P2DOS
  2212.  
  2213.     if    ZCPR3
  2214.  
  2215.     ORG    0FF00H
  2216.  
  2217. ;External ZCPR3 Environment
  2218. ;Because this holds the pointers to the other data areas, this gets fixed
  2219. ;at top of memory. It is initialized by the loader LDR.
  2220. Z3ENV:    DS    2*128
  2221.  
  2222.     endif    ;endif ZCPR3
  2223.  
  2224.     ORG    BIOS-115    ;Overlay code on top of P2DOS blank area
  2225.                 ;Only 115 bytes are available in P2DOS v23.
  2226.                 ;Note: P2DOS MUST have external stack.
  2227.  
  2228.  
  2229.     if    P2DOS and ZCPR3
  2230.  
  2231. ;ZCPR3 External Command Executive Name    (CMDRUN option)
  2232. EXTRUN:    DB    0    ;(A0:?)
  2233.     DB    'CMDRUN  '
  2234.     DB    'COM'
  2235.  
  2236. ;ZCPR3 External Search Path 
  2237. EXTPATH: DB    '$$'    ;This drive, this user#
  2238.     DB    '$',0    ;This drive, user 0
  2239.     DB    1,0    ;Drive A: user 0
  2240.     DB    0
  2241.  
  2242. ;ZCPR3 External Submit File FCB:
  2243. ;EXTSUB in Z3BASE.LIB must be set either to the value given here for SUBFCB,
  2244. ;or to zero. BE VERY SURE you aren't using this area for the ZCPR stack. The
  2245. ;part of this that is commented out does not need to be initialised, there-
  2246. ;fore it overlays the cold-boot code that may follow.
  2247. P2CWBT:    LXI    H,0        ;Clear Submit FCB
  2248.     SHLD    SUBEXT
  2249.     JMP    CCP
  2250.  
  2251. EXTSUB:    DB    1        ;Default Drive A:
  2252.     DB    '$$$     '    ;Submit filename
  2253.     DB    'SUB'        ;Submit filetype
  2254. SUBEXT:
  2255.     endif        ;P2DOS and ZCPR3
  2256.     if    FALSE        ;(force it to overlay)
  2257.     DB    0        ;Extent number - clear this on warmboot
  2258.     DB    0        ;s1
  2259. SUBFS2: DB    0        ;s2
  2260. SUBFRC: DB    0        ;record count
  2261.     DS    16        ;Disk Group Map
  2262. SUBFCR: DS    1        ;Current Record Number
  2263.     endif        ;FALSE
  2264.  
  2265.     if    P2DOS and ZCPR3
  2266. ;ZCPR3 Command Line Initialisation:
  2267. ;Because this code is used during coldboot only, which precedes the use of
  2268. ;either the Submit facility or ZCPR3, this code will be overlayed by the
  2269. ;Submit FCB area from below, and possibly by the ZCPR3 Stack from above.
  2270. P2CBT:    LXI    H,Z3CNIT
  2271.     LXI    D,Z3CL
  2272.     LXI    B,P2CBTE-Z3CNIT
  2273.     DW    LDIR
  2274.     JMP    GOCPM        ;Resume coldboot initialisation
  2275.  
  2276. Z3CNIT:    DW    Z3BF        ;Command Line image, must be same size as Z3CL
  2277.     DB    80        ;80 characters
  2278.     DB    0        ;Character count
  2279.     DB    'LDR SYS.ENV,SYS.NDR'    ;coldboot command 
  2280. P2CBTE:
  2281.     endif        ;ZCPR3 and P2DOS
  2282.  
  2283.  
  2284. ACIDOS    EQU    (ENDISK+OFFSET+0FFH)/100H    ;'SAVE xx ACIDOS.COM'
  2285.     END
  2286.  
  2287.