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

;:::::::::::::::::::::::::::::::::::::::::::::::::*************************
; 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 ==========================