home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / cpmug / cpmug082.ark / MBIOS56.ASM < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  52.3 KB  |  2,085 lines

  1.     TITLE    'MBIOS - N* DD CP/M 2.2 MODEM BIOS OF 05/02/82'
  2. ;    PAGE    44
  3. ;
  4. ; These routines copyright (c) 1980, 1981, 1982 by Steve Bogolub,
  5. ; 2338 S. Scoville Ave., Berwyn, IL 60402. Elements of the public
  6. ; domain program "BYE", based on an original program written by
  7. ; Dave Jaffe and modified by many others, are incorporated.
  8. ; This software may be used freely for non-commercial purposes
  9. ; only, and may not be sold.
  10. ;
  11. ;
  12. ;  THIS BIOS IS SPECIALIZED FOR REMOTE MODEM DIALUP
  13. ; USE. IF THE MEMORY LOCATION "MODEM" CONTAINS A
  14. ; VALUE OF ZERO WHEN THE COLD BOOT ROUTINE "INIT"
  15. ; IS ENTERED, A SPECIAL SET OF CONSOLE VECTORS
  16. ; IS PATCHED OVER THE GENNED-IN SET TO HANDLE THE
  17. ; PMMI MODEM INSTEAD OF THE NORMAL HORIZON DRIVERS.
  18. ; AFTER PATCHING THE VECTORS, THE ROUTINES WAIT FOR
  19. ; THE PHONE TO RING. UPON ANSWERING, THE BAUD RATE
  20. ; IS SENSED (110, 300, 450, 600, OR 710 BAUD) BY
  21. ; READING CARRIAGE RETURN OR LINE FEED CODES, THEN
  22. ; A PASSWORD IS REQUESTED. IF THE PASSWORD IS
  23. ; CORRECT, CCP AND BDOS ARE WARM BOOTED, AND THE
  24. ; MODEM TERMINAL CONTROLS THE MACHINE UNTIL CARRIER
  25. ; IS LOST OR CONTROL IS TRANSFERRED BY A PROGRAM
  26. ; TO THE MODEM COLD BOOT VECTOR, WHICH HANGS UP
  27. ; THE PHONE. AT THAT POINT, WE GO BACK TO WAITING
  28. ; FOR THE PHONE TO RING, AND START OVER AGAIN.
  29. ;
  30. ;  IF MEMORY LOCATION "MODEM" CONTAINS A NON-ZERO
  31. ; VALUE, THE NORMAL HORIZON SERIAL DEVICES ARE
  32. ; USED FOR THE CONSOLE AND A SERIAL PRINTER.
  33. ;
  34. ; DISK:    NORTH STAR MDS-AD2 DOUBLE DENSITY 5.25"
  35. ;    FLOPPY DISK UNITS 1 AND 2 AS CP/M DRIVES
  36. ;    A: AND B:, SINGLE-SIDED, DOUBLE DENSITY,
  37. ;    35 OR 40 TRACKS SELECTABLE AT ASSEMBLY
  38. ;    TIME. UNITS 3 AND 4 ARE SUPPORTED AS
  39. ;    CP/M DRIVES C: AND D:, DOUBLE-SIDED,
  40. ;    DOUBLE DENSITY, 80 TRACKS.
  41. ;
  42. ; SERIAL I/O:    HORIZON LEFT (LOW) SERIAL I/O PORT AS
  43. ;        CP/M DEVICE CRT:
  44. ;
  45. ;    HORIZON RIGHT (HIGH) SERIAL I/O PORT AS CP/M
  46. ;    DEVICE TTY: WITHOUT DTR SUPPORT, AND REQUIRING
  47. ;    DTR HIGH ON OUTPUT FOR LPT:
  48. ;
  49. ;    IF "MODEM" IS ZERO, IOBYTE IS NOT SUPPORTED,
  50. ;    AND CON:, LST:, RDR:, AND PCH: ALL USE THE
  51. ;    PMMI MODEM
  52. ;
  53. ;  SINCE THIS BIOS IS SO LARGE, MOVCPM SHOULD BE
  54. ; RUN FOR TWO LESS THAN THE DESIRED SYSTEM SIZE
  55. ; IN K, I.E. SPECIFY 30 FOR A 32K SYSTEM.
  56. ;
  57. ;   ***   IMPORTANT BOOTSTRAP INFO   ***
  58. ;
  59. ;  THIS BIOS IS INTENDED TO RUN IN THE LAST
  60. ; 3.5K OF MEMORY. THE LAST .5K IS SET ASIDE
  61. ; FOR A NORTH STAR SECTOR DEBLOCKING BUFFER.
  62. ; THE FIRST 3K IS GENNED-IN BIOS CODE, AND
  63. ; IS EXPECTED TO RESIDE ON TRACK 0 OF NORTH
  64. ; STAR DISK UNIT 1 (A:) IN SECTORS 5-9, AND
  65. ; 4. THE NORTH STAR BOOT PROM READS IN SECTOR
  66. ; 4 INTO CONSECUTIVE PAGES OF MEMORY, STARTING
  67. ; WITH THE PAGE NUMBER SPECIFIED BY THE FIRST
  68. ; BYTE OF SECTOR DATA, THEN JUMPS TO THAT
  69. ; ADDRESS + 10 (0AH). THIS BIOS IS SET UP TO
  70. ; USE THAT METHOD TO COLD BOOT ITSELF. CODE
  71. ; AT THAT ADDRESS READS THE LAST FIVE SECTORS
  72. ; OF TRACK ZERO INTO MEMORY AT ADDRESS "BIOS",
  73. ; THEN JUMPS TO THE BIOS COLD START ADDRESS.
  74. ;
  75. ;  THERE ARE TWO POSSIBLE CONFIGURATIONS OF
  76. ; THE SYSTEM. THE NORMAL CONFIGURATION ASSUMES
  77. ; THAT MEMORY IS CONTIGUOUS, AND IS GENERATED
  78. ; IN A STRAIGHTFORWARD FASION WITH MOVCPM.
  79. ; FOR THIS CONFIGURATION, SET THE VARIABLE
  80. ; "NSHOLE" FALSE, THEN THIS BIOS WILL LOOK
  81. ; FOR CCP AND BDOS IN THEIR NORMAL LOCATIONS
  82. ; ON THE SYSTEM TRACKS: TRACK 1, SECTORS 0-9,
  83. ; AND TRACK ZERO, SECTOR 3 (NORTH STAR PHYSICAL
  84. ; SECTOR NUMBERS). A HIGHLY ABNORMAL CONFIGURATION
  85. ; IS POSSIBLE WHERE BDOS IS SPLIT INTO TWO
  86. ; PIECES, AND WRAPPED AROUND THE NORTH STAR
  87. ; CONTROLLER. THIS CONFIGURATION IS TOUGH TO
  88. ; ACHIEVE WITHOUT A HIGHLY INTIMATE KNOWLEDGE
  89. ; OF THE BDOS SO THAT THE SPLIT CAN BE DONE.
  90. ; IN THIS CASE, "NSHOLE" IS SET TO TRUE, AND
  91. ; ALLOWS FULL UTILIZATION OF ALL MEMORY IN
  92. ; A NORTH STAR MACHINE.
  93. ;
  94. ;  THE BIOS WARM BOOT EXPECTS THE CCP AND
  95. ; THE LOW 2K OF BDOS TO RESIDE ON TRACK 1,
  96. ; SECTORS 0-7 INCLUSIVE, WITH THE REMAINING
  97. ; 1.5K OF BDOS ON TRACK 0, SECTORS 3, 1, AND
  98. ; 2, IN THAT ORDER. THIS PECULIAR LAYOUT IS
  99. ; DUE TO THE 1K "HOLE" IN THE CENTER OF OUR
  100. ; SPECIAL BDOS WHERE THE NORTH STAR CONTROLLER
  101. ; FITS. THE HOLE PUSHES THE LAST PART OF
  102. ; BDOS IN THE NSGEN MEMORY MAP UP INTO THE
  103. ; AREA USED ON THE STANDARD SYSTEM FOR THE
  104. ; JADE CONTROLLER CODE, WHICH IS UNUSED HERE.
  105. ;
  106. ;  WE USE THE Z80 INSTRUCTION "LD A,I" ON ENTRY
  107. ; TO THE DISK READ AND WRITE ROUTINES TO GET
  108. ; THE STATUS OF THE INTERRUPT FLIP/FLOP, SINCE
  109. ; WE MUST DISABLE INTERRUPTS WHILE THE NORTH
  110. ; STAR DISK READS OR WRITES ARE PERFORMED.
  111. ; USING THE Z80 STATUS, WE CAN RE-ENABLE
  112. ; INTERRUPTS AFTER WE LEAVE. THIS CHECK IS
  113. ; DONE BY THE ROUTINES "INTDI" AND "INDEN",
  114. ; AND CAN EASILY BE REMOVED IF WE EVER GO
  115. ; TO A NON-Z80 CPU (NEVER, I HOPE).
  116. ;
  117. LDAI    EQU    057EDH        ;Z80 "LD A,I" BYTE-SWAPPED
  118.                 ; FOR "DW" USE
  119. ;
  120. FALSE    EQU    0
  121. TRUE    EQU    NOT FALSE
  122. ;
  123. NSHOLE    EQU    FALSE        ;NO HOLE IN BDOS IS STANDARD
  124. ;
  125. ;  DISK OPERATING SYSTEM ADDRESSES
  126. ;
  127. KBYTE    EQU    1024        ;1K BYTE SIZE
  128. ;
  129.     IF    NSHOLE
  130. EXTRAK    EQU    KBYTE        ;HOLE SIZE
  131.     ENDIF
  132.     IF    NOT NSHOLE
  133. EXTRAK    EQU    0        ;NO HOLE, ZERO SIZE
  134.     ENDIF
  135. ;
  136. NKSYS    EQU    56        ;SYS SIZE IN K BYTES
  137. CPMSZ    EQU    NKSYS*KBYTE    ;TOP SYSTEM ADDRESS
  138. CPMBS    EQU    CPMSZ-(22*KBYTE)-EXTRAK ;CP/M BIAS VALUE
  139. CCP    EQU    CPMBS+3400H    ;ADDRESS OF CCP
  140. BDOS    EQU    CPMBS+3C00H    ;ADDRESS OF BDOS
  141. BIOS    EQU    CPMBS+4A00H+EXTRAK ;ADDRESS OF BIOS
  142.                 ;(EXTRA 1K IN BDOS IF NSHOLE
  143.                 ; TO SKIP N* CTRLR)
  144. BIOSR    EQU    1F80H-BIOS+400H    ;DDT LOAD OFFSET
  145. ;        ;(LEAVES ROOM FOR JADE DCM OR BDOS)
  146. IOBYTE    EQU    0003H        ;IOBYTE ADDRESS
  147. DEFDSK    EQU    0004H        ;DEFAULT CCP DISK
  148. SECSZ    EQU    128        ;BYTES PER SECTOR
  149. HSTSIZ    EQU    512        ;BYTES PER N* SECTOR
  150. DSKSIZ    EQU    165        ;35-TRACK DISK A: AND B:
  151. ;DSKSIZ    EQU    190        ;40-TRACK DISK A: AND B:
  152. NDRVS    EQU    4        ;# DRIVES IN SYSTEM
  153. ;
  154. ;  STEP RATES. THESE ARE LOOP COUNTS, AND CORRESPOND
  155. ; TO 7.75 USEC PER COUNT AT 4 MHZ. A 40 MSEC VALUE
  156. ; WOULD BE -5161 (0EBD7H) FOR A SLOW SHUGART 400 DRIVE,
  157. ; AND A 20 MSEC VALUE WOULD BE -2580 (0F5ECH) FOR A
  158. ; TYPICAL NEW SHUGART 400 DRIVE. THE VALUES EMPIRICALLY
  159. ; DETERMINED FOR A WANGCO 82 AND MPI 92 ARE -758 (0FD0AH)
  160. ; AND -528 (0FDF0H) RESPECTIVELY. THE 4 MSEC FOR THE
  161. ; MPI SEEMS POSSIBLE, BUT THE 6 MSEC FOR THE WANGCO 82
  162. ; SEEMS A BIT OVERSPEC. THE STEPPING ALGORITHM SEEMS
  163. ; TO HAVE A BIT OF SLOP IN IT, WHICH MAY HELP.
  164. ;
  165. STPSLW    EQU    -2580        ;SHUGART FOR TESTING
  166. ;STPSLW    EQU    -758        ;SLOW STEP CTR (WANGCO 82)
  167. STPFST    EQU    -528        ;FAST STEP CTR (MPI 92)
  168. ;
  169. ;  BDOS CONSTANTS ON ENTRY TO WRITE
  170. ;
  171. WRALL    EQU    0        ;WRITE TO ALLOCATED
  172. WRDIR    EQU    1        ;WRITE TO DIRECTORY
  173. WRUAL    EQU    2        ;WRITE TO UNALLOCATED
  174. ;
  175. ;  NORTH STAR MEMORY MAPPED I/O ADDRESSES
  176. ;
  177. NSROM    EQU    0E800H        ;COLD BOOT ROM ADDRESS
  178. WDATA    EQU    0E900H        ;WRITE DATA. DATA IS
  179.                 ; LOW 8 ADRESS BITS.
  180. CORDER    EQU    0EA00H        ;CONTROLLER ORDER
  181. CCMND    EQU    0EB00H        ;CONTROLLER COMMAND
  182. ;
  183. ;  CONSOLE DEFINITIONS
  184. ;
  185. MOTHR    EQU    000H        ;HORIZON MOTHERBOARD BASE
  186. CRT    EQU    MOTHR+2        ;HORIZON LEFT SERIAL BASE
  187. TTY    EQU    MOTHR+4        ;HORIZON RIGHT SERIAL BASE
  188. ;
  189. ;PMMI modem port equates
  190. ;
  191. TPORT    EQU    0E0H    ;UART CONTROL/STATUS PORT
  192. DPORT    EQU    TPORT+1 ;DATA PORT
  193. RPORT    EQU    TPORT+2 ;RATE GEN/MODEM STATUS
  194. CPORT    EQU    TPORT+3 ;MODEM CONTROL
  195. ;
  196. ;Switch hook and modem commands, output to TPORT (port 0)
  197. ;
  198. P0BYE    EQU    0    ;ON HOOK, OR DIALING BREAK
  199. P0ORIG    EQU    1    ;OFF HOOK, ORIG.
  200. P0ANSW    EQU    2    ;ANSWER PHONE
  201. P08BIT    EQU    0CH    ;8 DATA BITS
  202. P0NOPY    EQU    10H    ;NO PARITY
  203. P0EPS    EQU    20H    ;EVEN PARITY SELECT
  204. P0TSB    EQU    40H    ;2 STOP BITS
  205. P0EI    EQU    80H    ;ENABLE INTERRUPTS
  206. P0NORM    EQU    P08BIT+P0NOPY        ;NORMAL 8 BITS, NO PARITY
  207. P0110    EQU    P08BIT+P0NOPY+P0TSB ;SAME W/2 STOP BITS
  208. ;
  209. ;Modem status, input on RPORT (port 3)
  210. ;
  211. P2DTD    EQU    1    ;DIAL TONE DETECT
  212. P2RDET    EQU    2    ;RING DETECT
  213. P2CTS    EQU    4    ;CTS (CARRIER DETECT)
  214. P2RXBRK EQU    8    ;RECEIVE BREAK
  215. P2CONN    EQU    10H    ;CONNECTED? (0=YES, 1=MODEM CHIP HUNG UP)
  216. P2TMPUL EQU    80H    ;TIMER PULSES (40% UP CYCLE)
  217. ;
  218. ;Timer rate selection
  219. ;
  220. TRATE    EQU    250    ;VALUE FOR .1 SEC
  221. ;
  222. ;PMMI modem status masks
  223. ;
  224. P0TBMT    EQU    1    ;XMIT BUFF EMPTY
  225. P0DAV    EQU    2    ;DATA AVAILABLE
  226. P0TEOC    EQU    4    ;TEST END OF CHAR
  227. P0RPE    EQU    8    ;REC'D PARITY ERR
  228. P0ORUN    EQU    10H    ;OVERRUN
  229. P0FERR    EQU    20H    ;FRAMING ERROR
  230. ;
  231. ;Baud rate divisors
  232. ;
  233. B110    EQU    142    ;110 BAUD
  234. B300    EQU    52    ;300 BAUD
  235. B450    EQU    35    ;450 BAUD
  236. B600    EQU    26    ;600 BAUD
  237. B710    EQU    22    ;710 BAUD
  238. ;
  239. CR    EQU    0DH        ;ASCII CARRIAGE RETURN
  240. LF    EQU    0AH        ;ASCII LINE FEED
  241. SPACE    EQU    20H        ;ASCII SPACE
  242. ;
  243. ;  NORMAL BIOS JUMP VECTOR TABLE, IF NOT USING MODEM
  244. ;
  245.     ORG    BIOS        ;START OF BIOS CODE
  246. ;
  247. BTABLE:    JMP    NSROM        ;COLD BOOT FROM ROM
  248.     JMP    WARM        ;RELOAD CCP/BDOS
  249. ;
  250. ;  USE THE VECTORS TO THE CONSOLE ROUTINES FOR
  251. ; INTERNAL CONSOLE I/O INSTEAD OF CALLING THE
  252. ; ROUTINES DIRECTLY TO ALLOW USE OF BIOS
  253. ; MESSAGES WITH "BYE" AND OTHER VECTOR-PATCHING
  254. ; PROGRAMS.
  255. ;
  256. BCNSCK:    JMP    CNSCK        ;GET CONSOLE STATUS
  257. BCNSIN:    JMP    CNSIN        ;CONSOLE INPUT
  258. BCNSOT:    JMP    CNSOT        ;CONSOLE OUTPUT
  259. BLIST:    JMP    LIST        ;PRINTER OUTPUT
  260. ;
  261.     JMP    PUNCH        ;PUNCH OUTPUT
  262.     JMP    READER        ;READER INPUT
  263. ;
  264. ;  VECTORS BEYOND THIS POINT ARE COMMON TO MODEM
  265. ; AND NON-MODEM SYSTEMS
  266. ;
  267.     JMP    HOME        ;HOME SELECTED DRIVE
  268.     JMP    SELDSK        ;SELECT DISK DRIVE
  269.     JMP    SETTRK        ;SET TRACK NUMBER
  270.     JMP    SETSEC        ;SET SECTOR NUMBER
  271.     JMP    SETDMA        ;SET TRANSFER ADDRESS
  272.     JMP    DISKRD        ;PERFORM DISK READ
  273.     JMP    DISKWR        ;PERFORM DISK WRITE
  274.     JMP    LISTST        ;LIST STATUS
  275.     JMP    SECTRN        ;TRANSLATE SECTOR
  276. ;
  277. ;  SET THE FOLLOWING BYTE TO ZERO BEFORE GENNING THE
  278. ; SYSTEM TO DISK TO HAVE THE MODEM CONTROL THE BIOS
  279. ; CONSOLE AND LIST DEVICES, OTHERWISE OPERATION IS
  280. ; FOR A FAIRLY STANDARD NORTH STAR HORIZON.
  281. ;
  282. MODEM:    DB    0FFH        ;NORMAL LOCAL USE
  283. ;MODEM:    DB    000H        ;MODEM USE
  284. ;
  285. ;  FOLLOWING BYTE IS NON-ZERO IF MODEM IN USE AND
  286. ; TALKING TO PHONE, ZERO IF PHONE HUNG UP OR NOT
  287. ; TALKING TO PHONE. USED BY MSGOT TO DECIDE WHAT
  288. ; ROUTINE TO CALL TO OUTPUT TO CONSOLE.
  289. ;
  290. HUNGUP:    DS    1
  291. ;
  292. ;  ACCESS PASSWORD WHEN RUNNING WITH MODEM (ENDS
  293. ; WITH CARRIAGE RETURN)
  294. ;
  295. PASSWD:    DB    'PASSWORD'    ;THE PASSWORD ITSELF
  296.     DB    CR    ;END OF PASSWORD
  297. ;
  298. ;Allow room for bigger password to be patched in
  299. ;
  300.     DB    0,0,0,0,0,0,0,0,0,0
  301. ;
  302. ;  SIGN-ON MSG TYPED AFTER LOCAL OR REMOTE USE MSG
  303. ;
  304. SIGNON:    DB    'North Star '
  305.     DB    (NKSYS/10)+'0',(NKSYS MOD 10)+'0'
  306.     DB    'K CP/M 2.2 of 05/02/82',CR,LF+80H
  307. ;
  308. ;  MODEM VECTOR TABLE TO PATCH OVER NORMAL TABLE IF
  309. ; "MODEM" CONTAINS ZERO AT INIT TIME
  310. ;
  311. MTABLE:    JMP    HANGUP        ;HANG UP PHONE IF
  312.                 ; COLD BOOT CALLED
  313.     JMP    WARM        ;RELOAD CCP/BDOS
  314.     JMP    MSTAT        ;GET CONSOLE STATUS
  315.     JMP    MINPUT        ;CONSOLE INPUT
  316.     JMP    MOUTPUT        ;CONSOLE OUTPUT
  317.     JMP    MOUTPUT        ;PRINTER OUTPUT
  318.     JMP    MOUTPUT        ;PUNCH OUTPUT
  319.     JMP    MINPUT        ;READER INPUT
  320. ;
  321. MTLEN:    EQU    $-MTABLE    ;# BYTES TO MOVE
  322. ;
  323. ;  THE INIT ROUTINE IS ACTUALLY A CONTINUATION OF THE
  324. ; COLD BOOT BEGUN DOWN AT "BOOT".
  325. ;
  326. INIT:    MVI    A,81H        ;INIT THE IOBYTE
  327.     STA    IOBYTE        ; FOR CON:=CRT:,
  328.                 ; AND LST:=LPT:
  329.     LXI    SP,HSTBUF+HSTSIZ ;SET SP TO SCRATCH AREA
  330.     XRA    A        ;INIT HORIZON MOTHERBOARD
  331.     OUT    MOTHR+6
  332.     STA    COLDB        ;BIOS NOW IN MEMORY
  333.     STA    DFIMG        ;COLD BOOT A:, USER ZERO
  334.     CALL    IDELAY        ;DELAY FOR 8251'S
  335.     MVI    A,0AEH        ;INIT SERIAL PORTS
  336.     OUT    CRT+1        ;OUTPUT DUMMY MODE TO INSURE
  337.     OUT    TTY+1
  338.     CALL    IDELAY
  339.     MVI    A,040H        ; CMD EXPECTED, THEN OUTPUT
  340.     OUT    CRT+1        ; RESET CMD
  341.     OUT    TTY+1
  342.     CALL    IDELAY
  343.     MVI    A,04EH        ;MODE: 1 STOP BIT, 16X CLK,
  344.     OUT    CRT+1        ; 8 DATA BITS, NO PARITY
  345.     OUT    TTY+1
  346.     CALL    IDELAY
  347.     MVI    A,037H        ;CMD: RTS, ER, RXEN, DTR, TXEN
  348.     OUT    CRT+1
  349.     OUT    TTY+1
  350.     CALL    IDELAY
  351.     IN    CRT        ;FLUSH RECEIVER INPUTS
  352.     IN    TTY
  353.     LDA    MODEM        ;SEE IF MODEM USE DESIRED
  354.     ORA    A
  355.     JZ    MINIT        ;GO INIT FOR MODEM IF SO
  356.     STA    HUNGUP        ;INDICATE NORMAL CONSOLE
  357.                 ; USE THRU BCNSOT IF NOT
  358.     LXI    H,CCP        ;WHERE TO START CP/M
  359.     PUSH    H
  360.     CALL    ILPRT        ;ANNOUNCE OURSELVES
  361.     DB    CR,LF,'Local',' '+80H
  362.     LXI    H,SIGNON    ;ISSUE SIGNON
  363.     CALL    MSGOT
  364.     JMP    CPMLD        ;GO PERFORM WARM BOOT FUNCS
  365. ;
  366. ;  THIS DELAY SUBROUTINE IS USED TO HELP US OUT ON
  367. ; TIMING WHEN RESETTING THE 8251 CONSOLE SERIAL DEVICE.
  368. ;
  369. IDELAY:    LXI    B,600H
  370. IDEL5:    DCX    B
  371.     MOV    A,B
  372.     ORA    C
  373.     JNZ    IDEL5
  374.     RET
  375. ;
  376. ;  IOBYTE IS SUPPORTED FOR CONSOLE AND LIST DEVICE IF
  377. ; NOT RUNNING WITH MODEM
  378. ;
  379. ;  CONSOLE STATUS
  380. ;
  381. CNSCK:    CALL    CONS        ;GET HARDWARE STATUS
  382.     RZ            ;IF NO CHAR READY, RETURN 0
  383.     MVI    A,0FFH        ; ELSE RETURN 0FFH
  384.     RET
  385. ;
  386. CONS:    LDA    IOBYTE        ;GET IOBYTE
  387.     CALL    ROUTE        ;DISPATCH TO STATUS ROUTINE
  388.     DW    TTYCHK        ;TTY:
  389.     DW    CRTCHK        ;CRT:
  390.     DW    CRTCHK        ;BAT: (RDR: NOT SUPPORTED)
  391.     DW    CRTCHK        ;UC1:
  392. ;
  393. ;  CONSOLE INPUT
  394. ;
  395. CNSIN:    CALL    CONS        ;GET HARDWARE STATUS
  396.     JZ    CNSIN        ;WAIT FOR CHAR READY
  397.     CALL    CONIN        ; THEN GET CHAR
  398.     ANI    07FH        ;STRIP PARITY
  399.     RET            ; AND RETURN IN ACC
  400. ;
  401. CONIN:    LDA    IOBYTE
  402.     CALL    ROUTE        ;DISPATCH TO INPUT ROUTINE
  403.     DW    TTYIN        ;TTY:
  404.     DW    CRTIN        ;CRT:
  405.     DW    CRTIN        ;BAT: (RDR: NOT SUPPORTED)
  406.     DW    CRTIN        ;UC1:
  407. ;
  408. ;  CONSOLE OUTPUT
  409. ;
  410. CNSOT:    LDA    IOBYTE
  411.     CALL    ROUTE        ;DISPATCH TO OUTPUT ROUTINE
  412.     DW    TTYOT        ;TTY:
  413.     DW    CRTOT        ;CRT:
  414.     DW    LIST        ;BAT: (LST: DEVICE)
  415.     DW    CRTOT        ;UC1:
  416. ;
  417. ;  READER INPUT
  418. ;
  419. READER:    EQU    CNSIN        ;SAME AS CONSOLE INPUT
  420. ;
  421. ;  PUNCH OUTPUT
  422. ;
  423. PUNCH:    EQU    CNSOT        ;SAME AS CONSOLE OUTPUT
  424. ;
  425. ;  LIST STATUS
  426. ;
  427. LISTST:    XRA    A        ;SAY IT'S READY
  428.     DCR    A
  429.     RET
  430. ;
  431. ;  LIST OUTPUT
  432. ;
  433. LIST:    LDA    IOBYTE
  434.     RLC            ;ROTATE LST: BITS TO LOW
  435.     RLC            ; BIT POSITIONS
  436.     CALL    ROUTE        ;DISPATCH TO LIST ROUTINE
  437.     DW    TTYOT        ;TTY:
  438.     DW    CRTOT        ;CRT:
  439.     DW    LPTOT        ;LPT:
  440.     DW    TTYOT        ;UL1:
  441. ;
  442. ;  THE ROUTING ROUTINE
  443. ;
  444. ROUTE:    RLC            ;DOUBLE FOR WORD OFFSET
  445.     ANI    06H        ;STRIP UNUSED BITS
  446.     XTHL            ;GET DISPATCH TABLE ADDR
  447.     ADD    L        ;ADD OFFSET TO GET
  448.     MOV    L,A        ; TO CORRECT VECTOR
  449.     JNC    ROUTE5
  450.     INR    H
  451. ROUTE5:    MOV    A,M        ;PULL VECTOR
  452.     INX    H
  453.     MOV    H,M
  454.     MOV    L,A
  455.     XTHL            ;STACK VECTOR, RESTORE HL
  456.     RET            ; THEN OFF TO ROUTINE
  457. ;
  458. ;  HORIZON TTY: ROUTINES
  459. ;
  460. TTYCHK:    IN    TTY+1        ;GET PORT STATUS
  461.     ANI    2        ;CHECK RECEIVER
  462.     RET            ;RET NON-ZERO IF READY
  463. ;
  464. TTYIN:    IN    TTY        ;GET PORT DATA
  465.     RET
  466. ;
  467. TTYOT:    IN    TTY+1        ;GET PORT STATUS
  468.     RRC            ;XMIT BUFFER EMPTY?
  469.     JNC    TTYOT        ;IF NOT, WAIT TIL IS
  470.     MOV    A,C        ; THEN OUTPUT CHAR FROM C
  471.     OUT    TTY
  472.     RET
  473. ;
  474. ;  HORIZON CRT: ROUTINES. SAME AS TTY:, BUT DIFF PORT
  475. ;
  476. CRTCHK:    IN    CRT+1        ;GET PORT STATUS
  477.     ANI    2        ;CHECK RECEIVER
  478.     RET            ;RET NON-ZERO IF READY
  479. ;
  480. CRTIN:    IN    CRT        ;GET PORT DATA
  481.     RET
  482. ;
  483. CRTOT:    IN    CRT+1        ;GET PORT STATUS
  484.     RRC            ;XMIT BUFFER EMPTY?
  485.     JNC    CRTOT        ;IF NOT, WAIT TIL IS
  486.     MOV    A,C        ; THEN OUTPUT CHAR FROM C
  487.     OUT    CRT
  488.     RET
  489. ;
  490. ;  LIST CHAR OUT TO SERIAL PRINTER ON TTY:
  491. ;
  492. LPTOT:    PUSH    H        ;SAVE HL
  493.     PUSH    B        ;SAVE CHAR TO OUTPUT
  494. ;
  495. LOUT5:    LXI    H,0        ;LOAD UP FOR NICE LONG DELAY
  496.     MVI    B,20        ;APPROX 20 SECONDS AT 4 MHZ
  497. ;
  498. LOUT10:    DCX    H        ;COUNT DOWN
  499.     MOV    A,H        ;SEE IF ZERO YET
  500.     ORA    L
  501.     JNZ    LOUT20        ;PASS IF NOT
  502.     DCR    B        ;COUNT OFF HIGHER BITS
  503.     JNZ    LOUT20        ;PASS IF NOT ZERO YET
  504. ;
  505. LOUT15:    MVI    A,'P'        ;DISK P: NOT READY, FOR PRINTER
  506.     CALL    PNTRDY        ;REPORT, AND RETURN IF NO CTRL-C
  507.     MVI    A,11H        ;JAM PRINTER SELECT
  508.     OUT    TTY        ; AFTER PUT ONLINE
  509.     JMP    LOUT5        ;NOW GO TRY AGAIN
  510. ;
  511. LOUT20:    IN    TTY+1        ;GET 8251 STATUS
  512.     ANI    85H        ;STRIP OUT REQ NXT CHAR, XMIT
  513.     CPI    85H        ; BUF RDY, AND XMIT EMPTY,
  514.                 ; THEN CHECK THEM
  515.     JNZ    LOUT10        ;ALL 3 MUST BE UP TO SEND
  516. ;
  517. ;  PRINTER NOW READY. OUTPUT CHAR.
  518. ;
  519.     POP    B        ;RESTORE CHAR TO C
  520.     MOV    A,C        ; AND GET IT TO ACC
  521.     ANI    7FH        ;STRIP PARITY
  522.     OUT    TTY        ;OUTPUT THE CHAR
  523.     MOV    A,C        ;RESTORE CHAR TO ACC
  524.     POP    H        ;RESTORE HL
  525.     RET            ; AND RETURN
  526. ;
  527. ;
  528. ;  THESE ARE THE MODEM ROUTINES. MINIT SETS UP THE MODEM
  529. ; VECTORS, THEN DROPS INTO HANGUP TO BEGIN NORMAL MODEM
  530. ; OPERATION.
  531. ;
  532. MINIT:    LXI    H,MTABLE    ;MOVE VECTORS FROM HERE
  533.     LXI    D,BTABLE    ; OVER NORMAL TABLE
  534.     LXI    B,MTLEN        ;THIS MANY BYTES
  535.     CALL    BLOCK        ;DO THE MOVE
  536. ;
  537. ;Clear DTR causing phone to hang up
  538. ;
  539. HANGUP:    LXI    SP,HSTBUF+HSTSIZ ;SET SP TO SCRATCH AREA
  540.     LXI    H,CCP    ;INIT COLD CCP START ADDR
  541.     PUSH    H    ;IT GOES ON STACK FOR CPMLD RET
  542.     XRA    A    ;GET DISCONNECT VALUE
  543.     OUT    TPORT    ;RESET ORIG/ANSW
  544.     OUT    CPORT    ;TURN OFF DTR, DO BREAK
  545.     STA    DFIMG    ;SET DEF DISK TO A:, USER ZERO
  546.     STA    HUNGUP    ;PHONE HUNG UP
  547.     CALL    ILPRT
  548.     DB    CR,LF,'Phone hung up..','.'+80H
  549. ;
  550. ;Await ringing
  551. ;
  552. RINGWT:    IN    RPORT    ;GET THE STATUS
  553.     ANI    P2RDET    ;RINGING?
  554.     JNZ    RINGWT    ;NO, WAIT
  555. ;
  556. ;The phone may be ringing.  Wait .1 sec and look
  557. ;again to make sure it isn't just relay bounce
  558. ;
  559.     CALL    DELAY    ;.1 SEC DELAY FOR DEBOUNCE
  560.     IN    RPORT    ;GET STATUS
  561.     ANI    P2RDET    ;STILL RINGING?
  562.     JNZ    RINGWT    ;NO, IT WAS RELAY BOUNCE
  563. ;
  564. ;The phone is definitely ringing, now wait until ring is finished
  565. ;
  566. ENDRNG:    CALL    DELAY    ;.1 SEC DELAY FOR DEBOUNCE
  567.     IN    RPORT    ;GET STATUS
  568.     ANI    P2RDET    ;STILL RINGING?
  569.     JZ    ENDRNG ;WAIT UNTIL RING FINISHED
  570. ;
  571. ;Setup modem
  572. ;
  573. ANSWER:    MVI    A,7FH    ;TURN ON DTR
  574.     OUT    CPORT    ;.. AND SET FILTER VALUE FOR 300 BAUD
  575.     CALL    DELAY    ;GIVE TIME TO TURN ON
  576.     MVI    A,P0110+P0ANSW
  577.     OUT    TPORT    ;ANSWER PHONE
  578.     CALL    DELAY    ;GIVE TIME FOR ANSWER
  579.     IN    DPORT    ;CLEAR MODEM PORT
  580.     IN    DPORT    ;MAKE SURE ITS CLEAR
  581.     MVI    A,B110    ;SET DIVISOR
  582.     OUT    RPORT    ;.. TO 110 BAUD RATE
  583. ;
  584. ;Output value allowing modem to hang up on loss of carrier
  585. ;
  586.     MVI    A,P0110 ;NORMAL MODE FOR 110 BAUD
  587.     OUT    TPORT
  588.     CALL    CHECK    ;ABORT IF CARRIER LOST
  589. ;
  590. ;Now test input for baud rate
  591. ;
  592.     CALL    TSTBAUD  ;SEE IF BAUD = 110
  593.     JZ    WELCOME  ;YES, EXIT
  594. ;
  595.     MVI    A,P0NORM ;SET FOR 1 STOP BIT, ETC.
  596.     OUT    TPORT
  597.     MVI    A,B300     ;SET DIVISOR
  598.     OUT    RPORT     ;.. TO 300 RATE
  599.     CALL    TSTBAUD  ;SEE IF BAUD = 300
  600.     JZ    WELCOME  ;YES, EXIT
  601. ;
  602.     MVI    A,B450     ;SET DIVISOR
  603.     OUT    RPORT     ;.. TO 450 RATE
  604.     MVI    A,5FH     ;SET FILTER VALUE
  605.     OUT    CPORT     ;.. FOR > 300
  606.     CALL    TSTBAUD  ;SEE IF BAUD = 450
  607.     JZ    WELCOME  ;YES, EXIT
  608. ;
  609.     MVI    A,B600     ;SET DIVISOR
  610.     OUT    RPORT     ;.. TO 600 RATE
  611.     CALL    TSTBAUD  ;SEE IF BAUD = 600
  612.     JZ    WELCOME  ;YES, EXIT
  613. ;
  614.     MVI    A,B710     ;SET DIVISOR
  615.     OUT    RPORT     ;.. TO 710 RATE
  616.     CALL    TSTBAUD  ;SEE IF BAUD = 710
  617.     JZ    WELCOME  ;YES, EXIT
  618.     JMP    ANSWER     ;TEST MORE - INVALID BAUD RATE
  619. ;
  620. ;Welcome to the system -- get the password
  621. ;
  622. WELCOME: MVI    A,1    ;TALKING ON PHONE NOW
  623.     STA    HUNGUP
  624.     CALL    ILPRT    ;ANNOUNCE OURSELVES
  625.     DB    CR,LF,'Remote',' '+80H
  626.     LXI    H,SIGNON
  627.     CALL    MSGOT    ;TELL REST OF SIGNON
  628.     MVI    D,5    ;5 TRIES AT PASSWORD
  629. ;
  630. PASSINP: CALL    ILPRT
  631.     DB    CR,LF,'Enter password:',' '+80H
  632.     LXI    H,PASSWD ;POINT TO PASSWORD
  633.     MVI    E,0    ;NO MISSED LETTERS
  634.     IN    DPORT    ;CLEAR OUT GARBAGE
  635. ;
  636. PWMLP:    CALL    MINPUT    ;GET A CHAR
  637.     CPI    'U'-40H ;CTL-U?
  638.     JZ    PASSINP ;YES, RE-GET IT
  639.     CPI    60H    ;LOWER CASE?
  640.     JC    NOTLC    ;NO,
  641.     ANI    5FH    ;MAKE UPPER CASE ALPHA
  642. ;
  643. NOTLC:    CMP    M    ;MATCH PASSWORD?
  644.     JZ    PWMAT    ;..YES
  645.     MVI    E,1    ;..NO, SHOW MISS
  646.     CPI    CR    ;C/R?
  647.     JNZ    PWMLP    ;..NO, WAIT FOR C/R
  648. ;
  649. ;Password didn't match
  650. ;
  651. PWNMAT:    CALL    ILPRT
  652.     DB    '++INCORRECT++',CR,LF+80H
  653.     DCR    D    ;MORE TRIES?
  654.     JNZ    PASSINP ;YES
  655.     JMP    HANGUP ;NO, GO HANG UP
  656. ;
  657. ;Character matched in password
  658. ;
  659. PWMAT:    INX    H    ;TO NEXT CHAR
  660.     CPI    CR    ;END?
  661.     JNZ    PWMLP    ;..NO, LOOP
  662. ;
  663. ;End of password.  Any missed chars?
  664. ;
  665.     MOV    A,E    ;GET FLAG
  666.     ORA    A
  667.     JNZ    PWNMAT    ;NOT RIGHT
  668. ;
  669. ;Password correct
  670. ;
  671.     CALL    ILPRT
  672.     DB    CR,LF,'Entering CP/M . . .',' '+80H ;BOOT MSG
  673.     JMP    CPMLD    ;LOAD AND START CCP/BDOS
  674. ;
  675. ;TSTBAUD attempts to read a LF or CR, returns with
  676. ;zero flag if the character read is one of these two.
  677. ;
  678. TSTBAUD: CALL    MINPUT    ;GET CHARACTER FROM MODEM
  679.     CPI    CR    ;IF A CARRIAGE RETURN...
  680.     RZ        ;.. RETURN
  681.     CPI    LF    ;IF A LINEFEED...
  682.     RET        ;RET ZERO FLAG, ELSE NOT ZERO
  683. ;
  684. ;Loss of connection test
  685. ;
  686. ;The PMMI modem automatically hangs up the phone after
  687. ;15 seconds of loss of carrier, providing you output to
  688. ;port 0 to allow it (we do).
  689. ;
  690. ;..so, this routine first checks if the modem has hung up,
  691. ;and if so, aborts out to HANGUP.  If not, it checks for
  692. ;carrier and returns if carrier is on; otherwise waits for
  693. ;carrier while still testing for disconnect.
  694. ;
  695. ;It tests the PMMI "CTS" (clear to send) bit
  696. ;which is 0 when there is carrier
  697. ;
  698. CHECK:    IN    RPORT    ;GET STATUS
  699.     ANI    P2CONN    ;CONNECTED?
  700.     JNZ    HANGUP    ;HUNG UP
  701. ;
  702. ;Still connected, check for carrier
  703. ;
  704.     IN    RPORT    ;LOOK AT STATUS
  705.     ANI    P2CTS    ;GET CARRIER DETECT BIT
  706. ;
  707. ;Loop until either connection lost, or carrier returns
  708. ;
  709.     JNZ    CHECK
  710.     RET
  711. ;
  712. ;.1 sec delay routine for 4MHz clock Z80
  713. ;
  714. DELAY:    PUSH    B
  715. ;
  716.     LXI    B,16667 ;4 MHZ TIMING CONSTANT
  717. ;    LXI    B,8334    ;2 MHZ TIMING CONSTANT
  718. ;
  719. DELAY1:    DCX    B
  720.     MOV    A,B
  721.     ORA    C
  722.     JNZ    DELAY1
  723.     POP    B
  724.     RET
  725. ;
  726. ;Modem status test routine
  727. ;
  728. MSTAT:    CALL    CHECK    ;CHECK FOR CARRIER LOST
  729.     CALL    CNSCK    ;GET LOCAL CONSOLE STATUS
  730.     ORA    A
  731.     RNZ        ;GO BACK IF GOT LOCAL CHAR
  732.     IN    TPORT    ;GET STATUS
  733.     ANI    P0DAV    ;DATA AVAILABLE?
  734.     RZ        ;RETURN IF NOT READY
  735.     IN    TPORT    ;GET STATUS
  736.     ANI    30H    ;CHECK FRAMING AND OVERRUN BITS
  737.     JZ    MSTAT1    ;NO ERRORS...LEGIT CHARACTER
  738.     IN    DPORT    ;SWALLOW CHARACTER (CLEARS PODAV)
  739.     XRA    A    ;RETURN FALSE
  740.     RET
  741. ;
  742. MSTAT1:    XRA    A    ;SHOW READY
  743.     DCR    A
  744.     RET
  745. ;
  746. ;Modem input function
  747. ;
  748. MINPUT:    CALL    CHECK    ;CARRIER STILL ON?
  749.     CALL    MSTAT    ;ANYTHING?
  750.     ORA    A
  751.     JZ    MINPUT    ;LOOP TILL CHAR RCD
  752.     CALL    CNSCK    ;CHAR AT LOCAL CONSOLE?
  753.     ORA    A
  754.     JNZ    CNSIN    ;GO READ LOCAL CONSOLE IF SO
  755.     IN    DPORT    ;GET DATA BYTE
  756.     ANI    7FH    ;DELETE PARITY
  757.     JZ    MINPUT    ;IGNORE NULLS
  758.     RET
  759. ;
  760. ;Modem output function
  761. ;
  762. MOUTPUT: CALL    CHECK    ;CARRIER STILL ON?
  763.     IN    TPORT    ;GET MODEM STATUS
  764.     ANI    P0TBMT    ;TRANSMIT BUFFER EMPTY?
  765.     JZ    MOUTPUT ;LOOP IF NOT READY
  766.     MOV    A,C    ;GET CHAR
  767.     ANI    7FH    ;STRIP PARITY BIT
  768.     OUT    DPORT    ;OUTPUT TO MODEM
  769.     JMP    CNSOT    ;ECHO TO LOCAL CONSOLE
  770. ;
  771. ;Inline print routine
  772. ;
  773. ILPRT:    XTHL        ;SAVE HL, GET MSG
  774.     PUSH    B    ;SAVE BC REGS
  775.     CALL    MSGOT    ;OUTPUT STRING AT HL
  776.     POP    B    ;RESTORE BC REGS
  777.     XTHL        ;RESTORE HL, RET ADDR
  778.     RET        ;RET PAST MSG
  779. ;
  780. ;  SELECT DRIVE - LOGON
  781. ;
  782. SELDSK:    LXI    H,0        ;ERROR RETURN CODE
  783.     MOV    A,C        ;PUT DRIVE # IN A
  784.     CPI    NDRVS        ;CHECK IF LEGAL DRIVE
  785.     RNC            ;NO CARRY IF ILLEGAL
  786.     STA    SEKDSK        ;STORE DRIVE NUMBER
  787.     MOV    B,E        ;SAVE LOGON REQ REG
  788.     MOV    L,C        ;L = DISK NUMBER
  789.     MVI    H,0        ;ZERO H REG
  790.     DAD    H        ; *2
  791.     DAD    H        ; *4
  792.     DAD    H        ; *8
  793.     DAD    H        ; *16 (SIZE OF HEADER)
  794.     LXI    D,D0DPH        ;DRIVE 0 DPH
  795.     DAD    D        ;HL = DRIVE N DPH
  796.     SHLD    DTPTR        ;STORE DRIVE TBL PTR
  797. ;
  798. ;  LOG-ON - SET DISK PARAMETER BLOCK
  799. ;
  800. ;  -- CHECK IF LOG-ON REQUESTED
  801. ;
  802.     MOV    A,B        ;CHECK LOG REQUEST
  803.     ANI    001H        ;LOG ON BIT TEST
  804.     JNZ    NOLOG        ;PASS IF NO REQUEST
  805.     LDA    SEKDSK        ;NO LOGON IF C: OR D:
  806.     CPI    2
  807.     JNC    NOLOG
  808.     CALL    HFLUSH        ;MAKE SURE HOST BUF
  809.     JNZ    LOGERR        ; AVAILABLE, OUT ON ERR
  810. ;
  811. ;  LOG ON NORTH STAR BY READING ID SECTOR, THEN DECIDE
  812. ; WHICH TABLE TO USE BASED ON SINGLE OR DOUBLE DENSITY.
  813. ; THE ACTUAL ID SECTOR INFO IS IGNORED.
  814. ;
  815.     LDA    SEKDSK
  816.     STA    HSTDSK        ;GOING TO ACCESS THIS DISK
  817.     XRA    A
  818.     STA    HSTTRK        ;TRACK ZERO
  819.     STA    HSTSEC        ;N* SECTOR ZERO
  820.     CALL    INTDI        ;INTERRUPTS OFF
  821.     CALL    READHST        ;READ THE SECTOR
  822.     CALL    INTEN        ;INTERRUPTS RESTORED
  823.     LDA    ERFLAG        ;CHECK FOR READ ERROR
  824.     ORA    A
  825.     JNZ    LOGERR        ;LOG-ON ERROR IF SO
  826.     LDA    NSDENS        ;IF OK, GET DENSITY FLAG
  827.     LXI    B,TRAN5D    ;ASSUME DOUBLE DENSITY
  828.     LXI    D,DPBNSD
  829.     ORA    A        ;CHECK
  830.     JZ    LOGNSD        ;GO ON IF RIGHT
  831.     LXI    B,TRAN5S    ;CORRECT TO SINGLE DENSITY
  832.     LXI    D,DPBNSS    ; IF WRONG
  833. ;
  834. LOGNSD:    LHLD    DTPTR        ;LOAD DRIVE TBL PTR
  835.     MOV    M,C        ;SET TRANSLATE TABLE ADDR
  836.     INX    H
  837.     MOV    M,B
  838.     LXI    B,9        ;PT TO DPB ADDR
  839.     DAD    B
  840.     MOV    M,E        ;SET DPB ADDR
  841.     INX    H
  842.     MOV    M,D
  843. ;
  844. ;  SET UP DEBLOCKING VARIABLES FROM DPB VALUES
  845. ;
  846. NOLOG:    CALL    DPBAD        ;GET DPB ADDR
  847.     XCHG            ; IN HL
  848.     MOV    A,M        ;SET UP DEBLOCK
  849.     STA    CPMSPT        ; SECTORS PER TRACK
  850.     INX    H        ;GET TO GROUP MASK
  851.     INX    H
  852.     INX    H
  853.     MOV    A,M        ;GET IT
  854.     INR    A        ;CALC # BLOCKS/GROUP
  855.     STA    UNAVAL        ; AND SAVE THAT
  856.     LXI    D,12
  857.     DAD    D        ;PT TO SECTOR SHIFT
  858.     MOV    A,M        ; BIT FLAG
  859.     ORA    A        ;HAVE WE GOT ONE?
  860.     JZ    NOSHF        ;PASS IF NOT
  861.     MVI    B,0FFH        ;INIT SHIFT COUNT
  862. ;
  863. CALCSH:    INR    B        ;COUNT UP A SHIFT
  864.     RAR            ;SEE IF DONE
  865.     JNC    CALCSH        ;GO BACK IF NOT YET
  866.     MOV    A,B        ;SHIFT COUNT TO ACC
  867. ;
  868. NOSHF:    STA    SECSHF        ;STORE SHIFT COUNT
  869.     MOV    A,M        ;RELOAD BIT FLAG
  870.     DCR    A        ;FORM SECTOR MASK
  871.     STA    SECMSK        ; AND SET IT
  872.     LHLD    DTPTR        ;RELOAD PTR
  873.     XRA    A        ;NO ERRORS
  874.     RET            ; SO RET ZERO
  875. ;
  876. LOGERR:    LXI    H,0
  877.     RET
  878. ;
  879. ;  -- GET DRIVE PARA BLK ADDR
  880. ;
  881. DPBAD:    LHLD    DTPTR        ;ADDR DISK PARA HDED
  882.     LXI    D,10        ;DPB TBL PNTR OFFSET
  883.     DAD    D        ;NOW AT DPB PNTR
  884.     MOV    E,M        ;LOAD INTO DE
  885.     INX    H
  886.     MOV    D,M
  887.     RET            ;RETURN TO LOG USER
  888. ;
  889. ;  HOME DRIVE
  890. ;
  891. HOME:    MVI    C,0        ;SET TRACK TO ZERO TO HOME
  892.     LDA    HSTWRT        ;CHECK FOR PENDING WRITE
  893.     ORA    A
  894.     JNZ    SETTRK
  895.     STA    HSTACT        ;CLEAR HOST ACTIVE IF NOT
  896. ;
  897. ;  SET TRACK
  898. ;
  899. SETTRK:    MOV    A,C        ;MOVE TRACK NUMBER
  900.     STA    SEKTRK        ; THEN SAVE IT
  901.     RET            ;RETURN TO CALLER
  902. ;
  903. ;  SET SECTOR
  904. ;
  905. SETSEC:    MOV    A,C        ;MOVE SECTOR NUMBER
  906.     STA    SEKSEC        ; THEN SAVE IT
  907.     RET            ;RETURN TO CALLER
  908. ;
  909. ;  SET TRANSFER ADDRESS
  910. ;
  911. SETDMA:    MOV    H,B        ;MOVE ADDR TO HL
  912.     MOV    L,C
  913.     SHLD    DMAADR        ; THEN SAVE IT
  914.     RET            ;RETURN TO CALLER
  915. ;
  916. ;  SECTOR TRANSLATION
  917. ;
  918. SECTRN:    MOV    A,E        ;IS THERE A TABLE?
  919.     ORA    D
  920.     JZ    NOTRAN        ;SPECIAL XLATE IF SO
  921.     XCHG            ;MAP OFF TABLE
  922.     DAD    B
  923.     MOV    L,M
  924.     MVI    H,0
  925.     RET
  926. ;
  927. NOTRAN:    MOV    H,B        ;JUST BOP BY ONE
  928.     MOV    L,C        ; FOR SINGLE DENSITY
  929.     INX    H
  930.     RET
  931. ;
  932. ;  THIS IS THE REST OF THE DISK I/O ERROR ROUTINE.
  933. ; IT IS HERE BECAUSE (1) IT CAN'T BE USED IN COLD BOOT,
  934. ; WHILE THE FIRST PART MUST BE, AND (2) IT SAVES
  935. ; A JUMP WHEN PLACED BEFORE HXBOT.
  936. ;
  937. DSKER2:    PUSH    H        ;SAVE BODY ADDRESS
  938.     LXI    H,CRLF        ;EJECT LINE
  939.     CALL    MSGOT
  940.     POP    H
  941.     CALL    MSGOT        ;REPORT BODY
  942.     LDA    HSTDSK        ;THIS DISK
  943.     ADI    'A'
  944.     STA    ASCDSK
  945.     LXI    H,ERRMSG
  946.     CALL    MSGOT
  947.     LDA    HSTTRK        ;THIS TRACK
  948.     CALL    HXBOT
  949.     LXI    H,SECMSG
  950.     CALL    MSGOT
  951.     LDA    ERSEC        ;THIS SECTOR
  952.                 ;INTO HXBOT TO FINISH
  953. ;
  954. ;  HXBOT DISPLAYS HEXIDECIMAL EQUIV OF ACC CONTENTS.
  955. ;
  956. HXBOT:    PUSH    PSW        ;SAVE CHAR
  957.     RRC            ;SWAP NIBBLES
  958.     RRC
  959.     RRC
  960.     RRC
  961.     CALL    HXNOT        ;OUTPUT HIGH NIBBLE
  962.     POP    PSW        ; THEN LOW NIBBLE
  963. HXNOT:    ANI    0FH        ;STRIP HIGH NIBBLE
  964.     ADI    90H        ;CVT TO ASCII DECIMAL
  965.     DAA
  966.     ACI    40H
  967.     DAA
  968.     MOV    C,A        ;CHAR TO C
  969.     JMP    BCNSOT        ;THRU VECTOR TO CNSOT
  970. ;
  971. ;  DEBLOCKING DISK WRITE
  972. ;
  973. DISKWR:    CALL    INTDI        ;MASK INTERRUPTS
  974.     CALL    DSKWR        ;DO THE WRITE
  975.     JMP    INTEN        ;GO RESTORE INTS
  976. ;
  977. ;  DEBLOCKING DISK READ.  NOTE THAT ON DEBLOCKING READ
  978. ; AND WRITE, THE CALLER SECTOR NUMBERS RANGE FROM 1-XX
  979. ; DECIMAL. THIS IS FOR COMPATIBILITY WITH 8" FORMATS
  980. ; THAT ARE 1-ORIGIN. WE ADJUST FOR THIS THROUGHOUT THE
  981. ; DEBLOCKING ROUTINES BY SUBTRACTING 1 FROM SEKSEC
  982. ; BEFORE WE USE IT. VARIABLES TO CONTROL DEBLOCKING
  983. ; ARE SET UP FOR US WHEN DISK IS SELECTED.
  984. ;
  985. DISKRD:    CALL    INTDI        ;DISABLE INTERRUPTS
  986.     CALL    DSKRD        ;DO THE I/O
  987. ;
  988. INTEN:    PUSH    PSW        ;SAVE DISK I/O ERROR CODE
  989.     LHLD    ENTPSW        ;GET ENTRY PSW TO TEST
  990.     PUSH    H
  991.     POP    PSW
  992.     JPO    INTEN5        ;PASS IF INTS OFF WHEN ENTERED
  993.     EI            ; ELSE RE-ENABLE INTS
  994. ;
  995. INTEN5:    POP    PSW        ;RESTORE DISK I/O ERROR CODE
  996.     RET            ; THEN RETURN TO CALLER
  997. ;
  998. INTDI:    MVI    A,7FH        ;CHECK FOR RUNNING ON
  999.     INR    A        ; 8080 OR Z80
  1000.     JPO    NOTZ80        ;CAN'T GET INT STATE ON 8080
  1001.     DW    LDAI        ;GET INT STATE INTO
  1002.     PUSH    PSW        ; PARITY FLAG, THEN
  1003.     POP    H        ; SAVE PSW IN MEMORY
  1004.     SHLD    ENTPSW
  1005. ;
  1006. NOTZ80:    DI            ;ALLOW NO INTERRUPTS
  1007.     RET            ; DURING THE I/O XFER
  1008. ;
  1009. DSKRD:    MVI    A,WRUAL
  1010.     STA    WRTYPE        ;TREAT AS UNALLOC
  1011.     STA    READOP        ;READ OPERATION
  1012.     JMP    ALLOC        ;GO END UNALLOC SECTORS
  1013.                 ; AND FORCE READ
  1014. ;
  1015. DSKWR:    XRA    A
  1016.     STA    READOP        ;NOT A READ OPERATION
  1017.     MOV    A,C        ;WRITE TYPE IN C
  1018.     STA    WRTYPE
  1019.     CPI    WRUAL        ;WRITE UNALLOCATED?
  1020.     JNZ    CHKUNA        ;CHECK FOR UNALLOC
  1021. ;
  1022. ;  WRITE TO UNALLOCATED, SET PARAMETERS
  1023. ;
  1024.     LDA    UNAVAL        ;NEXT UNALLOC RECS
  1025.     STA    UNACNT
  1026.     LDA    SEKDSK        ;DISK TO SEEK
  1027.     STA    UNADSK        ;UNADSK = SEKDSK
  1028.     LDA    SEKTRK
  1029.     STA    UNATRK        ;UNATRK = SEKTRK
  1030.     LDA    SEKSEC
  1031.     STA    UNASEC        ;UNASEC = SEKSEC
  1032. ;
  1033. ;  CHECK FOR WRITE TO UNALLOCATED SECTOR
  1034. ;
  1035. CHKUNA:    LDA    UNACNT        ;ANY UNALLOC REMAIN?
  1036.     ORA    A
  1037.     JZ    ALLOC        ;SKIP IF NOT
  1038. ;
  1039. ;  MORE UNALLOCATED RECORDS REMAIN
  1040. ;
  1041.     DCR    A        ;UNACNT = UNACNT - 1
  1042.     STA    UNACNT
  1043.     LDA    SEKDSK        ;SAME DISK?
  1044.     LXI    H,UNADSK
  1045.     CMP    M        ;SEKDSK = UNADSK?
  1046.     JNZ    ALLOC        ;SKIP IF NOT
  1047. ;
  1048. ;  DISKS ARE THE SAME, CHECK TRACKS
  1049. ;
  1050.     LDA    SEKTRK
  1051.     LXI    H,UNATRK
  1052.     CMP    M        ;SEKTRK = UNATRK?
  1053.     JNZ    ALLOC        ;SKIP IF NOT
  1054. ;
  1055. ;  TRACKS ARE THE SAME, CHECK SECTORS
  1056. ;
  1057.     LDA    SEKSEC
  1058.     LXI    H,UNASEC
  1059.     CMP    M        ;SEKSEC = UNASEC?
  1060.     JNZ    ALLOC        ;SKIP IF NOT
  1061. ;
  1062. ;  MATCH, MOVE TO NEXT SECTOR FOR FUTURE REF
  1063. ;
  1064.     INR    M        ;UNASEC = UNASEC+1
  1065.     LDA    CPMSPT        ;CHECK FOR END OF TRACK
  1066.     CMP    M
  1067.     JNC    NOOVF        ;SKIP IF STILL ON TRACK
  1068. ;
  1069. ;  OVERFLOW TO NEXT TRACK
  1070. ;
  1071.     MVI    M,1        ;UNASEC = 1
  1072.     LXI    H,UNATRK
  1073.     INR    M        ;UNATRK = UNATRK+1
  1074. ;
  1075. ;  MATCH FOUND, MARK AS UNNECESSARY READ
  1076. ;
  1077. NOOVF:    XRA    A
  1078.     STA    RSFLAG        ;RSFLAG = 0
  1079.     JMP    RWOPER        ;GO DO WRITE
  1080. ;
  1081. ;  NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ
  1082. ;
  1083. ALLOC:    XRA    A
  1084.     STA    UNACNT        ;UNACNT = 0
  1085.     INR    A
  1086.     STA    RSFLAG        ;RSFLAG = 1
  1087. ;
  1088. ;  COMMON CODE FOR READ AND WRITE FOLLOWS
  1089. ;
  1090. RWOPER:    XRA    A
  1091.     STA    ERFLAG        ;NO ERRORS (YET)
  1092.     LDA    SECSHF        ;GET SECTOR SHIFT COUNT
  1093.     MOV    B,A        ; IN COUNT REG
  1094.     LDA    SEKSEC        ;COMPUTE HOST SECTOR
  1095.     DCR    A        ;ADJUST FOR 1-ORIGIN
  1096. ;
  1097. RWOPSH:    ORA    A        ;CARRY = 0
  1098.     RAR            ;SHIFT RIGHT
  1099.     DCR    B        ;COUNT OFF A SHIFT
  1100.     JNZ    RWOPSH        ;LOOP IF MORE
  1101.     STA    SEKHST        ;HOST SECTOR TO SEEK
  1102. ;
  1103. ;  ACTIVE HOST SECTOR?
  1104. ;
  1105.     LXI    H,HSTACT    ;HOST ACTIVE FLAG
  1106.     MOV    A,M
  1107.     MVI    M,1        ;ALWAYS BECOMES 1
  1108.     ORA    A        ;WAS IT ALREADY?
  1109.     JZ    FILHST        ;FILL HOST IF NOT
  1110. ;
  1111. ;  HOST BUFFER ACTIVE, SAME AS SEEK BUFFER?
  1112. ;
  1113.     LDA    SEKDSK
  1114.     LXI    H,HSTDSK    ;SAME DISK?
  1115.     CMP    M        ;SEKDSK = HSTDSK?
  1116.     JNZ    NOMATCH
  1117. ;
  1118. ;  SAME DISK, CHECK TRACK
  1119. ;
  1120.     LDA    SEKTRK
  1121.     LXI    H,HSTTRK
  1122.     CMP    M        ;SEKTRK = HSTTRK?
  1123.     JNZ    NOMATCH
  1124. ;
  1125. ;  SAME DISK AND TRACK, CHECK SECTOR
  1126. ;
  1127.     LDA    SEKHST
  1128.     LXI    H,HSTSEC
  1129.     CMP    M        ;SEKHST = HSTSEC?
  1130.     JZ    MATCH        ;SKIP IF MATCH
  1131. ;
  1132. ;  MUST FLUSH HOST BUFFER FOR NEW SECTOR
  1133. ;
  1134. NOMATCH: LDA    HSTWRT        ;HOST WRITTEN?
  1135.     ORA    A
  1136.     CNZ    WRITEHST    ;CLEAR HOST BUFFER
  1137.     LDA    ERFLAG        ;CHECK FOR ERROR
  1138.     ORA    A
  1139.     RNZ            ;RETURN ERROR IF SO
  1140. ;
  1141. FILHST:    LDA    SEKDSK        ;MAY HAVE TO FILL HOST BUFFER
  1142.     STA    HSTDSK
  1143.     LDA    SEKTRK
  1144.     STA    HSTTRK
  1145.     LDA    SEKHST
  1146.     STA    HSTSEC
  1147.     XRA    A
  1148.     STA    HSTWRT        ;NO PENDING WRITE
  1149.     LDA    RSFLAG        ;NEED TO READ?
  1150.     ORA    A
  1151.     JZ    MATCH        ;NO IF FLAG ZERO
  1152.     CALL    READHST        ;READ THE SECTOR
  1153.     LDA    ERFLAG        ;CHECK FOR ERRORS
  1154.     ORA    A
  1155.     RNZ            ;NO MORE IF SO
  1156.     CALL    GNSDEN        ;CHECK DENSITY
  1157.     LXI    H,NSDENS
  1158.     CMP    M        ;IS DENSITY RIGHT?
  1159.     JZ    MATCH        ;OK IF SO
  1160.     LXI    H,SDEMSG    ;ERROR IF NOT
  1161.     CALL    DSKERR        ;REPORT IT
  1162.     MVI    A,5
  1163.     STA    ERFLAG
  1164.     RET            ;RET NZ ACC TO CALLER
  1165. ;
  1166. ;  COPY DATA TO OR FROM BUFFER
  1167. ;
  1168. MATCH:    LDA    SECMSK        ;GET MASK
  1169.     MOV    H,A        ; INTO TEMP REG
  1170.     LDA    SEKSEC        ;MASK SECTOR BUFFER NUMBER
  1171.     DCR    A        ;ADJUST FOR 1-ORIGIN
  1172.     ANA    H        ;LEAST SIGNIF BITS
  1173.     RAR            ;GET VALUE SHIFTED
  1174.     MOV    H,A        ; LEFT 7 IN HL
  1175.     MVI    A,0
  1176.     RAR
  1177.     MOV    L,A
  1178. ;
  1179. ;  HL CONTAINS RELATIVE HOST BUFFER ADDRESS
  1180. ;
  1181.     LXI    D,HSTBUF    ;PT TO HOST BUFFER
  1182.     DAD    D        ;HL = HOST ADDRESS
  1183.     XCHG            ;NOW IN DE
  1184.     LHLD    DMAADR        ;GET/PUT CP/M DATA
  1185.     MVI    C,SECSZ        ;LENGTH OF MOVE
  1186.     LDA    READOP        ;WHICH WAY?
  1187.     ORA    A
  1188.     JNZ    RWMOVE        ;SKIP IF READ
  1189. ;
  1190. ;  WRITE OPERATION, MARK AND SWITCH DIRECTION
  1191. ;
  1192.     INR    A        ;ACC KNOWN ZERO ABOVE
  1193.     STA    HSTWRT        ;HSTWRT = 1
  1194.     XCHG            ;SOURCE/DEST SWAP
  1195. ;
  1196. RWMOVE:    LDAX    D        ;SOURCE CHARACTER
  1197.     INX    D
  1198.     MOV    M,A        ;TO DEST
  1199.     INX    H
  1200.     DCR    C        ;LOOP 128 TIMES
  1201.     JNZ    RWMOVE
  1202. ;
  1203. ;  DATA HAS BEEN MOVED TO/FROM HOST BUFFER
  1204. ;
  1205.     LDA    WRTYPE        ;WRITE TYPE
  1206.     CPI    WRDIR        ;TO DIRECTORY?
  1207.     MVI    A,0        ;NO ERROR AT THIS PT
  1208.     RNZ            ;RET IF NOT DIR WRITE
  1209. ;
  1210. ;  CLEAR HOST BUFFER FOR DIRECTORY WRITE
  1211. ;
  1212.     CALL    WRITEHST
  1213.     LDA    ERFLAG
  1214.     RET
  1215. ;
  1216. ;  WRITEHST PERFORMS THE PHYSICAL WRITE TO THE
  1217. ; NORTH STAR DISK. ON ENTRY, DRIVE IS IN HSTDSK,
  1218. ; TRACK IS IN HSTTRK, SECTOR IS IN HSTSEC. ON
  1219. ; EXIT, ERROR FLAG IS IN ERFLAG (ZERO IF NONE).
  1220. ;
  1221. ;  IT IS ASSUMED INTERRUPTS ARE DISABLED AT
  1222. ; THIS POINT. IF NOT, I/O MAY BE DISRUPTED.
  1223. ;
  1224. WRITEHST:            ;WRITE HOST
  1225.     XRA    A        ;BUFFER WILL BE CLEARED
  1226.     STA    HSTWRT
  1227.     CALL    GNSDEN        ;GET DENSITY BASED ON ID
  1228.     STA    NSCNT        ;SET WRITE BYTE COUNT
  1229.     CALL    SETUP        ;SELECT DRIVE AND
  1230.                 ; SEEK TO TRACK
  1231.     LDA    ERFLAG        ;CHECK FOR ERRORS
  1232.     ORA    A
  1233.     RNZ            ;INDEX PULSE NOT FOUND IS FATAL
  1234.     CALL    POSEC        ;POSITION TO SECTOR
  1235.     JNZ    SNFERR        ;OUT ON ERROR
  1236.     LDA    CCMND+20H    ;GET B-STATUS
  1237.     ANI    02H        ;IS DISK WRITE-PROTECTED?
  1238.     MVI    A,6        ;ASSUME SO, ERROR CODE 6
  1239.     STA    ERFLAG
  1240.     JNZ    WPERR        ;WRITE ALWAYS FAILS IF SO
  1241.     LHLD    HSTADR        ;GET ADDRESS TO WRITE FROM
  1242.     MVI    B,31        ;ASSUME DOUBLE DENSITY
  1243.     MVI    E,2
  1244.     LDA    NSCNT        ;CHECK
  1245.     MOV    C,A        ;SAVE COUNT FOR LATER
  1246.     ORA    A
  1247.     JZ    WRIT5        ;GO ON IF COUNTS RIGHT
  1248.     MVI    B,15        ;CORRECT FOR SINGLE DENS
  1249.     DCR    E
  1250. ;
  1251. WRIT5:    LDA    CCMND+16H    ;INITIATE SECTOR WRITE
  1252. ;
  1253. WRIT10:    LDA    CCMND+15H    ;KEEP MOTORS RUNNING, GET A-STAT
  1254.     ANI    08H        ;MUST LOOP UNTIL 96 USEC WINDOW
  1255.     JNZ    WRIT10        ; PAST, SO LOOP WHILE WI TRUE
  1256. ;
  1257. ;  NOW WRITE THE 31 OR 15 BYTES OF LEADING ZEROES ON THE SECTOR
  1258. ;
  1259. WRIT15:    LDA    WDATA+00H    ;WRITE A BYTE OF ZEROES
  1260.     NOP            ;KILL TIME
  1261.     MVI    D,WDATA SHR 8    ;KILL TIME BY LOADING D FOR LATER
  1262.     DCR    B        ;COUNT OFF A ZERO BYTE
  1263.     JNZ    WRIT15        ;DO THEM ALL
  1264. ;
  1265. ;  FOLLOW WITH ONE OR TWO SYNCH BYTES
  1266. ;
  1267. WRIT17:    LDA    WDATA+0FBH    ;WRITE A SYNCH BYTE
  1268.     DCR    E        ;CHECK FOR 2ND NEEDED
  1269.     JNZ    WRIT17        ;GO BACK IF SO
  1270. ;
  1271. ;  NOW WRITE OUT 256 OR 512 BYTES. DO THIS TWO AT A
  1272. ; TIME SO WE CAN USE SINGLE PRECISION COUNTER. B IS
  1273. ; ZERO FROM ABOVE TO INIT THE CRC BYTE.
  1274. ;
  1275. WRIT20:    MOV    A,M        ;GET NEXT BYTE TO OUTPUT
  1276.     MOV    E,A        ; IN OUTPUT REG
  1277.     XRA    B        ;ADD INTO CHECKSUM
  1278.     RLC
  1279.     MOV    B,A        ;LEAVE CHECKSUM IN B
  1280.     LDAX    D        ;WRITE DATA BYTE TO DISK
  1281.     INX    H        ;BOP BUF PTR
  1282.     MOV    A,M        ;REPEAT FOR NEXT BYTE
  1283.     MOV    E,A
  1284.     XRA    B
  1285.     RLC
  1286.     MOV    B,A
  1287.     LDAX    D
  1288.     INX    H
  1289.     DCR    C        ;COUNT OFF LAST PAIR OF BYTES
  1290.     JNZ    WRIT20        ;GO BACK IF MORE TO WRITE
  1291.     MOV    E,B        ;IF NOT, TIME TO WRITE CHECKSUM
  1292.     INX    B        ;KILL TIME
  1293.     LDAX    D        ; THEN WRITE THE BYTE
  1294.     XRA    A        ;DONE, INDICATE NO ERROR
  1295.     STA    ERFLAG
  1296.     RET            ;RETURN TO CALLER
  1297. ;
  1298. WPERR:    LXI    H,WPEMSG    ;WRITE PROTECT ERROR
  1299.     JMP    DSKERR        ;TELL OPERATOR ON WAY OUT
  1300. ;
  1301. ;  GNSDEN IS CALLED BY N* I/O ROUTINES TO DETERMINE THE
  1302. ; DENSITY OF THE CURRENT BLOCK BASED ON THE DENSITY OF
  1303. ; THE ID BLOCK. THAT IS DETERMINED BY TAKING ADVANTAGE
  1304. ; OF THE FACT THAT THE HOST DISK HAS NO TRANSLATE TABLE
  1305. ; IF SINGLE DENSITY.
  1306. ;
  1307. GNSDEN:    LXI    H,D0DPH        ;ASSUME A:
  1308.     LDA    HSTDSK        ;NOW CHECK
  1309.     CPI    2        ;IS DISK C: OR D:?
  1310.     JNC    GNSDC        ;ALWAYS DOUBLE IF SO
  1311.     ORA    A        ;A:?
  1312.     JZ    GNSDA        ;GO ON IF SO
  1313.     LXI    H,D1DPH        ;B: IF NOT
  1314. GNSDA:    MOV    A,M        ;SEE IF GOT XLATE TABLE
  1315.     INX    H
  1316.     ORA    M        ;IF NOT, SINGLE DENSITY
  1317.     MVI    A,80H        ;ASSUME SINGLE
  1318.     RZ            ;DONE IF RIGHT
  1319. GNSDC:    XRA    A        ;CORRECT IF DOUBLE DENSITY
  1320.     RET
  1321. ;
  1322. ;  COME HERE FROM SELDSK TO CLEAR ALL PENDING HOST WRITES
  1323. ;
  1324. HFLUSH:    LDA    HSTWRT        ;SEE IF BUFFER NEEDS FLUSH
  1325.     STA    ERFLAG        ;NO ERROR IF NOT
  1326.     ORA    A
  1327.     CNZ    WRITEHST    ;FLUSH IF SO, IF MAYBE
  1328.                 ; WILL USE BUFFER
  1329.     XRA    A
  1330.     STA    HSTACT        ;TOSS READ CONTENTS
  1331.     STA    UNACNT        ;BUFFER LEAVING, NEED
  1332.                 ; PRE-READ ON NEXT UNALLOC
  1333.     LDA    ERFLAG        ;SET UP ERROR STATUS
  1334.     ORA    A
  1335.     RET
  1336. ;
  1337. ;  BLOCK - BLOCK MOVE  (Z80 LDIR REGISTER USAGE)
  1338. ;
  1339. BLOCK:    MOV    A,M        ;GET BYTE
  1340.     STAX    D        ;STORE IT
  1341.     INX    H        ;BOP PTRS
  1342.     INX    D
  1343.     DCX    B        ;COUNT OFF BYTE
  1344.     MOV    A,B        ;CHECK FOR DONE
  1345.     ORA    C
  1346.     JNZ    BLOCK        ;GO BACK IF NOT
  1347.     RET
  1348.  
  1349.  
  1350. ;
  1351. ;  HERE TO REPORT DISK NOT READY. TELL CONSOLE WHICH
  1352. ; DISK IT WAS, THEN SOLICIT REPLY. IF CTRL-C, WARM
  1353. ; BOOT TO A:, ELSE RETURN TO CALLER.
  1354. ;
  1355. NOTRDY:    LDA    SEKDSK        ;STUFF DISK
  1356.     ADI    'A'
  1357. ;
  1358. ;  MERGE HERE FROM PRINTER OFFLINE
  1359. ;
  1360. PNTRDY:    STA    NRD        ; INTO MSG
  1361.     LXI    H,NRDMSG
  1362.     CALL    MSGOT        ;REPORT TO OPERATOR
  1363.     CALL    BCNSIN        ;GET REPLY
  1364.     SUI    3        ;IS ANSWER CTRL-C?
  1365.     RNZ            ;RETURN TO CALLER IF NOT
  1366.     STA    DEFDSK        ;SELECT A: IF SO,
  1367.                 ; THEN WARM BOOT IT
  1368. ;
  1369. ;  WARM BOOT ENTRY. LOAD CCP/BDOS AND INITIALIZE
  1370. ;
  1371. WARM:    DI            ;NO PROCESSOR INTS DURING BOOT
  1372.     LDA    DEFDSK        ;GET CURRENT DEFAULT DISK
  1373.     MOV    B,A        ;SAVE IT
  1374.     ANI    0F0H        ;GET USER #
  1375.     MOV    C,A        ;SAVE THAT
  1376.     MOV    A,B
  1377.     ANI    00FH        ;ISOLATE DISK #
  1378.     CPI    NDRVS        ;IS IT LEGAL?
  1379.     JC    WRMOK        ;GO ON IF SO
  1380.     XRA    A        ;BACK TO DRIVE ZERO IF NOT
  1381.     MOV    C,A        ;USER # PROB BAD TOO
  1382. WRMOK:    ORA    C        ;COMBINE WITH USER #
  1383.     STA    DFIMG        ;PUT TO BASE PAGE IMAGE
  1384.     LXI    SP,HSTBUF+HSTSIZ ;SET SP TO SCRATCH RAM
  1385.     LXI    H,CCP+3        ;CP/M WARM START ADDR
  1386.     PUSH    H
  1387. ;
  1388. ;  MERGE HERE FROM COLD BOOT
  1389. ;
  1390. CPMLD:    LDA    IOBYTE        ;GET CURRENT IOBYTE
  1391.     STA    IOIMG        ; INTO BASE PAGE IMAGE
  1392.     LXI    B,8        ;MOVE ZERO PAGE STUFF
  1393.     LXI    D,0        ; DOWN TO ZERO
  1394.     LXI    H,BSIMG
  1395.     CALL    BLOCK
  1396.     LXI    H,05959H    ;FORCE HOME OF N* DRIVES
  1397.     SHLD    NSTRK        ; A, B
  1398.     SHLD    NSTRK+2        ; C, D
  1399.     MOV    A,H        ;MAKE SURE NEW DISK SELECTED
  1400.     STA    CURDSK
  1401.     XRA    A        ;DRIVE ZERO VALUE
  1402.     STA    HSTDSK
  1403.     STA    HSTACT        ;HOST BUFFER INACTIVE
  1404.     STA    HSTWRT        ;NO HOST WRITE PENDING
  1405.     STA    UNACNT        ;CLEAR UNALLOC COUNT
  1406.     LXI    H,CCP        ;CP/M CCP ADDRESS
  1407.     SHLD    HSTADR        ;READ INTO THERE
  1408.     INR    A        ;GET 1 IN ACC
  1409.     STA    HSTTRK        ;READ FROM TRACK ONE
  1410.     CALL    WSETUP        ;KICK MOTORS AND SEEK TRK
  1411.     XRA    A        ;SECTOR ZERO
  1412. ;
  1413. ;  IF NOT NSHOLE:
  1414. ;
  1415. ;  READ ALL TEN SECTORS FROM TRACK ONE, THEN ONE MORE
  1416. ; SECTOR FROM TRACK ZERO, SECTOR THREE.
  1417. ;
  1418. ;  IF NSHOLE:
  1419. ;
  1420. ;  READ EIGHT SECTORS FROM TRACK 1, SECTORS 0-7, THEN
  1421. ; THREE SECTORS FROM TRACK 0, SECTORS 3, 1, AND 2, IN
  1422. ; THAT ORDER. SKIP THE 1K "HOLE" IN BDOS WHEN LOADING
  1423. ; WHERE THE NORTH STAR CONTROLLER WILL BE.
  1424. ;
  1425. WREAD:    STA    HSTSEC        ;SET CURRENT SECTOR TO READ
  1426.     CALL    WRMRD        ;READ SECTOR AND CHK STATUS
  1427.     LXI    D,HSTSIZ    ;SECTOR SIZE
  1428.     LHLD    HSTADR        ;CALC NEW ADDRESS
  1429.     DAD    D
  1430.     SHLD    HSTADR
  1431.     LDA    HSTSEC        ;BOP SECTOR #
  1432.     INR    A
  1433. ;
  1434.     IF    NOT NSHOLE
  1435.     CPI    10        ;THROUGH WITH TRACK ONE?
  1436.     ENDIF    ;NOT NSHOLE
  1437.     IF    NSHOLE
  1438.     CPI    8        ;THROUGH WITH TRACK ONE?
  1439.     ENDIF    ;NSHOLE
  1440. ;
  1441.     JNZ    WREAD        ;GO GET NEXT SECTOR IF NOT
  1442.     XRA    A        ;TO TRACK ZERO,
  1443.     STA    HSTTRK
  1444.     MVI    A,3        ; SECTOR 3 IF SO
  1445.     STA    HSTSEC
  1446.     CALL    WSETUP        ;KICK MOTORS AND SEEK TRK 0
  1447. ;
  1448.     IF    NSHOLE
  1449.     LXI    D,KBYTE        ;SKIP OVER N* CONTROLLER
  1450.     LHLD    HSTADR
  1451.     DAD    D
  1452.     SHLD    HSTADR
  1453.     CALL    WRMRD        ;READ NEXT SECTOR
  1454.     LXI    D,HSTSIZ    ;ADVANCE PTR FOR NEXT SECTOR
  1455.     LHLD    HSTADR
  1456.     DAD    D
  1457.     SHLD    HSTADR
  1458.     MVI    A,1        ;READING SECTOR 1
  1459.     STA    HSTSEC
  1460.     CALL    WRMRD        ;READ IT
  1461.     LXI    D,HSTSIZ    ;REPEAT FOR SECTOR 2
  1462.     LHLD    HSTADR
  1463.     DAD    D
  1464.     SHLD    HSTADR
  1465.     MVI    A,2
  1466.     STA    HSTSEC
  1467.     ENDIF    ;NSHOLE
  1468. ;
  1469.     CALL    WRMRD        ;READ THE LAST SECTOR
  1470.     LXI    H,HSTBUF    ;NOW READ AND WRITE
  1471.     SHLD    HSTADR        ; USING DEBLOCK BUFFER
  1472. ;
  1473. ;  THE NEXT TWO INSTRUCTIONS ARE ONLY INTERESTING IF YOU HAVE
  1474. ; AN EPSON PRINTER WITH DEVICE SELECT. OTHERS SHOULD REMOVE.
  1475. ; THE "OUT TTY" INSTRUCTION IS HARD-WIRED HERE INSTEAD OF MAKING
  1476. ; A CALL TO BLIST SO THAT THE ABSENCE OF AN EPSON WILL NOT HANG
  1477. ; US UP IN AN INFINITE WARM BOOT LOOP.
  1478. ;
  1479.     MVI    A,011H        ;TELL EPSON PRINTER TO SELECT
  1480.     OUT    TTY        ; IF THERE AND NOT SELECTED
  1481. ;
  1482.     LDA    DFIMG        ;RETRIEVE LAST USED DRIVE
  1483.     MOV    C,A        ; FOR BDOS
  1484.     RET            ; THEN GO TO CP/M
  1485. ;
  1486. WSETUP:    CALL    SETUP        ;KICK MOTORS AND SEEK TRK
  1487.     JMP    WECHK
  1488. ;
  1489. WRMRD:    CALL    READNS        ;READ HOST SECTOR
  1490. WECHK:    LDA    ERFLAG        ;CHECK FOR ERROR
  1491.     ORA    A
  1492.     RZ            ;RETURN IF NONE
  1493.     LXI    H,MSGLE        ;GET ERROR MESSAGE
  1494.     CALL    MSGOT        ;TYPE IT
  1495.     HLT            ; THEN GIVE UP
  1496. ;
  1497. ;  MSGOT DISPLAYS STRING OF CHARS PT'ED AT BY HL ON
  1498. ; CONSOLE, UNTIL CHAR WITH PARITY BIT SET IS OUTPUT.
  1499. ;
  1500. MSGOT:    PUSH    PSW        ;SAVE CALLER FLAGS
  1501. MSGL:    MOV    C,M        ;LOAD CHAR
  1502.     PUSH    H        ;SAVE HL
  1503.     LDA    HUNGUP        ;SEE IF TALKING ON PHONE
  1504.     ORA    A
  1505.     PUSH    PSW        ;SAVE DECISION
  1506.     CZ    CNSOT        ;NO MODEM OUTPUT IF NOT
  1507.     POP    PSW
  1508.     CNZ    BCNSOT        ;OUTPUT TO ALL CONSOLE
  1509.                 ; IF SO
  1510.     POP    H        ;RESTORE HL
  1511.     MOV    A,M        ;GET CHAR TO LOOK AT IT
  1512.     INX    H        ;LEAVE PTR ON NEXT CHAR
  1513.     RAL            ;IS HIGH BIT ON?
  1514.     JNC    MSGL        ;GO BACK IF NOT
  1515.     POP    PSW        ; ELSE RESTORE FLAGS
  1516.     RET            ; AND RETURN
  1517. ;
  1518. ;  DISK ERROR MESSAGES
  1519. ;
  1520. WPEMSG:    DB    'Protec','t'+80H
  1521. SDEMSG:    DB    'Densit','y'+80H
  1522. RERMSG:    DB    'CR','C'+80H
  1523. SYEMSG:    DB    'Syn','c'+80H
  1524. NIPMSG:    DB    'Inde','x'+80H
  1525. SNFMSG:    DB    'Secto','r'+80H
  1526. ;
  1527. ERRMSG:    DB    ' err '
  1528. ASCDSK:    DB    ' : trk',' '+80H
  1529. SECMSG:    DB    ' sec',' '+80H
  1530. NRDMSG:    DB    CR,LF,'Disk '
  1531. NRD:    DB    ' : not ready',' '+80H
  1532. CRLF:    DB    CR,LF+80H
  1533. ;
  1534. MSGLE:    DB    CR,LF,'Boot er','r'+80H
  1535. ;
  1536. ;  NORTH STAR DD SECTOR TRANSLATE TABLE. AFTER
  1537. ; DEBLOCKING, WORKS OUT TO SKEW FACTOR OF 5.
  1538. ;
  1539. TRAN5D:    DB    01,02,03,04
  1540.     DB    21,22,23,24
  1541.     DB    05,06,07,08
  1542.     DB    25,26,27,28
  1543.     DB    09,10,11,12
  1544.     DB    29,30,31,32
  1545.     DB    13,14,15,16
  1546.     DB    33,34,35,36
  1547.     DB    17,18,19,20
  1548.     DB    37,38,39,40
  1549. ;
  1550. ;  NORTH STAR DD DISK PARAMETER BLOCK
  1551. ;
  1552. DPBNSD:    DW    40    ;SECTORS PER TRACK
  1553.     DB    3    ;BLOCK SHIFT FACTOR
  1554.     DB    07H    ;BLOCK MASK
  1555.     DB    0    ;NULL MASK
  1556.     DW    DSKSIZ-1 ;DISK SIZE - 1
  1557.     DW    63    ;DIRECTORY MAX
  1558.     DB    11000000B ;ALLOC 0
  1559.     DB    0    ;ALLOC 1
  1560.     DW    16    ;CHECK SIZE
  1561.     DW    2    ;TRACK OFFSET
  1562. ;
  1563. ;  THE NEXT BYTE IS ONE WE HAVE ADDED SPECIFICALLY
  1564. ; FOR THIS BIOS TO CONVENIENCE OUR DEBLOCKING ROUTINES.
  1565. ; IT IS A SECTOR SHIFT MASK, AND EACH DISK PARAMETER
  1566. ; BLOCK HAS ONE IN THIS POSITION. THE ALLOWABLE VALUES
  1567. ; ARE AS FOLLOWS:
  1568. ;
  1569. ;    1000B        ;1024 BYTES/SECTOR
  1570. ;    0100B        ; 512 BYTES/SECTOR
  1571. ;    0010B        ; 256 BYTES/SECTOR
  1572. ;    0000B        ; 128 BYTES/SECTOR
  1573. ;
  1574. ;  FOR THE NORTH STAR DD DISKS, 512 IS HARD-CODED. FOR
  1575. ; THE NORTH STAR SD DISKS, 256 IS HARD-CODED.
  1576. ;
  1577.     DB    0100B    ;512 BYTES/SECTOR
  1578. ;
  1579. ;  THERE IS NO NORTH STAR SINGLE DENSITY TRANSLATE
  1580. ; TABLE.
  1581. ;
  1582. TRAN5S:    EQU    0    ;TELL SECTRN TO JUST ADD 1
  1583. ;
  1584. ;  NORTH STAR SD DISK PARAMETER BLOCK (35 TRACK ONLY)
  1585. ;
  1586. DPBNSS:    DW    20    ;SECTORS PER TRACK
  1587.     DB    3    ;BLOCK SHIFT FACTOR
  1588.     DB    07H    ;BLOCK MASK
  1589.     DB    0    ;NULL MASK
  1590.     DW    80-1    ;DISK SIZE - 1
  1591.     DW    63    ;DIRECTORY MAX
  1592.     DB    11000000B ;ALLOC 0
  1593.     DB    0    ;ALLOC 1
  1594.     DW    16    ;CHECK SIZE
  1595.     DW    3    ;TRACK OFFSET
  1596.     DB    0010B    ;256 BYTES/SECTOR
  1597. ;
  1598. ;  SPECIAL DPB FOR 80 TRACKS, DOUBLE SIDED
  1599. ;
  1600. DPBNSC:    DW    40    ;SECTORS PER TRACK
  1601.     DB    4    ;BLOCK SHIFT FACTOR
  1602.     DB    0FH    ;BLOCK MASK
  1603.     DB    0    ;NULL MASK
  1604.     DW    395-1    ;DISK SIZE - 1
  1605.     DW    127    ;DIRECTORY MAX
  1606.     DB    11000000B ;ALLOC 0
  1607.     DB    0    ;ALLOC 1
  1608.     DW    32    ;CHECK SIZE
  1609.     DW    2    ;TRACK OFFSET
  1610. ;
  1611.     DB    0100B    ;512 BYTES/SECTOR
  1612. ;
  1613. ;  DRIVE PARAMETER HEADER AREA
  1614. ;
  1615. ;  DRIVES A: AND B: ARE 40 TRACKS, SINGLE SIDED
  1616. ;
  1617. D0DPH:    DW    0    ;SECTOR TRAN TBL SET BY SELDSK
  1618.     DW    0    ;SCRATCH
  1619.     DW    0    ;SCRATCH
  1620.     DW    0    ;SCRATCH
  1621.     DW    DIRBF    ;DIRECTORY BUFFER
  1622.     DW    0    ;DRIVE PARAM BLK SET BY SELDSK
  1623.     DW    D0CHK    ;DRIVE CHANGE BLK
  1624.     DW    D0ALL    ;DRIVE ALLOCATION
  1625. ;
  1626. D1DPH:    DW    0,0,0,0,DIRBF,0,D1CHK,D1ALL
  1627. ;
  1628. ;  DRIVES C: AND D: ARE 80 TRACKS, DOUBLE SIDED
  1629. ;
  1630. D2DPH:    DW    TRAN5D,0,0,0,DIRBF,DPBNSC,D2CHK,D2ALL
  1631. ;
  1632. D3DPH:    DW    TRAN5D,0,0,0,DIRBF,DPBNSC,D3CHK,D3ALL
  1633. ;
  1634. ;  ZERO PAGE IMAGE -- BLOCK MOVED TO BASE PAGE
  1635. ;
  1636. BSIMG:    JMP    BIOS+03H    ;WARM BOOT VECTOR
  1637. IOIMG:    DS    1        ;IOBYTE SET BY CPMLD
  1638. DFIMG:    DS    1        ;DEF DISK AND USER, SET
  1639.                 ; TO ZERO AT HANGUP
  1640.     JMP    BDOS+06H    ;BDOS CALL VECTOR
  1641. ;
  1642. ;  BIOS VARIABLE STORAGE
  1643. ;
  1644. SEKDSK:    DB    0    ;DRIVE NUMBER
  1645. SEKTRK:    DS    1    ;TRACK NUMBER
  1646. SEKSEC:    DS    1    ;SECTOR NUMBER
  1647. SEKHST:    DS    1    ;SEEK SHR SECSHF
  1648. HSTACT:    DS    1    ;HOST ACTIVE FLAG
  1649. HSTWRT:    DS    1    ;HOST WRITTEN FLAG
  1650. ;
  1651. RSFLAG:    DS    1    ;READ SECTOR FLAG
  1652. READOP:    DS    1    ;1 IF READ OPERATION
  1653. WRTYPE:    DS    1    ;WRITE OPERATION TYPE
  1654. DMAADR:    DS    2    ;LAST DMA ADDRESS
  1655. ENTPSW:    DW    0    ;ENTRY PSW AT DISK READ/WRITE
  1656. DTPTR:    DW    0    ;DRIVE TABLE PTR
  1657. ;
  1658. UNACNT:    DS    1    ;UNALLOC REC CNT
  1659. UNADSK:    DS    1    ;LAST UNALLOC DISK
  1660. UNATRK:    DS    1    ;LAST UNALLOC TRACK
  1661. UNASEC:    DS    1    ;LAST UNALLOC SECTOR
  1662. ;
  1663. ;  DEBLOCKING INFO ABOUT THE CURRENTLY-SELECTED DISK
  1664. ;
  1665. UNAVAL:    DS    1    ;# UNALLOC RECS/GROUP
  1666. CPMSPT:    DS    1    ;# CP/M SECTORS/TRACK
  1667. SECSHF:    DS    1    ;SECTOR SHIFT COUNT,
  1668.         ; LOG2 (# CP/M SECTORS/HOST BLOCK)
  1669. SECMSK:    DS    1    ;SECTOR MASK, # CP/M
  1670.         ; SECTORS/HOST BLOCK - 1
  1671. ;
  1672. ;  DIRECTORY BUFFER
  1673. ;
  1674. DIRBF:    DS    SECSZ
  1675. ;
  1676. ;  BDOS ALLOCATION AND CHECKSUM BUFFERS
  1677. ;
  1678. D0ALL:    DS    (DSKSIZ/8)+1    ;ALLOC 0
  1679. D0CHK:    DS    16        ;CHECKSUMS 0
  1680. D1ALL:    DS    (DSKSIZ/8)+1    ;ALLOC 1
  1681. D1CHK:    DS    16        ;CHECKSUMS 1
  1682. D2ALL:    DS    (395/8)+1    ;ALLOC 2
  1683. D2CHK:    DS    32        ;CHECKSUMS 2
  1684. D3ALL:    DS    (395/8)+1    ;ALLOC 3
  1685. D3CHK:    DS    32        ;CHECKSUMS 3
  1686. ;
  1687. ;  EVERYTHING FROM THIS POINT FOR THE NEXT
  1688. ; 512 BYTES IS READ INTO MEMORY BY THE NORTH
  1689. ; STAR BOOT PROM. OUR GOAL HERE IS TO GET
  1690. ; A REASONABLE AMOUNT OF NORMAL BIOS CODE IN,
  1691. ; BUT AT THE SAME TIME WE NEED THE PORTIONS
  1692. ; THAT CAN READ THE DISK.
  1693. ;
  1694. ;  IF THIS SECTION OVERLAYS PREVIOUS BIOS CODE
  1695. ; OR DATA SPACE, THE PRECEDING BIOS MUST BE
  1696. ; TRIMMED DOWN.
  1697. ;
  1698. PRVCHK    EQU    $    ;** MUST NOT EXCEED BOOTA **
  1699. ;
  1700.     ORG    BIOS+(HSTSIZ*5)    ;ORG TO COLD BOOT
  1701. ;
  1702. BOOTA:    DB    BOOTA SHR 8    ;TELL PROM LOAD ADDR
  1703. ;
  1704. ;  THE NEXT NINE LOCATIONS ARE SKIPPED OVER
  1705. ; BY THE BOOT PROM, WHICH READS THIS SECTOR
  1706. ; THEN JUMPS TO BOOTA+0AH, SO PUT USEFUL VARIABLES
  1707. ; HERE. NOTE THAT ALL VARIABLES IN THIS SECTOR
  1708. ; WITH GENNED-IN VALUES ARE SET UP FOR COLD
  1709. ; BOOT LOADING OF BIOS.
  1710. ;
  1711. HSTADR:    DW    BIOS    ;READ BIOS INTO HERE TO START,
  1712.             ; BUT NORMALLY PTS TO HSTBUF
  1713. HSTTRK:    DB    0    ;HOST TRACK NUMBER
  1714. HSTSEC:    DB    5    ;HOST SECTOR NUMBER
  1715. HSTDSK:    DB    0    ;HOST DISK NUMBER
  1716. ERFLAG:    DB    0    ;ERROR REPORTING
  1717. CURDSK:    DB    059H    ;CURRENT ACTIVE DISK,
  1718.             ; GENNED-IN FORCE SELECT
  1719. COLDB:    DB    1    ;COLD BOOT WHEN NON-ZERO
  1720. ERSEC:    DS    1    ;SECTOR IN ERROR
  1721. ;
  1722. ;  THIS IS THE SECTION OF THE COLD BOOT THAT
  1723. ; READS IN THE REST OF BIOS. ON MORE CONVENTIONAL
  1724. ; CP/M SYSTEMS, THIS WOULD BE THE BLOCK ZERO
  1725. ; BOOT. READ BIOS INTO MEMORY, THEN JUMP TO
  1726. ; IT TO FINISH COLD BOOTING.
  1727. ;
  1728. BOOT:    DI            ;ALLOW NO PROCESSOR INTERRUPTS
  1729.     LXI    SP,HSTBUF+HSTSIZ ;SET SP TO SCRATCH RAM
  1730.     CALL    SETUP        ;GIVE MOTORS EXTRA KICK
  1731.                 ; AND SEEK TRK 0
  1732. ;
  1733. BOOTL:    CALL    READNS        ;READ NEXT SECTOR OF BIOS
  1734.                 ;WITH COLDB NON-ZERO, NO
  1735.                 ; RETURN IF I/O ERROR
  1736.     LXI    H,HSTSEC    ;IF OK, BOP SEC NUM
  1737.     INR    M
  1738.     LHLD    HSTADR        ; AND ADVANCE READ ADDR
  1739.     LXI    D,HSTSIZ
  1740.     DAD    D
  1741.     SHLD    HSTADR
  1742.     MVI    A,BOOTA SHR 8    ;SEE IF READ ENUFF
  1743.     CMP    H
  1744.     JNZ    BOOTL        ;LOOP IF NOT
  1745.     JMP    INIT        ;GO START BIOS IF SO
  1746. ;
  1747. ;  REMAINING NEEDED VARIABLES
  1748. ;
  1749. RTCNT:    DS    1    ;ERROR RETRY COUNTER
  1750. NSDENS:    DS    1    ;DENSITY OF LAST NS DISK BLOCK
  1751.             ; READ, SD=128, DD=0
  1752. NSCNT:    DB    00H    ;COUNT AND DENSITY FLAG, SET
  1753.             ; BY WRITEHST TO MATCH ID SECTOR
  1754. TRUTRK:    DS    1    ;TRUE DISK SEEK TRACK
  1755. ;
  1756. ;  NORTH STAR CURRENT TRACK TABLE
  1757. ;
  1758. NSTRK:    DB    059H    ;NO CURRENT TRACK YET
  1759.     DB    059H    ;EACH ENTRY CONTAINS
  1760.     DB    059H    ; THE LAST TRACK POSITION
  1761.     DB    059H    ; FOR THE UNIT 1-4
  1762. ;
  1763. ;  DRIVE STEPPING RATE TABLE (SEE STEP ROUTINE)
  1764. ;
  1765. STPTBL:    DW    STPSLW    ;DRIVE A = SLOW
  1766.     DW    STPSLW    ;DRIVE B = SLOW
  1767.     DW    STPFST    ;DRIVE C = FAST
  1768.     DW    STPFST    ;DRIVE D = FAST
  1769. ;
  1770. ;  READHST PERFORMS THE PHYSICAL READ FROM THE
  1771. ; NORTH STAR DISK. ON ENTRY, DRIVE IS IN HSTDSK,
  1772. ; TRACK IS IN HSTTRK, SECTOR IS IN HSTSEC. ON
  1773. ; EXIT, ERROR FLAG IS IN ERFLAG (ZERO IF NONE).
  1774. ;
  1775. ;  ***  INTERRUPTS MUST BE DISABLED HERE  ***
  1776. ;
  1777. READHST:
  1778.     MVI    A,10        ;RETRY COUNT ON ERROR
  1779.     STA    RTCNT
  1780. ;
  1781. READRT:    CALL    SETUP        ;SELECT DRIVE AND
  1782.                 ; SEEK TO TRACK
  1783.     LDA    ERFLAG        ;CHECK FOR ERRORS
  1784.     ORA    A
  1785.     RNZ            ;INDEX PULSE NOT FOUND IS FATAL
  1786. ;
  1787. ;  HERE TO READ NORTH STAR WITHOUT TRACK SEEK FOR SPEED
  1788. ;
  1789. READNS:    CALL    POSEC        ;POSITION TO OUR SECTOR
  1790.     JNZ    SNFERR        ;ERROR IF NOT FOUND
  1791.     MVI    B,08CH        ;COUNT FOR SYNC CHAR LOOP
  1792.     LXI    D,CCMND+40H    ;SET UP READ DATA REGS
  1793. ;
  1794. ;  WAIT FOR RE SO WE CAN DO SECTOR READ, AND TEST
  1795. ; THE DOUBLE DENSITY BIT.
  1796. ;
  1797. WAITRE:    LDA    CCMND+10H    ;GET A-STATUS
  1798.     ANI    04H        ;CHECK RE
  1799.     JZ    WAITRE        ;LOOP UNTIL RE TRUE
  1800.     XTHL            ;KILL TIME TO GET INTO ZEROES
  1801.     XTHL
  1802.     XTHL
  1803.     XTHL
  1804.     XTHL
  1805.     XTHL
  1806.     XTHL
  1807.     XTHL
  1808.     LDA    CCMND+10H    ;GET A-STATUS AGAIN
  1809.     ANI    20H        ;ARE WE READING DOUBLE DENS?
  1810.     RAL            ;MAKE 80H IF NOT, ZERO IF SO
  1811.     RAL
  1812.     XRI    80H
  1813.     STA    NSDENS        ;SAVE DENSITY FOR CALLER
  1814. ;
  1815. ;  NOW WAIT FOR SYNC CHAR DETECTED. ERROR IF WE HAVE TO
  1816. ; WAIT TOO LONG.
  1817. ;
  1818. READ5:    LDA    CCMND+10H    ;WAIT FOR SYNC CHAR DETECTED
  1819.     RRC            ;CHECK BIT
  1820.     JC    READ15        ;OUT IF GOT IT
  1821.     DCR    B        ;COUNT DOWN IF NOT
  1822.     JNZ    READ5        ;GO BACK IF STILL OK
  1823.     MVI    A,1        ;SYNC ERROR IF WAITED TOO LONG
  1824.     LXI    H,SYEMSG    ;SYNC ERROR MESSAGE
  1825. ;
  1826. RERR:    STA    ERFLAG        ;STORE ERROR CODE
  1827.     LDA    RTCNT        ;COUNT OFF A RETRY
  1828.     DCR    A
  1829.     STA    RTCNT
  1830.     JNZ    READRT        ;IF COUNT LEFT, GO RETRY
  1831. ;
  1832. ;  READ ERROR RETRIES FAILED. FLAG ERROR.
  1833. ;
  1834.     JMP    DSKERR        ;TELL OPERATOR OF ERROR THEN OUT
  1835. ;
  1836. SNFERR:    STA    ERFLAG        ;SET ERROR FLAG
  1837.     LXI    H,SNFMSG
  1838.     JMP    DSKERR        ;REPORT ERROR ON WAY OUT
  1839. ;
  1840. ;  READ THE DATA INTO HSTBUF
  1841. ;
  1842. READ15:    LHLD    HSTADR        ;READ INTO HERE
  1843.     MVI    B,0        ;INIT CHECKSUM BYTE
  1844.     LDA    NSDENS        ;GET # BYTES TO READ
  1845.     MOV    C,A        ;PUT READ COUNT IN C-REG
  1846. ;
  1847. READ20:    LDAX    D        ;READ NEXT DATA BYTE
  1848.     MOV    M,A        ; AND PUT IT IN BUFFER
  1849.     XRA    B        ;ADD TO CHECKSUM
  1850.     RLC
  1851.     MOV    B,A
  1852.     INX    H        ;BOP BUFFER PTR
  1853.     NOP            ;KILL TIME
  1854.     LDAX    D        ;GET NEXT BYTE
  1855.     MOV    M,A
  1856.     XRA    B
  1857.     RLC
  1858.     MOV    B,A
  1859.     INX    H
  1860.     DCR    C        ;COUNT OFF LAST PAIR
  1861.     JNZ    READ20        ;GO BACK IF MORE TO DO
  1862.     LDAX    D        ; ELSE READ CRC BYTE
  1863.     XRA    B        ; AND CHECK IT AGAINST OURS
  1864.     STA    ERFLAG        ;IF OK, ZERO EFLAG
  1865.     RZ            ; AND RETURN TO CALLER
  1866.     MVI    A,2        ; ELSE FLAG CHECKSUM ERROR
  1867.     LXI    H,RERMSG    ;MESSAGE IF NEEDED
  1868.     JMP    RERR        ;GO MAYBE RETRY
  1869. ;
  1870. ;  SETUP SELECTS THE UNIT CORRESPONDING TO HSTDSK,
  1871. ; THEN SEEKS TO THE TRACK SPECIFIED BY HSTTRK.
  1872. ; WRITE PRECOMPENSATION IS SET IF REQUIRED AS
  1873. ; WELL. ON ERROR, ERFLAG CONTAINS A NON-ZERO
  1874. ; VALUE ON RETURN. IF HSTTRK IS >= 80, SECOND SIDE
  1875. ; IS SELECTED.
  1876. ;
  1877. SETUP:    MVI    B,00H        ;ASSUME TOP SIDE
  1878.     LDA    HSTTRK        ;CHECK TARGET TRK
  1879.     STA    TRUTRK        ;ASSUME GOING HERE
  1880.     SUI    80        ;GOING TO SIDE TWO?
  1881.     JC    SIDE1        ;PASS IF NOT
  1882.     MVI    B,40H        ;SIDE TWO SELECT
  1883.     STA    TRUTRK        ;GOING HERE
  1884. SIDE1:
  1885.     LDA    NSCNT        ;GET DENSITY FLAG
  1886.     XRI    80H        ;INVERT TO SET DD
  1887.     MOV    C,A        ;SAVE MASK
  1888.     LDA    HSTDSK        ;WANT THIS DISK
  1889.     INR    A        ;REMAP TO CONTROLLER MASK
  1890.     CPI    03H        ;IF UNIT 1 OR 2,
  1891.     JC    SET0        ; GOT CORRECT MASK
  1892.     RAL            ;IF 3 OR 4, MUST MAP
  1893.     ANI    0CH        ; TO 4 OR 8 RESPECTIVELY
  1894. SET0:
  1895.     ORA    C        ;OR IN DENSITY MASK
  1896.     ORA    B        ;OR IN SIDE MASK
  1897.     MOV    C,A        ;SAVE IN REG C
  1898.     CALL    WAIT1S        ;WAIT A SECTOR TIME, GET A-STAT
  1899.     ANI    10H        ;ARE MOTORS ALREADY ON?
  1900.     LDA    CCMND+15H    ;GIVE THEM EXTRA KICK ANYWAY
  1901.     JNZ    SET5        ;BRANCH IF SO
  1902.     MVI    D,17H        ;WAIT FOR MOTORS TO
  1903.     CALL    SCWAIT        ; COME UP TO SPEED IF NOT
  1904.     JMP    SET10        ; THEN GO SELECT DRIVE
  1905. ;
  1906. SET5:    LDA    CURDSK        ;IS THIS THE CURRENT DISK?
  1907.     CMP    C        ;CHECK DISK AND SIDE SELECT
  1908.     JZ    SET20        ;GO SEEK TO TRACK IF MATCH
  1909. ;
  1910. ;  MUST SELECT NEW DISK OR CHANGE SIDE
  1911. ;
  1912. SET10:    MOV    A,C
  1913.     STA    CURDSK        ;NEW CURRENT DISK
  1914.     MVI    B,CORDER SHR 8    ;SET UP FOR SELECT
  1915.     LDAX    B        ; AND DO IT
  1916.     MVI    D,2        ;WAIT TWO SECTOR TIMES
  1917.     CALL    SCWAIT        ; BEFORE LOOKING FOR INDEX
  1918.     MVI    B,12        ;DON'T LOOK TOO LONG
  1919. ;
  1920. SET15:    CALL    WAIT1S        ;WAIT A SECTOR TIME, GET A-STAT
  1921.     ANI    40H        ;INDEX HOLE SEEN?
  1922.     JNZ    SET20        ;CAN GO SEEK NOW IF SO
  1923.     DCR    B        ;COUNT DOWN IF NOT
  1924.     JNZ    SET15        ; AND MAYBE GO LOOK AGAIN
  1925. ;
  1926. ;  INDEX HOLE NOT FOUND. DISK IS PROBABLY NOT LOADED.
  1927. ;
  1928.     MVI    A,4        ;NO INDEX PULSE
  1929.     STA    ERFLAG
  1930.     LXI    H,NIPMSG
  1931.     CALL    DSKERR        ;TELL OPERATOR
  1932.     CALL    NOTRDY        ; AND CLAIM DISK NOT READY
  1933.     MVI    A,059H        ;FORCE RESELECT OF DISK
  1934.     STA    CURDSK
  1935.     JMP    SETUP        ;TRY TO GET DISK AGAIN
  1936. ;
  1937. ;  SEEK TO TRACK SPECIFIED BY TRUTRK NOW, AND SET
  1938. ; WRITE PRECOMPENSATION IF APPROPRIATE.
  1939. ;
  1940. SET20:    LDA    HSTDSK        ;GET NSTRK INDEX
  1941.     MOV    C,A
  1942.     MVI    B,0
  1943.     LXI    H,NSTRK        ;PT AT TABLE
  1944.     DAD    B        ; THEN AT CORRECT ENTRY
  1945.     MOV    A,M        ;GET CURRENT TRACK
  1946.     PUSH    H        ;SAVE NSTRK PTR
  1947.     XRI    59H        ;DISK EVER ACCESSED?
  1948.     CZ    SEEK        ;IF NOT, HOME DRIVE
  1949.     POP    H        ;RESTORE NSTRK PTR
  1950.     LDA    TRUTRK        ;SEEK TO THIS TRACK
  1951.     PUSH    PSW        ;SAVE OVER CALL
  1952.     CALL    SEEK        ;DO FINAL SEEK
  1953.     POP    PSW        ;GET TRUTRK BACK
  1954.     CPI    14H+1        ;ARE WE BEYOND TRACK 14H?
  1955.     JC    SET25        ;GO ON IF NOT
  1956.     LDA    NSCNT        ;SEE IF DD OR SD
  1957.     ORA    A
  1958.     JNZ    SET25        ;NO PRECOMP IF SD
  1959.     LDA    CURDSK        ;IF SO, GET CURRENT MASK
  1960.     ORI    20H        ; AND SET PRECOMP BIT
  1961.     MVI    H,CORDER SHR 8
  1962.     MOV    L,A
  1963.     MOV    A,M        ;SET BIT IN CONTROLLER
  1964. ;
  1965. SET25:    XRA    A
  1966.     STA    ERFLAG        ;NO ERRORS
  1967.     RET
  1968. ;
  1969. ;  POSEC IS CALLED TO POSITION TO HSTSEC WITHIN
  1970. ; THE CURRENT TRACK. ERROR IS RETURNED BY NON-ZERO
  1971. ; IF WE CAN'T FIND THE SECTOR AFTER 30 TRIES.
  1972. ;
  1973. POSEC:    LDA    HSTSEC        ;GET TARGET SECTOR
  1974.     MOV    C,A        ;IN C
  1975.     STA    ERSEC        ;SET UP FOR POSSIBLE ERROR
  1976.     MVI    B,30        ;LOOK AT THIS MANY SECTORS
  1977. ;
  1978. POSC5:    CALL    WAIT1S        ;WAIT FOR NEXT SECTOR
  1979.     LDA    CCMND+35H    ;KICK MOTORS AND GET SECNUM
  1980.     ANI    0FH        ;STRIP NON-SECTOR BITS
  1981.     SUB    C        ;IS THIS THE TARGET SECTOR?
  1982.     RZ            ;OUT IF GOT IT
  1983.     DCR    B        ;COUNT OFF IF DIDN'T
  1984.     JNZ    POSC5        ;GO BACK IF NOT GIVING UP
  1985.     INR    B        ;SET NON-ZERO IF NOT FOUND
  1986.     RET
  1987. ;
  1988. ;  SEEK TO TRACK SPECIFIED BY ACC. CURRENT PTR INTO
  1989. ; NSTRK TABLE IS GIVEN BY HL.
  1990. ;
  1991. SEEK:    MOV    C,A        ;SAVE TARGET TRK #
  1992.     SUB    M        ;SEE HOW FAR AWAY WE ARE
  1993.                 ; FROM TARGET TRACK
  1994.     MOV    M,C        ; BUT ALWAYS SET NEW TRACK
  1995.     RZ            ;IF THERE, DONE
  1996.     LXI    H,CORDER+30H    ;ASSUME STEPPING IN
  1997.     MOV    C,A        ;SAVE STEP COUNT
  1998.     JP    STEPIN        ;BRANCH IF RIGHT
  1999.     CMA            ;IF WRONG, NEGATE COUNT
  2000.     INR    A
  2001.     MOV    C,A        ; THEN SAVE THAT
  2002.     LDA    CCMND+20H    ;GET B-STATUS
  2003.     ANI    01H        ;ARE WE ON TRACK ZERO?
  2004.     RNZ            ;MUST BE DONE IF SO
  2005.     MVI    L,10H        ;IF NOT, STEPPING OUT
  2006. ;
  2007. STEPIN:    LDA    CURDSK        ;GET CURRENT UNIT MASK
  2008.     ORA    L        ;FORM FINAL CORDER VALUE
  2009.     MOV    L,A
  2010.     MOV    D,M        ;SET THE STEP FLIP-FLOP
  2011.     ORI    10H
  2012.     MOV    L,A
  2013.     MOV    D,M        ;SET IT AGAIN FOR SOME REASON
  2014.     XRI    10H
  2015.     MOV    L,A
  2016.     MOV    D,M        ;NOW RESET THE STEP FLIP-FLOP
  2017. ;
  2018. ;  WAIT STEP DELAY TIME GIVEN BY CORRESPONDING ENTRY
  2019. ; IN STPTBL. NOTE THAT STEP TIMES ARE A FUNCTION OF
  2020. ; PROCESSOR SPEED AND DRIVE MODEL, AND MAY BE ADJUSTED
  2021. ; BY PATCHING STPTBL. THE DELAY LOOP BELOW TAKES
  2022. ; 31 T-STATES. AT 4 MHZ, THAT'S 7.75 USEC. AT 2.5 MHZ,
  2023. ; THAT'S 12.4 USEC. AT 4 MHZ WITH ONE M1 WAIT PER
  2024. ; OPCODE, THAT'S 8.5 USEC.
  2025. ;
  2026.     PUSH    H        ;SAVE SOME REGS
  2027.     LDA    HSTDSK        ;GET DRIVE #
  2028.     ADD    A        ;DOUBLE FOR WORD ENTRIES
  2029.     ADI    STPTBL AND 0FFH    ;CALC TABLE PTR
  2030.     MOV    L,A        ; AND PUT IN HL
  2031.     MVI    A,(STPTBL SHR 8) AND 0FFH
  2032.     ACI    0        ;PICK UP POSS CARRY
  2033.     MOV    H,A
  2034.     MOV    A,M        ;GET DELAY CTR
  2035.     INX    H
  2036.     MOV    H,M        ; INTO HL
  2037.     MOV    L,A
  2038. ;
  2039. STEPW:    LXI    D,1        ;DELAY
  2040.     DAD    D
  2041.     JNC    STEPW
  2042.     POP    H        ;RESTORE REGS
  2043.     LDA    CCMND+25H    ;GET B-STATUS AND KICK MOTORS
  2044.     ANI    01H        ;ARE WE AT TRACK ZERO?
  2045.     JNZ    WAIT1S        ;DONE STEPPING IF SO
  2046.     DCR    C        ; ELSE COUNT OFF LAST TRACK
  2047.     JNZ    STEPIN        ;GO BACK IF MORE TO DO
  2048.                 ; ELSE WAIT ONE MORE SECTOR TIME
  2049.                 ; TO MAKE SURE SAFE FOR I/O
  2050. ;
  2051. ;  SECTOR WAIT. ON ENTRY, # SECTORS TO WAIT IS IN D.
  2052. ; ON EXIT, D=0 AND ACC=A-STATUS. CALL WAIT1S TO WAIT
  2053. ; ONE SECTOR TIME.
  2054. ;
  2055. WAIT1S:    MVI    D,1        ;WAIT ONE SECTOR TIME
  2056. ;
  2057. SCWAIT:    LDA    CCMND+11H    ;RESET SECTOR FLAG
  2058. SCW5:    LDA    CCMND+10H    ;GET A-STATUS
  2059.     ORA    A        ;CHECK SECTOR FLAG
  2060.     JP    SCW5        ;WAIT FOR IT IF NOT UP
  2061.     LDA    CCMND+11H    ; ELSE RESET SECTOR FLAG
  2062.     DCR    D        ;COUNT DOWN WAIT COUNTER
  2063.     JNZ    SCW5        ;GO BACK IF MORE TO DO
  2064.     RET            ; ELSE RETURN A-STATUS IN ACC
  2065. ;
  2066. ;  DISK ERRORS REPORTED HERE, BECAUSE STUPID BDOS GIVES
  2067. ; NO USEFUL INFORMATION.
  2068. ;
  2069. DSKERR:    LDA    COLDB        ;IN COLD BOOT?
  2070.     ORA    A        ;IF SO, CNSOT NOT IN MEM YET
  2071.     JZ    DSKER2        ;CAN REPORT IF NOT
  2072.     JMP    NSROM        ;BACK TO N* BOOT ROM IF SO,
  2073.                 ; SINCE CNSOT NOT IN MEM
  2074. ;
  2075. EBOOT    EQU    $-1        ;LAST USED COLD BOOT BYTE
  2076. ;
  2077. ;
  2078. ;  NORTH STAR HOST SECTOR BUFFER
  2079. ;
  2080. HSTBUF:    DS    HSTSIZ        ;HOST BUFFER
  2081. ;
  2082. LAST    EQU    $-1        ;LAST USED BYTE IN MEM
  2083. ;
  2084.     END
  2085.