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