home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / cpmug / cpmug040.ark / BOOTER.ASM < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  36.2 KB  |  1,599 lines

  1. ;        --- PASCAL BOOTER PROGRAM ---
  2. ;
  3. ;                        S. J. SINGER  (714)-780-8853
  4. ;                        GEORGE BOLTHOFF
  5. ;
  6. ;
  7. ;    THIS PROGRAM IS A COMBINATION OF PINIT THE PASCAL INITIALIZATION
  8. ;PROGRAM AND A BIOS THAT SUPPORTS BOTH STANDARD IBM 3740 FORMAT DISKS AS WELL
  9. ;AS DISKS FORMATTED INTO 512 BYTE BLOCKS SINGLE AND DOUBLE DENSITY. THE PROGRAM
  10. ;HAS CONDITIONAL ASSEMBLIES FOR 3 DIFFERENT DISK CONTROLLERS, THE OLD TARBELL
  11. ;1771 CONTROLLER, THE NEW TARBELL DOUBLE DENSITY CONTROLLER AND THE DELTA
  12. ;DOUBLE DENSITY CONTROLLER.
  13. ;    THE INITIALIZATION SECTION POLLS UP TO 4 DRIVES AND INITIALIZES THE
  14. ;SYSTEM FOR THE DRIVES WHICH ARE READY. DRIVES 0 AND 1 CORRESPOND TO PASCAL
  15. ;LOGICAL UNITS 4 AND 5 RESPECTIVELY WHILE DRIVES 2 AND 3 CORRESPOND TO PASCAL
  16. ;LOGICAL UNITS 9 AND 10. AT LEAST ONE DRIVE UNIT 4 MUST BE READY.
  17. ;    THE PROGRAM THEN READS TRACK ZERO SECTOR ONE FOR EACH UNIT THAT IS
  18. ;READY AND EXAMINES THE FORMAT BYTE 7FH TO DETERMINE THE PROPER INITIALIZATION
  19. ;FOR EACH DISK. AT PRESENT FOUR DIFFERENT FORMATS ARE SUPPORTED.
  20. ;
  21. ;    FMT CODE            DISK FORMAT            BLOCKS
  22. ;      20H      SNGL DENSITY, SNGL SIDED, 26 SECTORS/TRK 128 BYTES      494
  23. ;      22H      SNGL DENSITY, SNGL SIDED,  8 SECTORS/TRK 512 BYTES      608
  24. ;      12H      DBL  DENSITY, SNGL SIDED, 16 SECTORS/TRK 512 BYTES     1216
  25. ;      92H      DBL  DENSITY, DBL  SIDED, 16 SECTORS/TRK 512 BYTES     2448
  26. ;
  27. ;
  28. ;IF AN IMPROPER FORMAT CODE IS READ SUCH AS ANY DOUBLE DENSITY CODE WITH
  29. ;A SINGLE DENSITY TARBELL CONTROLLER THE PROGRAM WILL HALT WITH AN ERROR MESSAGE
  30. ;A FORMAT CODE OF 0DDH IS ASSUMED TO BE DOUBLE DENSITY 128 BYTE SECTORS AND
  31. ;ANY OTHER CODE IS ASSUMED TO IDENTIFY A STANDARD IBM 3740 DISKETTE.
  32. ;IF THE DISK FORMATTING PROGRAM 'DFOCO' IS USED TO FORMAT THE DISKS THE
  33. ;PROPER FORMAT BYTE IS AUTOMATICALLY PLACED ON TRACK ZERO SECTOR ONE.
  34. ;SYSTEM VARIABLES ARE INITIALIZED FOR ALL DRIVES THAT ARE READY. IF FORMATS
  35. ;ARE DETERMINED TO BE INCOMPATABLE THE SYSTEM WILL HALT WITH AN ERROR MESSAGE
  36. ;IDENTIFYING THE DRIVE HAVING THE INCORRECT FORMAT (FOR EXAMPLE A DOUBLE
  37. ;DENSITY DISK WITH A 1771 CONTROLLER) AND ASK YOU TO REBOOT.
  38. ;
  39. ;  OFFSET FOR 64K SYSTEM IS 1380H IF BIOS STARTS AT 0FA00H
  40. FALSE    EQU    00H    ;LOGICAL FALSE
  41. TRUE    EQU    NOT FALSE
  42. ;
  43. DELTA    EQU    FALSE    ;CONDITIONAL ASSMEBLY FOR DELTA CONTROLLER
  44. TARBELL    EQU    FALSE    ;CONDITIONAL ASSEMBLY FOR NEW TARBELL CONTROLLER
  45. ISIO2    EQU    TRUE    ;CONDITIONAL FOR IMSAI SIO-2 SERIAL BOARD (8251'S)
  46. PT3PLUS    EQU    FALSE    ;CONDITIONAL FOR PROCESSOR TECH 3P+S BOARD
  47. TUART    EQU    FALSE    ;CONDITIONAL FOR CROMEMCO TUART SERIAL BOARD
  48. ADM3A    EQU    TRUE    ;CONDITIONAL FOR ADM-3A TERMINAL
  49. SOROC    EQU    FALSE    ;CONDITIONAL FOR SOROC OR OTHER TERM NO SOFTWARE DRV
  50. PERSCI    EQU    FALSE    ;CONDITIONAL FOR FAST SEEK ON DUAL PERSCI DRIVES
  51. STEP    EQU    1    ;STEP RATE 1791  0=3 MSEC, 1=6 MSEC, 2=10 MSEC
  52. MSIZE    EQU    64    ;MEMORY SIZE IN DECIMAL KB
  53. BIOSSZ    EQU    1536    ;BYTES IN THIS BIOS
  54. LOADP    EQU    MSIZE*1024-BIOSSZ    ;LOAD POINT
  55. ;
  56. ;  ---- LIST (PRINTER) EQUATES ----
  57. ;
  58. LSTAT    EQU    4    ;LIST STATUS PORT.
  59. LDATA    EQU    4    ;LIST DATA PORT.
  60. LMASK    EQU    1    ;LIST DATA READY MASK
  61. ;
  62. ; -----  TERMINAL EQUATES -----
  63.     IF    ISIO2
  64. TSTAT    EQU    3H    ;STATUS AND COMMAND PORT
  65. PORT01    EQU    2H    ;SERIAL PORT 1
  66. IMSK01    EQU    02H    ;RX READY PORT 1
  67. OMSK01    EQU    01H    ;TX READY PORT 1
  68.     ENDIF
  69. ;
  70.     IF    PT3PLUS
  71. TSTAT    EQU    00H    ;TERMINAL STATUS AND COMMAND PORT
  72. PORT01    EQU    01H    ;TERMINAL DATA PORT
  73. IMSK01    EQU    01H    ;RX READY PORT 1
  74. OMSK01    EQU    80H    ;TX READY PORT 1
  75.     ENDIF
  76. ;
  77. CTRLS    EQU    19    ;CONTROL S USED TO STOP DISPLAY ON TERMINAL
  78. CR    EQU    13    ;ASCII CARRIAGE RETURN
  79. ;
  80. ;   ----- DISK DRIVER EQUATES -----
  81. ;  
  82. DISK    EQU  0F8H    ;DISK BASE ADDRESS.
  83. DCOM    EQU  DISK    ;DISK COMMAND PORT.
  84. DSTAT    EQU  DISK    ;DISK STATUS PORT.
  85. TRACK    EQU  DISK+1    ;DISK TRACK PORT.
  86. SECTP    EQU  DISK+2    ;DISK SECTOR PORT.
  87. DDATA    EQU  DISK+3    ;DISK DATA PORT.
  88. WAIT    EQU  DISK+4    ;DISK WAIT PORT.
  89. DCONT    EQU  DISK+4    ;DISK CONTROL PORT.
  90. RTCNT    EQU  10        ;RETRY COUNT.
  91. ;
  92. ;---- PASCAL IO TEMPORARIES ---
  93. ;---- PBIOS TEMPORARIES ---
  94. ;
  95. BIOSADR:EQU    40H        ;CONTAINS HEX ADDR OF START OF BIOS
  96. UPTR    EQU    BIOSADR+2
  97. UREQ    EQU    UPTR+2
  98. UNIT    EQU    UREQ+1
  99. UBUF    EQU    UNIT+1
  100. ULEN    EQU    UBUF+2
  101. UBLK    EQU    ULEN+2
  102. UASY    EQU    UBLK+2
  103. URTN    EQU    UASY+2
  104. ERRFLG    EQU    URTN+2
  105. ;
  106. BIOSTEM:EQU    70H        ;ADDITIONAL TEMPORARIES FOR BIOS VARIABLES
  107. SECLEN    EQU    BIOSTEM        ;SECTOR LENGTH CODE 0=128 BYTES 2=512 BYTES
  108. DSKDR    EQU    SECLEN+1    ;CURRENTLY SELECTED DISK DRIVE
  109. NUMSEC    EQU    DSKDR+1        ;NUMBER OF SECTORS PER TRACK (8 OR 16 FOR 512)
  110. NUMDSK    EQU    NUMSEC+1    ;NUMBER OF DISKS ON LINE  1 TO 4
  111. DBLSID    EQU    NUMDSK+1    ;FLAG TRUE IF DOUBLE SIDED DISK
  112. ERCNT    EQU    DBLSID+1    ;ERROR COUNT FOR DISK I/O OPERATIONS
  113. DMAADD    EQU    ERCNT+1        ;MEMORY ADDRESS FOR DISK I/O TRANSFERS
  114. TRKTBL    EQU    DMAADD+2    ;CONTAINS PARAMETERS FOR ALL DISK DRIVES
  115. ;
  116. ;    FOR FLOPPY DISKS TRKTBL CONTAINS TRACK SECTOR SIZE AND DENSITY FOR EACH
  117. ;    DISK DRIVE (MAX OF FOUR FLOPPY DISK DRIVES AT PRESENT)
  118. ;
  119. ;DRIVE    ADDR        TRACK        DENSITY        SECSIZ
  120. ;  4    TRKTBL        0 - 76        1 OR 2        0 OR 2
  121. ;  5    TRKTBL+3
  122. ;  9    TRKTBL+6
  123. ; 10    TRKTBL+9
  124. ;
  125. ;
  126. ASNCBIT    EQU    01H
  127. DRCTBIT    EQU    02H
  128. ASYBIT    EQU    01H
  129. DSKBIT    EQU    02H
  130. EOFBIT    EQU    04H
  131. DLEBIT    EQU    04H
  132. CRLFBIT    EQU    08H
  133. INBIT    EQU    01H
  134. OUTBIT    EQU    02H
  135. CLRBIT    EQU    04H
  136. ALLBIT    EQU    07H
  137. ;  
  138. ;
  139.     MACLIB Z80    ;INCLUDE Z-80 MICROS
  140. ;
  141. BIOS$PAGE    EQU    2H        ;bios page pointer
  142. BIOS        EQU    MSIZE*1024-BIOSSZ
  143. IBASE        EQU    BIOS-1024    ;1024 byte allowed
  144. ;
  145. ; 8251 USART INIT. EQUATES,7 BIT CHAR-NO PARITY
  146. ; 1 STOP BIT-BAUD RATE 16X...COMMAND WORD = 4AH
  147. ;
  148. CMMND        EQU    4AH        ;USART COMMAND AS ABOVE
  149. INTERP$BASE    EQU    100H        ;first loc used by inte
  150. PBEGIN        EQU    INTERP$BASE+100H
  151. FIRSTSP        EQU    INTERP$BASE+103H
  152. DENTSZ        EQU    1AH        ;dir entry size,bytes
  153. DTITLE        EQU    06H
  154. NBLOCKS        EQU    19        ;size of SYSTEM.MICRO
  155. DIRTOP        EQU    IBASE-1000H
  156. BUFFER        EQU    DIRTOP        ;USED FOR DENSITY DETERMINATION
  157. ;
  158.     ORG    IBASE
  159. ;
  160.     LXI    SP,100H            ;INITIALIZE STACK POINTER
  161.     JMP    INIT$IO
  162. MAIN:    LXI    H,DIRTOP
  163.     CALL    READ$DIR    ;read dir into dirtop
  164.     LXI    H,DIRTOP    ;set dir entry pointer
  165.     LXI    D,DENTSZ    ;to firet entry after volume
  166.     DAD    D
  167.     SHLD    DENTP
  168. ;
  169.     CALL    FIND$INTERP    ;find the interpreter
  170.     LXI    H,LDMSG
  171.     CALL    MSG
  172.     CALL    READ$INTERP    ;then read it in
  173. ;
  174.     JMP    PBEGIN        ;boot in SYSTEM.PASCAL
  175. ;
  176. ; ---- INITIALIZE I/O -----
  177. ;All terminal,UART,etc initializing to be done here
  178. ;Initialize terminal first,in case error message needed
  179.     IF    PT3PLUS
  180. INIT$IO:NOP
  181.     ENDIF
  182. ;
  183. ;
  184.     IF    ISIO2        ;INITIALIZE 8251
  185. INIT$IO:MVI    A,80H
  186.     OUT    TSTAT        ;DO A SOFTWARE RESET
  187.     MVI    A,80H        ;KILL SOME TIME !
  188.     OUT    TSTAT
  189.     MVI    A,40H        ;HERE'S THE RESET
  190.     OUT    TSTAT
  191.     MVI    A,CMMND        ;INIT 8251
  192.     OUT    TSTAT
  193.     MVI    A,27H
  194.     OUT    TSTAT
  195.     ENDIF
  196. ;
  197.     IF    TUART        ;INITIALIZE CROMEMCO TUART
  198. BAUDRS:    DB    94H,0CEH,0A2H,92H,88H,84H,82H,1
  199. INIT$IO:MVI    A,1        ;SET A = 1.
  200.     OUT    54H        ;SELECT DEVICE A.
  201.     OUT    52H        ;RESET DEVICE B.
  202.     LXI    H,BAUDRS        ;GET ADR OF BAUD RATE TABLE.
  203.     MVI    A,11H        ;OCTUPLE THE CLOCK.
  204. IT1:    OUT    02H        ;& RESET CURRENT DEV.
  205.     MOV    A,M        ;GET BAUD RATE FROM TABLE.
  206.     INX    H        ;INCREMENT POINTER.
  207.     OUT    0        ;SET BAUD RATE.
  208.     CALL    CIN        ;READ KEYBOARD.
  209.     CALL    CIN        ;READ KEYBOARD AGAIN.
  210.     CPI    CR        ;IF NOT CARRIAGE-RETURN,
  211.     MVI    A,1        ;SLOW THE CLOCK.
  212.     JNZ    IT1        ;UNTIL A CARRIAGE-RETURN.
  213.     ENDIF
  214.  
  215.  
  216. ;
  217. SCRCLR:    LXI    H,CLRSCR    ;CLEAR TERMINAL
  218.     CALL    MSG
  219. ;
  220. ; INITIALIZE ALL VARIABLES, POINTERS ETC. AS REQUIRED
  221. ; DEFAULT FOR BOOT IS STANDARD 3740 FORMAT. PROGRAM CHECKS DENSITY FMT CODE
  222. ; TRK 0 SEC 1 BYTE 128 FOR OTHER FORMATS
  223. ;
  224. INIT01:    LXI    H,BIOS        ;ADDR OF BIOS
  225.     SHLD    BIOSADR        ;SET ADDR VECTOR FOR INTERPRETER
  226.     XRA    A        ;DEFAULT TO 128 BYTE SECTORS
  227.     STA    SECLEN
  228.     MVI    A,8        ;SECTORS PER TRACK
  229.     STA    NUMSEC
  230.     LXI    H,TRKTBL    ;POINT TO DISK PARAMETER TABLE
  231.     MVI    B,12        ;LIMIT
  232.     XRA    A
  233. INIT02:    MOV    M,A        ;STORE A ZERO
  234.     INX    H        ;INCR MEMORY POINTER
  235.     DCR    B        ;DECR COUNT
  236.     JNZ    INIT02        ;LOOP TILL DONE
  237. ;
  238. ;        CHECK WHICH DRIVES ARE ON LINE AND INITIALIZE THEM
  239. ;
  240.     CALL    DSKINT
  241.     LXI    H,ONMSG
  242.     CALL    MSG
  243.     LDA    NUMDSK        ;NUMBER OF DRIVES ON LINE
  244.     ADI    48        ;CONVERT TO ASCII
  245.     MOV    C,A
  246.     CALL    COUT        ;PRINT IT
  247.     LXI    H,ONMSG1
  248.     LDA    NUMDSK
  249.     CPI    1
  250.     JNZ    IND11
  251.     LXI    H,ONMSG2
  252. IND11:    CALL    MSG        ;DISK INITIALIZATION MESSAGE
  253.     LXI    H,TRKTBL+1    ;POINT TO DENSITY CODE UNIT #4
  254.     MOV    A,M        ;GET IT
  255.     PUSH    PSW
  256. ;
  257.     IF    DELTA        ;(1791)
  258.     CALL    DENSEL1        ;SELECT DENSITY FOR READING SYSTEM.MICRO
  259.     ENDIF
  260. ;
  261.     IF    TARBELL        ;(1791)
  262.     MVI    C,0        ;SELECT DRIVE 0 (UNIT 4)
  263.     CALL    SELECT        ;SELECTS DENSITY ALSO
  264.     ENDIF
  265. ;
  266.     LXI    H,ONMSG3
  267.     CALL    MSG
  268.     POP    PSW
  269.     LXI    H,ONMSG5
  270.     CPI    1
  271.     JZ    IND15
  272.     LXI    H,ONMSG4
  273. IND15:    CALL    MSG
  274.     LXI    H,TRKTBL+2    ;POINT TO SECTOR SIZE CODE
  275.     MOV    A,M
  276.     ORA    A        ;SET FLAGS
  277.     LXI    H,ONMSG6
  278.     JZ    IND18
  279.     LXI    H,ONMSG7
  280. IND18:    CALL    MSG        ;PRINT THE MESSAGE
  281.     LXI    D,TRKTBL+4    ;DENSITY CODE UNIT 5
  282.     LDAX    D        ;PICK UP THE CODE
  283.     ORA    A
  284.     JZ    MAIN        ;EXIT IF ONLY ONE DRIVE
  285.     LXI    H,ONMSG8
  286.     CALL    MSG
  287.     LDAX    D        ;DENSITY CODE
  288.     LXI    H,ONMSG4
  289.     CPI    2        ;SINGLE DENSITY ?
  290.     JZ    IND20
  291.     LXI    H,ONMSG5
  292. IND20:    CALL    MSG
  293.     LXI    H,TRKTBL+5    ;POINT AT SECSIZ UNIT 5
  294.     MOV    A,M        ;PICK IT UP
  295.     ORA    A
  296.     LXI    H,ONMSG6
  297.     JZ    IND23
  298.     LXI    H,ONMSG7
  299. IND23:    CALL    MSG
  300.     JMP    MAIN        ;RETURN WITH JUMP 
  301. ;
  302. ;---- READ DIRECTORY AND LOAD IN SYSTEM.MICRO ----
  303. ;
  304. READ$DIR:            ;read dir 4 blocks into buffer
  305.                 ;buffer adr in HL reg
  306.     SHLD    UBUF        ;DMA  DIRECTORY LOAD POINT
  307.     LXI    H,800H        ;LENGTH=2048 BYTES  800H
  308.     SHLD    ULEN
  309.     LXI    H,0002H        ;STARTING BLOCK
  310.     SHLD    UBLK
  311.     XRA    A        ;ZERO REG A
  312.     STA    UNIT
  313.     STA    UASY
  314.     MVI    A,1
  315.     STA    UREQ        ;READ REQUEST
  316.     MVI    C,0        ;SELECT DRIVE 0
  317.     CALL    BIOS        ;READ IN DIRECTORY
  318.     RET
  319. ;
  320. FIND$INTERP:            ;FIND 'SYSTEM.MICRO'
  321.     MVI    C,77        ;STOP AFTER THE 77'TH ENTRY
  322.     LHLD    DENTP        ;GET STARTING ENTRY
  323. FI$SCH$LP:
  324.     LXI    D,DTITLE    ;ADVANCE TO TITLE STRING
  325.     DAD    D
  326.     LXI    D,SYSTLE    ;SET DE-REG TO COMPARISON STRING
  327.     MVI    B,LENGTH+1    ;COMPARISON LENGTH
  328. FI$CMP$LP:            ;START COMPARING
  329.     LDAX    D
  330.     CMP    M
  331.     JNZ    FI$CONT        ;IT'S NOT THIS ONE
  332.     INX    D        ;HEY, WE'VE STILL GOT A CHANCE
  333.     INX    H
  334.     DCR    B        ;IS THIS THE END OF THE STRING
  335.     JNZ    FI$CMP$LP
  336.     JMP    FI$FOUND    ;I THINK WE FOUND IT
  337. FI$CONT:
  338.     LHLD    DENTP        ;ON TO THE NEXT ENTRY
  339.     LXI    D,DENTSZ
  340.     DAD    D
  341.     SHLD    DENTP
  342.     DCR    C        ;WAIT, IS THERE ANY DIR LEFT?
  343.     JNZ    FI$SCH$LP
  344. FI$HANG:            ;INTERPRETER NOT THERE, GO DUMB
  345.     LXI    H,NOMICRO
  346.     CALL    MSG
  347. HANG:    JMP    HANG
  348.  
  349. FI$FOUND:            ;WE'VE GOT IT
  350.     RET
  351. ;
  352. LENGTH    EQU    12        ;TITLE LENGTH
  353. SYSTLE    DB    LENGTH,'SYSTEM.MICRO'
  354. ;
  355. ;
  356. READ$INTERP:            ;PUT INTERP IN ITS PLACE
  357.     LHLD    DENTP        ;GET STARTING BLOCK
  358.     MOV    E,M        ;  INTO HL-REG
  359.     INX    H
  360.     MOV    D,M
  361.     XCHG
  362.     SHLD    UBLK        ;STARTING BLOCK
  363.     LXI    H,INTERP$BASE    ;DMA LOAD POINT
  364.     SHLD    UBUF
  365.     LXI    H,NBLOCKS*512
  366.     SHLD    ULEN
  367.     MVI    C,0        ;SELECT DRIVE 0
  368.     CALL    BIOS        ;READ IN INTERP
  369.     RET
  370. ;
  371. ;
  372. DENTP    DS    2
  373. ;
  374. ;--------- CHARACTER DRIVERS ---------------
  375. ;
  376. ; --- MESSAGE HANDLER -----
  377. ;
  378. MSG:    MOV    A,M        ;GET BYTE
  379.     ORA    A        ;IS IT ZERO
  380.     RZ            ;RETURN IF SO
  381.     MOV    C,A
  382.     PUSH    H        ;SAVE POINTER
  383.     CALL    COUT        ;GIVE BYTE TO TERMINAL
  384.     POP    H
  385.     INX    H
  386.     JMP    MSG
  387. ;
  388. ;        LOTS OF MESSAGES FOR INITIALIZE
  389. ;
  390. NOMICRO:DB    0DH,0AH,'No SYSTEM.MICRO .....',0
  391. LDMSG:    DB    0DH,0AH,0AH,'    Loading PASCAL system.....',0
  392. RDMSG:    DB    0DH,0AH,' ERROR ATTEMPTING TO READ DENSITY CODES ',0
  393. BADFMT:    DB    0DH,0AH,'UNSUPPORTED DISK FORMAT UNIT ',0
  394. BADFM1:    DB    ' .... PLEASE REBOOT',0DH,0AH,0AH,0
  395. QUITMSG:DB    0DH,0AH,'UNIT #4 NOT READY .... PLEASE REBOOT',0DH,0AH,0AH,0
  396. ONMSG:    DB    0DH,0AH,0AH,'PASCAL SYSTEM INITIALIZED FOR ',0
  397. ONMSG1:    DB    ' DISK DRIVES',0DH,0AH,0
  398. ONMSG2:    DB    ' DISK DRIVE',0DH,0AH,0
  399. ONMSG3:    DB    'UNIT NUMBER FOUR IS',0
  400. ONMSG4:    DB    ' SINGLE DENSITY',0
  401. ONMSG5:    DB    ' DOUBLE DENSITY',0
  402. ONMSG6:    DB    ' WITH 128 BYTE SECTORS',0DH,0AH,0
  403. ONMSG7:    DB    ' WITH 512 BYTE SECTORS',0DH,0AH,0
  404. ONMSG8:    DB    'UNIT NUMBER FIVE IS',0
  405. CLRSCR:    DB    27,42,26,0    ;CLEARSCREEN FOR ADM-3A AND SOROC
  406. ;
  407. ;
  408. ;---------- DISK ROUTINES -----------
  409. ;
  410. ; HOME ALL DRIVES THAT ARE READY, THEN READ FORMAT CODE FROM TRACK
  411. ; ZERO AND INITIALIZE TRKTBL ENTRIES. FINALLY BOOT SYSTEM FROM DRIVE 0
  412. ;
  413. DSKINT:    MVI    A,2        ;MAX NUMBER OF FLOPPY DRIVES
  414.     STA    NUMDSK        ;CHECK FOR UP TO 4 DRIVES
  415. IDSK01:    DCR    A
  416.     STA    DSKDR        ;SAVE FOR LATER
  417.     MOV    C,A        ;TO C ALSO FOR SELECT ROUTINES
  418.     LXI    H,TRKTBL+1    ;DENSITY UNIT 4 (WILL ALWAYS BE SINGLE)
  419.     CALL    SELECT        ;SELECT THE DRIVE
  420.     MVI    A,0DH
  421.     OUT    DCOM        ;INTERRUPT CONTROLLER
  422.     XTHL
  423.     XTHL
  424.     XTHL
  425.     XTHL            ;SHORT WAIT FOR STATUS
  426.     IN    DSTAT        ;READ DISK STATUS
  427.     ANI    80H        ;CHECK DRIVE READY
  428.     JZ    IDSK03        ;CONTINUE IF READY
  429.     LDA    NUMDSK        ;NUMBER OF DISKS
  430.     DCR    A
  431.     STA    NUMDSK        ;REDUCE NO OF DRIVES ON LINE BY ONE
  432.     LDA    DSKDR        ;LOAD DRIVE NO
  433.     JP    IDSK01        ;LOOP IF UNIT 4 OK
  434.     LXI    H,QUITMSG    ;UNIT 4 NOT READY
  435.     CALL    MSG
  436.     JMP    HANG        ;PROCESSOR HALT - MUST REBOOT
  437. IDSK03:    LDA    DSKDR        ;GET CURRENT DRIVE NO
  438.     CALL    INDEX        ;GET DISK PARAMETER TABLE POINTER
  439.     XRA    A
  440.     MOV    M,A        ;SET TRACK TO ZERO
  441.     PUSH    H        ;SAVE FOR LATER
  442.     CALL    HOME        ;home this drive
  443.     CALL    RDSEC1        ;READ IN SECTOR ONE
  444.     CALL    LONGDEL        ;JUST WAIT
  445.     LDA    BUFFER+7FH    ;GET DENSITY CODE FROM BUFFER
  446. ;
  447.     IF    NOT DELTA AND NOT TARBELL
  448.     CPI    12H        ;SINGLE SIDE DD
  449.     JZ    IDSK04
  450.     CPI    92H        ;DOUBLE SIDE DD
  451.     JZ    IDSK04
  452.     ENDIF
  453. ;
  454.     CPI    0DDH        ;CHECK FOR DD DISK WITH 128 BYTE SECTORS
  455.     JNZ    IDSK05
  456. IDSK04:    LXI    H,BADFMT    ;PRINT ERROR MESSAGE
  457.     CALL    MSG
  458.     LDA    DSKDR        ;DRIVE NO
  459.     ADI    52        ;COMPUTE UNIT NO
  460.     MOV    C,A
  461.     CALL    COUT        ;PRINT IT
  462.     LXI    H,BADFM1
  463.     CALL    MSG        ;PRINT REST OF MESSAGE
  464.     JMP    HANG        ;AND QUIT
  465. IDSK05:    RRC
  466.     RRC
  467.     RRC
  468.     RRC            ;SHIFT RIGHT 4
  469.     ANI    0FH        ;EXTRACT DENSITY (1=DBL, 2=SNGL)
  470.     POP    H        ;get back trktab pointer
  471.     INX    H        ;POINT TO DENSITY
  472.     MVI    B,2        ;DENSITY CODE FOR SINGLE DENSITY
  473.     MOV    M,B        ;DEFAULT FOR DISKS WITH NO ID CODE
  474.     ORA    A
  475.     JZ    IDSK09        ;3740 DISK
  476.     CPI    3
  477.     JP    IDSK09        ;SHOULDN'T BE > 2 EITHER
  478.     MOV    M,A        ;STORE DENSITY
  479.     INX    H        ;POINT TO SECTOR LENGTH CODE
  480.     LDA    BUFFER+7FH    ;DISK ID CODE
  481.     ANI    0FH        ;EXTRACT LENGTH
  482.     MOV    M,A        ;STORE IN TABLE
  483. IDSK09:    LDA    DSKDR        ;check if done yet
  484.     ORA    A
  485.     JNZ    IDSK01        ;not done,continue
  486.     LDA    TRKTBL+2    ;SECTOR SIZE UNIT 4
  487.     CPI    2        ;2 = 512 BYTE SECTORS
  488.     RNZ            ;ASSUME DEFAULT 128
  489.     LXI    H,NUMSEC    ;POINT TO NUMBER OF SECTORS UNIT 4
  490.     STA    SECLEN        ;SET SECTOR LENGTH TO 2 (512 BYTES)
  491.     LDA    TRKTBL+1    ;GET DENSITY FLAG
  492.     CPI    1        ;1 = DOUBLE DENSITY
  493.     MVI    A,8        ;8 SECTORS PER TRACK (SINGLE DENSITY)
  494.     MOV    M,A        ;SELECT SINGLE
  495.     RNZ            ;RETURN IF NOT DOUBLE
  496.     ADD    A        ;16 SECTORS PER TRACK (DOUBLE DENSITY)
  497.     MOV    M,A        ;SELECT DOUBLE
  498.     RET            ;exit DSKINT
  499. ;
  500. ;    READ SECTOR ONE TRACK ZERO INTO BUFFER
  501. ;
  502. RDSEC1:    LXI    H,BUFFER
  503.     SHLD    DMAADD        ;MEMORY ADDR FOR READ
  504.     LXI    H,128
  505.     SHLD    ULEN        ;NUMBER OF BYTES TO READ
  506.     XRA    A
  507.     STA    ERRFLG        ;ZERO DISK I/O ERROR FLAG
  508.     MVI    C,0
  509.     CALL    SETTRK        ;SET TRACK TO ZERO
  510.     MVI    A,1
  511.     STA    SECT        ;SELECT SECTOR ONE
  512.     CALL    READ
  513.     LDA    ERRFLG        ;CHECK ERROR FLAG
  514.     ORA    A
  515.     RZ
  516.     LXI    H,RDMSG
  517.     CALL    MSG
  518.     JMP    HANG
  519. ;
  520. ;
  521. ;Delay loop gives drive 11 mill sec to settle
  522. ;
  523. DELAY:    LXI    B,700H
  524. DELAY1:    DCX    B
  525.     MOV    A,B
  526.     ORA    C
  527.     JNZ    DELAY1
  528.     RET
  529. ;
  530. ;
  531. ;  LONGDEL  LONG DELAY FOR HOME COMMAND
  532. ;
  533. LONGDEL:LXI    H,5000H
  534.     LXI    D,0001H
  535.     XRA    A
  536. LD01:    DAD    D
  537.     JNC    LD01
  538.     RET
  539.  
  540. ; ***********************************************************
  541. ;
  542. ;  BIOS ROUTINES START HERE.
  543. ;
  544. ; ***********************************************************
  545. ;
  546. ;
  547. ;  PBIOS  PASCAL I-O ROUTINES       28-JULY-79
  548. ;  MODIFIED FOR DOUBLE DENSITY        15-NOV-79
  549.     ORG    LOADP
  550. ; I/O JUMP VECTOR
  551. BEGIN:    JMP    DSKIO    ;ENTRY POINT FOR DISK DRIVERS
  552.     JMP     CHDRVR    ;ENTRY FOR CHARACTER DRIVERS
  553.     JMP    REMIN    ;REMOTE IN
  554.     JMP    REMOUT    ;REMOTE OUT
  555. ;
  556. IOXIT:    RET
  557. ;----- PBIOS SCRATCH AREA ------
  558. TRK:    DB    0    ;CURRENT TRACK
  559. SECT:    DB    0    ;CURRENT SECTOR
  560. DSCT0:    DB    0    
  561. DSCT:    DB    0
  562. DTRK:    DB    0
  563. CLAST:    DB    0
  564. LATCH:    DB    0    ;LATCH FOR CURRENT DRIVE SELECT
  565. ;
  566. ;***************** CHARACTER DRIVERS ******************
  567. ;
  568. CHDRVR:    LDA    UREQ
  569.     ANI    CLRBIT
  570.     JRZ    CH01
  571.     XRA    A
  572.     STA    CLAST
  573.     JMP    CHX
  574. CH01:    LHLD    ULEN
  575.     XCHG
  576.     LHLD    UBUF
  577. CH02:    MOV    A,E        ;SET UP LOOP
  578.     ORA    D
  579.     JZ    CHX
  580.     DCX    D
  581.     LDA    UREQ        ;WHICH DIRECTION
  582.     ANI    OUTBIT
  583.     JRZ    CH03
  584.     MOV    C,M        ;DO OUTPUT
  585.     CALL    ECHO
  586.     JR    CH06
  587. CH03:    CALL    CIN        ;DO INPUT
  588.     MOV    C,A
  589.     MOV    M,A
  590.     LDA    UASY
  591.     ANI    EOFBIT
  592.     JRNZ    CH05
  593.     MVI    A,03H
  594.     CMP    M
  595.     JRNZ    CH05
  596.     LDA    UNIT
  597.     CPI    01H
  598.     JRNZ    CHX
  599.     INX    D
  600. CH04:    MVI    M,0        ;LOOP,PUTING ZERO'S IN BUFFER
  601.     DCX    D
  602.     INX    H
  603.     MOV    A,E
  604.     ORA    D
  605.     JRNZ    CH04
  606.     JR    CHX
  607. CH05:    LDA    UNIT
  608.     CPI    01H
  609.     CZ    ECHO
  610. CH06:    INX    H
  611.     JR    CH02
  612. CHX:    JP    IOXIT
  613. ;CHAR IN REG C IS INTERPRETED AND OUTPUT
  614. ECHO:    LDA    UASY
  615.     ANI    DLEBIT
  616.     JRNZ    ECH03
  617. ECH01:    LDA    CLAST
  618.     CPI    10H
  619.     JRNZ    ECH03
  620.     MOV    A,C
  621.     SUI    20H
  622.     STA    CLAST
  623. ECH02:    LDA    CLAST
  624.     DCR    A
  625.     JM    ECH05
  626.     STA    CLAST
  627.     MVI    C,32        ;ASCII SPACE
  628.     CALL    COUT
  629.     JR    ECH02
  630. ECH03:    MOV    A,C
  631.     STA    CLAST
  632.     CPI    10H
  633.     JRNZ    ECH04
  634.     LDA    UASY
  635.     ANI    DLEBIT
  636.     JRZ    ECH05
  637.     MVI    A,20H
  638.     STA    CLAST
  639. ECH04:    CALL    COUT
  640.     LDA    UASY
  641.     ANI    CRLFBIT
  642.     JRNZ    ECH05
  643.     LDA    CLAST
  644.     CPI    CR
  645.     JRNZ    ECH05
  646.     MVI    A,0AH
  647.     STA    CLAST
  648.     MOV    C,A
  649.     CALL    COUT
  650. ECH05:    RET
  651.  
  652. REMIN:    RET
  653. REMOUT:    RET
  654. ;
  655. ;------------- DISK DRIVERS -------------------
  656. DSKIO:    CALL    SELDSK        ;SELECT DRIVE IN REG C
  657.     LDA    UREQ
  658.     ANI    CLRBIT
  659.     JRZ    CHK00
  660. ;     DONT ALLOW PASCAL TO CLEAR (HOME) DRIVES
  661.     JP    XDSK
  662. CHK00:    LDA    UASY
  663.     ANI    DSKBIT        ;DONT ALLOW SECTOR ACCESS
  664.     JRZ    CHKDSK
  665.     JMP    IOERR
  666. CHKDSK:    LHLD    UBUF        ;INIT
  667.     SHLD    DMAADD
  668.     LHLD    ULEN        ;CHECK FOR NO BYTES
  669.     MOV    A,H
  670.     ORA    L
  671.     JZ    XDSK
  672. CHK01:    LDA    SECLEN        ;CHECK WHICH MAP TO USE
  673.     ANI    03H        ;LOOK AT ONLY 2 LSB'S
  674.     CPI    02H
  675.     JRZ    NEWMAP
  676.     ORA    A        ;CHECK IF ZERO
  677.     JZ    DSK03
  678.     JMP    IOERR        ;FORMAT ERROR
  679. ;
  680. ;************ MAP FOR 512 BYTE SECTORS ************
  681. ;
  682. NEWMAP:    LHLD    UBLK        ;TRACK=BLOCK DIV NUMSEC
  683.     LDA    NUMSEC        ;GET NUMBER OF SECTORS/TRACK
  684.     MOV    C,A        ;AND PUT INTO REG BC
  685.     MVI    B,0
  686.     CALL    DIVPOS
  687.     MOV    A,E        ;REG E = TRACK
  688.     STA    DTRK
  689.     INR    A        ;ADJUST FOR NO TRACK 0
  690.     MOV    C,A
  691.     CALL    SETTRK        ;SEEK FIRST TRACK
  692. ; SECTOR = (BLOCK-TRACK*NUMSEC)+1
  693.     LDA    DTRK        ;TRACK BEFORE ADJUSTMENT
  694.     MOV    E,A        ;PUT INTO REG DE
  695.     MVI    D,0
  696.     LXI    H,0000H
  697.     LDA    NUMSEC        ;GET COUNTER
  698.     MOV    B,A
  699. MULT:    DAD    D
  700.     DJNZ    MULT        ;MULTIPLY LOOP
  701.     XCHG            ;REG DE=TRK*NUMSEC
  702.     LHLD    UBLK        ;SET UP FOR SUBTRACTION
  703.     ANA    A        ;RESET CARRY FLAG
  704.     DSBC    DE        ;SUBTRACT  HL-DE
  705.     MOV    A,L        ;REG L =SECTOR
  706.     INR    A        ;ADJUST FOR NO SECTOR 0
  707.     STA    SECT        ;SAVE SECTOR
  708.     LDA    DTRK        ;UPDATE TRACK COUNTER
  709.     INR    A
  710.     STA    DTRK
  711. ;------------------------------------------------
  712. ;    LOOP ON BYTES (IN ULEN)
  713. ;------------------------------------------------
  714. NEW01:    LDA    UREQ        ;READ/WRITE
  715.     ANI    OUTBIT        ;LOOP ON BYTES IN ULEN
  716.     JRZ    NEW02
  717.     CALL    WRITE        ;DO WRITE
  718.     JR    NEW03
  719. NEW02:    CALL    READ        ;DO READ
  720. NEW03:    SHLD    DMAADD        ;SAVE COUNTERS AND POINTERS
  721.     SDED    ULEN
  722.     MOV    A,D        ;CHECK FOR DONE
  723.     ORA    E
  724.     JZ    XDSK        ;LEAVE IF DONE
  725. ;--- SECTOR MAP -----
  726.     LXI    H,NUMSEC    ;SETUP MEMORY POINTER
  727.     LDA    SECT        ;GET LAST SECTOR
  728.     CMP    M        ;END OF TRACK YET
  729.     JRZ    NEWTRK        
  730.     INR    A        ;ADD ONE TO SECTOR
  731.     STA    SECT        ;NO,SAVE NEW SECTOR
  732.     JMP    NEW01        ;CONTINUE
  733. NEWTRK:    LDA    DTRK        ;GET OLD TRACK
  734.     INR    A        ;ADD ONE
  735.     STA    DTRK
  736.     MOV    C,A
  737.     CALL    SETTRK        ;SEEK NEW TRACK
  738.     MVI    A,1        ;UPDATE SECTOR COUNTER
  739.     STA    SECT
  740.     JMP    NEW01
  741. TRKERR:    MVI    A,4        ;MUST BE BAD ERROR HERE
  742.     STA    ERRFLG
  743.     JMP    IOXIT
  744. ;
  745. ;
  746. ;******** STANDARD MAPPING ROUTINES ************
  747. ;
  748. ;------- START INITIALIZING FOR THE LOOP --------
  749. DSK03:    LHLD    UBLK
  750.     DAD    H
  751.     DAD    H
  752.     LXI    B,1AH
  753.     CALL    DIVPOS
  754.     PUSH    H
  755.     PUSH    D
  756.     MOV    A,E
  757.     INR    A    
  758.     STA    DTRK
  759.     MOV    C,A
  760.     CALL    SETTRK
  761.     POP    D
  762.     MVI    A,06H
  763.     LXI    H,0000H
  764. DSK04:    DAD    D
  765.     DCR    A
  766.     JRNZ    DSK04
  767.     LXI    B,1AH
  768.     CALL    DIVPOS
  769.     INX    H
  770.     POP    D
  771.     MOV    A,E
  772.     CPI    0CH+1
  773.     JC    DSK05
  774.     INX    H
  775. DSK05:    MOV    A,L
  776.     STA    DSCT0
  777.     ADD    E
  778.     ADD    E
  779.     DCR    A
  780. DSK06:    SUI    1AH
  781.     JNC    DSK06
  782.     ADI    1AH+1
  783.     STA    DSCT
  784.     STA    SECT
  785. ;
  786. ;----------------------------------------------
  787. ;   LOOP ON BYTES (IN ULEN)
  788. ;----------------------------------------------
  789. DSK07:    LDA    UREQ        ;DO THE INPUT/OUTPUT NOW
  790.     ANI    OUTBIT
  791.     JRZ    DSK08
  792.     CALL    WRITE
  793.     JR    DSK09
  794. DSK08:    CALL    READ
  795. DSK09:    SHLD    DMAADD        ;UPDATE COUNTERS AND POINTERS
  796.     SDED    ULEN
  797.     MOV    A,D    
  798.     ORA    E        ;CHECK IF DONE YET
  799.     JZ    XDSK        ;EXIT IF ULEN=0
  800. ;------ CALCULATE NEXT SECTOR -------
  801.     LDA    DSCT
  802.     ADI    02H
  803.     CPI    1BH
  804.     JC    DSK14
  805.     SUI    1AH
  806. DSK14:    LXI    H,DSCT0
  807.     CMP    M
  808.     JRNZ    DSK17
  809.     INR    A
  810.     RRC
  811.     RAL
  812.     JNC    DSK16
  813.     ADI    04H
  814.     CPI    1AH+1
  815.     JC    DSK15
  816.     SUI    1AH
  817. DSK15:    PUSH    PSW
  818.     LDA    DTRK
  819.     INR    A
  820.     STA    DTRK
  821.     MOV    C,A
  822.     CALL    SETTRK
  823.     POP    PSW
  824. DSK16:    STA    DSCT0
  825. DSK17:    STA    DSCT
  826.     STA    SECT
  827.     JMP    DSK07
  828. XDSK:    JMP    IOXIT
  829. ;  
  830. ;DIVPOS - DIVIDES 2 POSITIVE INTERGERS
  831. ;     ENTRY  BC=DIVISOR  HL=DIVIDEND
  832. ;     EXIT   BC=DIVISOR  HL=REMAINDER  DE=QUOTIENT
  833. ;
  834. DIVPOS:    LXI    D,0000H
  835.     MVI    A,01H
  836. DIV01:    INR    A
  837.     SLAR    C
  838.     RALR    B
  839.     JP    DIV01
  840. DIV02:    STC
  841.     RALR    E
  842.     RALR    D
  843.     DSBC    BC
  844.     JNC    DIV03
  845.     DAD    B
  846.     DCX    D
  847. DIV03:    SRLR    B
  848.     RARR    C
  849.     DCR    A
  850.     JRNZ    DIV02
  851.     RALR    C
  852.     RALR    B
  853.     RET
  854. ;
  855. ;---------- CHARACTER DRIVER PRIMATIVES -------------
  856. ;
  857. ;  DRIVER FOR CENTRONICS PRINTER  (HARDWARE STROBE)
  858. ; V-G "BIT STREAMER" WITH ADDED ONE SHOT FOR STROBE
  859. ;   CHARACTER IN REG C
  860. LIST:    MOV    A,C
  861.     CPI    0CH    ;FF CHAR
  862.     RZ        ;RETURN IF FF
  863. LSTLP:    IN    LSTAT
  864.     ANI    LMASK
  865.     JRNZ    LSTLP
  866.     MOV    A,C    ;GET CHAR
  867.     OUT    LDATA
  868.     RET
  869. ;
  870. ;
  871.     IF    ADM3A
  872. ;  ---------------------------------------------------------
  873. ;  ADM-3A DRIVER THIS CODE SIMULATES THE CLEAR TO END OF LINE
  874. ;  AND CLEAR TO END OF SCREEN FUNCTIONS FOR THE ADM-3A
  875. ;  ---------------------------------------------------------
  876. ;    CHARACTER EQUATES
  877. ;
  878. NULL    EQU    0        ; NULL
  879. OTHER    EQU    0        ; NULL CHARACTER
  880. HOMCRT    EQU    30        ; HOME CURSOR
  881. RIGHT    EQU    12        ; MOVE RIGHT 1 SPACE
  882. LEFT    EQU    8        ; MOVE LEFT 1 SPACE
  883. UP    EQU    11        ; MOVE UP 1 ROW
  884. DOWN    EQU    10        ; MOVE DOWN 1 ROW
  885. CR    EQU    13        ; CARRIAGE RETURN
  886. EOLN    EQU    28        ; CLEAR TO END OF LINE
  887. EOSN    EQU    25        ; CLEAR TO END OF SCREEN
  888. ERASE    EQU    26        ; ERASE SCREEN
  889. SETXY    EQU    29        ; SET X-Y CURSOR ADDRESS
  890. TAB    EQU    9        ; HORIZONTAL TAB
  891. CTLF    EQU    6        ; FLUSH CHARS TO SCREEN (TOGGLE)
  892. CTLS    EQU    19        ; FREEZE CRT (TOGGLE)
  893.  
  894. ;
  895. ;    CODES FOR CURSOR ACTION CONTROL TABLE (TBL1)
  896. ;
  897. DCOL    EQU    0        ; COL = COL-1
  898. ECOL    EQU    1        ; COL = COL
  899. ICOL    EQU    2        ; COL = COL + 1
  900. ZCOL    EQU    3        ; COL = 0
  901.  
  902.  
  903. ;
  904. ;    CONSOLE CHARACTER INPUT ROUTINE
  905. ;
  906. CIN:    XRA    A
  907.     STA    FFLG        ; RESET FLUSH FLAG
  908.     JMP    CONIN        ; GO TO CONSOLE INPUT
  909.  
  910.  
  911.  
  912. ;
  913. ;    CONSOLE OUTPUT DRIVER FOR PASCAL SYSTEM
  914. ;
  915. COUT:    PUSH    H        ; SAVE ENVIRONMENT
  916.     PUSH    D
  917.     PUSH    B
  918.     LDA    COL
  919.     MOV    E,A        ; E = CURRENT COLUMN ADDRESS
  920.     LXI    H,XYFLG
  921.     MOV    A,M
  922.     ORA    A
  923.     JRZ    COUT1        ; JUMP IF NOT PROCESSING X-Y CURSOR
  924.     DCR    M
  925.     JRNZ    DOROW        ; ROW ADDRESS
  926.     MOV    A,C        ; GET NEW COL POSITION
  927.     SUI    32        ; REMOVE ASCII BIAS
  928.     MOV    E,A        ; UPDATE COL POSITION
  929. DOXY:    CALL    CONOUT        ; POSITION CURSOR
  930.     JR    EXIT0
  931. DOROW:    MOV    A,C        ; ROW INDEX
  932.     SUI    32        ; ASCII BIAS
  933.     CPI    24        ; LIMIT
  934.     JM    DOROW1        ; DO NOT ALLOW SCREEN WRAP AROUND
  935.     MVI    C,'7'        ; ROW 23
  936.     MVI    A,23
  937. DOROW1:    STA    ROW        ; SAVE ROW INDEX
  938.     JR    DOXY
  939. ;
  940. COUT1:    PUSH    B        ; SAVE CHARACTER
  941.     MOV    A,C
  942.     LXI    H,CTBLND
  943.     LXI    B,CTBLSZ
  944.     CCDR            ; SEARCH CHARACTER TABLE
  945.     LXI    H,TBL1
  946.     DAD    B        ; H/L =ADR IN CHARACTER ACTION TABLE
  947.     MOV    A,M        ; A = ACTION BYTE
  948.     ANI    3
  949.     DCR    A
  950.     CPI    ZCOL-1        ; ZERO COLUMN IF NECESSARY
  951.     JRNZ    YC1
  952.     XRA    A
  953.     MOV    E,A
  954. YC1:    ADD    E        ; ADD IN COLUMN OFFSET
  955.     MOV    E,A
  956.     LXI    H,TBL2
  957.     DAD    B
  958.     DAD    B
  959.     MOV    A,M
  960.     INX    H
  961.     MOV    H,M
  962.     MOV    L,A        ; H/L = ADR OF PROCESSING ROUTINE FOR CHARACTER
  963.     POP    B        ; CHAR RESTORED TO C REG
  964.     PCHL            ; BYE
  965. ;
  966. ;    PROCESS X-Y CURSOR POSITIONING REQUEST
  967. ;
  968. GOXY:    LXI    H,XYFLG
  969.     MVI    M,2        ; COUNT FOR X, Y ADR BYTES
  970.     MVI    C,1BH        ; ESCAPE
  971.     CALL    CONOUT
  972.     MVI    C,'='        ; ESCAPE EQUALS SEQUENCE LOADS CURSOR
  973.     JR    PUT
  974. ;
  975. ;    PROCESS TAB EXPANSION TO BLANKS
  976. ;
  977. TABOUT:    MVI    C,RIGHT
  978. XT0:    CALL    CONOUT
  979.     INR    E        ; INCREMENT COL, STOP AT NEXT TAB STOP
  980.     MOV    A,E
  981.     ANI    7
  982.     JRNZ    XT0
  983.     JR    EXIT0
  984. ;
  985. ;    OUTPUT CHAR IN C WITH ROW PROCESSING
  986. ;
  987. PUTH:    XRA    A        ; ZERO
  988.     JR    PUTLF1        ; ROW ZERO FOR HOME
  989. PUTRLF:    LDA    ROW
  990.     DCR    A        ; DECR ROW INDEX
  991.     JP    PUTRLF1
  992.     XRA    A        ; SET ROW TO ZERO IF PAST TOP OF SCREEN
  993. PUTRLF1:JR    PUTLF1
  994. PUTLF:    LDA    ROW
  995.     INR    A        ; INCR ROW INDEX
  996.     CPI    24        ; MAX ROW IS 23
  997.     JM    PUTLF1
  998.     MVI    A,23
  999. PUTLF1:    STA    ROW        ; SAVE ROW INDEX
  1000. ;
  1001. ;    OUTPUT CHAR IN REG C
  1002. ;
  1003. PUT:    CALL    CONOUT
  1004. ;
  1005. ;    TEST AND UPDATE COL POSITION FROM REG E
  1006. ;
  1007. EXIT0:    MOV    A,E
  1008.     ORA    A        ;CHECK IF MOVED TO HIGHER LINE
  1009.     JP    YE0
  1010.     XRA    A        ;FORM CURSOR ADDR 0..79
  1011. YE0:    CPI    80        ;CHECK IF MOVED TO LOWER LINE
  1012.     JRC    XE1
  1013.     MVI    A,79        ; NO AUTO LINE FEED
  1014. XE1:    STA    COL        ; SAVE COL ADDRESS
  1015. ;
  1016. ;    RESTORE REGISTERS AND EXIT
  1017. ;
  1018. EXIT1:    POP    B
  1019.     POP    D
  1020.     POP    H
  1021.     MOV    A,C
  1022.     RET
  1023. ;
  1024. ;
  1025. RESET:    CALL    CLRLN        ; CALL CLEAR TO END OF LINE
  1026.     JR    EXIT0
  1027. ;
  1028. CLRLN:    MVI    C,' '        ; SPACE TO CLEAR END OF LINE
  1029.     MVI    A,80        ; COL LIMIT
  1030.     SUB    E
  1031.     JRZ    XR1        ; CONTINUE IF COL 80
  1032.     MOV    B,A        ; SPACE COUNT TO B
  1033. XR0:    CALL    CONOUT        ; PRINT A SPACE
  1034.     DJNZ    XR0        ; LOOP TILL END OF LINE
  1035. XR1:    MVI    C,0DH
  1036.     CALL    CONOUT        ; REPOSITION CURSOR ON ORIGINAL LINE
  1037.     MVI    C,RIGHT        ; FORWARD SPACE
  1038.     MOV    B,E        ; COL POSITION TO B
  1039.     MOV    A,B
  1040.     ORA    A
  1041.     RZ            ; EXIT IF AT COL 0
  1042. XR2:    CALL    CONOUT
  1043.     DJNZ    XR2        ; FORWARD SPACE TILL BACK TO ORIG POSITION
  1044.     RET
  1045. ;
  1046. ;    CLEAR TO END OF SCREEN 
  1047. ;
  1048. CLRS:    CALL    CLRLN        ; CLEAR TO END OF FIRST LINE
  1049.     LXI    H,ROW        ; POINT TO ROW INDEX
  1050.     MVI    A,23        ; ROW LIMIT
  1051.     SUB    M        ; SUBTRACT ROW INDEX
  1052.     JZ    EXIT0        ; EXIT IF ALREADY ON LAST ROW
  1053.     MOV    B,A        ; COUNT OF ROWS TO CLEAR
  1054.     MVI    C,0DH        ; CARRIAGE RET
  1055.     CALL    CONOUT        ; PRINT IT
  1056.     MOV    C,E        ; SAVE COL INDEX IN C
  1057.     MVI    E,0        ; SET COL TO ZERO
  1058. CLRS2:    PUSH    B        ; SAVE INDICES
  1059.     MVI    C,0AH        ; LINE FEED
  1060.     CALL    CONOUT
  1061.     CALL    CLRLN        ; CLEAR THE LINE
  1062.     POP    B        ; RESTORE INDICES
  1063.     DJNZ    CLRS2        ; LOOP TILL B IS ZERO
  1064.     MOV    E,C        ; RESTORE COL INDEX
  1065.     MVI    C,1BH        ; ESCAPE
  1066.     CALL    CONOUT
  1067.     MVI    C,'='        ; EQUALS
  1068.     CALL    CONOUT
  1069.     LDA    ROW
  1070.     MOV    C,A
  1071.     CALL    CONOUT        ; PRINT ROW
  1072.     MOV    A,E        ; COL INDEX
  1073.     ADI    32        ; ASCII BIAS
  1074.     MOV    C,A
  1075.     CALL    CONOUT        ; PRINT COL
  1076.     JMP    EXIT0
  1077. ;
  1078. ;    SPECIAL CHARACTER TABLE
  1079. ;
  1080. CHRTBL:    DB    OTHER        ; NON-SPECIAL CHARACTER
  1081.     DB    NULL        ; NULL CHARACTER
  1082.     DB    HOMCRT        ; HOME CURSOR
  1083.     DB    RIGHT        ; MOVE CURSOR RIGHT 1 SPACE
  1084.     DB    LEFT        ; MOVE CURSOR LEFT 1 SPACE
  1085.     DB    UP        ; MOVE CURSOR UP 1 SPACE
  1086.     DB    DOWN        ; MOVE CURSOR DOWN 1 SPACE
  1087.     DB    CR        ; CARRIAGE RETURN
  1088.     DB    EOLN        ; ERASE TO END OF LINE
  1089.     DB    EOSN        ; ERASE TO END OF SCREEN
  1090.     DB    ERASE        ; ERASE SCREEN, HOME CURSOR
  1091.     DB    SETXY        ; SET CURSOR ADDRESS
  1092. CTBLND:    DB    TAB        ; MOVE TO NEXT TAB STOP
  1093. CTBLSZ    EQU    $-CHRTBL    ; NUMBER OF ENTRIES IN TABLE
  1094. ;
  1095. ;    CURSOR MOTION AND LEAD IN TABLE
  1096. ;
  1097. TBL1:    DB    ICOL        ; NOTHING SPECIAL
  1098.     DB    ECOL        ; NULL
  1099.     DB    ZCOL        ; HOME
  1100.     DB    ICOL        ; RIGHT
  1101.     DB    DCOL        ; LEFT
  1102.     DB    ECOL        ; UP
  1103.     DB    ECOL        ; DOWN
  1104.     DB    ZCOL        ; CR
  1105.     DB    ECOL        ; EOLN
  1106.     DB    ECOL        ; EOSN
  1107.     DB    ZCOL        ; ERASE
  1108.     DB    ECOL        ; SET X-Y ADDRESS
  1109.     DB    ECOL        ; TAB (PROCESSING ROUTINE HANDLES COLUMN)
  1110. ;
  1111. ;    CHARACTER DISPATCH TABLE
  1112. ;
  1113. TBL2:    DW    PUT        ; NON-SPECIAL CHARACTER
  1114.     DW    PUT        ; NULL
  1115.     DW    PUTH        ; HOME
  1116.     DW    PUT        ; RIGHT
  1117.     DW    PUT        ; LEFT
  1118.     DW    PUTRLF        ; UP
  1119.     DW    PUTLF        ; DOWN
  1120.     DW    PUT        ; CR
  1121.     DW    RESET        ; EOLN
  1122.     DW    CLRS        ; EOSN
  1123.     DW    PUTH        ; ERASE
  1124.     DW    GOXY        ; SET X-Y ADDRESS
  1125.     DW    TABOUT        ; TAB
  1126. ;
  1127. ;    STORAGE LOCATIONS
  1128. ;
  1129. COL:    DB    0        ; CURRENT COLUMN
  1130. ROW:    DB    0        ; CURRENT ROW
  1131. FFLG:    DB    0        ; FLUSH FLAG
  1132. XYFLG:    DB    0        ; X-Y FLAG (INITIALLY RESET)
  1133. ATOGL:    DB    20H        ; UPPER-LOWER CASE TOGGLE ON ^A
  1134. PFLG:    DB    0        ; PRINT (ECHO) FLAG
  1135.  
  1136. CONST:    IN    3
  1137.     ANI    2
  1138.     RZ
  1139.     MVI    A,0FFH
  1140.     RET
  1141.  
  1142. CONIN:    IN    3
  1143.     ANI    2
  1144.     JRZ    CONIN
  1145.     IN    2
  1146.     ANI    7FH    ; REMOVE PARITY BIT
  1147.     CPI    1    ; CONTROL A
  1148.     JRNZ    CONIN4
  1149.     LDA    ATOGL    ; TOGGLE LOWER CASE SWITCH
  1150.     XRI    20H
  1151.     STA    ATOGL
  1152.     MVI    A,1    ; RETURN A CONTROL A
  1153.     RET
  1154. CONIN4:    MOV    C,A    ; SAVE CHAR IN C
  1155.     CPI    61H    ; LOWER CASE A
  1156.     JM    CONIN6    ; EXIT IF < A
  1157.     CPI    7BH    ; LOWER CASE Z + 1
  1158.     JP    CONIN6    ; EXIT IF > Z
  1159.     LDA    ATOGL    ; LOAD LOWER CASE SWITCH
  1160.     XRA    C    ; EXCLUSIVE OR WITH CHAR
  1161.     RET
  1162. CONIN6:    MOV    A,C    ; RESTORE CHAR TO A
  1163.     RET
  1164.  
  1165. CONOUT:    IN    3
  1166.     ANI    1
  1167.     JRZ    CONOUT
  1168.     MOV    A,C    ; GET OUTPUT CHAR
  1169.     OUT    2
  1170.     RET
  1171.     ENDIF
  1172. ;
  1173.     IF    SOROC
  1174. ; ************************************************************
  1175. ;
  1176. ; SOROC AND OTHER TERMINALS NOT REQUIRING COMPLEX SOFTWARE 
  1177. ; DRIVERS USE THIS CODE
  1178. ;
  1179. ; *************************************************************
  1180. ;
  1181. ;   ---- READ A CHARACTER FROM KEYBOARD ----
  1182. CIN:    IN    TSTAT    ;READ STATUS
  1183.     ANI    IMSK01
  1184.     JRZ    CIN
  1185.     IN    PORT01    ;GET CHAR
  1186.     ANI    7FH    ;REMOVE BIT 7
  1187.     RET
  1188. ;   ----- WRITE CHARACTER IN REG C TO SOROC TERMINAL  -----
  1189. ;
  1190. COUT:    LDA    UNIT
  1191.     CPI    06H
  1192.     JRZ    LIST
  1193.     MOV    A,C
  1194.     CPI    CR    ;IS IT A CR
  1195.     JRZ    CURET    ;YES,THEN CHECK IF TO FREEZE VIDEO
  1196. CHOUT:    IN    TSTAT    ; GIVE CHAR TO TERMINAL
  1197.     ANI    OMSK01
  1198.     JRZ    CHOUT    ;WAIT FOR 8251
  1199.     MOV    A,C    ;GET CHAR
  1200.     OUT    PORT01
  1201.     RET
  1202. ;
  1203. ; CARRAGE RETURN- CHECK IF CRT IS TO BE STOPPED - CTRL S
  1204. ;
  1205. CURET:    IN    TSTAT
  1206.     ANI    IMSK01
  1207.     JRZ    CHOUT
  1208.     IN    PORT01
  1209.     ANI    7FH
  1210.     CPI    CTRLS
  1211.     JRNZ    CHOUT
  1212. CRLOOP    CALL    CIN
  1213.     CPI    CTRLS
  1214.     JRZ    CHOUT
  1215.     JR    CRLOOP
  1216.     ENDIF
  1217. ;
  1218. ;************************************************************
  1219. ;
  1220. ;   DISK DRIVERS     TARBELL AND DELTA CONTROLLERS
  1221. ;
  1222. ;************************************************************
  1223. ;
  1224. ;   ----- SELECT DISK ,NUMBER IN REG. C -----
  1225. ;
  1226. SELDSK:    MOV    A,C        ;GET NEW DISK NUMBER.
  1227.     ANI    3        ;ONLY LOOK AT 2 LSBS
  1228.     MOV    C,A
  1229.     LDA    DSKDR        ;CURRENTLY SELECTED DRIVE
  1230.     CMP    C        ;COMPARE WITH NEW DRIVE
  1231.     RZ            ;IF SAME, RETURN.
  1232.     LDA    NUMDSK        ;NUMBER OF DRIVES ON LINE
  1233.     DCR    A        ;SUBTRACT 1 TO GET MAXIMUM DR CODE
  1234.     CMP    C        ;NEWDRIVE > NUMDISKS ?
  1235.     JP    SELMOR
  1236. ;
  1237. ;IO ERROR EXIT FOR UNRECOVERABLE IO ERRORS,SET ERROR FLAG
  1238. ;
  1239. IOERR:    MVI    A,4        ;DISK ERROR FLAG
  1240.     STA    ERRFLG        ;PUT IN FLAG
  1241.     RET
  1242. ;
  1243.     IF    PERSCI        ;DON'T UPDATE TRACK POSITION, SAME FOR ALL
  1244. SELMOR:    MOV    A,C        ;NEW DRIVE NO
  1245.     STA    DSKDR        ;SAVE IT
  1246.     CALL    INDEX        ;POINT TO DRIVE PARAMETERS
  1247.     ELSE
  1248. SELMOR:    LDA    DSKDR        ;UP DATE TRACK TABLE
  1249.     CALL    INDEX        ;FIND TABLE ENTRY FOR DRIVE PARAMETERS
  1250.     IN    TRACK
  1251.     MOV    M,A        ;SAVE IT IN TABLE
  1252.     MOV    A,C        ;GET NEW DRIVE
  1253.     STA    DSKDR        ;SAVE IN DISKDR
  1254.     CALL    INDEX        ;FIND PARAMETERS FOR NEW DRIVE
  1255.     MOV    A,M        ;GET LAST TRACK POSITION
  1256.     OUT    TRACK        ;UPDATE 1791 TRACK REGISTER
  1257.     ENDIF
  1258. ;
  1259.     IF    DELTA        ;(1791)
  1260.     INX    H        ;POINT TO DENSITY
  1261.     CALL    SELECT        ;DRIVE NO IS IN C
  1262.     CALL    DENSEL        ;SELECT IT AND SET SECLEN
  1263.     MOV    A,M        ;GET DENSITY CODE 
  1264.     CPI    1        ;IS IT DOUBLE
  1265.     RZ            ;RETURN IF DOUBLE
  1266.     ENDIF
  1267. ;
  1268.     IF    TARBELL        ;(1791)
  1269.     INX    H        ;POINT TO DENSITY
  1270.     CALL    SELECT        ;SELECT BOTH DRIVE AND DENSITY FOR TARBELL
  1271.     ORA    A        ;A CONTAINS A ZERO IF SINGLE DENSITY
  1272.     RNZ            ;RETURN IF DOUBLE DENSITY
  1273.     ENDIF
  1274. ;
  1275.     IF    NOT DELTA AND NOT TARBELL    ;(1771)
  1276.     CALL    SELECT
  1277.     ENDIF
  1278. ;
  1279.     CALL    TIME        ;ALLOW STEPPER SETTLE TIME
  1280.     CALL    IDREAD
  1281.     LDA    IDTAB3        ;SECTOR LENGTH CODE FROM ADDR FIELD
  1282.     STA    SECLEN
  1283.     MVI    A,8        ;512 BYTE SECTORS SINGLE DENSITY
  1284.     STA    NUMSEC        ;SET IT
  1285.     RET
  1286. ;
  1287. ;
  1288. ;  INDEX PUTS ADDR OF START OF DISK DRIVE PARAMETER BLOCK IN HL
  1289. ;  INDEX IS CALLED WITH THE DRIVE NUMBER IN A
  1290. ;
  1291. INDEX:    LXI    H,TRKTBL
  1292.     MOV    E,A        ;SAVE A COPY OF REG A
  1293.     ADD    A        ;FIGURE OFFSET INTO TABLE
  1294.     ADD    E
  1295.     MOV    E,A        ;ADD OFFSET TO BASE
  1296.     MVI    D,00
  1297.     DAD    D
  1298.     RET
  1299. ;
  1300. ;  SELECT WILL SELECT THE DISK IN C FOR APPROPRIATE CONTROLLER
  1301. ;
  1302.     IF    DELTA        ;(1791)
  1303. SELECT:    MOV    A,C        ;DRIVE NO TO A
  1304.     CMA            ;COMPLIMENT IT
  1305.     OUT    DCONT        ;ISSUE COMMAND
  1306.     RET
  1307.     ENDIF
  1308. ;
  1309.     IF    TARBELL        ;(1791)
  1310. SELECT:    MOV    A,M        ;PICK UP DENSITY CODE
  1311.     ADD    A
  1312.     ADD    A
  1313.     ADD    A        ;SHIFT LEFT 3 BITS
  1314.     ANI    8        ;MASK OFF TARBELL DD BIT
  1315.     MOV    B,A        ;SAVE IN B FOR LATER
  1316.     MOV    A,C        ;GET DRIVE NUMBER
  1317.     ADD    A
  1318.     ADD    A
  1319.     ADD    A
  1320.     ADD    A        ;SHIFT LEFT 4
  1321.     ORA    B        ;ADD IN THE SINGLE/DOUBLE DENSITY BIT
  1322.     OUT    DCONT        ;ISSUE COMMAND
  1323.     MOV    A,B        ;GET BACK DENSITY BIT
  1324.     ORA    A        ;CHECK FOR ZERO (SINGLE DENSITY)
  1325.     RZ
  1326.     MVI    A,2        ;IF NOT SET SECLEN AND NUMSEC
  1327.     STA    SECLEN
  1328.     MVI    A,16
  1329.     STA    NUMSEC        ;16 SECTORS PER TRACK DOUBLE DENSITY
  1330.     RET
  1331.     ENDIF
  1332. ;
  1333.     IF    NOT DELTA AND NOT TARBELL    ;(1771)
  1334. SELECT:    MOV    A,C        ;GET DRIVE NO
  1335.     CMA            ;COMPLIMENT IT
  1336.     ADD    A
  1337.     ADD    A
  1338.     ADD    A
  1339.     ADD    A        ;SHIFT LEFT FOUR
  1340.     ORI    02H
  1341.     STA    LATCH        ;SAVE IN LATCH
  1342.     OUT    DCONT        ;ISSUE COMMAND
  1343.     RET
  1344.     ENDIF
  1345. ;
  1346. ;  DENSEL SELECTS DENSITY, CODE IN (HL) 1=DOUBLE DENSITY 2=SINGLE DENSITY
  1347. ;
  1348.     IF    DELTA
  1349. DENSEL:    MOV    A,M        ;GET THE DENSITY CODE
  1350. DENSEL1:OUT    WAIT+1        ;SENT CODE TO DENSITY PORT
  1351.     CPI    2        ;IS IT SINGLE DENSITY
  1352.     RZ            ;IF SO RETURN
  1353.     MVI    A,2        ;IF NOT SET SECLEN AND NUMSEC
  1354.     STA    SECLEN
  1355.     MVI    A,16
  1356.     STA    NUMSEC        ;16 SECTORS PER TRACK DOUBLE DENSITY
  1357.     RET
  1358.     ENDIF
  1359. ;
  1360. ;
  1361. ;READ  READ THE SECTOR IN (SECT),FROM PRESENT TRACK
  1362. ;USE STARTING ADDRESS IN (DMAADD).
  1363. ;
  1364. READ:    MVI    A,RTCNT
  1365. RRETRY:    STA    ERCNT    ;STORE IN ERROR CTR.
  1366.     MVI    A,0D0H
  1367.     OUT    DCOM    ;INTERRUPT CONTROLLER
  1368.     LXI    H,RDDONE
  1369.     PUSH    H    ;SET UP RETURN ADDR
  1370.     LHLD    DMAADD    ;GET STARTING ADR.
  1371.     LDED    ULEN    ;BYTES TO DO
  1372.     MVI    C,DDATA    ;DISK DATA PORT
  1373.     XTHL
  1374.     XTHL        ;SHORT DELAY
  1375.     IN    DSTAT    ;READ STATUS.
  1376.     ANI    20H    ;LOOK AT HLD BIT.
  1377.     LDA    SECT    ;GET SECTOR NUMBER.
  1378.     OUT    SECTP    ;SET SECTOR INTO 1771.
  1379.     MVI    A,8CH    ;READ WITH HEAD LOAD
  1380.     JRZ    READE    ;HEAD NOT LOADED.
  1381.     MVI    A,88H    ;CODE FOR READ W/O HD LD.
  1382. READE:    OUT    DCOM    ;SEND COMMAND TO 1771.
  1383. RLOOP:    IN    WAIT    ;WAIT FOR DRQ OR INTRQ.
  1384.     ORA    A        ;SET FLAGS.
  1385.     RP        ;DONE IF INTRQ.
  1386.     INI        ;READ FROM DISK INTO (HL)
  1387.     DCX    D    ;DECREASE BYTE COUNTER
  1388.     MOV    A,D    ;AND CHECK FOR 0
  1389.     ORA    E
  1390.     JNZ    RLOOP    ;KEEP READING
  1391.     POP    B    ;FIX UP STACK
  1392. RDLP02:    CALL    BUSY
  1393.     ANI    18H
  1394.     JRNZ    CHECK
  1395.     RET
  1396. RDDONE:    IN    DSTAT    ;READ DISK STATUS
  1397.     ANI    9DH    ;LOOK AT ERROR BITS.
  1398.     RZ        ;RETURN IF NONE.
  1399. CHECK:    CALL    ERCHK    ;CHECK FOR SEEK ERROR.
  1400.     LDA    ERCNT    ;GET ERROR COUNT.
  1401.     DCR    A    ;DECREMENT COUNT.
  1402.     JRNZ    RRETRY    ;TRY TO READ AGAIN.
  1403.     JMP    IOERR    ;READ DISK ERROR
  1404. ;
  1405. ;ERROR CHECK  CHECK FOR RECORD NOT FOUND ERROR,AND SEEK TO
  1406. ;CORRECT TRACK IF REQUIRED.
  1407. ;
  1408. ERCHK:    ANI    10H
  1409.     RZ        ;NOT SEEK ERROR
  1410.     CALL    IDREAD    ;READ TRACK ADDRESS
  1411.     LDA    IDTAB
  1412.     MOV    C,A    ;SAVE TRACK
  1413.     IN    TRACK    ;CHECK 1771 TRACK REG
  1414.     CMP    C    ;IF SAME,NO ERROR
  1415.     RZ
  1416.     MOV    A,C    ;PUT CORRECT TRACK IN 1771
  1417.     OUT    TRACK
  1418.     LDA    TRK    ;GET TRACK WANTED
  1419.     MOV    C,A
  1420.     CALL    SEEK    ;AND GO TO IT
  1421.     RET
  1422. ;
  1423. ;WRITE  WRITE THE SECTOR IN (SECT),FROM PRESENT TRACK
  1424. ;USE STARTING ADDRESS IN (DMAADD)
  1425. ;
  1426. WRITE:    MVI    A,RTCNT
  1427. WRETRY:    STA    ERCNT    ;STORE IN ERROR COUNTER.
  1428.     MVI    A,0D0H    ;CAUSE INTERUPT
  1429.     OUT    DCOM
  1430.     LXI    H,WDONE
  1431.     PUSH    H    ;SET UP RETURN ADDR
  1432.     LHLD    DMAADD    ;GET STARTING ADR
  1433.     LDED    ULEN    ;BYTES TO DO
  1434.     MVI    C,DDATA    ;DISK DATA PORT
  1435.     XTHL
  1436.     XTHL        ;SHORT DELAY
  1437.     IN    DSTAT    ;GET 1771 STATUS.
  1438.     ANI    20H    ;CHECK FOR HEAD LOAD.
  1439.     LDA    SECT    ;GET SECTOR NUMBER.
  1440. WRITE1:    OUT    SECTP    ;SET THE SECTOR INTO 1771.
  1441.     MVI    A,0ACH    ;SET UP 1771 FOR WRITE.
  1442.     JRZ    WRITE2    ;HEAD IS NOT LOADED
  1443.     MVI    A,0A8H    ;CODE FOR WRITE W/O HD LD.
  1444. WRITE2:    OUT    DCOM
  1445. WLOOP:    IN    WAIT    ;WAIT FOR READY.
  1446.     ORA    A    ;SET FLAGS.
  1447.     RP        ;HOP OUT WHEN DONE.
  1448.     OUTI        ;WRITE TO DISK FROM (HL)
  1449.     DCX    D    ;DECREASE BYTE COUNTER
  1450.     MOV    A,D    ;AND CHECK FOR 0
  1451.     ORA    E
  1452.     JNZ    WLOOP    ;KEEP WRITING.
  1453.     POP    B    ;FIX UP STACK
  1454. WRT02:    CALL    BUSY
  1455.     ANI    18H    ;DONT LOOK AT LOST DATA BIT
  1456.     JRNZ    PROCER
  1457.     RET
  1458. WDONE:    IN    DSTAT    ;READ DISK STATUS.
  1459.     ANI    0FDH    ;LOOK AT THESE BITS.
  1460.     RZ        ;RETURN IF NO ERRORS
  1461. PROCER:    CALL    ERCHK    ;CHECK/CORRECT SEEK ERROR
  1462.     LDA    ERCNT    ;GET ERROR COUNT.
  1463.     DCR    A    ;DECREMENT COUNT.
  1464.     JNZ    WRETRY    ;TRY TO WRITE AGAIN.
  1465.     JMP    IOERR    ;WRITE DISK ERROR
  1466. ;
  1467. ;HOME  MOVES HEAD TO TRACK ZERO.USES RESTORE COMMAND,NO HDL
  1468. ;
  1469. HOME:    MVI    A,0D0H        ;CAUSE INTERUPT
  1470.     OUT    DCOM    
  1471.     CALL    BUSY
  1472.     MVI    A,01H        ;RESTORE,NO HDL,NO VERIFY
  1473.     OUT    DCOM
  1474.     CALL    BUSY
  1475.     IN    DSTAT
  1476.     ANI    04H        ;MAKE SURE IT'S HOMED
  1477.     JRZ    HOME
  1478.     RET
  1479. ;
  1480. ;
  1481. ;SET TRACK  CHECK IF TRACK IN REG C IS EQUAL TO PRESENT
  1482. ;TRACK,AND MOVE TO NEW TRACK IF NOT.
  1483. ;CALLABLE ROUTINES:
  1484. ;SEEK:MOVES HEAD TO TRACK IN REG A
  1485. ;
  1486. SETTRK:    IN    TRACK
  1487.     MOV    B,A        ;SAVE PRESENT TRACK IN B
  1488.     CMP    C        ;COMPARE WITH NEW TRACK
  1489.     RZ            ;GO BACK IF SAME
  1490. ;
  1491.     IF    NOT PERSCI
  1492.     MOV    A,C        ;MOVE TRACK TO SEEK TO 
  1493. SEEK:    OUT    DDATA
  1494.     STA    TRK        ;DO UPDATING WHILE WAITING FOR 1791
  1495.     CALL    BUSY        ;WAIT UNTIL 1791 NOT BUSY
  1496.     MVI    A,18H+STEP
  1497.     OUT    DCOM        ;SEEK COMMAND,NO VERIFY,WITH HDL
  1498.     IN    WAIT
  1499.     RET
  1500.     ENDIF
  1501. ;
  1502.     IF    PERSCI
  1503. SEEK:    MVI    A,48H+STEP    ;STEP IN WITH HEAD LOAD
  1504.     JC    SDIR        ;STEP IN IF MINUS
  1505.     MVI    A,68H+STEP    ;STEP OUT WITH HEAD LOAD
  1506. SDIR:    OUT    DCOM        ;ISSUE STEP COMMAND
  1507.     MVI    A,20
  1508. DLOOP:    DCR    A        ;SHORT DELAY LOOP
  1509.     JNZ    DLOOP
  1510.     MOV    A,B        ;GET PRESENT TRACK
  1511.     SUB    C        ;CALC REQUIRED NUMBER OF STEPS
  1512.     JP    STEP0        ;CHECK PLUS OR MINUS
  1513.     CMA            ;COMPLIMENT IF MINUS
  1514.     INR    A        ;TWO'S COMP
  1515. STEP0:    MOV    B,A        ;STEPS TO B
  1516.     MVI    A,1        ;PERSCI STEP COMMAND
  1517. STEP1:    OUT    DCONT        ;ISSUE PERSCI STEP
  1518.     DCR    B        ;COUNT DOWN NO OF STEPS
  1519.     JNZ    STEP1        ;LOOP TILL STEPS DOWN TO ZERO
  1520.     IN    WAIT        ;CLEAR 1791
  1521.     IN    DSTAT        ;READ STATUS
  1522.     MOV    A,C        ;GET DESTINATION TRACK
  1523.     OUT    TRACK        ;UPDATE TRACK REGISTER
  1524.     LDA    LATCH        ;SELECT LATCH CODE
  1525.     ANI    72H        ;MAKE SEEK COMPLETE COMMAND
  1526.     OUT    DCONT        ;ISSUE IT
  1527.     IN    WAIT        ;WAIT TILL SEEK COMPLETE
  1528.     LDA    LATCH        ;GET BACK LATCH
  1529.     OUT    DCONT        ;RESTORE OLD LATCH CODE
  1530.     RET
  1531.     ENDIF
  1532. ;
  1533. ;BUSY  CHECKS 1791 FOR BUSY,RETURNS WHEN NOT BUSY
  1534. ;
  1535. BUSY:    MVI    A,6        ;ALLOW 12 MICRO SEC SETTLE TIME
  1536. BUSY1:    DCR    A
  1537.     JNZ    BUSY1
  1538. BUSY2:    IN    DSTAT        ;GET 1791 STATUS
  1539.     RRC            ;CHECK BIT 0
  1540.     JC    BUSY2        ;not done, continue
  1541.     RAL            ;PUT BITS BACK
  1542.     RET
  1543. ;
  1544. ; DELAY LOOP,APPROX 1.8 MILL/SEC  ALLOW TIME FOR DRIVE TO SETTLE
  1545. ;
  1546. TIME:    LXI    B,2000H
  1547. DEL:    DCX    B
  1548.     MOV    A,B
  1549.     ORA    C
  1550.     JRNZ    DEL
  1551.     RET
  1552. ;
  1553. ;
  1554. ;ID READ  READS THE ID FIELD ON CURRENT TRACK,AND PUTS DATA
  1555. ;INTO IDTAB. USED TO DETERMINE SECTOR LENGTH,AND CURRENT TRACK
  1556. ;
  1557. IDREAD:    IN    TRACK
  1558.     ORA    A        ;MAY HAVE DIFFERENT FORMAT
  1559.     JRNZ    IDRD00
  1560.     INR    A        ;MOVE TO TRACK 1
  1561.     CALL    SEEK
  1562. IDRD00:    MVI    A,RTCNT
  1563. IDRD01:    STA    IDECNT
  1564.     MVI    A,0D0H
  1565.     OUT    DCOM
  1566.     LXI    H,IDTAB
  1567.     CALL    BUSY
  1568.     MVI    A,0C4H        ;READ ADDRESS COMMAND
  1569.     OUT    DCOM
  1570. IDRD02:    IN    WAIT        ;WAIT FOR DATA OR INTER
  1571.     ORA    A
  1572.     JP    IDRD03
  1573.     IN    DDATA
  1574.     MOV    M,A        ;PUT BYTE IN TO TABLE
  1575.     INX    H
  1576.     JMP    IDRD02
  1577. IDRD03:    IN    DSTAT
  1578.     ANI    08H
  1579.     RZ
  1580.     LDA    IDECNT
  1581.     DCR    A
  1582.     JRNZ    IDRD01        ;TRY AGAIN
  1583.     JMP    IOERR        ;ID READ ERROR
  1584.  
  1585.  
  1586. IDECNT:    DB    0        ;RETRY COUNTER
  1587. IDTAB:    DB    0
  1588. IDTAB1:    DB    0        ;ZERO
  1589. IDTAB2:    DB    0        ;SECTOR ADDRESS
  1590. IDTAB3:    DB    0
  1591. IDTAB4:    DB    0        ;CRC
  1592. IDTAB5:    DB    0        ;CRC
  1593. ;
  1594.          END
  1595.