home *** CD-ROM | disk | FTP | other *** search
- TITLE 'MBIOS - N* DD CP/M 2.2 MODEM BIOS OF 05/02/82'
- ; PAGE 44
- ;
- ; These routines copyright (c) 1980, 1981, 1982 by Steve Bogolub,
- ; 2338 S. Scoville Ave., Berwyn, IL 60402. Elements of the public
- ; domain program "BYE", based on an original program written by
- ; Dave Jaffe and modified by many others, are incorporated.
- ; This software may be used freely for non-commercial purposes
- ; only, and may not be sold.
- ;
- ;
- ; THIS BIOS IS SPECIALIZED FOR REMOTE MODEM DIALUP
- ; USE. IF THE MEMORY LOCATION "MODEM" CONTAINS A
- ; VALUE OF ZERO WHEN THE COLD BOOT ROUTINE "INIT"
- ; IS ENTERED, A SPECIAL SET OF CONSOLE VECTORS
- ; IS PATCHED OVER THE GENNED-IN SET TO HANDLE THE
- ; PMMI MODEM INSTEAD OF THE NORMAL HORIZON DRIVERS.
- ; AFTER PATCHING THE VECTORS, THE ROUTINES WAIT FOR
- ; THE PHONE TO RING. UPON ANSWERING, THE BAUD RATE
- ; IS SENSED (110, 300, 450, 600, OR 710 BAUD) BY
- ; READING CARRIAGE RETURN OR LINE FEED CODES, THEN
- ; A PASSWORD IS REQUESTED. IF THE PASSWORD IS
- ; CORRECT, CCP AND BDOS ARE WARM BOOTED, AND THE
- ; MODEM TERMINAL CONTROLS THE MACHINE UNTIL CARRIER
- ; IS LOST OR CONTROL IS TRANSFERRED BY A PROGRAM
- ; TO THE MODEM COLD BOOT VECTOR, WHICH HANGS UP
- ; THE PHONE. AT THAT POINT, WE GO BACK TO WAITING
- ; FOR THE PHONE TO RING, AND START OVER AGAIN.
- ;
- ; IF MEMORY LOCATION "MODEM" CONTAINS A NON-ZERO
- ; VALUE, THE NORMAL HORIZON SERIAL DEVICES ARE
- ; USED FOR THE CONSOLE AND A SERIAL PRINTER.
- ;
- ; DISK: NORTH STAR MDS-AD2 DOUBLE DENSITY 5.25"
- ; FLOPPY DISK UNITS 1 AND 2 AS CP/M DRIVES
- ; A: AND B:, SINGLE-SIDED, DOUBLE DENSITY,
- ; 35 OR 40 TRACKS SELECTABLE AT ASSEMBLY
- ; TIME. UNITS 3 AND 4 ARE SUPPORTED AS
- ; CP/M DRIVES C: AND D:, DOUBLE-SIDED,
- ; DOUBLE DENSITY, 80 TRACKS.
- ;
- ; SERIAL I/O: HORIZON LEFT (LOW) SERIAL I/O PORT AS
- ; CP/M DEVICE CRT:
- ;
- ; HORIZON RIGHT (HIGH) SERIAL I/O PORT AS CP/M
- ; DEVICE TTY: WITHOUT DTR SUPPORT, AND REQUIRING
- ; DTR HIGH ON OUTPUT FOR LPT:
- ;
- ; IF "MODEM" IS ZERO, IOBYTE IS NOT SUPPORTED,
- ; AND CON:, LST:, RDR:, AND PCH: ALL USE THE
- ; PMMI MODEM
- ;
- ; SINCE THIS BIOS IS SO LARGE, MOVCPM SHOULD BE
- ; RUN FOR TWO LESS THAN THE DESIRED SYSTEM SIZE
- ; IN K, I.E. SPECIFY 30 FOR A 32K SYSTEM.
- ;
- ; *** IMPORTANT BOOTSTRAP INFO ***
- ;
- ; THIS BIOS IS INTENDED TO RUN IN THE LAST
- ; 3.5K OF MEMORY. THE LAST .5K IS SET ASIDE
- ; FOR A NORTH STAR SECTOR DEBLOCKING BUFFER.
- ; THE FIRST 3K IS GENNED-IN BIOS CODE, AND
- ; IS EXPECTED TO RESIDE ON TRACK 0 OF NORTH
- ; STAR DISK UNIT 1 (A:) IN SECTORS 5-9, AND
- ; 4. THE NORTH STAR BOOT PROM READS IN SECTOR
- ; 4 INTO CONSECUTIVE PAGES OF MEMORY, STARTING
- ; WITH THE PAGE NUMBER SPECIFIED BY THE FIRST
- ; BYTE OF SECTOR DATA, THEN JUMPS TO THAT
- ; ADDRESS + 10 (0AH). THIS BIOS IS SET UP TO
- ; USE THAT METHOD TO COLD BOOT ITSELF. CODE
- ; AT THAT ADDRESS READS THE LAST FIVE SECTORS
- ; OF TRACK ZERO INTO MEMORY AT ADDRESS "BIOS",
- ; THEN JUMPS TO THE BIOS COLD START ADDRESS.
- ;
- ; THERE ARE TWO POSSIBLE CONFIGURATIONS OF
- ; THE SYSTEM. THE NORMAL CONFIGURATION ASSUMES
- ; THAT MEMORY IS CONTIGUOUS, AND IS GENERATED
- ; IN A STRAIGHTFORWARD FASION WITH MOVCPM.
- ; FOR THIS CONFIGURATION, SET THE VARIABLE
- ; "NSHOLE" FALSE, THEN THIS BIOS WILL LOOK
- ; FOR CCP AND BDOS IN THEIR NORMAL LOCATIONS
- ; ON THE SYSTEM TRACKS: TRACK 1, SECTORS 0-9,
- ; AND TRACK ZERO, SECTOR 3 (NORTH STAR PHYSICAL
- ; SECTOR NUMBERS). A HIGHLY ABNORMAL CONFIGURATION
- ; IS POSSIBLE WHERE BDOS IS SPLIT INTO TWO
- ; PIECES, AND WRAPPED AROUND THE NORTH STAR
- ; CONTROLLER. THIS CONFIGURATION IS TOUGH TO
- ; ACHIEVE WITHOUT A HIGHLY INTIMATE KNOWLEDGE
- ; OF THE BDOS SO THAT THE SPLIT CAN BE DONE.
- ; IN THIS CASE, "NSHOLE" IS SET TO TRUE, AND
- ; ALLOWS FULL UTILIZATION OF ALL MEMORY IN
- ; A NORTH STAR MACHINE.
- ;
- ; THE BIOS WARM BOOT EXPECTS THE CCP AND
- ; THE LOW 2K OF BDOS TO RESIDE ON TRACK 1,
- ; SECTORS 0-7 INCLUSIVE, WITH THE REMAINING
- ; 1.5K OF BDOS ON TRACK 0, SECTORS 3, 1, AND
- ; 2, IN THAT ORDER. THIS PECULIAR LAYOUT IS
- ; DUE TO THE 1K "HOLE" IN THE CENTER OF OUR
- ; SPECIAL BDOS WHERE THE NORTH STAR CONTROLLER
- ; FITS. THE HOLE PUSHES THE LAST PART OF
- ; BDOS IN THE NSGEN MEMORY MAP UP INTO THE
- ; AREA USED ON THE STANDARD SYSTEM FOR THE
- ; JADE CONTROLLER CODE, WHICH IS UNUSED HERE.
- ;
- ; WE USE THE Z80 INSTRUCTION "LD A,I" ON ENTRY
- ; TO THE DISK READ AND WRITE ROUTINES TO GET
- ; THE STATUS OF THE INTERRUPT FLIP/FLOP, SINCE
- ; WE MUST DISABLE INTERRUPTS WHILE THE NORTH
- ; STAR DISK READS OR WRITES ARE PERFORMED.
- ; USING THE Z80 STATUS, WE CAN RE-ENABLE
- ; INTERRUPTS AFTER WE LEAVE. THIS CHECK IS
- ; DONE BY THE ROUTINES "INTDI" AND "INDEN",
- ; AND CAN EASILY BE REMOVED IF WE EVER GO
- ; TO A NON-Z80 CPU (NEVER, I HOPE).
- ;
- LDAI EQU 057EDH ;Z80 "LD A,I" BYTE-SWAPPED
- ; FOR "DW" USE
- ;
- FALSE EQU 0
- TRUE EQU NOT FALSE
- ;
- NSHOLE EQU FALSE ;NO HOLE IN BDOS IS STANDARD
- ;
- ; DISK OPERATING SYSTEM ADDRESSES
- ;
- KBYTE EQU 1024 ;1K BYTE SIZE
- ;
- IF NSHOLE
- EXTRAK EQU KBYTE ;HOLE SIZE
- ENDIF
- IF NOT NSHOLE
- EXTRAK EQU 0 ;NO HOLE, ZERO SIZE
- ENDIF
- ;
- NKSYS EQU 56 ;SYS SIZE IN K BYTES
- CPMSZ EQU NKSYS*KBYTE ;TOP SYSTEM ADDRESS
- CPMBS EQU CPMSZ-(22*KBYTE)-EXTRAK ;CP/M BIAS VALUE
- CCP EQU CPMBS+3400H ;ADDRESS OF CCP
- BDOS EQU CPMBS+3C00H ;ADDRESS OF BDOS
- BIOS EQU CPMBS+4A00H+EXTRAK ;ADDRESS OF BIOS
- ;(EXTRA 1K IN BDOS IF NSHOLE
- ; TO SKIP N* CTRLR)
- BIOSR EQU 1F80H-BIOS+400H ;DDT LOAD OFFSET
- ; ;(LEAVES ROOM FOR JADE DCM OR BDOS)
- IOBYTE EQU 0003H ;IOBYTE ADDRESS
- DEFDSK EQU 0004H ;DEFAULT CCP DISK
- SECSZ EQU 128 ;BYTES PER SECTOR
- HSTSIZ EQU 512 ;BYTES PER N* SECTOR
- DSKSIZ EQU 165 ;35-TRACK DISK A: AND B:
- ;DSKSIZ EQU 190 ;40-TRACK DISK A: AND B:
- NDRVS EQU 4 ;# DRIVES IN SYSTEM
- ;
- ; STEP RATES. THESE ARE LOOP COUNTS, AND CORRESPOND
- ; TO 7.75 USEC PER COUNT AT 4 MHZ. A 40 MSEC VALUE
- ; WOULD BE -5161 (0EBD7H) FOR A SLOW SHUGART 400 DRIVE,
- ; AND A 20 MSEC VALUE WOULD BE -2580 (0F5ECH) FOR A
- ; TYPICAL NEW SHUGART 400 DRIVE. THE VALUES EMPIRICALLY
- ; DETERMINED FOR A WANGCO 82 AND MPI 92 ARE -758 (0FD0AH)
- ; AND -528 (0FDF0H) RESPECTIVELY. THE 4 MSEC FOR THE
- ; MPI SEEMS POSSIBLE, BUT THE 6 MSEC FOR THE WANGCO 82
- ; SEEMS A BIT OVERSPEC. THE STEPPING ALGORITHM SEEMS
- ; TO HAVE A BIT OF SLOP IN IT, WHICH MAY HELP.
- ;
- STPSLW EQU -2580 ;SHUGART FOR TESTING
- ;STPSLW EQU -758 ;SLOW STEP CTR (WANGCO 82)
- STPFST EQU -528 ;FAST STEP CTR (MPI 92)
- ;
- ; BDOS CONSTANTS ON ENTRY TO WRITE
- ;
- WRALL EQU 0 ;WRITE TO ALLOCATED
- WRDIR EQU 1 ;WRITE TO DIRECTORY
- WRUAL EQU 2 ;WRITE TO UNALLOCATED
- ;
- ; NORTH STAR MEMORY MAPPED I/O ADDRESSES
- ;
- NSROM EQU 0E800H ;COLD BOOT ROM ADDRESS
- WDATA EQU 0E900H ;WRITE DATA. DATA IS
- ; LOW 8 ADRESS BITS.
- CORDER EQU 0EA00H ;CONTROLLER ORDER
- CCMND EQU 0EB00H ;CONTROLLER COMMAND
- ;
- ; CONSOLE DEFINITIONS
- ;
- MOTHR EQU 000H ;HORIZON MOTHERBOARD BASE
- CRT EQU MOTHR+2 ;HORIZON LEFT SERIAL BASE
- TTY EQU MOTHR+4 ;HORIZON RIGHT SERIAL BASE
- ;
- ;PMMI modem port equates
- ;
- TPORT EQU 0E0H ;UART CONTROL/STATUS PORT
- DPORT EQU TPORT+1 ;DATA PORT
- RPORT EQU TPORT+2 ;RATE GEN/MODEM STATUS
- CPORT EQU TPORT+3 ;MODEM CONTROL
- ;
- ;Switch hook and modem commands, output to TPORT (port 0)
- ;
- P0BYE EQU 0 ;ON HOOK, OR DIALING BREAK
- P0ORIG EQU 1 ;OFF HOOK, ORIG.
- P0ANSW EQU 2 ;ANSWER PHONE
- P08BIT EQU 0CH ;8 DATA BITS
- P0NOPY EQU 10H ;NO PARITY
- P0EPS EQU 20H ;EVEN PARITY SELECT
- P0TSB EQU 40H ;2 STOP BITS
- P0EI EQU 80H ;ENABLE INTERRUPTS
- P0NORM EQU P08BIT+P0NOPY ;NORMAL 8 BITS, NO PARITY
- P0110 EQU P08BIT+P0NOPY+P0TSB ;SAME W/2 STOP BITS
- ;
- ;Modem status, input on RPORT (port 3)
- ;
- P2DTD EQU 1 ;DIAL TONE DETECT
- P2RDET EQU 2 ;RING DETECT
- P2CTS EQU 4 ;CTS (CARRIER DETECT)
- P2RXBRK EQU 8 ;RECEIVE BREAK
- P2CONN EQU 10H ;CONNECTED? (0=YES, 1=MODEM CHIP HUNG UP)
- P2TMPUL EQU 80H ;TIMER PULSES (40% UP CYCLE)
- ;
- ;Timer rate selection
- ;
- TRATE EQU 250 ;VALUE FOR .1 SEC
- ;
- ;PMMI modem status masks
- ;
- P0TBMT EQU 1 ;XMIT BUFF EMPTY
- P0DAV EQU 2 ;DATA AVAILABLE
- P0TEOC EQU 4 ;TEST END OF CHAR
- P0RPE EQU 8 ;REC'D PARITY ERR
- P0ORUN EQU 10H ;OVERRUN
- P0FERR EQU 20H ;FRAMING ERROR
- ;
- ;Baud rate divisors
- ;
- B110 EQU 142 ;110 BAUD
- B300 EQU 52 ;300 BAUD
- B450 EQU 35 ;450 BAUD
- B600 EQU 26 ;600 BAUD
- B710 EQU 22 ;710 BAUD
- ;
- CR EQU 0DH ;ASCII CARRIAGE RETURN
- LF EQU 0AH ;ASCII LINE FEED
- SPACE EQU 20H ;ASCII SPACE
- ;
- ; NORMAL BIOS JUMP VECTOR TABLE, IF NOT USING MODEM
- ;
- ORG BIOS ;START OF BIOS CODE
- ;
- BTABLE: JMP NSROM ;COLD BOOT FROM ROM
- JMP WARM ;RELOAD CCP/BDOS
- ;
- ; USE THE VECTORS TO THE CONSOLE ROUTINES FOR
- ; INTERNAL CONSOLE I/O INSTEAD OF CALLING THE
- ; ROUTINES DIRECTLY TO ALLOW USE OF BIOS
- ; MESSAGES WITH "BYE" AND OTHER VECTOR-PATCHING
- ; PROGRAMS.
- ;
- BCNSCK: JMP CNSCK ;GET CONSOLE STATUS
- BCNSIN: JMP CNSIN ;CONSOLE INPUT
- BCNSOT: JMP CNSOT ;CONSOLE OUTPUT
- BLIST: JMP LIST ;PRINTER OUTPUT
- ;
- JMP PUNCH ;PUNCH OUTPUT
- JMP READER ;READER INPUT
- ;
- ; VECTORS BEYOND THIS POINT ARE COMMON TO MODEM
- ; AND NON-MODEM SYSTEMS
- ;
- JMP HOME ;HOME SELECTED DRIVE
- JMP SELDSK ;SELECT DISK DRIVE
- JMP SETTRK ;SET TRACK NUMBER
- JMP SETSEC ;SET SECTOR NUMBER
- JMP SETDMA ;SET TRANSFER ADDRESS
- JMP DISKRD ;PERFORM DISK READ
- JMP DISKWR ;PERFORM DISK WRITE
- JMP LISTST ;LIST STATUS
- JMP SECTRN ;TRANSLATE SECTOR
- ;
- ; SET THE FOLLOWING BYTE TO ZERO BEFORE GENNING THE
- ; SYSTEM TO DISK TO HAVE THE MODEM CONTROL THE BIOS
- ; CONSOLE AND LIST DEVICES, OTHERWISE OPERATION IS
- ; FOR A FAIRLY STANDARD NORTH STAR HORIZON.
- ;
- MODEM: DB 0FFH ;NORMAL LOCAL USE
- ;MODEM: DB 000H ;MODEM USE
- ;
- ; FOLLOWING BYTE IS NON-ZERO IF MODEM IN USE AND
- ; TALKING TO PHONE, ZERO IF PHONE HUNG UP OR NOT
- ; TALKING TO PHONE. USED BY MSGOT TO DECIDE WHAT
- ; ROUTINE TO CALL TO OUTPUT TO CONSOLE.
- ;
- HUNGUP: DS 1
- ;
- ; ACCESS PASSWORD WHEN RUNNING WITH MODEM (ENDS
- ; WITH CARRIAGE RETURN)
- ;
- PASSWD: DB 'PASSWORD' ;THE PASSWORD ITSELF
- DB CR ;END OF PASSWORD
- ;
- ;Allow room for bigger password to be patched in
- ;
- DB 0,0,0,0,0,0,0,0,0,0
- ;
- ; SIGN-ON MSG TYPED AFTER LOCAL OR REMOTE USE MSG
- ;
- SIGNON: DB 'North Star '
- DB (NKSYS/10)+'0',(NKSYS MOD 10)+'0'
- DB 'K CP/M 2.2 of 05/02/82',CR,LF+80H
- ;
- ; MODEM VECTOR TABLE TO PATCH OVER NORMAL TABLE IF
- ; "MODEM" CONTAINS ZERO AT INIT TIME
- ;
- MTABLE: JMP HANGUP ;HANG UP PHONE IF
- ; COLD BOOT CALLED
- JMP WARM ;RELOAD CCP/BDOS
- JMP MSTAT ;GET CONSOLE STATUS
- JMP MINPUT ;CONSOLE INPUT
- JMP MOUTPUT ;CONSOLE OUTPUT
- JMP MOUTPUT ;PRINTER OUTPUT
- JMP MOUTPUT ;PUNCH OUTPUT
- JMP MINPUT ;READER INPUT
- ;
- MTLEN: EQU $-MTABLE ;# BYTES TO MOVE
- ;
- ; THE INIT ROUTINE IS ACTUALLY A CONTINUATION OF THE
- ; COLD BOOT BEGUN DOWN AT "BOOT".
- ;
- INIT: MVI A,81H ;INIT THE IOBYTE
- STA IOBYTE ; FOR CON:=CRT:,
- ; AND LST:=LPT:
- LXI SP,HSTBUF+HSTSIZ ;SET SP TO SCRATCH AREA
- XRA A ;INIT HORIZON MOTHERBOARD
- OUT MOTHR+6
- STA COLDB ;BIOS NOW IN MEMORY
- STA DFIMG ;COLD BOOT A:, USER ZERO
- CALL IDELAY ;DELAY FOR 8251'S
- MVI A,0AEH ;INIT SERIAL PORTS
- OUT CRT+1 ;OUTPUT DUMMY MODE TO INSURE
- OUT TTY+1
- CALL IDELAY
- MVI A,040H ; CMD EXPECTED, THEN OUTPUT
- OUT CRT+1 ; RESET CMD
- OUT TTY+1
- CALL IDELAY
- MVI A,04EH ;MODE: 1 STOP BIT, 16X CLK,
- OUT CRT+1 ; 8 DATA BITS, NO PARITY
- OUT TTY+1
- CALL IDELAY
- MVI A,037H ;CMD: RTS, ER, RXEN, DTR, TXEN
- OUT CRT+1
- OUT TTY+1
- CALL IDELAY
- IN CRT ;FLUSH RECEIVER INPUTS
- IN TTY
- LDA MODEM ;SEE IF MODEM USE DESIRED
- ORA A
- JZ MINIT ;GO INIT FOR MODEM IF SO
- STA HUNGUP ;INDICATE NORMAL CONSOLE
- ; USE THRU BCNSOT IF NOT
- LXI H,CCP ;WHERE TO START CP/M
- PUSH H
- CALL ILPRT ;ANNOUNCE OURSELVES
- DB CR,LF,'Local',' '+80H
- LXI H,SIGNON ;ISSUE SIGNON
- CALL MSGOT
- JMP CPMLD ;GO PERFORM WARM BOOT FUNCS
- ;
- ; THIS DELAY SUBROUTINE IS USED TO HELP US OUT ON
- ; TIMING WHEN RESETTING THE 8251 CONSOLE SERIAL DEVICE.
- ;
- IDELAY: LXI B,600H
- IDEL5: DCX B
- MOV A,B
- ORA C
- JNZ IDEL5
- RET
- ;
- ; IOBYTE IS SUPPORTED FOR CONSOLE AND LIST DEVICE IF
- ; NOT RUNNING WITH MODEM
- ;
- ; CONSOLE STATUS
- ;
- CNSCK: CALL CONS ;GET HARDWARE STATUS
- RZ ;IF NO CHAR READY, RETURN 0
- MVI A,0FFH ; ELSE RETURN 0FFH
- RET
- ;
- CONS: LDA IOBYTE ;GET IOBYTE
- CALL ROUTE ;DISPATCH TO STATUS ROUTINE
- DW TTYCHK ;TTY:
- DW CRTCHK ;CRT:
- DW CRTCHK ;BAT: (RDR: NOT SUPPORTED)
- DW CRTCHK ;UC1:
- ;
- ; CONSOLE INPUT
- ;
- CNSIN: CALL CONS ;GET HARDWARE STATUS
- JZ CNSIN ;WAIT FOR CHAR READY
- CALL CONIN ; THEN GET CHAR
- ANI 07FH ;STRIP PARITY
- RET ; AND RETURN IN ACC
- ;
- CONIN: LDA IOBYTE
- CALL ROUTE ;DISPATCH TO INPUT ROUTINE
- DW TTYIN ;TTY:
- DW CRTIN ;CRT:
- DW CRTIN ;BAT: (RDR: NOT SUPPORTED)
- DW CRTIN ;UC1:
- ;
- ; CONSOLE OUTPUT
- ;
- CNSOT: LDA IOBYTE
- CALL ROUTE ;DISPATCH TO OUTPUT ROUTINE
- DW TTYOT ;TTY:
- DW CRTOT ;CRT:
- DW LIST ;BAT: (LST: DEVICE)
- DW CRTOT ;UC1:
- ;
- ; READER INPUT
- ;
- READER: EQU CNSIN ;SAME AS CONSOLE INPUT
- ;
- ; PUNCH OUTPUT
- ;
- PUNCH: EQU CNSOT ;SAME AS CONSOLE OUTPUT
- ;
- ; LIST STATUS
- ;
- LISTST: XRA A ;SAY IT'S READY
- DCR A
- RET
- ;
- ; LIST OUTPUT
- ;
- LIST: LDA IOBYTE
- RLC ;ROTATE LST: BITS TO LOW
- RLC ; BIT POSITIONS
- CALL ROUTE ;DISPATCH TO LIST ROUTINE
- DW TTYOT ;TTY:
- DW CRTOT ;CRT:
- DW LPTOT ;LPT:
- DW TTYOT ;UL1:
- ;
- ; THE ROUTING ROUTINE
- ;
- ROUTE: RLC ;DOUBLE FOR WORD OFFSET
- ANI 06H ;STRIP UNUSED BITS
- XTHL ;GET DISPATCH TABLE ADDR
- ADD L ;ADD OFFSET TO GET
- MOV L,A ; TO CORRECT VECTOR
- JNC ROUTE5
- INR H
- ROUTE5: MOV A,M ;PULL VECTOR
- INX H
- MOV H,M
- MOV L,A
- XTHL ;STACK VECTOR, RESTORE HL
- RET ; THEN OFF TO ROUTINE
- ;
- ; HORIZON TTY: ROUTINES
- ;
- TTYCHK: IN TTY+1 ;GET PORT STATUS
- ANI 2 ;CHECK RECEIVER
- RET ;RET NON-ZERO IF READY
- ;
- TTYIN: IN TTY ;GET PORT DATA
- RET
- ;
- TTYOT: IN TTY+1 ;GET PORT STATUS
- RRC ;XMIT BUFFER EMPTY?
- JNC TTYOT ;IF NOT, WAIT TIL IS
- MOV A,C ; THEN OUTPUT CHAR FROM C
- OUT TTY
- RET
- ;
- ; HORIZON CRT: ROUTINES. SAME AS TTY:, BUT DIFF PORT
- ;
- CRTCHK: IN CRT+1 ;GET PORT STATUS
- ANI 2 ;CHECK RECEIVER
- RET ;RET NON-ZERO IF READY
- ;
- CRTIN: IN CRT ;GET PORT DATA
- RET
- ;
- CRTOT: IN CRT+1 ;GET PORT STATUS
- RRC ;XMIT BUFFER EMPTY?
- JNC CRTOT ;IF NOT, WAIT TIL IS
- MOV A,C ; THEN OUTPUT CHAR FROM C
- OUT CRT
- RET
- ;
- ; LIST CHAR OUT TO SERIAL PRINTER ON TTY:
- ;
- LPTOT: PUSH H ;SAVE HL
- PUSH B ;SAVE CHAR TO OUTPUT
- ;
- LOUT5: LXI H,0 ;LOAD UP FOR NICE LONG DELAY
- MVI B,20 ;APPROX 20 SECONDS AT 4 MHZ
- ;
- LOUT10: DCX H ;COUNT DOWN
- MOV A,H ;SEE IF ZERO YET
- ORA L
- JNZ LOUT20 ;PASS IF NOT
- DCR B ;COUNT OFF HIGHER BITS
- JNZ LOUT20 ;PASS IF NOT ZERO YET
- ;
- LOUT15: MVI A,'P' ;DISK P: NOT READY, FOR PRINTER
- CALL PNTRDY ;REPORT, AND RETURN IF NO CTRL-C
- MVI A,11H ;JAM PRINTER SELECT
- OUT TTY ; AFTER PUT ONLINE
- JMP LOUT5 ;NOW GO TRY AGAIN
- ;
- LOUT20: IN TTY+1 ;GET 8251 STATUS
- ANI 85H ;STRIP OUT REQ NXT CHAR, XMIT
- CPI 85H ; BUF RDY, AND XMIT EMPTY,
- ; THEN CHECK THEM
- JNZ LOUT10 ;ALL 3 MUST BE UP TO SEND
- ;
- ; PRINTER NOW READY. OUTPUT CHAR.
- ;
- POP B ;RESTORE CHAR TO C
- MOV A,C ; AND GET IT TO ACC
- ANI 7FH ;STRIP PARITY
- OUT TTY ;OUTPUT THE CHAR
- MOV A,C ;RESTORE CHAR TO ACC
- POP H ;RESTORE HL
- RET ; AND RETURN
- ;
- ;
- ; THESE ARE THE MODEM ROUTINES. MINIT SETS UP THE MODEM
- ; VECTORS, THEN DROPS INTO HANGUP TO BEGIN NORMAL MODEM
- ; OPERATION.
- ;
- MINIT: LXI H,MTABLE ;MOVE VECTORS FROM HERE
- LXI D,BTABLE ; OVER NORMAL TABLE
- LXI B,MTLEN ;THIS MANY BYTES
- CALL BLOCK ;DO THE MOVE
- ;
- ;Clear DTR causing phone to hang up
- ;
- HANGUP: LXI SP,HSTBUF+HSTSIZ ;SET SP TO SCRATCH AREA
- LXI H,CCP ;INIT COLD CCP START ADDR
- PUSH H ;IT GOES ON STACK FOR CPMLD RET
- XRA A ;GET DISCONNECT VALUE
- OUT TPORT ;RESET ORIG/ANSW
- OUT CPORT ;TURN OFF DTR, DO BREAK
- STA DFIMG ;SET DEF DISK TO A:, USER ZERO
- STA HUNGUP ;PHONE HUNG UP
- CALL ILPRT
- DB CR,LF,'Phone hung up..','.'+80H
- ;
- ;Await ringing
- ;
- RINGWT: IN RPORT ;GET THE STATUS
- ANI P2RDET ;RINGING?
- JNZ RINGWT ;NO, WAIT
- ;
- ;The phone may be ringing. Wait .1 sec and look
- ;again to make sure it isn't just relay bounce
- ;
- CALL DELAY ;.1 SEC DELAY FOR DEBOUNCE
- IN RPORT ;GET STATUS
- ANI P2RDET ;STILL RINGING?
- JNZ RINGWT ;NO, IT WAS RELAY BOUNCE
- ;
- ;The phone is definitely ringing, now wait until ring is finished
- ;
- ENDRNG: CALL DELAY ;.1 SEC DELAY FOR DEBOUNCE
- IN RPORT ;GET STATUS
- ANI P2RDET ;STILL RINGING?
- JZ ENDRNG ;WAIT UNTIL RING FINISHED
- ;
- ;Setup modem
- ;
- ANSWER: MVI A,7FH ;TURN ON DTR
- OUT CPORT ;.. AND SET FILTER VALUE FOR 300 BAUD
- CALL DELAY ;GIVE TIME TO TURN ON
- MVI A,P0110+P0ANSW
- OUT TPORT ;ANSWER PHONE
- CALL DELAY ;GIVE TIME FOR ANSWER
- IN DPORT ;CLEAR MODEM PORT
- IN DPORT ;MAKE SURE ITS CLEAR
- MVI A,B110 ;SET DIVISOR
- OUT RPORT ;.. TO 110 BAUD RATE
- ;
- ;Output value allowing modem to hang up on loss of carrier
- ;
- MVI A,P0110 ;NORMAL MODE FOR 110 BAUD
- OUT TPORT
- CALL CHECK ;ABORT IF CARRIER LOST
- ;
- ;Now test input for baud rate
- ;
- CALL TSTBAUD ;SEE IF BAUD = 110
- JZ WELCOME ;YES, EXIT
- ;
- MVI A,P0NORM ;SET FOR 1 STOP BIT, ETC.
- OUT TPORT
- MVI A,B300 ;SET DIVISOR
- OUT RPORT ;.. TO 300 RATE
- CALL TSTBAUD ;SEE IF BAUD = 300
- JZ WELCOME ;YES, EXIT
- ;
- MVI A,B450 ;SET DIVISOR
- OUT RPORT ;.. TO 450 RATE
- MVI A,5FH ;SET FILTER VALUE
- OUT CPORT ;.. FOR > 300
- CALL TSTBAUD ;SEE IF BAUD = 450
- JZ WELCOME ;YES, EXIT
- ;
- MVI A,B600 ;SET DIVISOR
- OUT RPORT ;.. TO 600 RATE
- CALL TSTBAUD ;SEE IF BAUD = 600
- JZ WELCOME ;YES, EXIT
- ;
- MVI A,B710 ;SET DIVISOR
- OUT RPORT ;.. TO 710 RATE
- CALL TSTBAUD ;SEE IF BAUD = 710
- JZ WELCOME ;YES, EXIT
- JMP ANSWER ;TEST MORE - INVALID BAUD RATE
- ;
- ;Welcome to the system -- get the password
- ;
- WELCOME: MVI A,1 ;TALKING ON PHONE NOW
- STA HUNGUP
- CALL ILPRT ;ANNOUNCE OURSELVES
- DB CR,LF,'Remote',' '+80H
- LXI H,SIGNON
- CALL MSGOT ;TELL REST OF SIGNON
- MVI D,5 ;5 TRIES AT PASSWORD
- ;
- PASSINP: CALL ILPRT
- DB CR,LF,'Enter password:',' '+80H
- LXI H,PASSWD ;POINT TO PASSWORD
- MVI E,0 ;NO MISSED LETTERS
- IN DPORT ;CLEAR OUT GARBAGE
- ;
- PWMLP: CALL MINPUT ;GET A CHAR
- CPI 'U'-40H ;CTL-U?
- JZ PASSINP ;YES, RE-GET IT
- CPI 60H ;LOWER CASE?
- JC NOTLC ;NO,
- ANI 5FH ;MAKE UPPER CASE ALPHA
- ;
- NOTLC: CMP M ;MATCH PASSWORD?
- JZ PWMAT ;..YES
- MVI E,1 ;..NO, SHOW MISS
- CPI CR ;C/R?
- JNZ PWMLP ;..NO, WAIT FOR C/R
- ;
- ;Password didn't match
- ;
- PWNMAT: CALL ILPRT
- DB '++INCORRECT++',CR,LF+80H
- DCR D ;MORE TRIES?
- JNZ PASSINP ;YES
- JMP HANGUP ;NO, GO HANG UP
- ;
- ;Character matched in password
- ;
- PWMAT: INX H ;TO NEXT CHAR
- CPI CR ;END?
- JNZ PWMLP ;..NO, LOOP
- ;
- ;End of password. Any missed chars?
- ;
- MOV A,E ;GET FLAG
- ORA A
- JNZ PWNMAT ;NOT RIGHT
- ;
- ;Password correct
- ;
- CALL ILPRT
- DB CR,LF,'Entering CP/M . . .',' '+80H ;BOOT MSG
- JMP CPMLD ;LOAD AND START CCP/BDOS
- ;
- ;TSTBAUD attempts to read a LF or CR, returns with
- ;zero flag if the character read is one of these two.
- ;
- TSTBAUD: CALL MINPUT ;GET CHARACTER FROM MODEM
- CPI CR ;IF A CARRIAGE RETURN...
- RZ ;.. RETURN
- CPI LF ;IF A LINEFEED...
- RET ;RET ZERO FLAG, ELSE NOT ZERO
- ;
- ;Loss of connection test
- ;
- ;The PMMI modem automatically hangs up the phone after
- ;15 seconds of loss of carrier, providing you output to
- ;port 0 to allow it (we do).
- ;
- ;..so, this routine first checks if the modem has hung up,
- ;and if so, aborts out to HANGUP. If not, it checks for
- ;carrier and returns if carrier is on; otherwise waits for
- ;carrier while still testing for disconnect.
- ;
- ;It tests the PMMI "CTS" (clear to send) bit
- ;which is 0 when there is carrier
- ;
- CHECK: IN RPORT ;GET STATUS
- ANI P2CONN ;CONNECTED?
- JNZ HANGUP ;HUNG UP
- ;
- ;Still connected, check for carrier
- ;
- IN RPORT ;LOOK AT STATUS
- ANI P2CTS ;GET CARRIER DETECT BIT
- ;
- ;Loop until either connection lost, or carrier returns
- ;
- JNZ CHECK
- RET
- ;
- ;.1 sec delay routine for 4MHz clock Z80
- ;
- DELAY: PUSH B
- ;
- LXI B,16667 ;4 MHZ TIMING CONSTANT
- ; LXI B,8334 ;2 MHZ TIMING CONSTANT
- ;
- DELAY1: DCX B
- MOV A,B
- ORA C
- JNZ DELAY1
- POP B
- RET
- ;
- ;Modem status test routine
- ;
- MSTAT: CALL CHECK ;CHECK FOR CARRIER LOST
- CALL CNSCK ;GET LOCAL CONSOLE STATUS
- ORA A
- RNZ ;GO BACK IF GOT LOCAL CHAR
- IN TPORT ;GET STATUS
- ANI P0DAV ;DATA AVAILABLE?
- RZ ;RETURN IF NOT READY
- IN TPORT ;GET STATUS
- ANI 30H ;CHECK FRAMING AND OVERRUN BITS
- JZ MSTAT1 ;NO ERRORS...LEGIT CHARACTER
- IN DPORT ;SWALLOW CHARACTER (CLEARS PODAV)
- XRA A ;RETURN FALSE
- RET
- ;
- MSTAT1: XRA A ;SHOW READY
- DCR A
- RET
- ;
- ;Modem input function
- ;
- MINPUT: CALL CHECK ;CARRIER STILL ON?
- CALL MSTAT ;ANYTHING?
- ORA A
- JZ MINPUT ;LOOP TILL CHAR RCD
- CALL CNSCK ;CHAR AT LOCAL CONSOLE?
- ORA A
- JNZ CNSIN ;GO READ LOCAL CONSOLE IF SO
- IN DPORT ;GET DATA BYTE
- ANI 7FH ;DELETE PARITY
- JZ MINPUT ;IGNORE NULLS
- RET
- ;
- ;Modem output function
- ;
- MOUTPUT: CALL CHECK ;CARRIER STILL ON?
- IN TPORT ;GET MODEM STATUS
- ANI P0TBMT ;TRANSMIT BUFFER EMPTY?
- JZ MOUTPUT ;LOOP IF NOT READY
- MOV A,C ;GET CHAR
- ANI 7FH ;STRIP PARITY BIT
- OUT DPORT ;OUTPUT TO MODEM
- JMP CNSOT ;ECHO TO LOCAL CONSOLE
- ;
- ;Inline print routine
- ;
- ILPRT: XTHL ;SAVE HL, GET MSG
- PUSH B ;SAVE BC REGS
- CALL MSGOT ;OUTPUT STRING AT HL
- POP B ;RESTORE BC REGS
- XTHL ;RESTORE HL, RET ADDR
- RET ;RET PAST MSG
- ;
- ; SELECT DRIVE - LOGON
- ;
- SELDSK: LXI H,0 ;ERROR RETURN CODE
- MOV A,C ;PUT DRIVE # IN A
- CPI NDRVS ;CHECK IF LEGAL DRIVE
- RNC ;NO CARRY IF ILLEGAL
- STA SEKDSK ;STORE DRIVE NUMBER
- MOV B,E ;SAVE LOGON REQ REG
- MOV L,C ;L = DISK NUMBER
- MVI H,0 ;ZERO H REG
- DAD H ; *2
- DAD H ; *4
- DAD H ; *8
- DAD H ; *16 (SIZE OF HEADER)
- LXI D,D0DPH ;DRIVE 0 DPH
- DAD D ;HL = DRIVE N DPH
- SHLD DTPTR ;STORE DRIVE TBL PTR
- ;
- ; LOG-ON - SET DISK PARAMETER BLOCK
- ;
- ; -- CHECK IF LOG-ON REQUESTED
- ;
- MOV A,B ;CHECK LOG REQUEST
- ANI 001H ;LOG ON BIT TEST
- JNZ NOLOG ;PASS IF NO REQUEST
- LDA SEKDSK ;NO LOGON IF C: OR D:
- CPI 2
- JNC NOLOG
- CALL HFLUSH ;MAKE SURE HOST BUF
- JNZ LOGERR ; AVAILABLE, OUT ON ERR
- ;
- ; LOG ON NORTH STAR BY READING ID SECTOR, THEN DECIDE
- ; WHICH TABLE TO USE BASED ON SINGLE OR DOUBLE DENSITY.
- ; THE ACTUAL ID SECTOR INFO IS IGNORED.
- ;
- LDA SEKDSK
- STA HSTDSK ;GOING TO ACCESS THIS DISK
- XRA A
- STA HSTTRK ;TRACK ZERO
- STA HSTSEC ;N* SECTOR ZERO
- CALL INTDI ;INTERRUPTS OFF
- CALL READHST ;READ THE SECTOR
- CALL INTEN ;INTERRUPTS RESTORED
- LDA ERFLAG ;CHECK FOR READ ERROR
- ORA A
- JNZ LOGERR ;LOG-ON ERROR IF SO
- LDA NSDENS ;IF OK, GET DENSITY FLAG
- LXI B,TRAN5D ;ASSUME DOUBLE DENSITY
- LXI D,DPBNSD
- ORA A ;CHECK
- JZ LOGNSD ;GO ON IF RIGHT
- LXI B,TRAN5S ;CORRECT TO SINGLE DENSITY
- LXI D,DPBNSS ; IF WRONG
- ;
- LOGNSD: LHLD DTPTR ;LOAD DRIVE TBL PTR
- MOV M,C ;SET TRANSLATE TABLE ADDR
- INX H
- MOV M,B
- LXI B,9 ;PT TO DPB ADDR
- DAD B
- MOV M,E ;SET DPB ADDR
- INX H
- MOV M,D
- ;
- ; SET UP DEBLOCKING VARIABLES FROM DPB VALUES
- ;
- NOLOG: CALL DPBAD ;GET DPB ADDR
- XCHG ; IN HL
- MOV A,M ;SET UP DEBLOCK
- STA CPMSPT ; SECTORS PER TRACK
- INX H ;GET TO GROUP MASK
- INX H
- INX H
- MOV A,M ;GET IT
- INR A ;CALC # BLOCKS/GROUP
- STA UNAVAL ; AND SAVE THAT
- LXI D,12
- DAD D ;PT TO SECTOR SHIFT
- MOV A,M ; BIT FLAG
- ORA A ;HAVE WE GOT ONE?
- JZ NOSHF ;PASS IF NOT
- MVI B,0FFH ;INIT SHIFT COUNT
- ;
- CALCSH: INR B ;COUNT UP A SHIFT
- RAR ;SEE IF DONE
- JNC CALCSH ;GO BACK IF NOT YET
- MOV A,B ;SHIFT COUNT TO ACC
- ;
- NOSHF: STA SECSHF ;STORE SHIFT COUNT
- MOV A,M ;RELOAD BIT FLAG
- DCR A ;FORM SECTOR MASK
- STA SECMSK ; AND SET IT
- LHLD DTPTR ;RELOAD PTR
- XRA A ;NO ERRORS
- RET ; SO RET ZERO
- ;
- LOGERR: LXI H,0
- RET
- ;
- ; -- GET DRIVE PARA BLK ADDR
- ;
- DPBAD: LHLD DTPTR ;ADDR DISK PARA HDED
- LXI D,10 ;DPB TBL PNTR OFFSET
- DAD D ;NOW AT DPB PNTR
- MOV E,M ;LOAD INTO DE
- INX H
- MOV D,M
- RET ;RETURN TO LOG USER
- ;
- ; HOME DRIVE
- ;
- HOME: MVI C,0 ;SET TRACK TO ZERO TO HOME
- LDA HSTWRT ;CHECK FOR PENDING WRITE
- ORA A
- JNZ SETTRK
- STA HSTACT ;CLEAR HOST ACTIVE IF NOT
- ;
- ; SET TRACK
- ;
- SETTRK: MOV A,C ;MOVE TRACK NUMBER
- STA SEKTRK ; THEN SAVE IT
- RET ;RETURN TO CALLER
- ;
- ; SET SECTOR
- ;
- SETSEC: MOV A,C ;MOVE SECTOR NUMBER
- STA SEKSEC ; THEN SAVE IT
- RET ;RETURN TO CALLER
- ;
- ; SET TRANSFER ADDRESS
- ;
- SETDMA: MOV H,B ;MOVE ADDR TO HL
- MOV L,C
- SHLD DMAADR ; THEN SAVE IT
- RET ;RETURN TO CALLER
- ;
- ; SECTOR TRANSLATION
- ;
- SECTRN: MOV A,E ;IS THERE A TABLE?
- ORA D
- JZ NOTRAN ;SPECIAL XLATE IF SO
- XCHG ;MAP OFF TABLE
- DAD B
- MOV L,M
- MVI H,0
- RET
- ;
- NOTRAN: MOV H,B ;JUST BOP BY ONE
- MOV L,C ; FOR SINGLE DENSITY
- INX H
- RET
- ;
- ; THIS IS THE REST OF THE DISK I/O ERROR ROUTINE.
- ; IT IS HERE BECAUSE (1) IT CAN'T BE USED IN COLD BOOT,
- ; WHILE THE FIRST PART MUST BE, AND (2) IT SAVES
- ; A JUMP WHEN PLACED BEFORE HXBOT.
- ;
- DSKER2: PUSH H ;SAVE BODY ADDRESS
- LXI H,CRLF ;EJECT LINE
- CALL MSGOT
- POP H
- CALL MSGOT ;REPORT BODY
- LDA HSTDSK ;THIS DISK
- ADI 'A'
- STA ASCDSK
- LXI H,ERRMSG
- CALL MSGOT
- LDA HSTTRK ;THIS TRACK
- CALL HXBOT
- LXI H,SECMSG
- CALL MSGOT
- LDA ERSEC ;THIS SECTOR
- ;INTO HXBOT TO FINISH
- ;
- ; HXBOT DISPLAYS HEXIDECIMAL EQUIV OF ACC CONTENTS.
- ;
- HXBOT: PUSH PSW ;SAVE CHAR
- RRC ;SWAP NIBBLES
- RRC
- RRC
- RRC
- CALL HXNOT ;OUTPUT HIGH NIBBLE
- POP PSW ; THEN LOW NIBBLE
- HXNOT: ANI 0FH ;STRIP HIGH NIBBLE
- ADI 90H ;CVT TO ASCII DECIMAL
- DAA
- ACI 40H
- DAA
- MOV C,A ;CHAR TO C
- JMP BCNSOT ;THRU VECTOR TO CNSOT
- ;
- ; DEBLOCKING DISK WRITE
- ;
- DISKWR: CALL INTDI ;MASK INTERRUPTS
- CALL DSKWR ;DO THE WRITE
- JMP INTEN ;GO RESTORE INTS
- ;
- ; DEBLOCKING DISK READ. NOTE THAT ON DEBLOCKING READ
- ; AND WRITE, THE CALLER SECTOR NUMBERS RANGE FROM 1-XX
- ; DECIMAL. THIS IS FOR COMPATIBILITY WITH 8" FORMATS
- ; THAT ARE 1-ORIGIN. WE ADJUST FOR THIS THROUGHOUT THE
- ; DEBLOCKING ROUTINES BY SUBTRACTING 1 FROM SEKSEC
- ; BEFORE WE USE IT. VARIABLES TO CONTROL DEBLOCKING
- ; ARE SET UP FOR US WHEN DISK IS SELECTED.
- ;
- DISKRD: CALL INTDI ;DISABLE INTERRUPTS
- CALL DSKRD ;DO THE I/O
- ;
- INTEN: PUSH PSW ;SAVE DISK I/O ERROR CODE
- LHLD ENTPSW ;GET ENTRY PSW TO TEST
- PUSH H
- POP PSW
- JPO INTEN5 ;PASS IF INTS OFF WHEN ENTERED
- EI ; ELSE RE-ENABLE INTS
- ;
- INTEN5: POP PSW ;RESTORE DISK I/O ERROR CODE
- RET ; THEN RETURN TO CALLER
- ;
- INTDI: MVI A,7FH ;CHECK FOR RUNNING ON
- INR A ; 8080 OR Z80
- JPO NOTZ80 ;CAN'T GET INT STATE ON 8080
- DW LDAI ;GET INT STATE INTO
- PUSH PSW ; PARITY FLAG, THEN
- POP H ; SAVE PSW IN MEMORY
- SHLD ENTPSW
- ;
- NOTZ80: DI ;ALLOW NO INTERRUPTS
- RET ; DURING THE I/O XFER
- ;
- DSKRD: MVI A,WRUAL
- STA WRTYPE ;TREAT AS UNALLOC
- STA READOP ;READ OPERATION
- JMP ALLOC ;GO END UNALLOC SECTORS
- ; AND FORCE READ
- ;
- DSKWR: XRA A
- STA READOP ;NOT A READ OPERATION
- MOV A,C ;WRITE TYPE IN C
- STA WRTYPE
- CPI WRUAL ;WRITE UNALLOCATED?
- JNZ CHKUNA ;CHECK FOR UNALLOC
- ;
- ; WRITE TO UNALLOCATED, SET PARAMETERS
- ;
- LDA UNAVAL ;NEXT UNALLOC RECS
- STA UNACNT
- LDA SEKDSK ;DISK TO SEEK
- STA UNADSK ;UNADSK = SEKDSK
- LDA SEKTRK
- STA UNATRK ;UNATRK = SEKTRK
- LDA SEKSEC
- STA UNASEC ;UNASEC = SEKSEC
- ;
- ; CHECK FOR WRITE TO UNALLOCATED SECTOR
- ;
- CHKUNA: LDA UNACNT ;ANY UNALLOC REMAIN?
- ORA A
- JZ ALLOC ;SKIP IF NOT
- ;
- ; MORE UNALLOCATED RECORDS REMAIN
- ;
- DCR A ;UNACNT = UNACNT - 1
- STA UNACNT
- LDA SEKDSK ;SAME DISK?
- LXI H,UNADSK
- CMP M ;SEKDSK = UNADSK?
- JNZ ALLOC ;SKIP IF NOT
- ;
- ; DISKS ARE THE SAME, CHECK TRACKS
- ;
- LDA SEKTRK
- LXI H,UNATRK
- CMP M ;SEKTRK = UNATRK?
- JNZ ALLOC ;SKIP IF NOT
- ;
- ; TRACKS ARE THE SAME, CHECK SECTORS
- ;
- LDA SEKSEC
- LXI H,UNASEC
- CMP M ;SEKSEC = UNASEC?
- JNZ ALLOC ;SKIP IF NOT
- ;
- ; MATCH, MOVE TO NEXT SECTOR FOR FUTURE REF
- ;
- INR M ;UNASEC = UNASEC+1
- LDA CPMSPT ;CHECK FOR END OF TRACK
- CMP M
- JNC NOOVF ;SKIP IF STILL ON TRACK
- ;
- ; OVERFLOW TO NEXT TRACK
- ;
- MVI M,1 ;UNASEC = 1
- LXI H,UNATRK
- INR M ;UNATRK = UNATRK+1
- ;
- ; MATCH FOUND, MARK AS UNNECESSARY READ
- ;
- NOOVF: XRA A
- STA RSFLAG ;RSFLAG = 0
- JMP RWOPER ;GO DO WRITE
- ;
- ; NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ
- ;
- ALLOC: XRA A
- STA UNACNT ;UNACNT = 0
- INR A
- STA RSFLAG ;RSFLAG = 1
- ;
- ; COMMON CODE FOR READ AND WRITE FOLLOWS
- ;
- RWOPER: XRA A
- STA ERFLAG ;NO ERRORS (YET)
- LDA SECSHF ;GET SECTOR SHIFT COUNT
- MOV B,A ; IN COUNT REG
- LDA SEKSEC ;COMPUTE HOST SECTOR
- DCR A ;ADJUST FOR 1-ORIGIN
- ;
- RWOPSH: ORA A ;CARRY = 0
- RAR ;SHIFT RIGHT
- DCR B ;COUNT OFF A SHIFT
- JNZ RWOPSH ;LOOP IF MORE
- STA SEKHST ;HOST SECTOR TO SEEK
- ;
- ; ACTIVE HOST SECTOR?
- ;
- LXI H,HSTACT ;HOST ACTIVE FLAG
- MOV A,M
- MVI M,1 ;ALWAYS BECOMES 1
- ORA A ;WAS IT ALREADY?
- JZ FILHST ;FILL HOST IF NOT
- ;
- ; HOST BUFFER ACTIVE, SAME AS SEEK BUFFER?
- ;
- LDA SEKDSK
- LXI H,HSTDSK ;SAME DISK?
- CMP M ;SEKDSK = HSTDSK?
- JNZ NOMATCH
- ;
- ; SAME DISK, CHECK TRACK
- ;
- LDA SEKTRK
- LXI H,HSTTRK
- CMP M ;SEKTRK = HSTTRK?
- JNZ NOMATCH
- ;
- ; SAME DISK AND TRACK, CHECK SECTOR
- ;
- LDA SEKHST
- LXI H,HSTSEC
- CMP M ;SEKHST = HSTSEC?
- JZ MATCH ;SKIP IF MATCH
- ;
- ; MUST FLUSH HOST BUFFER FOR NEW SECTOR
- ;
- NOMATCH: LDA HSTWRT ;HOST WRITTEN?
- ORA A
- CNZ WRITEHST ;CLEAR HOST BUFFER
- LDA ERFLAG ;CHECK FOR ERROR
- ORA A
- RNZ ;RETURN ERROR IF SO
- ;
- FILHST: LDA SEKDSK ;MAY HAVE TO FILL HOST BUFFER
- STA HSTDSK
- LDA SEKTRK
- STA HSTTRK
- LDA SEKHST
- STA HSTSEC
- XRA A
- STA HSTWRT ;NO PENDING WRITE
- LDA RSFLAG ;NEED TO READ?
- ORA A
- JZ MATCH ;NO IF FLAG ZERO
- CALL READHST ;READ THE SECTOR
- LDA ERFLAG ;CHECK FOR ERRORS
- ORA A
- RNZ ;NO MORE IF SO
- CALL GNSDEN ;CHECK DENSITY
- LXI H,NSDENS
- CMP M ;IS DENSITY RIGHT?
- JZ MATCH ;OK IF SO
- LXI H,SDEMSG ;ERROR IF NOT
- CALL DSKERR ;REPORT IT
- MVI A,5
- STA ERFLAG
- RET ;RET NZ ACC TO CALLER
- ;
- ; COPY DATA TO OR FROM BUFFER
- ;
- MATCH: LDA SECMSK ;GET MASK
- MOV H,A ; INTO TEMP REG
- LDA SEKSEC ;MASK SECTOR BUFFER NUMBER
- DCR A ;ADJUST FOR 1-ORIGIN
- ANA H ;LEAST SIGNIF BITS
- RAR ;GET VALUE SHIFTED
- MOV H,A ; LEFT 7 IN HL
- MVI A,0
- RAR
- MOV L,A
- ;
- ; HL CONTAINS RELATIVE HOST BUFFER ADDRESS
- ;
- LXI D,HSTBUF ;PT TO HOST BUFFER
- DAD D ;HL = HOST ADDRESS
- XCHG ;NOW IN DE
- LHLD DMAADR ;GET/PUT CP/M DATA
- MVI C,SECSZ ;LENGTH OF MOVE
- LDA READOP ;WHICH WAY?
- ORA A
- JNZ RWMOVE ;SKIP IF READ
- ;
- ; WRITE OPERATION, MARK AND SWITCH DIRECTION
- ;
- INR A ;ACC KNOWN ZERO ABOVE
- STA HSTWRT ;HSTWRT = 1
- XCHG ;SOURCE/DEST SWAP
- ;
- RWMOVE: LDAX D ;SOURCE CHARACTER
- INX D
- MOV M,A ;TO DEST
- INX H
- DCR C ;LOOP 128 TIMES
- JNZ RWMOVE
- ;
- ; DATA HAS BEEN MOVED TO/FROM HOST BUFFER
- ;
- LDA WRTYPE ;WRITE TYPE
- CPI WRDIR ;TO DIRECTORY?
- MVI A,0 ;NO ERROR AT THIS PT
- RNZ ;RET IF NOT DIR WRITE
- ;
- ; CLEAR HOST BUFFER FOR DIRECTORY WRITE
- ;
- CALL WRITEHST
- LDA ERFLAG
- RET
- ;
- ; WRITEHST PERFORMS THE PHYSICAL WRITE TO THE
- ; NORTH STAR DISK. ON ENTRY, DRIVE IS IN HSTDSK,
- ; TRACK IS IN HSTTRK, SECTOR IS IN HSTSEC. ON
- ; EXIT, ERROR FLAG IS IN ERFLAG (ZERO IF NONE).
- ;
- ; IT IS ASSUMED INTERRUPTS ARE DISABLED AT
- ; THIS POINT. IF NOT, I/O MAY BE DISRUPTED.
- ;
- WRITEHST: ;WRITE HOST
- XRA A ;BUFFER WILL BE CLEARED
- STA HSTWRT
- CALL GNSDEN ;GET DENSITY BASED ON ID
- STA NSCNT ;SET WRITE BYTE COUNT
- CALL SETUP ;SELECT DRIVE AND
- ; SEEK TO TRACK
- LDA ERFLAG ;CHECK FOR ERRORS
- ORA A
- RNZ ;INDEX PULSE NOT FOUND IS FATAL
- CALL POSEC ;POSITION TO SECTOR
- JNZ SNFERR ;OUT ON ERROR
- LDA CCMND+20H ;GET B-STATUS
- ANI 02H ;IS DISK WRITE-PROTECTED?
- MVI A,6 ;ASSUME SO, ERROR CODE 6
- STA ERFLAG
- JNZ WPERR ;WRITE ALWAYS FAILS IF SO
- LHLD HSTADR ;GET ADDRESS TO WRITE FROM
- MVI B,31 ;ASSUME DOUBLE DENSITY
- MVI E,2
- LDA NSCNT ;CHECK
- MOV C,A ;SAVE COUNT FOR LATER
- ORA A
- JZ WRIT5 ;GO ON IF COUNTS RIGHT
- MVI B,15 ;CORRECT FOR SINGLE DENS
- DCR E
- ;
- WRIT5: LDA CCMND+16H ;INITIATE SECTOR WRITE
- ;
- WRIT10: LDA CCMND+15H ;KEEP MOTORS RUNNING, GET A-STAT
- ANI 08H ;MUST LOOP UNTIL 96 USEC WINDOW
- JNZ WRIT10 ; PAST, SO LOOP WHILE WI TRUE
- ;
- ; NOW WRITE THE 31 OR 15 BYTES OF LEADING ZEROES ON THE SECTOR
- ;
- WRIT15: LDA WDATA+00H ;WRITE A BYTE OF ZEROES
- NOP ;KILL TIME
- MVI D,WDATA SHR 8 ;KILL TIME BY LOADING D FOR LATER
- DCR B ;COUNT OFF A ZERO BYTE
- JNZ WRIT15 ;DO THEM ALL
- ;
- ; FOLLOW WITH ONE OR TWO SYNCH BYTES
- ;
- WRIT17: LDA WDATA+0FBH ;WRITE A SYNCH BYTE
- DCR E ;CHECK FOR 2ND NEEDED
- JNZ WRIT17 ;GO BACK IF SO
- ;
- ; NOW WRITE OUT 256 OR 512 BYTES. DO THIS TWO AT A
- ; TIME SO WE CAN USE SINGLE PRECISION COUNTER. B IS
- ; ZERO FROM ABOVE TO INIT THE CRC BYTE.
- ;
- WRIT20: MOV A,M ;GET NEXT BYTE TO OUTPUT
- MOV E,A ; IN OUTPUT REG
- XRA B ;ADD INTO CHECKSUM
- RLC
- MOV B,A ;LEAVE CHECKSUM IN B
- LDAX D ;WRITE DATA BYTE TO DISK
- INX H ;BOP BUF PTR
- MOV A,M ;REPEAT FOR NEXT BYTE
- MOV E,A
- XRA B
- RLC
- MOV B,A
- LDAX D
- INX H
- DCR C ;COUNT OFF LAST PAIR OF BYTES
- JNZ WRIT20 ;GO BACK IF MORE TO WRITE
- MOV E,B ;IF NOT, TIME TO WRITE CHECKSUM
- INX B ;KILL TIME
- LDAX D ; THEN WRITE THE BYTE
- XRA A ;DONE, INDICATE NO ERROR
- STA ERFLAG
- RET ;RETURN TO CALLER
- ;
- WPERR: LXI H,WPEMSG ;WRITE PROTECT ERROR
- JMP DSKERR ;TELL OPERATOR ON WAY OUT
- ;
- ; GNSDEN IS CALLED BY N* I/O ROUTINES TO DETERMINE THE
- ; DENSITY OF THE CURRENT BLOCK BASED ON THE DENSITY OF
- ; THE ID BLOCK. THAT IS DETERMINED BY TAKING ADVANTAGE
- ; OF THE FACT THAT THE HOST DISK HAS NO TRANSLATE TABLE
- ; IF SINGLE DENSITY.
- ;
- GNSDEN: LXI H,D0DPH ;ASSUME A:
- LDA HSTDSK ;NOW CHECK
- CPI 2 ;IS DISK C: OR D:?
- JNC GNSDC ;ALWAYS DOUBLE IF SO
- ORA A ;A:?
- JZ GNSDA ;GO ON IF SO
- LXI H,D1DPH ;B: IF NOT
- GNSDA: MOV A,M ;SEE IF GOT XLATE TABLE
- INX H
- ORA M ;IF NOT, SINGLE DENSITY
- MVI A,80H ;ASSUME SINGLE
- RZ ;DONE IF RIGHT
- GNSDC: XRA A ;CORRECT IF DOUBLE DENSITY
- RET
- ;
- ; COME HERE FROM SELDSK TO CLEAR ALL PENDING HOST WRITES
- ;
- HFLUSH: LDA HSTWRT ;SEE IF BUFFER NEEDS FLUSH
- STA ERFLAG ;NO ERROR IF NOT
- ORA A
- CNZ WRITEHST ;FLUSH IF SO, IF MAYBE
- ; WILL USE BUFFER
- XRA A
- STA HSTACT ;TOSS READ CONTENTS
- STA UNACNT ;BUFFER LEAVING, NEED
- ; PRE-READ ON NEXT UNALLOC
- LDA ERFLAG ;SET UP ERROR STATUS
- ORA A
- RET
- ;
- ; BLOCK - BLOCK MOVE (Z80 LDIR REGISTER USAGE)
- ;
- BLOCK: MOV A,M ;GET BYTE
- STAX D ;STORE IT
- INX H ;BOP PTRS
- INX D
- DCX B ;COUNT OFF BYTE
- MOV A,B ;CHECK FOR DONE
- ORA C
- JNZ BLOCK ;GO BACK IF NOT
- RET
-
-
- ;
- ; HERE TO REPORT DISK NOT READY. TELL CONSOLE WHICH
- ; DISK IT WAS, THEN SOLICIT REPLY. IF CTRL-C, WARM
- ; BOOT TO A:, ELSE RETURN TO CALLER.
- ;
- NOTRDY: LDA SEKDSK ;STUFF DISK
- ADI 'A'
- ;
- ; MERGE HERE FROM PRINTER OFFLINE
- ;
- PNTRDY: STA NRD ; INTO MSG
- LXI H,NRDMSG
- CALL MSGOT ;REPORT TO OPERATOR
- CALL BCNSIN ;GET REPLY
- SUI 3 ;IS ANSWER CTRL-C?
- RNZ ;RETURN TO CALLER IF NOT
- STA DEFDSK ;SELECT A: IF SO,
- ; THEN WARM BOOT IT
- ;
- ; WARM BOOT ENTRY. LOAD CCP/BDOS AND INITIALIZE
- ;
- WARM: DI ;NO PROCESSOR INTS DURING BOOT
- LDA DEFDSK ;GET CURRENT DEFAULT DISK
- MOV B,A ;SAVE IT
- ANI 0F0H ;GET USER #
- MOV C,A ;SAVE THAT
- MOV A,B
- ANI 00FH ;ISOLATE DISK #
- CPI NDRVS ;IS IT LEGAL?
- JC WRMOK ;GO ON IF SO
- XRA A ;BACK TO DRIVE ZERO IF NOT
- MOV C,A ;USER # PROB BAD TOO
- WRMOK: ORA C ;COMBINE WITH USER #
- STA DFIMG ;PUT TO BASE PAGE IMAGE
- LXI SP,HSTBUF+HSTSIZ ;SET SP TO SCRATCH RAM
- LXI H,CCP+3 ;CP/M WARM START ADDR
- PUSH H
- ;
- ; MERGE HERE FROM COLD BOOT
- ;
- CPMLD: LDA IOBYTE ;GET CURRENT IOBYTE
- STA IOIMG ; INTO BASE PAGE IMAGE
- LXI B,8 ;MOVE ZERO PAGE STUFF
- LXI D,0 ; DOWN TO ZERO
- LXI H,BSIMG
- CALL BLOCK
- LXI H,05959H ;FORCE HOME OF N* DRIVES
- SHLD NSTRK ; A, B
- SHLD NSTRK+2 ; C, D
- MOV A,H ;MAKE SURE NEW DISK SELECTED
- STA CURDSK
- XRA A ;DRIVE ZERO VALUE
- STA HSTDSK
- STA HSTACT ;HOST BUFFER INACTIVE
- STA HSTWRT ;NO HOST WRITE PENDING
- STA UNACNT ;CLEAR UNALLOC COUNT
- LXI H,CCP ;CP/M CCP ADDRESS
- SHLD HSTADR ;READ INTO THERE
- INR A ;GET 1 IN ACC
- STA HSTTRK ;READ FROM TRACK ONE
- CALL WSETUP ;KICK MOTORS AND SEEK TRK
- XRA A ;SECTOR ZERO
- ;
- ; IF NOT NSHOLE:
- ;
- ; READ ALL TEN SECTORS FROM TRACK ONE, THEN ONE MORE
- ; SECTOR FROM TRACK ZERO, SECTOR THREE.
- ;
- ; IF NSHOLE:
- ;
- ; READ EIGHT SECTORS FROM TRACK 1, SECTORS 0-7, THEN
- ; THREE SECTORS FROM TRACK 0, SECTORS 3, 1, AND 2, IN
- ; THAT ORDER. SKIP THE 1K "HOLE" IN BDOS WHEN LOADING
- ; WHERE THE NORTH STAR CONTROLLER WILL BE.
- ;
- WREAD: STA HSTSEC ;SET CURRENT SECTOR TO READ
- CALL WRMRD ;READ SECTOR AND CHK STATUS
- LXI D,HSTSIZ ;SECTOR SIZE
- LHLD HSTADR ;CALC NEW ADDRESS
- DAD D
- SHLD HSTADR
- LDA HSTSEC ;BOP SECTOR #
- INR A
- ;
- IF NOT NSHOLE
- CPI 10 ;THROUGH WITH TRACK ONE?
- ENDIF ;NOT NSHOLE
- IF NSHOLE
- CPI 8 ;THROUGH WITH TRACK ONE?
- ENDIF ;NSHOLE
- ;
- JNZ WREAD ;GO GET NEXT SECTOR IF NOT
- XRA A ;TO TRACK ZERO,
- STA HSTTRK
- MVI A,3 ; SECTOR 3 IF SO
- STA HSTSEC
- CALL WSETUP ;KICK MOTORS AND SEEK TRK 0
- ;
- IF NSHOLE
- LXI D,KBYTE ;SKIP OVER N* CONTROLLER
- LHLD HSTADR
- DAD D
- SHLD HSTADR
- CALL WRMRD ;READ NEXT SECTOR
- LXI D,HSTSIZ ;ADVANCE PTR FOR NEXT SECTOR
- LHLD HSTADR
- DAD D
- SHLD HSTADR
- MVI A,1 ;READING SECTOR 1
- STA HSTSEC
- CALL WRMRD ;READ IT
- LXI D,HSTSIZ ;REPEAT FOR SECTOR 2
- LHLD HSTADR
- DAD D
- SHLD HSTADR
- MVI A,2
- STA HSTSEC
- ENDIF ;NSHOLE
- ;
- CALL WRMRD ;READ THE LAST SECTOR
- LXI H,HSTBUF ;NOW READ AND WRITE
- SHLD HSTADR ; USING DEBLOCK BUFFER
- ;
- ; THE NEXT TWO INSTRUCTIONS ARE ONLY INTERESTING IF YOU HAVE
- ; AN EPSON PRINTER WITH DEVICE SELECT. OTHERS SHOULD REMOVE.
- ; THE "OUT TTY" INSTRUCTION IS HARD-WIRED HERE INSTEAD OF MAKING
- ; A CALL TO BLIST SO THAT THE ABSENCE OF AN EPSON WILL NOT HANG
- ; US UP IN AN INFINITE WARM BOOT LOOP.
- ;
- MVI A,011H ;TELL EPSON PRINTER TO SELECT
- OUT TTY ; IF THERE AND NOT SELECTED
- ;
- LDA DFIMG ;RETRIEVE LAST USED DRIVE
- MOV C,A ; FOR BDOS
- RET ; THEN GO TO CP/M
- ;
- WSETUP: CALL SETUP ;KICK MOTORS AND SEEK TRK
- JMP WECHK
- ;
- WRMRD: CALL READNS ;READ HOST SECTOR
- WECHK: LDA ERFLAG ;CHECK FOR ERROR
- ORA A
- RZ ;RETURN IF NONE
- LXI H,MSGLE ;GET ERROR MESSAGE
- CALL MSGOT ;TYPE IT
- HLT ; THEN GIVE UP
- ;
- ; MSGOT DISPLAYS STRING OF CHARS PT'ED AT BY HL ON
- ; CONSOLE, UNTIL CHAR WITH PARITY BIT SET IS OUTPUT.
- ;
- MSGOT: PUSH PSW ;SAVE CALLER FLAGS
- MSGL: MOV C,M ;LOAD CHAR
- PUSH H ;SAVE HL
- LDA HUNGUP ;SEE IF TALKING ON PHONE
- ORA A
- PUSH PSW ;SAVE DECISION
- CZ CNSOT ;NO MODEM OUTPUT IF NOT
- POP PSW
- CNZ BCNSOT ;OUTPUT TO ALL CONSOLE
- ; IF SO
- POP H ;RESTORE HL
- MOV A,M ;GET CHAR TO LOOK AT IT
- INX H ;LEAVE PTR ON NEXT CHAR
- RAL ;IS HIGH BIT ON?
- JNC MSGL ;GO BACK IF NOT
- POP PSW ; ELSE RESTORE FLAGS
- RET ; AND RETURN
- ;
- ; DISK ERROR MESSAGES
- ;
- WPEMSG: DB 'Protec','t'+80H
- SDEMSG: DB 'Densit','y'+80H
- RERMSG: DB 'CR','C'+80H
- SYEMSG: DB 'Syn','c'+80H
- NIPMSG: DB 'Inde','x'+80H
- SNFMSG: DB 'Secto','r'+80H
- ;
- ERRMSG: DB ' err '
- ASCDSK: DB ' : trk',' '+80H
- SECMSG: DB ' sec',' '+80H
- NRDMSG: DB CR,LF,'Disk '
- NRD: DB ' : not ready',' '+80H
- CRLF: DB CR,LF+80H
- ;
- MSGLE: DB CR,LF,'Boot er','r'+80H
- ;
- ; NORTH STAR DD SECTOR TRANSLATE TABLE. AFTER
- ; DEBLOCKING, WORKS OUT TO SKEW FACTOR OF 5.
- ;
- TRAN5D: DB 01,02,03,04
- DB 21,22,23,24
- DB 05,06,07,08
- DB 25,26,27,28
- DB 09,10,11,12
- DB 29,30,31,32
- DB 13,14,15,16
- DB 33,34,35,36
- DB 17,18,19,20
- DB 37,38,39,40
- ;
- ; NORTH STAR DD DISK PARAMETER BLOCK
- ;
- DPBNSD: DW 40 ;SECTORS PER TRACK
- DB 3 ;BLOCK SHIFT FACTOR
- DB 07H ;BLOCK MASK
- DB 0 ;NULL MASK
- DW DSKSIZ-1 ;DISK SIZE - 1
- DW 63 ;DIRECTORY MAX
- DB 11000000B ;ALLOC 0
- DB 0 ;ALLOC 1
- DW 16 ;CHECK SIZE
- DW 2 ;TRACK OFFSET
- ;
- ; THE NEXT BYTE IS ONE WE HAVE ADDED SPECIFICALLY
- ; FOR THIS BIOS TO CONVENIENCE OUR DEBLOCKING ROUTINES.
- ; IT IS A SECTOR SHIFT MASK, AND EACH DISK PARAMETER
- ; BLOCK HAS ONE IN THIS POSITION. THE ALLOWABLE VALUES
- ; ARE AS FOLLOWS:
- ;
- ; 1000B ;1024 BYTES/SECTOR
- ; 0100B ; 512 BYTES/SECTOR
- ; 0010B ; 256 BYTES/SECTOR
- ; 0000B ; 128 BYTES/SECTOR
- ;
- ; FOR THE NORTH STAR DD DISKS, 512 IS HARD-CODED. FOR
- ; THE NORTH STAR SD DISKS, 256 IS HARD-CODED.
- ;
- DB 0100B ;512 BYTES/SECTOR
- ;
- ; THERE IS NO NORTH STAR SINGLE DENSITY TRANSLATE
- ; TABLE.
- ;
- TRAN5S: EQU 0 ;TELL SECTRN TO JUST ADD 1
- ;
- ; NORTH STAR SD DISK PARAMETER BLOCK (35 TRACK ONLY)
- ;
- DPBNSS: DW 20 ;SECTORS PER TRACK
- DB 3 ;BLOCK SHIFT FACTOR
- DB 07H ;BLOCK MASK
- DB 0 ;NULL MASK
- DW 80-1 ;DISK SIZE - 1
- DW 63 ;DIRECTORY MAX
- DB 11000000B ;ALLOC 0
- DB 0 ;ALLOC 1
- DW 16 ;CHECK SIZE
- DW 3 ;TRACK OFFSET
- DB 0010B ;256 BYTES/SECTOR
- ;
- ; SPECIAL DPB FOR 80 TRACKS, DOUBLE SIDED
- ;
- DPBNSC: DW 40 ;SECTORS PER TRACK
- DB 4 ;BLOCK SHIFT FACTOR
- DB 0FH ;BLOCK MASK
- DB 0 ;NULL MASK
- DW 395-1 ;DISK SIZE - 1
- DW 127 ;DIRECTORY MAX
- DB 11000000B ;ALLOC 0
- DB 0 ;ALLOC 1
- DW 32 ;CHECK SIZE
- DW 2 ;TRACK OFFSET
- ;
- DB 0100B ;512 BYTES/SECTOR
- ;
- ; DRIVE PARAMETER HEADER AREA
- ;
- ; DRIVES A: AND B: ARE 40 TRACKS, SINGLE SIDED
- ;
- D0DPH: DW 0 ;SECTOR TRAN TBL SET BY SELDSK
- DW 0 ;SCRATCH
- DW 0 ;SCRATCH
- DW 0 ;SCRATCH
- DW DIRBF ;DIRECTORY BUFFER
- DW 0 ;DRIVE PARAM BLK SET BY SELDSK
- DW D0CHK ;DRIVE CHANGE BLK
- DW D0ALL ;DRIVE ALLOCATION
- ;
- D1DPH: DW 0,0,0,0,DIRBF,0,D1CHK,D1ALL
- ;
- ; DRIVES C: AND D: ARE 80 TRACKS, DOUBLE SIDED
- ;
- D2DPH: DW TRAN5D,0,0,0,DIRBF,DPBNSC,D2CHK,D2ALL
- ;
- D3DPH: DW TRAN5D,0,0,0,DIRBF,DPBNSC,D3CHK,D3ALL
- ;
- ; ZERO PAGE IMAGE -- BLOCK MOVED TO BASE PAGE
- ;
- BSIMG: JMP BIOS+03H ;WARM BOOT VECTOR
- IOIMG: DS 1 ;IOBYTE SET BY CPMLD
- DFIMG: DS 1 ;DEF DISK AND USER, SET
- ; TO ZERO AT HANGUP
- JMP BDOS+06H ;BDOS CALL VECTOR
- ;
- ; BIOS VARIABLE STORAGE
- ;
- SEKDSK: DB 0 ;DRIVE NUMBER
- SEKTRK: DS 1 ;TRACK NUMBER
- SEKSEC: DS 1 ;SECTOR NUMBER
- SEKHST: DS 1 ;SEEK SHR SECSHF
- HSTACT: DS 1 ;HOST ACTIVE FLAG
- HSTWRT: DS 1 ;HOST WRITTEN FLAG
- ;
- RSFLAG: DS 1 ;READ SECTOR FLAG
- READOP: DS 1 ;1 IF READ OPERATION
- WRTYPE: DS 1 ;WRITE OPERATION TYPE
- DMAADR: DS 2 ;LAST DMA ADDRESS
- ENTPSW: DW 0 ;ENTRY PSW AT DISK READ/WRITE
- DTPTR: DW 0 ;DRIVE TABLE PTR
- ;
- UNACNT: DS 1 ;UNALLOC REC CNT
- UNADSK: DS 1 ;LAST UNALLOC DISK
- UNATRK: DS 1 ;LAST UNALLOC TRACK
- UNASEC: DS 1 ;LAST UNALLOC SECTOR
- ;
- ; DEBLOCKING INFO ABOUT THE CURRENTLY-SELECTED DISK
- ;
- UNAVAL: DS 1 ;# UNALLOC RECS/GROUP
- CPMSPT: DS 1 ;# CP/M SECTORS/TRACK
- SECSHF: DS 1 ;SECTOR SHIFT COUNT,
- ; LOG2 (# CP/M SECTORS/HOST BLOCK)
- SECMSK: DS 1 ;SECTOR MASK, # CP/M
- ; SECTORS/HOST BLOCK - 1
- ;
- ; DIRECTORY BUFFER
- ;
- DIRBF: DS SECSZ
- ;
- ; BDOS ALLOCATION AND CHECKSUM BUFFERS
- ;
- D0ALL: DS (DSKSIZ/8)+1 ;ALLOC 0
- D0CHK: DS 16 ;CHECKSUMS 0
- D1ALL: DS (DSKSIZ/8)+1 ;ALLOC 1
- D1CHK: DS 16 ;CHECKSUMS 1
- D2ALL: DS (395/8)+1 ;ALLOC 2
- D2CHK: DS 32 ;CHECKSUMS 2
- D3ALL: DS (395/8)+1 ;ALLOC 3
- D3CHK: DS 32 ;CHECKSUMS 3
- ;
- ; EVERYTHING FROM THIS POINT FOR THE NEXT
- ; 512 BYTES IS READ INTO MEMORY BY THE NORTH
- ; STAR BOOT PROM. OUR GOAL HERE IS TO GET
- ; A REASONABLE AMOUNT OF NORMAL BIOS CODE IN,
- ; BUT AT THE SAME TIME WE NEED THE PORTIONS
- ; THAT CAN READ THE DISK.
- ;
- ; IF THIS SECTION OVERLAYS PREVIOUS BIOS CODE
- ; OR DATA SPACE, THE PRECEDING BIOS MUST BE
- ; TRIMMED DOWN.
- ;
- PRVCHK EQU $ ;** MUST NOT EXCEED BOOTA **
- ;
- ORG BIOS+(HSTSIZ*5) ;ORG TO COLD BOOT
- ;
- BOOTA: DB BOOTA SHR 8 ;TELL PROM LOAD ADDR
- ;
- ; THE NEXT NINE LOCATIONS ARE SKIPPED OVER
- ; BY THE BOOT PROM, WHICH READS THIS SECTOR
- ; THEN JUMPS TO BOOTA+0AH, SO PUT USEFUL VARIABLES
- ; HERE. NOTE THAT ALL VARIABLES IN THIS SECTOR
- ; WITH GENNED-IN VALUES ARE SET UP FOR COLD
- ; BOOT LOADING OF BIOS.
- ;
- HSTADR: DW BIOS ;READ BIOS INTO HERE TO START,
- ; BUT NORMALLY PTS TO HSTBUF
- HSTTRK: DB 0 ;HOST TRACK NUMBER
- HSTSEC: DB 5 ;HOST SECTOR NUMBER
- HSTDSK: DB 0 ;HOST DISK NUMBER
- ERFLAG: DB 0 ;ERROR REPORTING
- CURDSK: DB 059H ;CURRENT ACTIVE DISK,
- ; GENNED-IN FORCE SELECT
- COLDB: DB 1 ;COLD BOOT WHEN NON-ZERO
- ERSEC: DS 1 ;SECTOR IN ERROR
- ;
- ; THIS IS THE SECTION OF THE COLD BOOT THAT
- ; READS IN THE REST OF BIOS. ON MORE CONVENTIONAL
- ; CP/M SYSTEMS, THIS WOULD BE THE BLOCK ZERO
- ; BOOT. READ BIOS INTO MEMORY, THEN JUMP TO
- ; IT TO FINISH COLD BOOTING.
- ;
- BOOT: DI ;ALLOW NO PROCESSOR INTERRUPTS
- LXI SP,HSTBUF+HSTSIZ ;SET SP TO SCRATCH RAM
- CALL SETUP ;GIVE MOTORS EXTRA KICK
- ; AND SEEK TRK 0
- ;
- BOOTL: CALL READNS ;READ NEXT SECTOR OF BIOS
- ;WITH COLDB NON-ZERO, NO
- ; RETURN IF I/O ERROR
- LXI H,HSTSEC ;IF OK, BOP SEC NUM
- INR M
- LHLD HSTADR ; AND ADVANCE READ ADDR
- LXI D,HSTSIZ
- DAD D
- SHLD HSTADR
- MVI A,BOOTA SHR 8 ;SEE IF READ ENUFF
- CMP H
- JNZ BOOTL ;LOOP IF NOT
- JMP INIT ;GO START BIOS IF SO
- ;
- ; REMAINING NEEDED VARIABLES
- ;
- RTCNT: DS 1 ;ERROR RETRY COUNTER
- NSDENS: DS 1 ;DENSITY OF LAST NS DISK BLOCK
- ; READ, SD=128, DD=0
- NSCNT: DB 00H ;COUNT AND DENSITY FLAG, SET
- ; BY WRITEHST TO MATCH ID SECTOR
- TRUTRK: DS 1 ;TRUE DISK SEEK TRACK
- ;
- ; NORTH STAR CURRENT TRACK TABLE
- ;
- NSTRK: DB 059H ;NO CURRENT TRACK YET
- DB 059H ;EACH ENTRY CONTAINS
- DB 059H ; THE LAST TRACK POSITION
- DB 059H ; FOR THE UNIT 1-4
- ;
- ; DRIVE STEPPING RATE TABLE (SEE STEP ROUTINE)
- ;
- STPTBL: DW STPSLW ;DRIVE A = SLOW
- DW STPSLW ;DRIVE B = SLOW
- DW STPFST ;DRIVE C = FAST
- DW STPFST ;DRIVE D = FAST
- ;
- ; READHST PERFORMS THE PHYSICAL READ FROM THE
- ; NORTH STAR DISK. ON ENTRY, DRIVE IS IN HSTDSK,
- ; TRACK IS IN HSTTRK, SECTOR IS IN HSTSEC. ON
- ; EXIT, ERROR FLAG IS IN ERFLAG (ZERO IF NONE).
- ;
- ; *** INTERRUPTS MUST BE DISABLED HERE ***
- ;
- READHST:
- MVI A,10 ;RETRY COUNT ON ERROR
- STA RTCNT
- ;
- READRT: CALL SETUP ;SELECT DRIVE AND
- ; SEEK TO TRACK
- LDA ERFLAG ;CHECK FOR ERRORS
- ORA A
- RNZ ;INDEX PULSE NOT FOUND IS FATAL
- ;
- ; HERE TO READ NORTH STAR WITHOUT TRACK SEEK FOR SPEED
- ;
- READNS: CALL POSEC ;POSITION TO OUR SECTOR
- JNZ SNFERR ;ERROR IF NOT FOUND
- MVI B,08CH ;COUNT FOR SYNC CHAR LOOP
- LXI D,CCMND+40H ;SET UP READ DATA REGS
- ;
- ; WAIT FOR RE SO WE CAN DO SECTOR READ, AND TEST
- ; THE DOUBLE DENSITY BIT.
- ;
- WAITRE: LDA CCMND+10H ;GET A-STATUS
- ANI 04H ;CHECK RE
- JZ WAITRE ;LOOP UNTIL RE TRUE
- XTHL ;KILL TIME TO GET INTO ZEROES
- XTHL
- XTHL
- XTHL
- XTHL
- XTHL
- XTHL
- XTHL
- LDA CCMND+10H ;GET A-STATUS AGAIN
- ANI 20H ;ARE WE READING DOUBLE DENS?
- RAL ;MAKE 80H IF NOT, ZERO IF SO
- RAL
- XRI 80H
- STA NSDENS ;SAVE DENSITY FOR CALLER
- ;
- ; NOW WAIT FOR SYNC CHAR DETECTED. ERROR IF WE HAVE TO
- ; WAIT TOO LONG.
- ;
- READ5: LDA CCMND+10H ;WAIT FOR SYNC CHAR DETECTED
- RRC ;CHECK BIT
- JC READ15 ;OUT IF GOT IT
- DCR B ;COUNT DOWN IF NOT
- JNZ READ5 ;GO BACK IF STILL OK
- MVI A,1 ;SYNC ERROR IF WAITED TOO LONG
- LXI H,SYEMSG ;SYNC ERROR MESSAGE
- ;
- RERR: STA ERFLAG ;STORE ERROR CODE
- LDA RTCNT ;COUNT OFF A RETRY
- DCR A
- STA RTCNT
- JNZ READRT ;IF COUNT LEFT, GO RETRY
- ;
- ; READ ERROR RETRIES FAILED. FLAG ERROR.
- ;
- JMP DSKERR ;TELL OPERATOR OF ERROR THEN OUT
- ;
- SNFERR: STA ERFLAG ;SET ERROR FLAG
- LXI H,SNFMSG
- JMP DSKERR ;REPORT ERROR ON WAY OUT
- ;
- ; READ THE DATA INTO HSTBUF
- ;
- READ15: LHLD HSTADR ;READ INTO HERE
- MVI B,0 ;INIT CHECKSUM BYTE
- LDA NSDENS ;GET # BYTES TO READ
- MOV C,A ;PUT READ COUNT IN C-REG
- ;
- READ20: LDAX D ;READ NEXT DATA BYTE
- MOV M,A ; AND PUT IT IN BUFFER
- XRA B ;ADD TO CHECKSUM
- RLC
- MOV B,A
- INX H ;BOP BUFFER PTR
- NOP ;KILL TIME
- LDAX D ;GET NEXT BYTE
- MOV M,A
- XRA B
- RLC
- MOV B,A
- INX H
- DCR C ;COUNT OFF LAST PAIR
- JNZ READ20 ;GO BACK IF MORE TO DO
- LDAX D ; ELSE READ CRC BYTE
- XRA B ; AND CHECK IT AGAINST OURS
- STA ERFLAG ;IF OK, ZERO EFLAG
- RZ ; AND RETURN TO CALLER
- MVI A,2 ; ELSE FLAG CHECKSUM ERROR
- LXI H,RERMSG ;MESSAGE IF NEEDED
- JMP RERR ;GO MAYBE RETRY
- ;
- ; SETUP SELECTS THE UNIT CORRESPONDING TO HSTDSK,
- ; THEN SEEKS TO THE TRACK SPECIFIED BY HSTTRK.
- ; WRITE PRECOMPENSATION IS SET IF REQUIRED AS
- ; WELL. ON ERROR, ERFLAG CONTAINS A NON-ZERO
- ; VALUE ON RETURN. IF HSTTRK IS >= 80, SECOND SIDE
- ; IS SELECTED.
- ;
- SETUP: MVI B,00H ;ASSUME TOP SIDE
- LDA HSTTRK ;CHECK TARGET TRK
- STA TRUTRK ;ASSUME GOING HERE
- SUI 80 ;GOING TO SIDE TWO?
- JC SIDE1 ;PASS IF NOT
- MVI B,40H ;SIDE TWO SELECT
- STA TRUTRK ;GOING HERE
- SIDE1:
- LDA NSCNT ;GET DENSITY FLAG
- XRI 80H ;INVERT TO SET DD
- MOV C,A ;SAVE MASK
- LDA HSTDSK ;WANT THIS DISK
- INR A ;REMAP TO CONTROLLER MASK
- CPI 03H ;IF UNIT 1 OR 2,
- JC SET0 ; GOT CORRECT MASK
- RAL ;IF 3 OR 4, MUST MAP
- ANI 0CH ; TO 4 OR 8 RESPECTIVELY
- SET0:
- ORA C ;OR IN DENSITY MASK
- ORA B ;OR IN SIDE MASK
- MOV C,A ;SAVE IN REG C
- CALL WAIT1S ;WAIT A SECTOR TIME, GET A-STAT
- ANI 10H ;ARE MOTORS ALREADY ON?
- LDA CCMND+15H ;GIVE THEM EXTRA KICK ANYWAY
- JNZ SET5 ;BRANCH IF SO
- MVI D,17H ;WAIT FOR MOTORS TO
- CALL SCWAIT ; COME UP TO SPEED IF NOT
- JMP SET10 ; THEN GO SELECT DRIVE
- ;
- SET5: LDA CURDSK ;IS THIS THE CURRENT DISK?
- CMP C ;CHECK DISK AND SIDE SELECT
- JZ SET20 ;GO SEEK TO TRACK IF MATCH
- ;
- ; MUST SELECT NEW DISK OR CHANGE SIDE
- ;
- SET10: MOV A,C
- STA CURDSK ;NEW CURRENT DISK
- MVI B,CORDER SHR 8 ;SET UP FOR SELECT
- LDAX B ; AND DO IT
- MVI D,2 ;WAIT TWO SECTOR TIMES
- CALL SCWAIT ; BEFORE LOOKING FOR INDEX
- MVI B,12 ;DON'T LOOK TOO LONG
- ;
- SET15: CALL WAIT1S ;WAIT A SECTOR TIME, GET A-STAT
- ANI 40H ;INDEX HOLE SEEN?
- JNZ SET20 ;CAN GO SEEK NOW IF SO
- DCR B ;COUNT DOWN IF NOT
- JNZ SET15 ; AND MAYBE GO LOOK AGAIN
- ;
- ; INDEX HOLE NOT FOUND. DISK IS PROBABLY NOT LOADED.
- ;
- MVI A,4 ;NO INDEX PULSE
- STA ERFLAG
- LXI H,NIPMSG
- CALL DSKERR ;TELL OPERATOR
- CALL NOTRDY ; AND CLAIM DISK NOT READY
- MVI A,059H ;FORCE RESELECT OF DISK
- STA CURDSK
- JMP SETUP ;TRY TO GET DISK AGAIN
- ;
- ; SEEK TO TRACK SPECIFIED BY TRUTRK NOW, AND SET
- ; WRITE PRECOMPENSATION IF APPROPRIATE.
- ;
- SET20: LDA HSTDSK ;GET NSTRK INDEX
- MOV C,A
- MVI B,0
- LXI H,NSTRK ;PT AT TABLE
- DAD B ; THEN AT CORRECT ENTRY
- MOV A,M ;GET CURRENT TRACK
- PUSH H ;SAVE NSTRK PTR
- XRI 59H ;DISK EVER ACCESSED?
- CZ SEEK ;IF NOT, HOME DRIVE
- POP H ;RESTORE NSTRK PTR
- LDA TRUTRK ;SEEK TO THIS TRACK
- PUSH PSW ;SAVE OVER CALL
- CALL SEEK ;DO FINAL SEEK
- POP PSW ;GET TRUTRK BACK
- CPI 14H+1 ;ARE WE BEYOND TRACK 14H?
- JC SET25 ;GO ON IF NOT
- LDA NSCNT ;SEE IF DD OR SD
- ORA A
- JNZ SET25 ;NO PRECOMP IF SD
- LDA CURDSK ;IF SO, GET CURRENT MASK
- ORI 20H ; AND SET PRECOMP BIT
- MVI H,CORDER SHR 8
- MOV L,A
- MOV A,M ;SET BIT IN CONTROLLER
- ;
- SET25: XRA A
- STA ERFLAG ;NO ERRORS
- RET
- ;
- ; POSEC IS CALLED TO POSITION TO HSTSEC WITHIN
- ; THE CURRENT TRACK. ERROR IS RETURNED BY NON-ZERO
- ; IF WE CAN'T FIND THE SECTOR AFTER 30 TRIES.
- ;
- POSEC: LDA HSTSEC ;GET TARGET SECTOR
- MOV C,A ;IN C
- STA ERSEC ;SET UP FOR POSSIBLE ERROR
- MVI B,30 ;LOOK AT THIS MANY SECTORS
- ;
- POSC5: CALL WAIT1S ;WAIT FOR NEXT SECTOR
- LDA CCMND+35H ;KICK MOTORS AND GET SECNUM
- ANI 0FH ;STRIP NON-SECTOR BITS
- SUB C ;IS THIS THE TARGET SECTOR?
- RZ ;OUT IF GOT IT
- DCR B ;COUNT OFF IF DIDN'T
- JNZ POSC5 ;GO BACK IF NOT GIVING UP
- INR B ;SET NON-ZERO IF NOT FOUND
- RET
- ;
- ; SEEK TO TRACK SPECIFIED BY ACC. CURRENT PTR INTO
- ; NSTRK TABLE IS GIVEN BY HL.
- ;
- SEEK: MOV C,A ;SAVE TARGET TRK #
- SUB M ;SEE HOW FAR AWAY WE ARE
- ; FROM TARGET TRACK
- MOV M,C ; BUT ALWAYS SET NEW TRACK
- RZ ;IF THERE, DONE
- LXI H,CORDER+30H ;ASSUME STEPPING IN
- MOV C,A ;SAVE STEP COUNT
- JP STEPIN ;BRANCH IF RIGHT
- CMA ;IF WRONG, NEGATE COUNT
- INR A
- MOV C,A ; THEN SAVE THAT
- LDA CCMND+20H ;GET B-STATUS
- ANI 01H ;ARE WE ON TRACK ZERO?
- RNZ ;MUST BE DONE IF SO
- MVI L,10H ;IF NOT, STEPPING OUT
- ;
- STEPIN: LDA CURDSK ;GET CURRENT UNIT MASK
- ORA L ;FORM FINAL CORDER VALUE
- MOV L,A
- MOV D,M ;SET THE STEP FLIP-FLOP
- ORI 10H
- MOV L,A
- MOV D,M ;SET IT AGAIN FOR SOME REASON
- XRI 10H
- MOV L,A
- MOV D,M ;NOW RESET THE STEP FLIP-FLOP
- ;
- ; WAIT STEP DELAY TIME GIVEN BY CORRESPONDING ENTRY
- ; IN STPTBL. NOTE THAT STEP TIMES ARE A FUNCTION OF
- ; PROCESSOR SPEED AND DRIVE MODEL, AND MAY BE ADJUSTED
- ; BY PATCHING STPTBL. THE DELAY LOOP BELOW TAKES
- ; 31 T-STATES. AT 4 MHZ, THAT'S 7.75 USEC. AT 2.5 MHZ,
- ; THAT'S 12.4 USEC. AT 4 MHZ WITH ONE M1 WAIT PER
- ; OPCODE, THAT'S 8.5 USEC.
- ;
- PUSH H ;SAVE SOME REGS
- LDA HSTDSK ;GET DRIVE #
- ADD A ;DOUBLE FOR WORD ENTRIES
- ADI STPTBL AND 0FFH ;CALC TABLE PTR
- MOV L,A ; AND PUT IN HL
- MVI A,(STPTBL SHR 8) AND 0FFH
- ACI 0 ;PICK UP POSS CARRY
- MOV H,A
- MOV A,M ;GET DELAY CTR
- INX H
- MOV H,M ; INTO HL
- MOV L,A
- ;
- STEPW: LXI D,1 ;DELAY
- DAD D
- JNC STEPW
- POP H ;RESTORE REGS
- LDA CCMND+25H ;GET B-STATUS AND KICK MOTORS
- ANI 01H ;ARE WE AT TRACK ZERO?
- JNZ WAIT1S ;DONE STEPPING IF SO
- DCR C ; ELSE COUNT OFF LAST TRACK
- JNZ STEPIN ;GO BACK IF MORE TO DO
- ; ELSE WAIT ONE MORE SECTOR TIME
- ; TO MAKE SURE SAFE FOR I/O
- ;
- ; SECTOR WAIT. ON ENTRY, # SECTORS TO WAIT IS IN D.
- ; ON EXIT, D=0 AND ACC=A-STATUS. CALL WAIT1S TO WAIT
- ; ONE SECTOR TIME.
- ;
- WAIT1S: MVI D,1 ;WAIT ONE SECTOR TIME
- ;
- SCWAIT: LDA CCMND+11H ;RESET SECTOR FLAG
- SCW5: LDA CCMND+10H ;GET A-STATUS
- ORA A ;CHECK SECTOR FLAG
- JP SCW5 ;WAIT FOR IT IF NOT UP
- LDA CCMND+11H ; ELSE RESET SECTOR FLAG
- DCR D ;COUNT DOWN WAIT COUNTER
- JNZ SCW5 ;GO BACK IF MORE TO DO
- RET ; ELSE RETURN A-STATUS IN ACC
- ;
- ; DISK ERRORS REPORTED HERE, BECAUSE STUPID BDOS GIVES
- ; NO USEFUL INFORMATION.
- ;
- DSKERR: LDA COLDB ;IN COLD BOOT?
- ORA A ;IF SO, CNSOT NOT IN MEM YET
- JZ DSKER2 ;CAN REPORT IF NOT
- JMP NSROM ;BACK TO N* BOOT ROM IF SO,
- ; SINCE CNSOT NOT IN MEM
- ;
- EBOOT EQU $-1 ;LAST USED COLD BOOT BYTE
- ;
- ;
- ; NORTH STAR HOST SECTOR BUFFER
- ;
- HSTBUF: DS HSTSIZ ;HOST BUFFER
- ;
- LAST EQU $-1 ;LAST USED BYTE IN MEM
- ;
- END
-