mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 14:11:48 -06:00
1296 lines
39 KiB
Z80 Assembly
1296 lines
39 KiB
Z80 Assembly
;:::::::::::::::::::::::::::::::::::::::::::::::::*************************
|
||
; 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 ==========================
|
||
|