forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1296 lines
39 KiB
1296 lines
39 KiB
;:::::::::::::::::::::::::::::::::::::::::::::::::*************************
|
|
; Byte I/O Routines *** Hardware Specific ***
|
|
; - D-X Designs Pty Ltd P112 - *************************
|
|
;
|
|
; Several serial and parallel options exist on the P112, with two serial
|
|
; ports available at RS-232 signalling levels. The primary port defined here
|
|
; as COM1 uses SCC Channel A of the Z80182. A 16550-compatible serial port
|
|
; on the SMC FDC37C665 is used as COM2. Three other serial ports (the two
|
|
; ACSI ports in the Z180 core, and SCC Channel B) are available at TTL
|
|
; voltage levels on a single header and may be defined as COM3-5 if the pins
|
|
; from the Z182 are not otherwise used.
|
|
; This code supports the additional serial channels if the MORDEV equate
|
|
; is set to YES. If any of the three additional serial ports are defined
|
|
; (ESCC_B, ASCI_0, ASCI_1), then the System Configuration Register is set to
|
|
; Zero activating the additional signals in the conditions specified herein
|
|
; as activated by options in DEF-DX.LIB.
|
|
; A full Parallel port on the SMC FDC37C655 (in Normal Centronics mode) is
|
|
; used as the primary List (Printer) Device.
|
|
;
|
|
; NOTE: At the present time, it appears that port 0D9H (ENH182) cannot be set
|
|
; so ESCC operation at 24 MHz will occur at the full clock rate instead
|
|
; of being divided by Two as specified in Zilog documentation. Code
|
|
; managing ENH182 is commented out with ";;--" markers (HFB).
|
|
;
|
|
; 1.2 - 28 Aug 01 - Final scrub for GPL release. HFB
|
|
; 1.1a- 11 May 97 - Cleaned code, fixed added port accesses. HFB
|
|
; 1.1 - 25 Jan 97 - Revised ESCC Baud rate calcs, added COM3-5. HFB
|
|
; 1.0 - 19 Jun 96 - Initial Release for the P112 from YASBEC. HFB
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Place constants for Expansions here
|
|
|
|
CSEG
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Byte Device Control Tables
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
|
|
DEVCFG:
|
|
|
|
; The Clock Rate for the SCC channels on the Z80182 is based on a divider
|
|
; constant loaded in extended registers, the Processor Crystal frequency,
|
|
; and the setting of the divider in the SCC Register (1FH).
|
|
;
|
|
; NOTE: Divisor values are computed based on a compromise between the Crystal
|
|
; rates considered "standard" (6.144, 9.216, 12.288 MHz, etc) and the
|
|
; 16.000 MHz initially placed on the P112. Higher data rates (38.4 kbps
|
|
; and higher) may be out of tolerance, particularly at low CPU speeds.
|
|
;
|
|
; Clock rates for the serial port on the SMC 37C655 are based on a software
|
|
; programmable divider from the 24 MHz crystal driving the chip.
|
|
|
|
COM1: DEFB 'COM1' ; 4-Char ID
|
|
DEFB 11101011B ; Baud Rate
|
|
; ||||++++--- Baud Rate setting (19.2 kbps)
|
|
; ++++------- Maximum Baud Rate (115.2 kbps)
|
|
; Rates are as:
|
|
; 0000 = None 0001 = 134.5 0011 = 50 0011 = 75
|
|
; 0100 = 150 0101 = 300 0110 = 600 0111 = 1200
|
|
; 1000 = 2400 1001 = 4800 1010 = 9600 1011 = 19200
|
|
; 1100 = 38400 1101 = 76800 1110 = 115200 1111 = Fixed
|
|
|
|
DEFB 11100001B ; Config Byte (In,Out,CTS/RTS control,1 Stop)
|
|
; |||||||+---------- Stop Bits 1 (1), 2 (0)
|
|
; ||||||+----------- Parity Enable (1), Disable (0)
|
|
; |||||+------------ Parity Even (1), Odd (0)
|
|
; ||||+------------- Data Bits 8 (0), 7 (1)
|
|
; |||+-------------- Xon-Xoff Handshake
|
|
; ||+--------------- CTS/RTS Handshake
|
|
; |+---------------- Input Device No (0), Yes (1)
|
|
; +----------------- Output Device No (0), Yes (1)
|
|
|
|
DEFB 0FFH ; Input Data Mask
|
|
DEFB 0FFH ; Output Data Mask
|
|
|
|
DEFW COM1OT ; COM 1 Byte Output
|
|
DEFW COM1OS ; COM 1 Output Status
|
|
DEFW COM1IN ; COM 1 Byte Input
|
|
DEFW COM1IS ; COM 1 Input Status
|
|
|
|
COM2: DEFB 'COM2' ; 4-Char ID
|
|
DEFB 11101010B ; Baud Rate (115.2k Max, 9600 Set)
|
|
DEFB 11100001B ; Config Byte (In,Out,CTS/RTS control,1 Stop)
|
|
DEFB 0FFH ; Input Data Mask
|
|
DEFB 0FFH ; Output Data Mask
|
|
|
|
DEFW COM2OT ; COM 2 Byte Output
|
|
DEFW COM2OS ; COM 2 Output Status
|
|
DEFW COM2IN ; COM 2 Byte Input
|
|
DEFW COM2IS ; COM 2 Input Status
|
|
|
|
PIO1: DEFB 'PIO1' ; 4-Char ID
|
|
DEFB 00000000B ; Baud Rate (None)
|
|
DEFB 10000000B ; Config Byte (Output Only)
|
|
DEFB 0FFH ; Input Data Mask
|
|
DEFB 07FH ; Output Data Mask
|
|
|
|
DEFW PIO1OT ; PIO Byte Output
|
|
DEFW PIO1OS ; PIO Output Status
|
|
DEFW PIO1IN ; PIO Byte Input
|
|
DEFW PIO1IS ; PIO Input Status
|
|
|
|
IF MOVCPM OR [MORDEV AND NOT [ESCC_B OR ASCI_0 OR ASCI_1]]
|
|
DEFB 'NULL' ; 4-Char ID
|
|
DEFB 00000000B ; Baud Rate (None)
|
|
DEFB 11000000B ; Config Byte
|
|
DEFB 0FFH ; Input Data Mask
|
|
DEFB 0FFH ; Output Data Mask
|
|
|
|
DEFW ISFALSE ; Null Output
|
|
DEFW ISTRUE ; Null Output Status
|
|
DEFW ISFALSE ; Null Input
|
|
DEFW ISTRUE ; Null Input Status
|
|
ENDIF
|
|
|
|
IF MORDEV AND NOT MOVCPM ; Include additional devices
|
|
; Add Expansion Char IO here with Device format as above
|
|
|
|
IF ESCC_B
|
|
COM3: DEFB 'COM3' ; 4-Char ID
|
|
DEFB 11101010B ; Baud Rate (115.2k Max, 9600 Set)
|
|
DEFB 11100001B ; Config Byte (In,Out,CTS/RTS control,1 Stop)
|
|
DEFB 0FFH ; Input Data Mask
|
|
DEFB 0FFH ; Output Data Mask
|
|
|
|
DEFW COM3OT ; COM 3 Byte Output
|
|
DEFW COM3OS ; COM 3 Output Status
|
|
DEFW COM3IN ; COM 3 Byte Input
|
|
DEFW COM3IS ; COM 3 Input Status
|
|
ENDIF
|
|
IF ASCI_0
|
|
COM4: DEFB 'COM4' ; 4-Char ID
|
|
DEFB 11001010B ; Baud Rate (38.4k Max, 9600 Set)
|
|
DEFB 11100001B ; Config Byte (In,Out,CTR/RTS control, 1 Stop)
|
|
DEFB 0FFH ; Input Data Mask
|
|
DEFB 0FFH ; Output Data Mask
|
|
|
|
DEFW COM4OT ; COM 4 Byte Output
|
|
DEFW COM4OS ; COM 4 Output Status
|
|
DEFW COM4IN ; COM 4 Byte Input
|
|
DEFW COM4IS ; COM 4 Input Status
|
|
ENDIF
|
|
IF ASCI_1
|
|
COM5: DEFB 'COM5' ; 4-Char ID
|
|
DEFB 11001010B ; Baud Rate (38.4k Max, 9600 Set)
|
|
DEFB 11100001B ; Config Byte (In,Out,CTR/RTS control, 1 Stop)
|
|
DEFB 0FFH ; Input Data Mask
|
|
DEFB 0FFH ; Output Data Mask
|
|
|
|
DEFW COM5OT ; COM 5 Byte Output
|
|
DEFW COM5OS ; COM 5 Output Status
|
|
DEFW COM5IN ; COM 5 Byte Input
|
|
DEFW COM5IS ; COM 5 Input Status
|
|
ENDIF
|
|
ENDIF ;Mordev & Not Movcpm
|
|
|
|
DEFB 0 ; - End-of-Table marker
|
|
MAXBDV EQU [$-DEVCFG-1]/[COM2-COM1] ; Number of Character Devices Defined
|
|
|
|
DEVTBL: LD HL,DEVCFG ; BYTE device table
|
|
RET ; CP/M-3 device init
|
|
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; COM1 Drivers
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Uses Z80182 SCC Channel A (Default to Console)
|
|
;.....
|
|
; COM1 Input Status Test
|
|
; Bit 0 of SCC Ch.A Control Port signifies Char Ready
|
|
|
|
COM1IS: IN0 A,(SCCACNT) ; Console Input Status
|
|
RRA ; Input Ready = Bit0 -> Carry
|
|
SBC A,A ; A=00 if Not Ready, FF if Char Ready
|
|
RET
|
|
|
|
;.....
|
|
; COM1 Input Routine
|
|
; Remain in Loop until Char ready, then Return Char in A
|
|
|
|
COM1IN: CALL COM1IS ; Console input from SCC Ch.A Ready?
|
|
JR Z,COM1IN ; ..loop if Not
|
|
IN0 A,(SCCAD) ; Else Read SCC Ch.A Data
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD C,A ; Store byte temporarily
|
|
LD A,(COM1+6) ; .get Input mask
|
|
AND C ; ..and apply to byte
|
|
ELSE ; (Swapping permitted)
|
|
IPAT1: AND $-$ ; Char Mask patched in Config
|
|
ENDIF ;Movcpm
|
|
RET
|
|
|
|
;.....
|
|
; COM1 Output Status Test
|
|
|
|
COM1OS:
|
|
IF XONOFF
|
|
LD A,(COM1+5) ; Get this Chan's Config settings
|
|
AND 00010000B ; Xon/Xoff in use?
|
|
JR Z,COM1O0 ; ..jump if Not
|
|
LD A,(COM1WT) ; Else get Current flow status
|
|
RLA
|
|
LD A,00 ; (prepare for stopped)
|
|
JR C,SOSTV ; ..jump to return Not Ready if Stopped
|
|
COM1O0:
|
|
ENDIF ;Xonoff
|
|
IN0 A,(SCCACNT) ; Read SCC Ch.A Control Reg
|
|
RRA ; Output Ready = Bit 2
|
|
RRA
|
|
RRA ; -> Carry
|
|
SBC A,A ; A=00 if Not Ready, FF if Xmt Buffer Empty
|
|
RET
|
|
|
|
;.....
|
|
; COM1 Output Routine (Byte to Send in C)
|
|
|
|
COM1OT: CALL COM1OS ; Output to SCC Ch.A Ready?
|
|
JR Z,COM1OT ; ..loop if Not
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD A,(COM1+7) ; Get output mask
|
|
AND C ; .apply to byte
|
|
ELSE ; (Swapping permitted)
|
|
LD A,C ; Get Char
|
|
OPAT1: AND $-$ ; mask as set in Config
|
|
ENDIF ; Movcpm
|
|
OUT0 (SCCAD),A ; and send
|
|
RET
|
|
|
|
PAGE
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; COM2 Drivers
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Uses 16550-compatible SMC FDC37C665 Serial Port (defaults to Aux)
|
|
;.....
|
|
; COM2 Input Status Test
|
|
|
|
COM2IS: IN0 A,(_LSR) ; Input Status Reg Byte
|
|
RRA ; Rcv Rdy Bit[0] -> Carry
|
|
SBC A,A ; A=00 if Not Ready, FF if Char received
|
|
RET
|
|
|
|
;.....
|
|
; COM2 Input Routine
|
|
|
|
COM2IN: CALL COM2IS ; Char Ready?
|
|
JR Z,COM2IN ; ..loop if Not
|
|
IN0 A,(_RBR) ; Else Read Receive Buffer
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD C,A ; Save byte
|
|
LD A,(COM2+6) ; .get mask
|
|
AND C ; ..apply it
|
|
ELSE ; (Swapping permitted)
|
|
IPAT2: AND $-$ ; Mask as set in Config
|
|
ENDIF ;Movcpm
|
|
RET
|
|
|
|
;.....
|
|
; COM2 Output Status Test
|
|
|
|
COM2OS:
|
|
IF XONOFF
|
|
LD A,(COM2+5) ; Get Config Byte
|
|
AND 00010000B ; Xon/Xoff Active?
|
|
JR Z,COM2O0 ; ..jump if Not
|
|
LD A,(COM2WT) ; Get Flags Byte
|
|
RLA ; Xoff to Carry
|
|
LD A,0 ; (prepare for Xoff active)
|
|
JR C,SOSTV ; ..jump if Waiting to Return Not Rdy
|
|
COM2O0: ;..else fall thru to Check Real Status..
|
|
ENDIF ;xonoff
|
|
IF RTSCTS
|
|
LD A,(COM2+5) ; Get this Chan's Config settings
|
|
AND 00100000B ; RTS/CTS in use?
|
|
JR Z,COM2O1 ; ..jump if Not
|
|
IN0 A,(_MMSR) ; Else Get Port 1 Modem Status
|
|
BIT 4,A ; Clear-To-Send?
|
|
LD A,0 ; (prepare for No)
|
|
JR Z,SOSTV ; ..jump if Not
|
|
COM2O1:
|
|
ENDIF ;Rtscts
|
|
IN0 A,(_LSR) ; Read Status Reg
|
|
SOSTV: AND 20H ; Mask Bit of interest
|
|
RETST: RET Z ; ..return if nothing valid
|
|
ISTRUE: OR 0FFH ; Else set flags for Ready
|
|
RET
|
|
|
|
;.....
|
|
; COM2 Output Routine
|
|
|
|
COM2OT: CALL COM2OS ; Test if ready
|
|
JR Z,COM2OT ; ..loop if not
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD A,(COM2+7) ; Get output mask
|
|
AND C ; apply
|
|
ELSE ; (Swapping permitted)
|
|
LD A,C ; Get Output Char
|
|
OPAT2: AND $-$ ; mask as set in Config
|
|
ENDIF ;Movcpm
|
|
OUT0 (_THR),A ; and send char to Xmt Holding Reg
|
|
RET
|
|
|
|
PAGE
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Parallel I/O Drivers
|
|
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Uses "Standard" Parallel Centronics mode of SMC37C655 (output only)
|
|
;.....
|
|
; Parallel Input Status Test
|
|
|
|
PIO1IS: JR ISTRUE ; Not implemented
|
|
|
|
;.....
|
|
; Parallel Input Data fetch
|
|
|
|
PIO1IN: JP ISFALSE ; Not implemented
|
|
|
|
;.....
|
|
; Parallel Output Status Test
|
|
|
|
PIO1OS: IN0 A,(SPORT) ; Read Port Status
|
|
RLA ; Status Bit [7] -> Carry
|
|
SBC A,A ; A=0 if Not Ready, FF if Ready to Send
|
|
RET
|
|
|
|
;.....
|
|
; Parallel Output Routine
|
|
|
|
PIO1OT: CALL PIO1OS ; List on the parallel device
|
|
JR Z,PIO1OT
|
|
IF MOVCPM ; (No Swap Allowed)
|
|
LD A,(PIO1+7) ; Get output mask
|
|
AND C ; ..and apply to char
|
|
ELSE ; (Swapping permitted)
|
|
LD A,C ; Get Output Char
|
|
OPATP: AND $-$ ; .mask as set in Config
|
|
ENDIF ;Movcpm
|
|
OUT0 (DPORT),A ; Latch the output byte to Data Port
|
|
LD A,0DH
|
|
OUT0 (CPORT),A ; Strobe (STB) = 1 to Control Port
|
|
NOP ; (delay)
|
|
NOP
|
|
LD A,0CH
|
|
OUT0 (CPORT),A ; then Strobe = 0 to Control Port
|
|
RET
|
|
PAGE
|
|
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
;---->> Additional Driver Code goes Here <<----
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; To constrain the size of the boot system to available space on
|
|
; Floppy Disks, The additional drivers are only included if a
|
|
; banked system is being assembled, and "MorDev" is set TRUE.
|
|
|
|
IF MORDEV AND NOT MOVCPM
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; COM3 Driver
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Z80182 SCC Channel B, Auxiliary Serial Port
|
|
IF ESCC_B
|
|
;.....
|
|
; COM3 Input Status Test
|
|
; Bit 0 of SCC Ch.B Control Port signifies Char Ready
|
|
|
|
COM3IS: IN0 A,(SCCBCNT) ; Input Status
|
|
RRA ; Input Ready = Bit0 -> Carry
|
|
SBC A,A ; A=00 if Not Ready, FF if Char Ready
|
|
RET
|
|
|
|
;.....
|
|
; COM3 Input Routine
|
|
; Remain in Loop until Char ready, then Return Char in A
|
|
|
|
COM3IN: CALL COM3IS ; Console input from SCC Ch.B Ready?
|
|
JR Z,COM3IN ; ..loop if Not
|
|
IN0 A,(SCCBD) ; Else Read SCC Ch.B Data
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD C,A ; Store byte temporarily
|
|
LD A,(COM3+6) ; .get Input mask
|
|
AND C ; ..and apply to byte
|
|
ELSE ; (Swapping permitted)
|
|
IPAT3: AND $-$ ; Char Mask patched in Config
|
|
ENDIF ;Movcpm
|
|
RET
|
|
|
|
;.....
|
|
; COM3 Output Status Test
|
|
|
|
COM3OS:
|
|
IF XONOFF
|
|
LD A,(COM3+5) ; Get this Chan's Config settings
|
|
AND 00010000B ; Xon/Xoff in use?
|
|
JR Z,COM3O0 ; ..jump if Not
|
|
LD A,(COM3WT) ; Else get Current flow status
|
|
RLA
|
|
LD A,00 ; (prepare for stopped)
|
|
JR C,SOSTV ; ..jump to return Not Ready if Stopped
|
|
COM3O0:
|
|
ENDIF ;Xonoff
|
|
IN0 A,(SCCACNT) ; Read SCC Ch.A Control Reg
|
|
RRA ; Output Ready = Bit 2
|
|
RRA
|
|
RRA ; -> Carry
|
|
SBC A,A ; A=00 if Not Ready, FF if Xmt Buffer Empty
|
|
RET
|
|
|
|
;.....
|
|
; COM3 Output Routine (Byte to Send in C)
|
|
|
|
COM3OT: CALL COM3OS ; Output to SCC Ch.B Ready?
|
|
JR Z,COM3OT ; ..loop if Not
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD A,(COM3+7) ; Get output mask
|
|
AND C ; .apply to byte
|
|
ELSE ; (Swapping permitted)
|
|
LD A,C ; Get Char
|
|
OPAT3: AND $-$ ; mask as set in Config
|
|
ENDIF ;Movcpm
|
|
OUT0 (SCCBD),A ; and send
|
|
RET
|
|
ENDIF ;Escc_b
|
|
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; ASCI0 Driver Routines
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
IF ASCI_0
|
|
IF NOT BUFFA0
|
|
;.....
|
|
; COM4 Input Status Test
|
|
|
|
COM4IS: IN0 A,(STAT0) ; Get Status byte
|
|
RLA ; RDRF Bit to Carry
|
|
SBC A,A ; set A=0 if Not Rdy, FF if Ready
|
|
RET
|
|
|
|
;.....
|
|
; COM4 Input Routine
|
|
|
|
COM4IN: CALL COM4IS ; Anything ready?
|
|
JR Z,COM4IN ; ..loop if Not
|
|
IN0 A,(RDR0)
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD C,A ; Store byte temporarily
|
|
LD A,(COM4+6) ; get input mask
|
|
AND C ; apply to byte
|
|
ELSE ; (swapping permitted)
|
|
IPAT4: AND $-$ ; Char Mask patched in Config
|
|
ENDIF ;Movcpm
|
|
RET
|
|
ELSE ; Proceed with Buffered input
|
|
;.....
|
|
; COM4 Input Status Test (Buffered)
|
|
|
|
COM4IS: LD A,(COM4Q) ; Get COM4 Queue Char Count
|
|
OR A ; Anything there?
|
|
JR RETST ; ..set appropriate flag and exit
|
|
|
|
;.....
|
|
; COM4 Input Routine (Buffered)
|
|
|
|
COM4IN: CALL COM4IS ; Anything there?
|
|
JR Z,COM4IN ; ..loop if Not
|
|
DI
|
|
PUSH HL ; Save Regs
|
|
PUSH BC
|
|
LD HL,COM4Q+QSIZE ; Point to end of Input Buffer
|
|
LD BC,QSIZE*256 ; length to B, Null in C
|
|
|
|
; "Pop" character from the Buffer
|
|
|
|
COM4LP: LD A,(HL) ; Get a byte
|
|
LD (HL),C ; store Null 1st time, else character
|
|
LD C,A ; move previous char for later save
|
|
DEC HL ; down to previous char
|
|
DJNZ COM4LP ; ..loop til Done
|
|
DEC (HL) ; Decrement Count in Queue
|
|
IF MOVCPM ; (No Swap Allowed)
|
|
LD A,(COM4+6) ; Get Input Mask
|
|
AND C ; apply setting flags based on Char
|
|
ELSE ; (swapping permitted)
|
|
IPAT4: AND $-$ ; Mask as set in Config
|
|
ENDIF ;Movcpm
|
|
POP BC ; Restore Regs
|
|
POP HL
|
|
EI
|
|
RET
|
|
ENDIF ;BuffA0
|
|
|
|
;.....
|
|
; COM4 Output Status Test
|
|
|
|
COM4OS: IN0 A,(STAT0) ; ASCI0 Output Status
|
|
RRA ; TDRE Bit
|
|
RRA ; to Carry
|
|
SBC A,A ; set status, A=0 if Not ready, FF if Rdy
|
|
RET
|
|
|
|
;.....
|
|
; COM4 Output Routine
|
|
|
|
COM4OT: CALL COM4OS ; Ready to Send?
|
|
JR Z,COM4OT ; ..loop if Not
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD A,(COM4+7) ; Get output mask
|
|
AND C ; apply to byte
|
|
ELSE ; (swapping permitted)
|
|
LD A,C ; Get Char
|
|
OPAT4: AND $-$ ; mask as set in Config
|
|
ENDIF ;Movcpm
|
|
OUT0 (TDR0),A ; and Send
|
|
RET
|
|
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Interrupt service routines for ASCI0
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
IF BUFFA0
|
|
RCAA: LD (INTSP),SP
|
|
LD SP,INTSP
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH HL
|
|
|
|
IN0 A,(RDR0) ; Get character from ASCI0
|
|
LD C,A ; ..save it
|
|
|
|
IF XONOFF
|
|
LD A,(COM4+5) ; Get Config Byte
|
|
AND 00010000B ; Xon/Xoff Active?
|
|
JR Z,RCAA0 ; ..jump if Not
|
|
LD HL,COM4WT ; Else Point to Flags Byte
|
|
LD A,C ; get Byte Back
|
|
CP XON ; Is it Xon?
|
|
JR NZ,RCAA1 ; ..jump if Not
|
|
RES 7,(HL) ; Else Enable Sending again
|
|
JR RCAAX ; and Exit
|
|
|
|
RCAA1: CP XOFF ; Is it Xoff?
|
|
JR NZ,RCAA0 ; ..jump if Not to add to Queue
|
|
SET 7,(HL) ; Else Stop Sending
|
|
JR RCAAX ; and Exit
|
|
ENDIF ;Xonoff
|
|
|
|
RCAA0: LD HL,COM4Q ; Point to char count
|
|
LD A,(HL) ; ..and get it
|
|
INC A ; Bump
|
|
CP QSIZE ; Buffer Full?
|
|
JR NC,RCAAX ; ..exit if so
|
|
LD (HL),A ; Else save new char count
|
|
CALL ADDAHL ; Offset to storage in Queue
|
|
LD (HL),C ; ..and save the character
|
|
RCAAX: POP HL ; Restore Regs
|
|
POP BC
|
|
POP AF
|
|
LD SP,(INTSP) ; and Entry Stack Ptr
|
|
EI ; Ints back On
|
|
RET
|
|
ENDIF ;BuffA0
|
|
ENDIF ;Asci_0
|
|
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; ASCI1 Driver Routines
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
IF ASCI_1
|
|
IF NOT BUFFA1
|
|
;.....
|
|
; COM5 Input Status Test
|
|
|
|
COM5IS: IN0 A,(STAT1) ; Get Status byte
|
|
RLA ; RDRF Bit to Carry
|
|
SBC A,A ; set A=0 if Not Rdy, FF if Ready
|
|
RET
|
|
|
|
;.....
|
|
; COM5 Input Routine
|
|
|
|
COM5IN: CALL COM5IS ; Anything ready?
|
|
JR Z,COM5IN ; ..loop if Not
|
|
IN0 A,(RDR1)
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD C,A ; Store byte temporarily
|
|
LD A,(COM5+6) ; get input mask
|
|
AND C ; apply to byte
|
|
ELSE ; (swapping permitted)
|
|
IPAT5: AND $-$ ; Char Mask patched in Config
|
|
ENDIF ;Movcpm
|
|
RET
|
|
|
|
ELSE ;proceed w/buffered input
|
|
;.....
|
|
; COM5 Input Status Test (Buffered)
|
|
|
|
COM5IS: LD A,(COM5Q) ; Get COM5 Queue Char Count
|
|
OR A ; Anything there?
|
|
JP RETST
|
|
|
|
;.....
|
|
; COM5 Input Routine (Buffered)
|
|
|
|
COM5IN: CALL COM5IS ; COM5 input
|
|
JR Z,COM5IN
|
|
DI
|
|
PUSH HL ; Save registers
|
|
PUSH BC
|
|
LD HL,COM5Q+QSIZE ; Point to end of Type ahead Buffer
|
|
LD BC,QSIZE*256 ; Length in B, Null in C
|
|
|
|
; "Pop" character from the Buffer
|
|
|
|
COM5LP: LD A,(HL) ; Get a character
|
|
LD (HL),C ; Store Null 1st time, else character
|
|
LD C,A ; Move previous char for later save
|
|
DEC HL ; down to previous char
|
|
DJNZ COM5LP ; Loop til done
|
|
DEC (HL) ; Decrement Count in Queue
|
|
IF MOVCPM ; (No Swap Allowed)
|
|
LD A,(COM5+6) ; Get input mask
|
|
AND C ; apply setting flags based on char
|
|
ELSE ; (Swapping permitted)
|
|
IPAT5: AND $-$ ; Mask as set in Config
|
|
ENDIF ;Movcpm
|
|
POP BC ; Restore regs
|
|
POP HL
|
|
EI
|
|
RET
|
|
ENDIF ;buffered
|
|
|
|
;.....
|
|
; COM5 Output Status Test
|
|
|
|
COM5OS: IN0 A,(STAT1) ; ASCI1 Output Status
|
|
RRA ; TDRE Bit
|
|
RRA ; to Carry
|
|
SBC A,A ; set status, A=0 if Not ready, FF if Rdy
|
|
RET
|
|
|
|
;.....
|
|
; COM5 Output Routine
|
|
|
|
COM5OT: CALL COM5OS ; Ready to Send?
|
|
JR Z,COM5OT ; ..loop if Not
|
|
IF MOVCPM ; (No Swap allowed)
|
|
LD A,(COM5+7) ; Get output mask
|
|
AND C ; apply to byte
|
|
ELSE ; (swapping permitted)
|
|
LD A,C ; Get Char
|
|
OPAT5: AND $-$ ; mask as set in Config
|
|
ENDIF ;Movcpm
|
|
OUT0 (TDR1),A ; and Send
|
|
RET
|
|
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Interrupt service routines for ASCI1
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
IF BUFFA1
|
|
RCAB: LD (INTSP),SP
|
|
LD SP,INTSP
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH HL
|
|
|
|
IN0 A,(RDR1) ; Get character from ASCI1
|
|
LD C,A ; ..save it
|
|
|
|
IF XONOFF
|
|
LD A,(COM5+5) ; Get Config Byte
|
|
AND 00010000B ; Xon/Xoff Active?
|
|
JR Z,RCAB0 ; ..jump if Not
|
|
LD HL,COM5WT ; Else Point to Flags Byte
|
|
LD A,C ; get Byte Back
|
|
CP XON ; Is it Xon?
|
|
JR NZ,RCAB1 ; ..jump if Not
|
|
RES 7,(HL) ; Else Enable Sending again
|
|
JR RCABX ; and Exit
|
|
|
|
RCAB1: CP XOFF ; Is it Xoff?
|
|
JR NZ,RCAB0 ; ..jump if Not to add to Queue
|
|
SET 7,(HL) ; Else Stop Sending
|
|
JR RCABX ; and Exit
|
|
ENDIF ;Xonoff
|
|
RCAB0: LD HL,COM5Q ; Point to char count
|
|
LD A,(HL) ; ..and get it
|
|
INC A ; Bump
|
|
CP QSIZE ; Buffer Full?
|
|
JR NC,RCABX ; ..exit if so
|
|
LD (HL),A ; Else save new char count
|
|
CALL ADDAHL ; Offset to storage in Queue
|
|
LD (HL),C ; ..and save the character
|
|
RCABX: POP HL ; Restore Regs
|
|
POP BC
|
|
POP AF
|
|
LD SP,(INTSP) ; and Entry Stack Ptr
|
|
EI ; Ints back On
|
|
RET
|
|
ENDIF ;BuffA1
|
|
ENDIF ;Asci_1
|
|
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Skeletons for Additional Expansion IO
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
;.....
|
|
; COMx Input Status (Non-buffered)
|
|
COMxIS:
|
|
;.....
|
|
; COMx Input Routine (Non-buffered)
|
|
COMxIN:
|
|
;.....
|
|
; COMx Output Status (Non-buffered)
|
|
COMxOS:
|
|
;.....
|
|
; COMx Output Routine (Non-buffered)
|
|
COMxOT:
|
|
ENDIF ;Mordev
|
|
|
|
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
;:: I n t e r r u p t T a b l e ::
|
|
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; The Z80182 Interrupt Vector table is placed here on a 32-byte
|
|
; boundary for internal peripherals.
|
|
|
|
DEFS 32-[$-BIOSJT AND 31] ; Align
|
|
INTTBL:
|
|
DEFW BADINT ; FDC Controller w/Ints (FDCINT if Real Ints)
|
|
DEFW BADINT ; Parallel output port (INTPIO if Real Ints)
|
|
DEFW TIMER ; Timer0
|
|
DEFW BADINT ; Timer1
|
|
DEFW BADINT ; DMA Channel 0
|
|
DEFW BADINT ; DMA Channel 1
|
|
DEFW BADINT ; Clocked Serial IO
|
|
IF MORDEV AND ASCI_0 AND BUFFA0
|
|
DEFW RCAA ; ASCI 0
|
|
ELSE
|
|
DEFW BADINT ; ASCI 0 if Not Interrupt/Mordev
|
|
ENDIF
|
|
IF MORDEV AND ASCI_1 AND BUFFA1
|
|
DEFW RCAB ; ASCI 1
|
|
ELSE
|
|
DEFW BADINT ; ASCI 1 if Not Interrupt/Mordev
|
|
ENDIF
|
|
|
|
; Error trap for unimplemented Interrupts
|
|
|
|
BADINT: CALL PRINT
|
|
DEFC CR,LF,'Bad Int.'
|
|
JP WBOOT
|
|
|
|
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
;:: D e v i c e I n i t i a l i z a t i o n ::
|
|
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
|
|
CSEG
|
|
DEVINI:
|
|
IF BANKED
|
|
CALL BIOSTK
|
|
CALL GOSYSB
|
|
JP JDVINI
|
|
COMMON /BANK2/
|
|
JDVINI:
|
|
ENDIF
|
|
|
|
; Synchronize Environment Descriptor Speed byte to Bios CPU Clock Speed setting
|
|
|
|
LD A,(SPEED) ; Get Processor Speed from Bios Setting
|
|
LD HL,(ENVADR) ; Get ENV Address
|
|
LD L,2BH ; offset to CPU Clock rate
|
|
LD (HL),A ; and slam it into the ENV
|
|
|
|
; Set Clock Rate and Dividers before we initialize devices
|
|
;;--(ENH182 doesn't seem to be variable at present)
|
|
|
|
;;-- LD C,0 ; (preset ESCC Div-by-1, No Halt)
|
|
;;-- CP 20 ; < 20 MHz?
|
|
;;-- JR C,IsBy1 ; ..jump if So
|
|
;;-- LD C,00001000B ; Else Divide ESCC clock by 2
|
|
; |||||+++- (reserved)
|
|
; ||||+---- 0 = ESCC Clk Div-by-1, 1 = ESCC Clk Div-by-2
|
|
; |||+----- 1 = TxDA Disable on Halt
|
|
; ||+------ 1 = Force Halt
|
|
; ++------- (reserved)
|
|
;;--IsBy1: OUT0 (ENH182),C ; Set ESC Divider
|
|
|
|
LD C,10000000B ; (preset flags)
|
|
; |+++++++- Normal Drive, Standby/Idle Disabled
|
|
; +-------- 0 = XTAL/2 Rate, 1 = XTAL/1 Rate
|
|
CP 12+1 ; Is Clock Speed > 12 MHz?
|
|
JR NC,ISHI ; jump if Yes
|
|
LD C,0 ; Else Set for Low (Xtal / 2) Speed
|
|
ISHI: OUT0 (1FH),C ; and Set Speed
|
|
|
|
; Set Configured Wait States for IO and Memory
|
|
|
|
LD A,(WAITS) ; Get # Wait states for Memory & IO
|
|
AND 00110011B ; Mask off all but 2 LSBs in each nybble
|
|
RLCA ; move Mem bits to B7,6
|
|
RLCA
|
|
LD C,A ; Save partially shifted byte
|
|
RLCA ; Move IO to Bits 5,4
|
|
RLCA
|
|
OR C ; OR in Memory waits
|
|
AND 11110000B ; and mask off all others
|
|
OR 00001100B ; Edge Triggering for both DMA channels
|
|
OUT0 (DCNTL),A ; set parameters
|
|
|
|
; Set Refresh to Assembled Setting
|
|
|
|
IF REFRSH ; (Must be TRUE if using Dynamic RAM)
|
|
LD A,83H ; Set refreshing on for Dynamic Rams
|
|
ELSE ; (Don't need wasted time if Static Memory)
|
|
LD A,00H ; Else disable Refresh cycles
|
|
ENDIF
|
|
OUT0 (RCR),A ; Set Refresh timing specs
|
|
|
|
; Set Reload constant to values in header
|
|
|
|
LD HL,(RELOD0) ; Get the timer reload constant
|
|
OUT0 (RLDR0L),L ; send low byte
|
|
OUT0 (RLDR0H),H ; and hi byte
|
|
|
|
; Configure COM1 IO Masks and Channel characteristics
|
|
|
|
IF NOT MOVCPM ; (Swapping permitted)
|
|
LD DE,C1NAM ; Point to COM1 Name String
|
|
CALL SETPTR ; locate data returning ptr
|
|
JR Z,DEVIN0 ; jump to next if No Device Name
|
|
LD A,(HL) ; Else Get Dev+7 Mask
|
|
LD (OPAT1+1),A ; patch
|
|
DEC HL ; Down to Input Mask @ Dev+6
|
|
LD A,(HL) ; fetch
|
|
LD (IPAT1+1),A ; and patch
|
|
DEC HL ; Down to Config byte @ Dev+5
|
|
ELSE ; (No Swap Allowed)
|
|
LD HL,DEVCFG+5 ; Point to second COM1 Config byte
|
|
ENDIF ;Movcpm
|
|
LD BC,SCCACNT ; Point to SCC Channel A Control Port
|
|
CALL INSCC ; Set the SCC parameters
|
|
|
|
; Configure COM2 IO Masks and Channel Characteristics
|
|
|
|
DEVIN0:
|
|
IF NOT MOVCPM ; (Swapping permitted)
|
|
LD DE,C2NAM ; Point to COM2 Name String
|
|
CALL SETPTR ; locate data returning ptr
|
|
JR Z,DEVIN1 ; ..jump to next if No Device Name
|
|
LD A,(HL) ; Else Get Dev+7 Mask
|
|
LD (OPAT2+1),A ; patch
|
|
DEC HL ; Down to Input Mask @ Dev+6
|
|
LD A,(HL) ; fetch
|
|
LD (IPAT2+1),A ; and patch
|
|
DEC HL ; Down to Config Byte @ Dev+5
|
|
ELSE ; (No Swap Allowed)
|
|
LD HL,DEVCFG+[COM2-COM1]+5 ; Point to second COM2 Config byte
|
|
ENDIF ;Movcpm
|
|
CALL IOI550 ; Initialize 16550-compatible 37C665 Port
|
|
|
|
; Configure Parallel Port IO Masks and Characteristics and Reset
|
|
|
|
IF NOT MOVCPM ; (No Swap Allowed)
|
|
DEVIN1: LD DE,P1NAM ; Point to PIO1 Name String
|
|
CALL SETPTR ; locate data returning ptr
|
|
JR Z,DEVIN2 ; jump if No Device Name
|
|
LD A,(HL) ; Get Dev+7 Mask
|
|
LD (OPATP+1),A ; and patch
|
|
DEVIN2:
|
|
ENDIF ;Movcpm
|
|
; Reset Parallel port on FDC37C665 Multi-IO Chip
|
|
LD A,00001000B ; Command to Reset Parallel Port
|
|
OUT0 (CPORT),A ; by bringing INIT Low
|
|
LD BC,4000
|
|
PDly: DEC BC ; and
|
|
LD A,B
|
|
OR C
|
|
JR NZ,PDly ; holding there for a while
|
|
LD A,00001100B ; Re-activate Port
|
|
OUT0 (CPORT),A ; by bringing INIT High
|
|
IN0 A,(SPORT) ; Clear by
|
|
IN0 A,(SPORT) ; reading status twice
|
|
|
|
IF MORDEV AND NOT MOVCPM
|
|
; -- Add necessary Initialization for Expansion Drivers here --
|
|
IF ESCC_B
|
|
; Initialize ESCC Channel B
|
|
LD DE,C3NAM ; Point to COM3 Name String
|
|
CALL SETPTR ; locate data returning ptr
|
|
JR Z,DEVIN3 ; jump to next if No Device Name
|
|
LD A,(HL) ; Else Get Dev+7 Mask
|
|
LD (OPAT3+1),A ; patch
|
|
DEC HL ; Down to Input Mask @ Dev+6
|
|
LD A,(HL) ; fetch
|
|
LD (IPAT3+1),A ; and patch
|
|
DEC HL ; Down to Config byte @ Dev+5
|
|
LD BC,SCCBCNT ; Point to SCC Channel B Control Port
|
|
CALL INSCC ; Set the SCC parameters
|
|
ENDIF ;Escc_b
|
|
DEVIN3:
|
|
IF ASCI_0
|
|
; Initialize ASCI0
|
|
LD DE,C4NAM ; Point to COM4 Name String
|
|
CALL SETPTR ; locate data returning ptr
|
|
JR Z,DEVIN4 ; jump to next if No Device Name
|
|
LD A,(HL) ; Else Get Dev+7 Mask
|
|
LD (OPAT4+1),A ; patch
|
|
DEC HL ; Down to Input Mask @ Dev+6
|
|
LD A,(HL) ; fetch
|
|
LD (IPAT4+1),A ; and patch
|
|
DEC HL ; Down to Config byte @ Dev+5
|
|
LD BC,CNTLA0 ; B=0 for Hi-order IO Address, C=CNTLA0 Port
|
|
LD E,01100000B ; CNTLA0 Mask, RE, TE, RTS*
|
|
CALL INASCI ; and set a couple of bytes
|
|
DEVIN4:
|
|
IF BUFFA0
|
|
LD A,00001000B ; Enable ASCI0 Interrupts
|
|
ELSE
|
|
XOR A ; No Interrupts
|
|
ENDIF
|
|
OUT0 (STAT0),A
|
|
ENDIF ;Asci_0
|
|
IF ASCI_1
|
|
; Initialize ASCI1
|
|
LD DE,C5NAM ; Point to COM5 Name String
|
|
CALL SETPTR ; locate data returning ptr
|
|
JR Z,DEVIN5 ; jump to next if No Device Name
|
|
LD A,(HL) ; Else Get Dev+7 Mask
|
|
LD (OPAT5+1),A ; patch
|
|
DEC HL ; Down to Input Mask @ Dev+6
|
|
LD A,(HL) ; fetch
|
|
LD (IPAT5+1),A ; and patch
|
|
DEC HL ; Down to Config byte @ Dev+5
|
|
LD BC,CNTLA1 ; B=0 for Hi-order IO Address, C=CNTLA1 Port
|
|
LD E,01110000B ; CNTLA1 Mask, RE, TE, Internal Clk
|
|
CALL INASCI ; and set a couple of bytes
|
|
DEVIN5:
|
|
IF BUFFA1
|
|
LD A,00001100B ; Enable ASCI1 Interrupts & CTS1*
|
|
ELSE
|
|
LD A,00000100B ; No Interrupts, Enable CTS1*
|
|
ENDIF
|
|
OUT0 (STAT1),A
|
|
ENDIF ;Asci_1
|
|
ENDIF ;Mordev & Not Movcpm
|
|
|
|
; Set IOByte(s) to Configured Device Settings
|
|
|
|
IF BANKED
|
|
LD A,(TPABNK) ; Get Bank # for TPA
|
|
LD C,A ; and set for destination
|
|
LD HL,0003H ; Point to IOBYTE
|
|
LD A,(IOBYT) ; get the new settings
|
|
CALL FRPUTB ; and stuff it in TPA bank
|
|
ENDIF
|
|
LD A,(IOBYT) ; If Non-banked, just get the byte
|
|
LD (0003H),A ; and stuff it, else stuff in SYStem bank
|
|
|
|
; De-Select any IDE Drives to force re-initialization on first select
|
|
|
|
IF IDE
|
|
OR 0FFH ; Set all bits
|
|
LD (hdUnit),A ; to mismatch select on current unit
|
|
ENDIF
|
|
|
|
; Set Interrupt Conditions
|
|
|
|
LD A,00010001B ; Turn Ints On and enable downcounting
|
|
OUT0 (TCR),A
|
|
|
|
LD A,00000111B ; Activate INT0 and Internals
|
|
OUT0 (ITC),A
|
|
EI ; Insure interrupts enabled
|
|
RET
|
|
|
|
;.....
|
|
; Z182 [E]SCC Configuration Routine.
|
|
; Enter= BC -> respective Control Register SCCACNT/SCCBCNT.
|
|
; HL -> Dev+5 Configuration byte
|
|
|
|
INSCC: LD DE,0100010000101010B ; Skeleton WR4 (D), WR5 (E) contents
|
|
; |||||||||||||||+- Tx CRC Enable \---------------+
|
|
; ||||||||||||||+-- RTS |
|
|
; |||||||||||||+--- /SDLC/CRC-16 |
|
|
; ||||||||||||+---- Tx Enable WR5
|
|
; |||||||||||+----- Send Break |
|
|
; |||||||||++------ Bits/Char (00=5, 01=7, 10=6, 11=8) |
|
|
; ||||||||+-------- DTR /---------------+
|
|
; |||||||+--------- Parity Enable \---------------+
|
|
; ||||||+---------- Parity EVEN/ODD | WR4
|
|
; ||||++----------- 00=Sync, 01=1 Stop, 10=1.5 Stop, 11=2
|
|
; ||++------------- Sync Char Settings |
|
|
; ++--------------- Clock 00=X1,01=X16,10=X32,11=X64 /-+
|
|
BIT 0,(HL) ; One Stop Bit?
|
|
JR NZ,INSCC0 ; ..jump if So
|
|
SET 3,D ; Else Set for 2 Stop bits
|
|
INSCC0: BIT 1,(HL) ; Parity On?
|
|
JR Z,INSCC1 ; ..jump if Not
|
|
SET 0,D ; Else Turn it On
|
|
BIT 2,(HL) ; Is Odd parity desired?
|
|
JR NZ,INSCC1 ; ..jump if Even parity
|
|
SET 1,D ; Else set to Odd
|
|
INSCC1: BIT 3,(HL) ; 7-bit Data?
|
|
JR NZ,INSCC2 ; ..jump if So
|
|
SET 6,E ; Else set for 8-bit data
|
|
INSCC2: LD A,WR4
|
|
CALL IWdOut ; Set basic Parms
|
|
LD A,E ; Get WR4 Config Byte
|
|
SCF ; (prep to set LSB)
|
|
ADC A,A ; Move old B6/5 to B7/6 and Set LSB
|
|
AND 0C1H ; strip off Garbage
|
|
BIT 5,(HL) ; RTS/CTS Handshake selected?
|
|
JR Z,INSCC8 ; ..jump if Not
|
|
OR 00100000B ; Else Set Auto-Enables
|
|
INSCC8: LD E,A ; (position)
|
|
LD A,WR3
|
|
CALL IBytO ; Set Receive Bits/Char & activate
|
|
|
|
CALL ChkRat ; Can we set the Data Rate?
|
|
RET Z ; ..quit if Not
|
|
|
|
PUSH BC ; Else Save regs (A [0..3] = Rate index)
|
|
DEC A ; adjust index to Base 0
|
|
LD C,A ; store
|
|
LD HL,brSCC ; Pt to Start of Baud Rate Table
|
|
CALL ADDAHL ; -> appropriate constant
|
|
LD L,(HL) ; fetch constant
|
|
;;-- IN0 A,(ENH182) ; Get Enhancement Reg
|
|
;;-- AND 00001000B ; Keep ESCC Divide Rate Bit
|
|
LD A,(SPEED) ; Fetch Clock speed
|
|
;;-- JR Z,INSCC9 ; ..jump if Div-by-1
|
|
;;-- SRL A ; Else Divide Rate by 2 (by dividing Clk)
|
|
;;--INSCC9:
|
|
LD H,A
|
|
LD A,C
|
|
CP 3 ; Rate In [134.5, 50, 75]?
|
|
JR NC,INSCC3 ; ..jump if Not
|
|
LD A,H ; Else
|
|
ADD A,A ; Multiply
|
|
ADD A,H ; constant * 3
|
|
LD H,A
|
|
INSCC3: MLT HL ; Multiply Clock Rate by Constant
|
|
LD A,C
|
|
CP 7 ; Rate < 2400 bps?
|
|
JR C,INSCC4 ; ..jump if Yes
|
|
LD C,18 ; Else Compute Divisor / 18
|
|
LD B,17 ; 17 times thru loop for 16 bits
|
|
XOR A ; start w/Carry Clear
|
|
|
|
; Divide computed value in HL by 18 (in C), Ret: Remainder in A, Quotient in HL
|
|
|
|
SDiv0: ADC A,A
|
|
SBC A,C
|
|
JR NC,SDiv1
|
|
ADD A,C ; correct for underflow
|
|
SDiv1: CCF
|
|
ADC HL,HL
|
|
DJNZ SDiv0 ; ..loop til Done
|
|
SRL C ; Dividend / 2
|
|
CP C ; Rounding Needed?
|
|
JR C,INSCC4 ; ..jump if Not
|
|
INC HL ; Else round up
|
|
|
|
INSCC4: POP BC
|
|
DEC HL ; Compute Divisor
|
|
DEC HL ; - 2
|
|
LD A,H
|
|
OR L ; If Divisor = 0
|
|
JR NZ,INSCC5
|
|
INC L ; default to 1
|
|
INSCC5: LD A,WR12 ; Address Divisor Reg pair
|
|
LD E,H ; swap
|
|
LD D,L ; bytes to send Lower first
|
|
|
|
IWdOut: DI
|
|
OUT (C),A ; Address WR4
|
|
OUT (C),D ; Set values
|
|
INC A ; Bump to WR5
|
|
IBytO: OUT (C),A ; address it
|
|
OUT (C),E ; Set values
|
|
EI
|
|
RET
|
|
|
|
;.....
|
|
; Divisor factors are computed as:
|
|
; (Xtal Freq (Hz) / (2 * bps * Divisor)) - 2
|
|
; These rate constants represent a compromise between the "standard" rates of
|
|
; multiples of 6.144 and 9.216 MHz, and the 8.000/16.000 MHz used in the P112.
|
|
; All factors are based on a x16 clock divisor.
|
|
|
|
brSCC: DEFB 79 ; 1 = 134.5 bps / 3
|
|
DEFB 213 ; 2 = 50 bps / 3
|
|
DEFB 142 ; 3 = 75 bps / 3
|
|
DEFB 213 ; 4 = 150 bps
|
|
DEFB 106 ; 5 = 300 bps
|
|
DEFB 53 ; 6 = 600 bps
|
|
DEFB 26 ; 7 = 1200 bps
|
|
DEFB 240 ; 8 = 2400 bps * 18
|
|
DEFB 120 ; 9 = 4800 bps * 18
|
|
DEFB 60 ; 10 = 9600 bps * 18
|
|
DEFB 30 ; 11 = 19.2 kbps * 18
|
|
DEFB 15 ; 12 = 38.4 kbps * 18
|
|
DEFB 10 ; 13 = 57.6 kbps * 18
|
|
DEFB 5 ; 14 = 115.2 kbps * 18
|
|
|
|
;.....
|
|
; 16550-compatible Configuration Routine
|
|
|
|
IOI550: LD E,00000011B ; Start w/byte going to Line Contr Reg (LCR)
|
|
; ||||||++- Word Len in Bits (00=5, 01=6, 10=7, 11=8)
|
|
; |||||+--- Stop Bits (0=1, 1=1.5 or 2)
|
|
; ||||+---- 0 = No Parity, 1 = Parity Enabled
|
|
; ||++----- (If Parity) 00=Odd, 01=Even, 10=Mark, 11=Space
|
|
; |+-------- 0 = Normal, 1 = Send Break
|
|
; +--------- 0 = Normal, 1 = Set Baud Rate
|
|
BIT 0,(HL) ; One Stop Bit?
|
|
JR NZ,IOI55a ; ..jump if So
|
|
SET 2,E ; Else Set for 2 Stop Bits
|
|
IOI55a: BIT 1,(HL) ; Parity On?
|
|
JR Z,IOI55b ; ..jump if Not
|
|
SET 3,E ; Else Turn it On
|
|
BIT 2,(HL) ; Even Parity?
|
|
JR Z,IOI55b ; ..jump if Odd
|
|
SET 4,E ; Else Set Even Parity
|
|
IOI55b: CALL ChkRat ; Can we set the Data Rate?
|
|
JR Z,IOI55c ; ..jump if Not
|
|
ADD A,A ; Else double index
|
|
LD C,A
|
|
LD B,0
|
|
LD HL,RATE55-2 ; Pt to compensated Table
|
|
ADD HL,BC
|
|
SET 7,E ; Address DLAB
|
|
OUT0 (_LCR),E
|
|
LD A,(HL)
|
|
OUT0 (_DDL),A ; send Low Byte
|
|
INC HL
|
|
LD A,(HL)
|
|
OUT0 (_DLM),A ; and High Byte
|
|
IOI55c: RES 7,E ; Clear DLAB Bit
|
|
OUT0 (_LCR),E ; and Set configuration
|
|
LD A,00000011B
|
|
; |||||||+-- 1 = DTR Active
|
|
; ||||||+--- 1 = RTS Active
|
|
; |||||+---- (unused)
|
|
; ||||+----- 1 = Send Ints to CPU, 0 = Ints Hi-Z
|
|
; |||+------ 1 = Line Loopback
|
|
; +++------- (unused)
|
|
OUT0 (_MCR),A ; Activate Port
|
|
LD A,00000000B
|
|
; |||||||+-- 1 = Enable Rcv Buff Full Interrupt
|
|
; ||||||+--- 1 = Enable Xmt Buff Empty Interrupt
|
|
; |||||+---- 1 = Enable Line Status Interrupt
|
|
; ||||+----- 1 = Enable Delta Status Signals Inerrupt
|
|
; ++++------ (unused)
|
|
OUT0 (_IER),A ; Set Interrupt Settings
|
|
RET
|
|
|
|
; Clock Divisor factors for various rates
|
|
|
|
RATE55: DEFW 857 ; 1 = 134.5 bps
|
|
DEFW 2304 ; 2 = 50 bps
|
|
DEFW 1536 ; 3 = 75 bps
|
|
DEFW 768 ; 4 = 150 bps
|
|
DEFW 384 ; 5 = 300 bps
|
|
DEFW 192 ; 6 = 600 bps
|
|
DEFW 96 ; 7 = 1200 bps
|
|
DEFW 48 ; 8 = 2400 bps
|
|
DEFW 24 ; 9 = 4800 bps
|
|
DEFW 12 ; 10 = 9600 bps
|
|
DEFW 6 ; 11 = 19.2 kbps
|
|
DEFW 3 ; 12 = 38.4 kbps
|
|
DEFW 2 ; 13 = 57.6 kbps (non-std)
|
|
DEFW 1 ; 14 = 115.2 kbps
|
|
|
|
;.....
|
|
; Expansion Common routines may be places here
|
|
IF MORDEV AND NOT MOVCPM
|
|
IF ASCI_0 OR ASCI_1
|
|
INASCI: BIT 0,(HL) ; One Stop Bit?
|
|
JR NZ,INASC0 ; ..jump if Not
|
|
SET 0,E ; Else Set for 2 Stop bits
|
|
INASC0: BIT 1,(HL) ; Parity On?
|
|
JR Z,INASC1 ; ..jump if Not
|
|
SET 1,E ; Else Turn it On
|
|
INASC1: BIT 3,(HL) ; 7-bit Data?
|
|
JR NZ,INASC2 ; ..jump if So
|
|
SET 2,E ; Else set for 8-bit Data
|
|
INASC2: OUT (C),E ; Send the byte to CNTLA0/1
|
|
INC C ; advance to CNTLB0/1
|
|
INC C
|
|
DEC HL ; Back up to first Config byte
|
|
LD A,(HL) ; fetch
|
|
AND 0F0H ; Check Config Status
|
|
LD E,0111B ; (preset for External clock in case)
|
|
JR Z,INASCX ; ..jump if No rate to Set
|
|
LD A,(HL) ; Refetch the rate byte
|
|
AND 0FH ; masking off all but desired rate
|
|
PUSH HL ; Save Config byte pointer
|
|
LD HL,ASCRAT-1 ; pt to Rate Table (Correcting for Base 0)
|
|
CALL ADDAHL ; offsetting to desired byte
|
|
LD E,0 ; Prepare an initial mask
|
|
LD A,(SPEED) ; Check processor speed
|
|
CP 6+1 ; Is it 6 or below?
|
|
JR C,INASC8 ; ..jump assuming 6.144 MHz if <= 6
|
|
DEC HL ; (prepare for 12 test)
|
|
CP 12 ; Is it 12 MHz?
|
|
JR Z,INASC8 ; ..jump assuming 12.288 MHz if = 12
|
|
DEC HL ; (prepare for 24 test)
|
|
CP 24 ; Is it 24 MHz?
|
|
JR NC,INASC8 ; ..jump if >= 24 MHz
|
|
INC HL ; Else correct pointer
|
|
INC HL ; Advance for 18 MHz
|
|
SET 5,E ; Set additional divisor bit for 9/18 MHz
|
|
CP 16 ; Is it >= 16 MHz? (including 18 MHz)
|
|
JR NC,INASC8 ; ..jump to use 6 MHz rates if So
|
|
INC HL ; Else bump up one in Rate Table
|
|
INASC8: LD A,(HL) ; Get the Rate Setting Byte
|
|
OR E ; add in any additional divisor
|
|
LD E,A ; back to output reg
|
|
POP HL ; Restore Config byte ptr
|
|
INASCX: INC HL ; advance to second byte
|
|
BIT 2,(HL) ; Is Odd parity desired?
|
|
JR NZ,INASC9 ; ..jump if Even parity
|
|
SET 4,E ; Else set to Odd
|
|
INASC9: OUT (C),E ; Send the byte to CNTLB0/1
|
|
RET
|
|
|
|
; bps @ 6MHz 9MHz 12MHz 18MHz 24MHz
|
|
DEFB 00001110B ; 0 (protection)
|
|
ASCRAT: DEFB 00001110B ; 1 = default to lowest rate
|
|
DEFB 00001110B ; 2 = default to lowest rate
|
|
DEFB 00001110B ; 3 = default to lowest rate
|
|
DEFB 00001110B ; 4 = 150 75 300 150 600
|
|
DEFB 00001101B ; 5 = 300 150 600 300 1200
|
|
DEFB 00000110B ; 6 = 600 300 1200 600 2400
|
|
DEFB 00000101B ; 7 = 1200 600 2400 1200 4800
|
|
DEFB 00000100B ; 8 = 2400 1200 4800 2400 9600
|
|
DEFB 00000011B ; 9 = 4800 2400 9600 4800 19.2k
|
|
DEFB 00000010B ; 10 = 9600 4800 19.2k 9600 38.4k
|
|
DEFB 00000001B ; 11 = 19.2 k 9600 38.4k 19.2k 76.8k
|
|
DEFB 00000000B ; 12 = 38.4 k 19.2 k 76.8k 38.4k 153.6k
|
|
DEFB 00000000B ; 13 = default to highest rate
|
|
DEFB 00000000B ; 14 = default to highest rate
|
|
DEFB 00000000B ; 15 = default to highest rate
|
|
ENDIF ;Asci_0 | Asci_1
|
|
ENDIF ;Mordev
|
|
|
|
;.....
|
|
; Check Data Rate Config byte for authority and limits on configuration
|
|
; Enter: HL -> Second Config byte (back up to get rate byte)
|
|
; Exit : Zero Set if Can't configure
|
|
|
|
ChkRat: DEC HL ; Pt to Data Rate
|
|
LD A,(HL) ; fetch
|
|
AND 0F0H ; Any Allowed rate to set?
|
|
RET Z ; ..quit if Not (Z Set)
|
|
LD A,(HL) ; Fetch byte again
|
|
AND 0FH ; Anything to Set?
|
|
RET Z ; ..quit if Not (Z Set)
|
|
CP 0FH ; Fixed Rate?
|
|
RET ; ..exit w/Z Set if Fixed, else NZ for Ok
|
|
|
|
;.....
|
|
; Locate Named Device and return pointer to last Config byte
|
|
IF NOT MOVCPM
|
|
SETPTR: LD HL,DEVCFG-[COM2-COM1] ; Point ahead of start
|
|
SETPTL: LD BC,COM2-COM1 ; Set size of entries
|
|
ADD HL,BC ; advance to next entry
|
|
LD B,4 ; Set # chars to compare
|
|
LD A,(HL) ; Get first char
|
|
OR A ; Is it Table End?
|
|
RET Z ; ..return Zero Set if so
|
|
PUSH DE ; (save source & dest strings)
|
|
PUSH HL
|
|
SETPT0: LD A,(DE)
|
|
CP (HL) ; Compare each char
|
|
JR NZ,SETPTX ; ..quitting if mismatch
|
|
INC DE ; Else advance to next
|
|
INC HL
|
|
DJNZ SETPT0 ; ..loop to next char
|
|
SETPTX: POP HL ; Restore source & dest ptrs
|
|
POP DE
|
|
JR NZ,SETPTL ; ..try next entry if mismatch
|
|
LD DE,7 ; Else advance to Dev+7
|
|
ADD HL,DE
|
|
OR 0FFH ; Insure Zero Clear on Return
|
|
RET ; ..and quit
|
|
|
|
C1NAM: DEFB 'COM1' ; Device needing Configuration to match
|
|
C2NAM: DEFB 'COM2'
|
|
P1NAM: DEFB 'PIO1'
|
|
ENDIF ;Movcpm
|
|
; Name strings for Expansion IO added here after Primary Devices
|
|
IF MORDEV AND ESCC_B AND NOT MOVCPM
|
|
C3NAM: DEFB 'COM3' ; ESCC Channel B Expansion Device
|
|
ENDIF
|
|
IF MORDEV AND ASCI_0 AND NOT MOVCPM
|
|
C4NAM: DEFB 'COM4' ; ASCI0 Expansion Device
|
|
ENDIF
|
|
IF MORDEV AND ASCI_1 AND NOT MOVCPM
|
|
C5NAM: DEFB 'COM5' ; ASCI1 Expansion Device
|
|
ENDIF
|
|
;.....
|
|
; NOTE: BuffA0 and BuffA1 Intrpt Buffers are located at end of B/P Root module.
|
|
|
|
;===================== End of IIO-DX.Z80 ==========================
|
|
|