PAGE 60 TITLE MP/M vers 1.1 Extended I/O System ; ; XIOS.MAC ; EXTENDED I/O SYSTEM FOR MP/M 1.1 ; CREATED 80DEC04 ; ; LAST EDIT: 6/26/81 ; EDIT HISTORY, ; 2/5/81 JL - FULL INTERRUPT SUPPORT FOR CPD-2800 AND INO-288 FOR ; UP TO 10 CONSOLES AND ONE CLOCK. ; 3/8/81 JL - SUPPORT ADDED FOR CPC-2810 AND INO-288 FOR UP TO 12 ; CONSOLES AND ONE CLOCK. ; 6/26/81 JL IDLE ROUTINE FORCES DISPATCH NOW, MP/M TICK CLOCK ; SET TO 20 MS. ; 9/10/81 JL UPDATED CPC DIVISOR CONSTANT FOR CPC-2810 REV B. ; ; Z80 XIOS FOR SYSTEMS GROUP CPD-2800 OR THE CPC-2810 CPU BOARD, PLUS ; ADDITIONAL CONSOLES ON AN INO-288 8-LINE SERIAL BOARD. .Z80 ; FOR MACRO-80 ASSEMBLER ; CONDITIONAL EQUATE AND SOME DEFINITIONS LOCATED IN FOLLOWING FILE INCLUDE SYSTEM.EQU ; GLOBALS USED BY THE LOW-LEVEL DRIVER MODULE. ; THE LOW-LEVEL DISK DRIVER MAY USE THESE ENTRY POINTS TO ; WAIT ON DISK OPERATIONS USING MP/M FLAGWAIT, THEN SETTING THE FLAG ; WITHIN AN INTERRUPT SERVICE ROUTINE. GLOBAL ISRSTK ; STACK SAVER ENTRY POINT GLOBAL FLAGSET ; MP/M FLAG SET FUNCTION (ACC=FLAG) GLOBAL FLAGWAIT ; MP/M FLAG WAIT FUNCTION (ACC=FLAG) ; GLOBALS USED BY THE XDSK MODULE TO GAIN ACCESS TO THE CURRENT ; CONSOLE IN CASE OF DISK ERRORS. GLOBAL COLDSTART ; FOR TERMINATION PROCCESS (DISK ERRORS) GLOBAL CHRIN ; FOR DISK ERROR PROMPTS GLOBAL CHROUT ; ALSO FOR DISK ERROR PROMPTS ; THIS EXTERNALS ARE IN THE XDSK MODULE. CALLED ONCE AT ; SYSTEMINIT TIME AND USED TO INITIALIZE THE DRIVER. EXTRN INIDVR ; DRIVER INITIALIZATION EXTRN SECBUF ; DRIVER SECTOR BUFFER ADDRESS ; THESE EXTERNALS ARE IN THE XDSK MODULE. EXTRN HOME ; THE REST ARE DIRECTLY EXTRN SELDSK ; FROM THE XIOS JUMP TABLE. EXTRN SETTRK EXTRN SETSEC EXTRN SETDMA EXTRN READ EXTRN WRITE EXTRN SECTRN ; ************* ASSEMBLY INFORMATION ************ IF1 IF CPD280 ; if this CPU .PRINTX "CPD-2800 CPU board system" IF INO288 .PRINTX "Maximum Consoles = 10" ELSE .PRINTX "Maximum Consoles = 2" ENDIF ENDIF IF CPC281 ; must be this CPU .PRINTX "CPC-2810 CPU board system" IF INO288 .PRINTX "Maximum Consoles = 12" ELSE .PRINTX "Maximum Consoles = 4" ENDIF ENDIF IF BNKMEM .PRINTX "Bank Switched Memory" ENDIF IF INTDC .PRINTX "All Consoles use Receiver Interrupts" ENDIF ENDIF ; ********************************************** ; ; EXTERNAL JUMP TABLE TO MPM FUNCTIONS. (BELOW XIOS BASE) ; PDISP EQU $-3 XDOS EQU PDISP-3 ; ; ****** MP/M FUNCTIONS ****** ; POLL EQU 131 ; POLL DEVICE FLWAIT EQU 132 ; FLAG WAIT FLSET EQU 133 ; FLAG SET ; ; ****** MP/M FLAGS ****** ; TICFL EQU 1 ; SYSTEM TICK FLAG SECFL EQU 2 ; 1 SECOND FLAG IDCFLB EQU 16 ; BASE OF CONSOLE FLAGS ; ; ****** BASIC I/O SYSTEM JUMP VECTOR ****** ; JP COLDSTART ; COLD START. JP WARMSTART ; WARM START. JP CONST ; CONSOLE STATUS. JP CONIN ; CONSOLE INPUT. JP CONOT ; CONSOLE OUTPUT. JP LIST ; LIST CHARACTER OUT. JP RTNX ; PUNCH CHARACTER OUT. JP RTNX ; READER CHARACTER IN. JP HOME ; RESET DISK. JP SELDSK ; SELECT DISK DRIVE. JP SETTRK ; SELECT TRACK. JP SETSEC ; SELECT SECTOR NUMBER. JP SETDMA ; SET THE ADDRESS TO READ OR WRITE FROM DISK. JP READ ; READ DATA FROM DISK. JP WRITE ; WRITE DATA TO DISK. JP LISTST ; READ LIST DEVICE STATUS. JP SECTRN ; DO SECTOR TRANSLATION. ; ; VECTORS FOR THE EXTENDED I/O SYSTEM. ; JP SELMEMORY ; SELECT MEMORY BANK. JP POLLDEVICE ; POLL SPECIFIED DEVICE FOR STATUS. JP STARTCLOCK ; START THE SYSTEM CLOCK. JP STOPCLOCK ; STOP THE SYSTEM CLOCK. JP EXITREGION ; INTERRUPT EXIT FUNCTION. JP MAXCONSOLE ; OBTAIN THE MAXIMUM CONSOLE NUMBER. JP SYSTEMINIT ; SYSTEM INITIALIZATION. DB 0,0,0 ; FORCE IDLE TIME DISPATCH. ; ; ;********** GENERAL EQUATES ********** ; RTCVEC EQU 36H ; REAL TIME CLOCK ISR ADDR (MODE 2) COMVEC EQU 34H ; COMMUNICATIONS ISR ADDR (MODE 2) ; ; ****** SIO SERIAL DEVICE EQUATES ****** ; SIOAD EQU CPUB+0 ; DEVICE A DATA PORT SIOAC EQU CPUB+1 ; DEVICE A STATUS PORT SIOBD EQU CPUB+2 ; DEVICE B DATA PORT SIOBC EQU CPUB+3 ; DEVICE B STATUS PORT ; CTS EQU 0CH ; TBE AND DCD BITS SIOABR EQU 9600 ; DEVICE A BAUD RATE IF SERLST IF DIABLO SIOBBR EQU 1200 ; MAX DIABLO BAUD RATE ELSE SIOBBR EQU 9600 ; BAUD RATE FOR PRINTER ENDIF ELSE SIOBBR EQU 9600 ; DEVICE B BAUD RATE ENDIF IF CPD280 ; IF THIS CPU BOARD ;*********** 9519 UIC EQUATES ************ ; UICD EQU CPUB+12 UICC EQU CPUB+13 ; ;********** TIMER EQUATES ********** ; CTR0 EQU CPUB+8 ; COUNTER 0. CTR1 EQU CPUB+9 ; COUNTER 1. CTR2 EQU CPUB+10 ; COUNTER 2. CTRM EQU CPUB+11 ; CONTROL PORT. CDIV0 EQU 7680/(SIOABR/10) ; BAUD RATE DIVISOR CHANNEL A CDIV1 EQU 7680/(SIOBBR/10) ; BAUD RATE DIVISOR CHANNEL B ENDIF ; CPD280 IF CPC281 ; IF THIS CPU BOARD ; ADDITIONAL SIO EQUATES (PRESENCE OPTIONAL). ; SIOCD EQU CPUB+8 ; CHANNEL C DATA PORT SIOCC EQU CPUB+9 ; CHANNEL C STATUS PORT SIODD EQU CPUB+10 ; CHANNEL D DATA PORT SIODC EQU CPUB+11 ; CHANNEL D STATUS PORT ; SIOCDBR EQU 9600 ; CHANNEL C & D BAUD RATES ; ; PROM ON/OFF CONTROL ; PROM EQU CPUB+16 ; PROM CONTROL PORT ROMENA EQU 1 ; VALUE TO ENABLE PROM ROMDIS EQU 0 ; VALUE TO DISABLE PROM ; ; Z80-CTC USED FOR BAUD RATE GENERATORS AND REAL TIME CLOCK ; CTCA EQU CPUB+12 ; COUNTER A CTCB EQU CPUB+13 ; COUNTER B CTCC EQU CPUB+14 ; COUNTER C CTCD EQU CPUB+15 ; COUNTER D ; IF SIOABR GE 600 CTMODA EQU 045H ; NO PRE-SCALER, LOAD CONSTANT CTDIVA EQU 3840/(SIOABR/10) ; CONSTANT ELSE CTMODA EQU 005H ; PRE-SCALE = 16, LOAD CONSTANT CTDIVA EQU 15625/SIOABR ; CONSTANT ENDIF IF SIOBBR GE 600 CTMODB EQU 045H ; SEE CTMODA CTDIVB EQU 3840/(SIOBBR/10) ELSE CTMODB EQU 005H CTDIVB EQU 15625/SIOBBR ENDIF IF SIOCDBR GE 600 CTMODC EQU 045H ; SEE CTMODA CTDIVC EQU 3840/(SIOCDBR/10) ELSE CTMODC EQU 005H CTDIVC EQU 15625/SIOCDBR ENDIF ENDIF ; CPC281 ; ;********** PIO PORT EQUATES ********** ; PIOAD EQU CPUB+4 ; CHANNEL A DATA PIOAC EQU CPUB+5 ; CHANNEL A CONTROL PIOBD EQU CPUB+6 ; CHANNEL B DATA PIOBC EQU CPUB+7 ; CHANNEL B CONTROL PBSY EQU 0 ; STATUS BIT FOR PRINTER ; ; ********** EQUATES FOR 8 CHANNEL SERIAL I/O BOARD ********** ; BAUD12 EQU INOB+16 BAUD34 EQU INOB+18 BAUD56 EQU INOB+20 BAUD78 EQU INOB+22 DAT8A1 EQU INOB+0 ; DATA PORT CHANNEL 1. DAT8A2 EQU INOB+2 DAT8A3 EQU INOB+4 DAT8A4 EQU INOB+6 DAT8A5 EQU INOB+8 DAT8A6 EQU INOB+10 DAT8A7 EQU INOB+12 DAT8A8 EQU INOB+14 ; DATA PORT CHANNEL 8. ; STA8A1 EQU INOB+1 ; STATUS PORT CHANNEL 1. STA8A2 EQU INOB+3 STA8A3 EQU INOB+5 STA8A4 EQU INOB+7 STA8A5 EQU INOB+9 STA8A6 EQU INOB+11 STA8A7 EQU INOB+13 STA8A8 EQU INOB+15 ; STATUS PORT CHANNEL 8. ; ; AMD 9519 UIC DEVICES ON INO 288 UICD1 EQU INOB+24 ; UIC DEVICE 1 DATA UICC1 EQU INOB+25 ; UIC DEVICE 1 CONTROL/STATUS UICD2 EQU INOB+26 ; UIC DEVICE 2 DATA UICC2 EQU INOB+27 ; UIC DEVICE 2 CONTROL/STATUS ; ; DIABLO EQUATES ETX EQU 3 ; END OF TEXT ACK EQU 6 ; ACKNOLEDGE ; ;********************** FUNCTIONS ******************************* ; ; ; THE COLD START AND THE WARM START ARE PUT INTO THE SYSTEM TO MAINTAIN ; COMPATIBILITY WITH CP/M SOFTWARE. ; COLDSTART: WARMSTART: LD C,0 ; C = "TERMINATE PROCESS" FUNCTION. JP XDOS ; ; ; THE "RTNX" FUNCTION HANDLES NON-EXISTANT FUNCTIONS. ; RTNX: XOR A ; A = "NON-EXISTANT". RET ; ; ; ****** CONSOLE HANDLERS ****** ; ; ; CONSOLE STATUS -- CHECK THE STATUS OF THE CONSOLE NUMBER IN THE D REGISTER. ; IF INTDC ; IF INTERRUPT DRIVEN CONSOLE CONST: PUSH IY ; SAVE REGS LD IY,IOTABI ; INPUT DEVICE TABLE BASE CALL CBSET ; POINT TO ENTRY (D=CONSOLE #) ; CALL TSTPT ; TEST THE BUFFER POINTERS POP IY ; RESTORE REGS LD A,0 RET Z ; IF NO CHAR WAITING (ACC=0) CPL RET ; IF CHAR WAITING (ACC=FF) ELSE ; NOT INTDC CONST: PUSH IY ; SAVE USER'S IY. LD IY,IOTABI ; POINT TO I/O TABLE. CALL CSET ; POINT IY AT ENTRY FOR THIS TERMINAL. ENDIF ; INTDC ; POLLX: LD C,(IY) ; C = DEVICE ADDRESS OF STATUS PORT. IN A,(C) ; A = STATUS OF DEVICE. AND (IY+2) ; MASK WITH STATUS BIT. POP IY ; RESTORE USER'S IY. LD A,0 RET Z ; IF DEVICE IS NOT READY (ACC=0) CPL RET ; IF CHAR WAITINT (ACC=FF) ; ; ; ***** INTERNAL CONSOLE INPUT ROUTINE ***** ; CHRIN: LD C,99H ; GET CURRENT CONSOLE NUMBER CALL XDOS ; FROM XDOS LD D,A ; PREP IN D REG ; ***** CONSOLE INPUT ROUTINE ***** ; ; INPUT A CHARACTER FROM THE CONSOLE NUMBER IN THE D REGISTER. ; RETURNS WITH THE CHARACTER IN THE A REGISTER. ; IF INTDC ; INTERRUPT DRIVEN CONSOLES CONIN: PUSH IY LD IY,IOTABI ; INPUT DEVICE TABLE BASE CALL CBSET ; POINT TO ENTRY (D=CONSOLE #) ; CONIN0: CALL TSTPT ; TEST BUFFER POINTERS JR NZ,CONIN1 ; IF BUFFER HAS A CHAR ; ; DEVICE BUFFER NOT READY, CALL XDOS FLAG WAIT FUNCTION ; LD A,(IY+9) CALL FLAGWAIT JR CONIN0 ; GO BACK AND TEST BUFFER ; ; NOW DEVICE BUFFER HAS A CHAR, INPUT IT ; CONIN1: LD E,(IY+2) LD D,(IY+3) ; OUTPUT POINTER IN DE INC DE LD L,(IY+4) LD H,(IY+5) ; BUFFER BASE IN HL LD BC,CBLEN ADD HL,BC ; FIND BUFFER END SBC HL,DE ; COMPARE TO END OF BUFFER JR NZ,CONIN2 LD E,(IY+4) LD D,(IY+5) ; WRAP BUFFER CONIN2: LD (IY+2),E LD (IY+3),D ; STORE NEW OUTPUT POINTER ; LD A,(DE) ; GET CHAR AND 7FH ; MASK IT POP IY ; RESTORE INDEX REGISTER RET ELSE ; NOT INTDC CONIN: PUSH IY ; SAVE USER'S IY REGGISTER. LD IY,IOTABI ; POINT TO TABLE OF I/O DESCRIPTORS. CALL CSET ; POINT IY TO ENTRY FOR THIS DEVICE. ; ; CHECK IF THE DEVICE IS READY FOR INPUT. ; LD C,(IY) ; C = STATUS I/O ADDRESS. IN A,(C) ; A = STATUS OF DEVICE. AND (IY+2) ; CHECK THE INPUT STATUS BIT. JR NZ,CONIN1 ; JUMP IF DEVICE IS READY. ; ; ; DEVICE IS NOT READY SO MAKE MP/M POLL FOR READY. ; LD C,POLL ; C = MP/M "POLL" FUNCTION. LD E,(IY+3) ; E = POLLING DEVICE NUMBER. CALL XDOS ; ; DEVICE IS NOW READY FOR INPUT SO READ THE DATA CHARACTER. ; CONIN1: LD C,(IY+1) ; C = I/O ADDRESS FOR DATA. IN A,(C) ; A = DATA CHARACTER. AND 07FH ; GET RID OF HI-ORDER BIT. POP IY ; RESTORE USER'S IY. RET ; ENDIF ; INTDC ; ; ; ***** INTERNAL CONSOLE OUTPUT ROUTINE ***** ; CHROUT: LD C,A ; PREP CHAR IN REG C PUSH BC ; AND SAVE IT LD C,99H ; GET CURRENT CONSOLE NUMBER CALL XDOS ; FROM XDOS LD D,A ; PREP IN REG D POP BC ; RESTORE CHAR ; ***** CONSOLE OUTPUT ROUTINE ***** ; ; OUTPUT A CHARACTER TO THE CONSOLE NUMBER IN THE D REGISTER. ; THE CHARACTER TO BE OUTPUT IS IN THE C REGISTER. ; CONOT: PUSH IY ; SAVE USER'S IY REGISTER. PUSH BC ; SAVE THE CHARACTER TO BE OUTPUT. LD IY,IOTABO ; POINT TO TABLE OF OUTPUT DEVICES. CALL CSET ; POINT IY AT ENTRY FOR THIS DEVICE. ; ; CHECK IF THE DEVICE IS READY FOR OUTPUT. ; LD C,(IY) ; C = I/O PORT FOR OUTPUT STATUS. IN A,(C) ; A = DEVICE STATUS. AND (IY+2) ; CHECK ONLY THE OUTPUT STATUS. JR NZ,CON1 ; JUMP IF DEVICE IS READY. ; ; NOT READY SO MAKE MP/M POLL FOR DEVICE READY. ; LD E,(IY+3) ; E = POLL DEVICE NUMBER. LD C,POLL ; C = MP/M "POLL" FUNCTION. CALL XDOS ; ; DEVICE IS READY FOR OUTPUT. ; CON1: POP BC ; RESTORE CHARACTER TO BE OUTPUT. LD A,C ; A = CHARACTER TO BE OUTPUT. LD C,(IY+1) ; C = I/O ADDRESS OF OUTPUT PORT. OUT (C),A ; OUTPUT THE CHARACTER. POP IY ; RESTORE USER'S IY REGISTER. RET ; ***** LIST STATUS AND OUTPUT ROUTINES ***** IF SERLST ; USE SERIAL PORT FOR PRINTER LISTST: IF SERCTS ; USE HARDWARE HANDSHAKING LD A,10H ; RESET EXT/STATUS INT OUT (SIOBC),A ; SEND TO SIO IN A,(SIOBC) ; READ STATUS PORT AND CTS ; MASK TBE AND DCD BITS CP CTS ; TEST FOR BOTH TRUE LD A,0 RET NZ ; IF DEVICE NOT READY CPL ; SET ACC=FF RET ELSE IN A,(SIOBC) ; READ STATUS PORT BIT 2,A ; TEST FOR BUFFER READY LD A,0 ; SET ACC=0 RET Z ; IF BUFFER NOT READY CPL ; SET ACC=FF RET ; BUFFER IS READY ENDIF LIST: CALL LISTST ; GET PRINTER STATUS OR A ; SET FLAGS JR NZ,LIST1 ; IF DEVICE IS READY ; PUSH BC ; SAVE CHARACTER LD E,PLDEVS ; USE MAX POLLED CONS FOR NUMBER LD C,POLL ; MP/M "POLL" FUNCTION CALL XDOS POP BC ; RESTORE CHARACTER ; LIST1: LD A,C OUT (SIOBD),A ; SEND CHAR IF DIABLO CP "L"-40H ; FORM FEED CHAR JR Z,LIST.1 ; QUEUE ON THIS CP "J"-40H ; LINE FEED RET NZ ; ONLY QUEUE ON THESE CHARS LIST.1: PUSH BC LD C,ETX ; GET EXT CHAR CALL LIST ; SEND IT LIST.2: IN A,(SIOBC) ; GET STATUS BIT 0,A ; TEST RECEIVER STATUS JR Z,LIST.2 ; LOOP UNTILL ACK ARRIVES IN A,(SIOBD) ; GET CHAR AND 07FH ; ASCII MASK CP ACK ; IS IT AN ACK JR NZ,LIST.2 ; NO, WAIT FOR IT POP BC LD A,C ; RESTORE REGISTERS ENDIF ; DIABLO RET ; DONE ELSE ; USE THE PIO DEVICE FOR PRINTER LISTST: IN A,(PIOBD) ; GET STATUS BYTE BIT PBSY,A ; TEST PRINTER BUSY BIT LD A,0 RET NZ ; IF BUSY (ACC=0) CPL RET ; IF PRINTER READY (ACC=FF) LIST: IN A,(PIOBD) ; GET STATUS BYTE BIT PBSY,A ; TEST PRINTER BUSY BIT JR Z,LIST1 ; BRANCH IF READY ; PUSH BC ; SAVE CHARACTER LD E,PLDEVS ; USE MAX POLLED CONS FOR NUMBER LD C,POLL ; MP/M "POLL" FUNCTION CALL XDOS POP BC ; RESTORE CHARACTER ; LIST1: LD A,C ; GET THE CHAR OUT (PIOAD),A ; SEND TO PRINTER RET ; DONE ENDIF ; ***** DEVICE POLLING ROUTINE ; ; THIS CODE IS CALLED FROM THE MP/M POLLING LOGIC TO CHECK THE STATUS ; OF ANY DEVICE WHICH THE SYSTEM IS WAITING FOR. ; ; ENTRY: ; C = DEVICE NUMBER TO CHECK. ; ; EXIT: ; A = 0FFH IF READY, 0 IF BUSY. ; POLLDEVICE: ; LD A,C ; A = DEVICE NUMBER. CP PLDEVS ; COMPARE TO MAX # DEVICES ALLOWED. JP Z,LISTST ; POLL PRINTER IF EQUAL. JR C,DEVOK ; JUMP IF OK. XOR A ; A = INVALID DEVICE NUMBER. RET ; ; VALID DEVICE NUMBER SO GET THE STATUS OF THE DEVICE. ; DEVOK: PUSH IY ; SAVE USER'S IY REGISTER. LD IY,PLTAB ; POINT TO I/O POLLING TABLE. CALL CSET1 ; POINT TO ENTRY FOR THIS DEVICE. JP POLLX ; USER STATUS INPUT LOGIC TO POLL. ; ; ; ROUTINE TO CHECK THE VALIDITY OF THE DEVICE NUMBER IN "D" AND SET ; IY POINTING TO THE TABLE ENTRY FOR THAT DEVICE. ; CSET: LD A,D ; A = DEVICE NUMBER. CP INDEVS ; CHECK AGAINST MAX ALLOWABLE DEVICES. JR C,CSET1 ; JUMP IF OK. ; POP AF ; GET RID OF RETURN ADDRESS. XOR A ; SET FLAG FOR INVALID AND RETURN RET ; DIRECTLY TO MP/M. ; ; VALID DEVICE NUMBER. ; CSET1: RLC A ; MULTIPLY BY 4 SINCE THERE ARE 4 RLC A ; BYTES FOR EACH DEVICE ENTRY. AND 0FCH ; CLEAR ANY JUNK BITS. LD C,A LD B,0 ; B,C = INDEX INTO DEVICE TABLE. ADD IY,BC ; IY POINTS TO DEVICE ENTRY. RET ; IF INTDC ; ; ROUTINE TO CHECK THE VALIDITY OF THE INPUT DEVICE IN REG D ; AND SET IY POINTING TO THAT INPUT DEVICE ENTRY IN TABLE ; CBSET: LD A,D ; A = DEVICE NUMBER CP INDEVS ; VALIDATE AGAINST INPUT DEVICE NUMBER JR C,CBSET1 ; BRANCH IF VALID ; POP AF ; THROW AWAY RETURN ADDRESS XOR A ; FORCE DEVICE NOT READY RET ; RETURN TO MP/M ; ; VALID DEVICE NUMBER ; CBSET1: ADD A,A ; MULTIPLY DEVICE NUMBER LD B,A ; BY 10 SINCE EACH INPUT DEVICE ADD A,A ; ENTRY IS 10 BYTES LONG ADD A,A ADD A,B ; ACC = DEVICE NUMBER X 10 LD C,A LD B,0 ; PREP FOR DOUBLE ADD ADD IY,BC ; POINT IY TO ENTRY RET ; ; ROUTINE TO COMPARE THE BUFFER INPUT POINTER TO THE BUFFER ; OUTPUT POINTER AND RETURN WITH ZERO FLAG SET IF EQUAL. ; TSTPT: LD E,(IY+0) LD D,(IY+1) ; INPUT POINTER IN DE LD L,(IY+2) LD H,(IY+3) ; OUTPUT POINTER IN HL OR A ; CLEAR CARRY SBC HL,DE ; 16-BIT COMPARE RET ; ENDIF ; INTDC ; ; ***************** I/O DEVICE TABLE ****************************** ; IF INTDC ; IF INTERRUPT DRIVEN CONSOLES ; EACH ENTRY IN THE INPUT DEVICE TABLE FOR INTERRUPT DRIVEN INPUT ; REQUIRE 10 BYTES DEFINED AS FOLLOWS. ; ; WORD 1 = BUFFER INPUT POINTER (INITIALIZED TO BASE) ; WORD 2 = BUFFER OUTPUT POINTER (INITIALIZED TO BASE) ; WORD 3 = BASE OF CONSOLE BUFFER ; BYTE 1 = DEVICE STATUS PORT ADDRESS ; BYTE 2 = DEVICE DATA PORT ADDRESS ; BYTE 3 = DEVICE STATUS PORT MASK (FOR READY TESTING) ; BYTE 4 = ASSIGNED DEVICE FLAG ; ; INPUT DEVICES FOR INTERRUPT DRIVEN CONSOLES ; IOTABI: DW CBUFA,CBUFA,CBUFA DB SIOAC,SIOAD,1,($-IOTABI)/10+IDCFLB IFF SERLST DW CBUFB,CBUFB,CBUFB DB SIOBC,SIOBD,1,($-IOTABI)/10+IDCFLB ENDIF ; IF CPC281 DW CBUFC,CBUFC,CBUFC DB SIOCC,SIOCD,1,($-IOTABI)/10+IDCFLB DW CBUFD,CBUFD,CBUFD DB SIODC,SIODD,1,($-IOTABI)/10+IDCFLB ENDIF ; IF INO288 DW CBUF0,CBUF0,CBUF0 DB STA8A1,DAT8A1,2,($-IOTABI)/10+IDCFLB DW CBUF1,CBUF1,CBUF1 DB STA8A2,DAT8A2,2,($-IOTABI)/10+IDCFLB DW CBUF2,CBUF2,CBUF2 DB STA8A3,DAT8A3,2,($-IOTABI)/10+IDCFLB DW CBUF3,CBUF3,CBUF3 DB STA8A4,DAT8A4,2,($-IOTABI)/10+IDCFLB DW CBUF4,CBUF4,CBUF4 DB STA8A5,DAT8A5,2,($-IOTABI)/10+IDCFLB DW CBUF5,CBUF5,CBUF5 DB STA8A6,DAT8A6,2,($-IOTABI)/10+IDCFLB DW CBUF6,CBUF6,CBUF6 DB STA8A7,DAT8A7,2,($-IOTABI)/10+IDCFLB DW CBUF7,CBUF7,CBUF7 DB STA8A8,DAT8A8,2,($-IOTABI)/10+IDCFLB ENDIF ; INDEVS EQU ($-IOTABI)/10 ; NUMBER OF INPUT DEVICES ; ; WHEN GENERATING THE INTERRUPT DRIVEN CONSOLES INPUT TABLE, ; THE POLLING DEVICE TABLE WILL BEGIN WITH THE OUTPUT DEVICES. ; PLTAB: ; ELSE ; NOT INTDC ; FOR EACH DEVICE FOR POLLED OPERATION, THE TABLES CONTAINS ; A 4 BYTE ENTRY DEFINED AS FOLLOWS. ; ; BYTE 1 = DEVICE STATUS PORT ADDRESS ; BYTE 2 = DEVICE DATA PORT ADDRESS ; BYTE 3 = DEVICE STATUS PORT MASK (FOR READY TESTING) ; BYTE 4 = DEVICE POLL NUMBER (TO LET MP/M POLL THE DEVICE) ; ; SINCE BOTH INPUT AND OUTPUT DEVICES WILL BE POLLED, THE POLL ; TABLE BEGINS WITH THE INPUT DEVICES. ; PLTAB: ; ; INPUT DEVICES FOR POLLED OPERATION ; IOTABI: DB SIOAC,SIOAD,1,($-PLTAB)/4 ; CONSOLE 0 IFF SERLST DB SIOBC,SIOBD,1,($-PLTAB)/4 ; CONSOLE 1 ENDIF ; IF CPC281 ; IF THIS CPU DB SIOCC,SIOCD,1,($-PLTAB)/4 DB SIODC,SIODD,1,($-PLTAB)/4 ENDIF ; IF INO288 DB STA8A1,DAT8A1,2,($-PLTAB)/4 ; CONSOLE 2 DB STA8A2,DAT8A2,2,($-PLTAB)/4 DB STA8A3,DAT8A3,2,($-PLTAB)/4 DB STA8A4,DAT8A4,2,($-PLTAB)/4 DB STA8A5,DAT8A5,2,($-PLTAB)/4 DB STA8A6,DAT8A6,2,($-PLTAB)/4 DB STA8A7,DAT8A7,2,($-PLTAB)/4 DB STA8A8,DAT8A8,2,($-PLTAB)/4 ; CONSOLE 9 ENDIF ; INDEVS EQU ($-IOTABI)/4 ; ENDIF ; INTDC ; ; OUTPUT DEVICES FOR POLLED OPERATION ; IOTABO: DB SIOAC,SIOAD,4,($-PLTAB)/4 ; CONSOLE 0 IFF SERLST DB SIOBC,SIOBD,4,($-PLTAB)/4 ; CONSOLE 1 ENDIF ; IF CPC281 ; IF THIS CPU DB SIOCC,SIOCD,4,($-PLTAB)/4 DB SIODC,SIODD,4,($-PLTAB)/4 ENDIF ; IF INO288 IOTAB8: DB STA8A1,DAT8A1,1,($-PLTAB)/4 ; CONSOLE 2 DB STA8A2,DAT8A2,1,($-PLTAB)/4 DB STA8A3,DAT8A3,1,($-PLTAB)/4 DB STA8A4,DAT8A4,1,($-PLTAB)/4 DB STA8A5,DAT8A5,1,($-PLTAB)/4 DB STA8A6,DAT8A6,1,($-PLTAB)/4 DB STA8A7,DAT8A7,1,($-PLTAB)/4 DB STA8A8,DAT8A8,1,($-PLTAB)/4 ; CONSOLE 9 ENDIF ; PLDEVS EQU ($-PLTAB)/4 ; NUMBER OF POLLED CONSOLE DEVICES. ; ; ;********** SELECT MEMORY ********** ; ; BC POINTS TO A TABLE OF 1 BYTE ENTRIES: ; BASE, SIZE, ATTRIBUTE, BANK ; SELMEMORY: ; IF BNKMEM ; IF BANKED MEMORY ; GET THE DESIRED BANK FROM THE TABLE. ; INC BC LD A,(BC) ; GET BANK SIZE OR A RET Z ; IF SYSTEMINIT SELMEM CALL INC BC INC BC ; POINT AT BANK. LD A,(BC) ; A = BANK NUMBER. ; ; SELECT THE BANK. ; CALL SELBNK RET ; ; ; ***** SELECT MEMORY BANK ***** ; ; ENTRY: ; A = DESIRED BANK. ; SELBNK: ; FIND TABLE LENGTH BY MULTIPLYING BANK NUMBER BY THE ; NUMBER OF BOARDS X 2. ; LD C,A LD B,NOMBDS XOR A SELB0: ADD A,C DJNZ SELB0 ADD A,A ; LD C,A LD B,0 ; BC = BANK NUMBER * 8. LD HL,BNKTBL ADD HL,BC ; HL POINTS TO DESIRED ENTRY. LD B,NOMBDS ; SET LOOP FOR # OF MEMORY BOARDS ; SELB1: LD C,(HL) ; C = IO PORT. INC HL LD A,(HL) ; A = BIT PATTERN. INC HL OUT (C),A DJNZ SELB1 ; LOOP FOR ALL BOARDS. ; RET ; ; ; BANK SELECT TABLE: ; ; THIS TABLE DEFINES BANK SELECT USING "NOMBDS" EQUATED EARLIER. ; EACH ENTRY IS NOMBDS X 2 LONG, 2 BYTES FOR EACH BOARD. ; THE 1ST BYTE IS THE BOARD BANK SELECT PORT ADDRESS (I/O) ; AND THE 2ND IS THE BIT PATTERN TO SELECT THE BANK DEFINED ; BY THE ENTRY. IF MEM32 NOMBDS EQU 4 BNKTBL: DB 40H,0FH,41H,00H,42H,00H,43H,00H ; BANK 0 DB 40H,03H,41H,0CH,42H,00H,43H,00H ; BANK 1 DB 40H,03H,41H,03H,42H,00H,43H,00H ; BANK 2 DB 40H,03H,41H,00H,42H,0CH,43H,00H ; BANK 3 DB 40H,03H,41H,00H,42H,03H,43H,00H ; BANK 4 DB 40H,03H,41H,00H,42H,00H,43H,0CH ; BANK 5 DB 40H,03H,41H,00H,42H,00H,43H,03H ; BANK 6 ENDIF IF MEM48 NOMBDS EQU 4 BNKTBL: DB 40H,0FH,41H,00H,42H,00H,43H,00H ; BANK 0 DB 40H,01H,41H,0EH,42H,00H,43H,00H ; BANK 1 DB 40H,01H,41H,00H,42H,0EH,43H,00H ; BANK 2 DB 40H,01H,41H,00H,42H,00H,43H,0EH ; BANK 3 DB 40H,01H,41H,01H,42H,01H,43H,01H ; BANK 4 ENDIF NOBNKS EQU ($-BNKTBL)/(NOMBDS*2) ELSE ; NOT BNKMEM RET ; nothing to do ENDIF ; BNKMEM ; ; ;********** START CLOCK ********** ; ; THIS SETS A FLAG WHICH TELLS THE INTERRUPT RESPONSE CODE TO DO A FLAG ; SET FOR EACH CLOCK TICK. ; STARTCLOCK: LD A,0FFH LD (TICKN),A ; SET THE FLAG. RET ; ; ;********** STOP CLOCK ********** ; ; THIS STOPS THE FLAG SET OPERATION IN THE INTERRUPT RESPONSE CODE. ; STOPCLOCK: XOR A LD (TICKN),A ; RESET THE FLAG. RET ; ; ;********** EXIT REGION ********** ; ; THIS EXIT CHECKS A FLAG TO SEE WHETHER OR NOT TO ENABLE INTERRUPTS. THIS ; IS USED WITH FLAG SET OPERATIONS TO ENABLE THE MPM CALL TO DO A FLAG SET ; AND HAVE MPM NOT TURN ON INTERRUPTS AT THE END OF THE CALL. THIS ALLOWS ; THE INTERRUPT RESPONSE CODE TO MAKE THE FLAG SET CALL AND KEEP THE ; INTERRUPTS OFF. ; EXITREGION: LD A,(PREEMP) ; A = "PREEMPTED" FLAG. OR A RET NZ ; XOR A LD I,A ; INTERRUPT REGISTER PAGE IM 2 ; SET INTERRUPT MODE 2 EI ; FLAG NOT SET SO ENABLE INTERRUPTS. RET ; ; ; ********** REAL TIME CLOCK INTERRUPT HANDLER ********** ; RTCISR: PUSH AF LD A,(EOTIK) ; GET EVEN/ODD TICK FLAG CPL LD (EOTIK),A ; FLIP THE FLAG OR A ; TEST FLAG JR Z,RISR.1 ; CONTINUE SERVICE IF EVEN TICK POP AF EI RETI ; WAIT FOR EVEN TICK RISR.1: POP AF ; ADJUST STACK CALL ISRSTK LD A,(TICKN) OR A ; CHECK FOR DELAYED PROCESS. JR Z,NOTTIC ; LD A,TICFL ; SET SYSTEM TICK FLAG CALL FLAGSET NOTTIC: LD HL,CNTTIK ; CHECK IF ONE SECOND HAS ELAPSED. DEC (HL) JR NZ,RTCDN ; DONE IF NOT 1 SECOND ; ; ONE SECOND HAS ELAPSED. ; LD (HL),50 ; RESET THE ONE SECOND COUNTER. LD A,SECFL ; SET ONE SECOND FLAG CALL FLAGSET ; RTCDN: RETI ; FOR CTC ON CPC-2810 BOARD ; ; ; GENERAL PURPOSE STACK SAVER ROUTINE. ; EACH AND EVERY INTERRUPT HANDLER ROUTINE SHOULD CALL THIS ROUTINE ; FIRST TO SAVE THE CURRENT STACK AND SUBSTITUTE THE INT STACK. THE ; EXIT REGION PRE-EMP FLAG IS SET TO ALLOW XDOS "FLAG SET" FUNCTIONS ; TO BE PERFORMED. THIS ROUTINE RETURNS TO THE CALLER WITH THE ADDRESS ; OF THE RESTORE ROUTINE FIRST ON THE STACK (INVERSE OF STACK SAVER ; ROUTINE). THE USERS INTERRUPT SERVICE ROUTINE NEED ONLY RETURN AFTER ; FIRST CLEARING SOURCE OF INTERRUPT. ; ISRSTK: LD (HLSAV),HL ; SAVE HL REG PAIR POP HL ; SAVE CALLERS RETURN ADDR IN HL LD (OLDSP),SP ; STORE OLD STACK LD SP,INTSTK ; SET INT STACK PUSH AF PUSH BC PUSH DE ; SAVE ALL REGS LD DE,ISRRES PUSH DE ; PUSH STACK RESTORE ADDR FIRST ; LD A,-1 LD (PREEMP),A ; SET EXIT REGION PRE-EMP ; JP (HL) ; RETURN TO CALLER ; STACK RESTORE ROUTINE (INVERSE OF STACK SAVER ROUTINE). ; ISRRES: XOR A LD (PREEMP),A ; RESET PRE-EMP FLAG ; POP DE POP BC POP AF ; RESTORE REGS LD SP,(OLDSP) ; RESTORE OLD STACK LD HL,(HLSAV) ; RESTORE HL REG PAIR ; ; THE FOLLOWING DISPATCH CALL WILL FORCE ROUND ROBIN SCHEDULLING OF ; PROCESSES EXECUTING AT THE SAME PRIORITY LEVEL. ; ; INTERRUPTS ARE NOT ENABLED UNTIL THE DISPATCHER RESUMES THE NEXT PROCESS. ; DISPAT: JP PDISP ; MP/M DISPATCH. ; ; ; ***** MAXIMUM CONSOLE NUMBER ***** ; ; DETERMINS THE MAXIMUM NUMBER OF CONSOLES THAT MP/M MAY USE. ; MAXCONSOLE: LD A,INDEVS ; A = MAX NUMBER OF CONSOLSES. RET ; ; ; GENERAL PERPOSE MP/M FLAG WAIT ROUTINE ; ON ENTRY, REG A = FLAG NUMBER ; ON EXIT, XDOS STATUS IN REG A ; FLAGWAIT: LD E,A LD C,FLWAIT JP XDOS ; ; GENERAL PURPOSE MP/M FLAG SET ENTRY POINT ; ON ENTRY, REG A = FLAG NUMBER ; ON EXIT, XDOS STATUS IN REG A ; FLAGSET: LD E,A LD C,FLSET JP XDOS ; ; IF INTDC ; IF INTERRUPT DRIVEN INPUT ; ; ***** RECEIVER INTERRUPT SERVICE ROUTINE ***** ; COMISR: CALL ISRSTK ; SAVE THE STACK PUSH IY ; SAVE THIS TOO LD IY,IOTABI ; POINT TO BASE OF I/O TABLE ; LD B,INDEVS ; SET LOOP FOR NUMBER OF INPUT DEVICES ; CISR0: LD C,(IY+6) ; DEVICE STATUS PORT IN A,(C) ; GET STATUS AND (IY+8) ; AND WITH MASK BYTE JR Z,CISR1 ; IF NO CHAR WAITING PUSH BC CALL RECEIV ; RECEIVE THE CHARACTER POP BC CISR1: LD DE,10 ; LENGTH OF TABLE ENTRY ADD IY,DE ; POINT TO NEXT ENTRY DJNZ CISR0 ; LOOP IF MORE DEVICES TO CHECK ; POP IY RETI ; FOR SIO PRIORITY ; ; ***** CHARACTER RECEIVE ROUTINE ***** ; RECEIV: LD E,(IY+0) LD D,(IY+1) ; INPUT POINTER IN DE INC DE ; BUMP IT LD L,(IY+4) LD H,(IY+5) ; BASE OF BUFFER IN HL LD BC,CBLEN ; BUFFER LENGTH ADD HL,BC ; COMPUTE END OF BUFFER SBC HL,DE ; COMPARE WITH INPUT POINTER JR NZ,RCV1 ; IF NO WRAP LD E,(IY+4) LD D,(IY+5) ; WRAP THE BUFFER RCV1: LD (IY+0),E LD (IY+1),D ; STORE NEW BUFFER ADDRESS LD C,(IY+7) ; GET DEVICE DATA PORT IN A,(C) ; GET CHARACTER WAITING LD (DE),A ; PLACE IN BUFFER ; LD A,(IY+9) ; GET ASSOCIATED FLAG CALL FLAGSET ; XDOS FLAG SET FUNCTION RET ; ENDIF ; INTDC ; ; ; ********** SYSTEM INITIALIZATION ********** ; SYSTEMINIT: ; ; ***** INITIALIZE REG I FOR Z80 MODE 2 INTERRUPTS ***** ; XOR A LD I,A ; USER PAGE 0 IM 2 ; LD HL,RTCISR ; HL = ADDRESS OF INTERRUPT HANDLER. LD (RTCVEC),HL ; STORE IN I REGISTER PAGE ; IF CPD280 ; this CPU board ; ***** 9519 UIC INITIALIZATION ***** ; ; THE MAIN INITIALIZATION FOR THE AMD 9519 UNIVERSAL INTERRUPT ; CONTROLLER LOCATED ON THE CPD-2800 CPU BOARD IS PERFORMED FIRST. ; XOR A OUT (UICC),A ; RESET UIC DEVICE ; ; IREQ LINES ACTIVE LOW, GROUP INTERRUPT ACTIVE LOW, ; SET FOR ROTATING PRIORITY, INDIVIDUAL VECTOR, INTERRUPT MODE. ; (SEE PAGE 4 OF AM9519 DATA SHEET) ; LD A,81H OUT (UICC),A ; ; SET "M7" ("CHIP ARMED BIT"). ; LD A,0A9H OUT (UICC),A ; ; ENABLE THE "AUTO-CLEAR" BITS FOR ALL IREQ LINES. ; LD A,0C0H ; PRE-SELECT AUTO CLEAR OUT (UICC),A LD A,0FFH ; LOAD AUTO CLEAR REGISTER OUT (UICD),A ; ; CLEAR THE INTERRUPT REQUEST AND INTERRUPT SERVICE REGISTERS. ; LD A,40H OUT (UICC),A ; CLEAR INT REQUEST REG. LD A,70H OUT (UICC),A ; CLEAR INT SERV REG. ; ; NOW PROGRAM THE 9519 FOR RTC INTERRUPTS ON IREQ-0 LINE. ; SET UP THE LOW-ORDER BYTE FOR THE RTC INTERRUPT HANDLER IN MODE 2 ; LD A,0E0H ; A=1 BYTE,RESPONSE LEVEL 0, OUT (UICC),A ; REAL TIME CLOCK CHANNEL. ; LD A,RTCVEC AND 0FFH OUT (UICD),A ; SEND LOW-ORDER BYTE RESPONSE ; ; ; CLEAR THE REAL TIME CLOCK INTERRUPT MASK (ENABLE IREQ-0 INTERRUPTS). ; LD A,028H OUT (UICC),A ; CLEAR IREQ-0 IMR ; ; SET THE RATE FOR THE REAL TIME CLOCK (SECTION 2 OF 8253 ON CPD-2800). ; LD A,0B6H ; CNTR 2,MODE 3, BINARY COUNT. OUT (CTRM),A LD BC,12288 ; 10 MS. DIVISOR LD A,C OUT (CTR2),A LD A,B OUT (CTR2),A ; ; PROGRAM CHANNEL A BAUD RATE (SECTION 0 OF 8253 ON CPD-2800). ; LD A,036H ; CHANNEL 0, BINARY OUT (CTRM),A ; LOAD COUNTER LD A,CDIV0 AND 0FFH OUT (CTR0),A ; SEND LSB LD A,CDIV0 SHR 8 OUT (CTR0),A ; SEND MSB ; ; PROGRAM CHANNEL B BAUD RATE (SECTION 1 OF 8253 ON CPD-2800). ; LD A,76H ; CHANNEL 1, BINARY OUT (CTRM),A LD A,CDIV1 AND 0FFH OUT (CTR1),A LD A,CDIV1 SHR 8 OUT (CTR1),A ; ENDIF ; CPD280 IF CPC281 ; THIS CPU BOARD ; PROGRAM CHANNEL A&B (FIRST SIO) BAUD RATE (SECTIONS A&B OF CTC DEVICE). ; PROGRAM CHANNEL C&D (SECOND SIO) BAUD RATE (SHARED SECTION C OF CTC). ; LD A,CTMODA OUT (CTCA),A ; SEND MODE LD A,CTDIVA OUT (CTCA),A ; AND CONSTANT LD A,CTMODB OUT (CTCB),A ; SEND MODE LD A,CTDIVB OUT (CTCB),A ; AND CONSTANT LD A,CTMODC OUT (CTCC),A ; SEND MODE LD A,CTDIVC OUT (CTCC),A ; AND CONSTANT ; ; SET UP THE REAL TIME CLOCK USING CHANNEL D OF CTC DEVICE. ; LD A,RTCVEC AND 0F8H ; CTC VECTOR BASE OUT (CTCA),A LD A,0A5H ; ENABLE INTRPS, TIMER MODE OUT (CTCD),A ; PRESCALER=256, LOAD TIME CONSTANT LD A,156 OUT (CTCD),A ; TIME CONSTANT ENDIF ; CPC281 ; IF INTERRUPT DRIVEN CONSOLE, SET PAGE 0 VECTOR WORD HERE. ; IF INTDC LD HL,COMISR ; ADDRESS OF SERVICE ROUTINE LD (COMVEC),HL ; STORE IN PAGE 0 ENDIF ; ; INITIALIZE THE SIO SERIAL DEVICES ON THE CPU BOARD ; LD HL,ISIOA ; CHANNEL A INIT TABLE LD BC,ISIOAL*256+SIOAC ; LENGTH IN B & PORT IN C OTIR ; INITIALIZE SIO CHANNEL A ; LD HL,ISIOB ; CHANNEL B INIT TABLE LD BC,ISIOBL*256+SIOBC ; LENGTH IN B & PORT IN C OTIR ; INITIALIZE SIO CHANNEL B IF CPC281 ; if this CPU ; INITIALIZE THE SECOND SIO FOR SERIAL CHANNEL C&D. ; LD HL,ISIOA ; USE INIT TABLE FOR A LD BC,ISIOAL*256+SIOCC ; LENGTH AND CHANNEL C STATUS PORT OTIR ; INIT SIO CHANNEL C ; LD HL,ISIOD ; USE INIT TABLE FOR B LD BC,ISIODL*256+SIODC ; LENGTH AND CHANNEL D STATUS PORT OTIR ; INIT SIO CHANNEL D ENDIF ; CPC281 ; ; ***** INITIALIZE THE PIO FOR CENTRONICS MODE ***** ; LD A,00FH OUT (PIOAC),A ; CHANNEL A = OUTPUT PORT LD A,0CFH OUT (PIOBC),A ; CHANNEL B = BIT CONTROL LD A,1 OUT (PIOBC),A ; BIT 0 = BUSY STATUS BIT LD A,80H OUT (PIOBD),A ; ENABLE CENTRONICS INTERFACE ; ; IF INO288 ; ***** SET UP THE 8-CHANNEL SERIAL BOARD (INO-288) ***** ; ; SET UP THE BAUD RATE. (READ THE SWITCHES AND OUTPUT THE VALUE TO THE ; BAUD RATE GENERATOR. THIS CONSTITUTES THE "HARDWARE SELECTIBLE" NATURE ; OF THE I/O BOARD. THE "SOFTWARE SELECTION" IS SIMPLY OUTPUTTING THE ; BAUD RATE WITHOUT READING THE SWITCHES.) ; IN A,(BAUD12) OUT (BAUD12),A ; SET UP CHANNELS 1 & 2. IN A,(BAUD34) OUT (BAUD34),A ; SET UP CHANNELS 3 & 4. IN A,(BAUD56) OUT (BAUD56),A ; SET UP CHANNELS 5 & 6. IN A,(BAUD78) OUT (BAUD78),A ; SET UP CHANNELS 7 & 8. ; ; RESET AND PROGRAM EACH 8251 CHANNEL ON INO-288. ; LD B,8 ; SET UP TO DO 8 CHANNELS. LD DE,4 ; TABLE ENTRY IS 4 BYTES LONG. LD HL,IOTAB8 ; POINT TO TABLE OF ADDRESSES. ; ILOOP8: LD C,(HL) ; C = I/O ADDRESS OF STATUS PORT. XOR A OUT (C),A ; OUTPUT 3 NULLS. OUT (C),A OUT (C),A LD A,40H ; A = "RESET" COMMAND. OUT (C),A LD A,8EH OUT (C),A LD A,37H OUT (C),A DEC C ; C = DATA PORT. IN A,(C) ; CLEAR THE JUNK BITS. ; ADD HL,DE ; POINT HL TO NEXT ENTRY. DJNZ ILOOP8 ; JUMP IF MORE I/O TO INITIALIZE. ; ; ; INITIALIZE THE 9519 UIC DEVICES ON THE INO-288. ; XOR A OUT (UICC1),A ; RESET UIC DEVICE 1 OUT (UICC2),A ; RESET UIC DEVICE 2 IF INTDC ; IF RECEIVER INTERRUPTS FOR INO288 ; IREQ LINES ACTIVE HIGH, GROUP INTERRUPT ACTIVE LOW, ; SET FOR ROTATING PRIORITY, COMMOM VECTOR, INTERRUPT MODE. ; (SEE PAGE 4 OF AM9519 DATA SHEET) ; LD A,93H OUT (UICC1),A ; UIC DEVICE 1 OUT (UICC2),A ; UIC DEVICE 2 ; ; SET "M7" ("CHIP ARMED BIT"). ; LD A,0A9H OUT (UICC1),A ; UIC DEVICE 1 OUT (UICC2),A ; UIC DEVICE 2 ; ; ENABLE THE "AUTO-CLEAR" BITS FOR ALL IREQ LINES. ; LD A,0C0H ; PRE-SELECT AUTO CLEAR REGISTER OUT (UICC1),A OUT (UICC2),A LD A,0FFH OUT (UICD1),A ; UIC DEVICE 1 OUT (UICD2),A ; UIC DEVICE 2 ; ; CLEAR THE INTERRUPT REQUEST AND INTERRUPT SERVICE REGISTERS. ; LD A,40H OUT (UICC1),A ; CLEAR INT REQUEST REG. OUT (UICC2),A LD A,70H OUT (UICC1),A ; CLEAR INT SERV REG. OUT (UICC2),A ; ; SET IREQ-0 RESPONSE MEMORY FOR LOW-ORDER ADDRESS OF INTERRUPT ; SERVICE ROUTINE ADDRESS STORAGE. NOTE, COMMON VECTORING FORCES ; ALL IREQ'S TO THIS RESPONSE LEVEL. ; LD A,0E0H ; 1 BYTE, IREQ-0 RESPONSE OUT (UICC1),A ; UIC DEVICE 1 OUT (UICC2),A ; UIC DEVICE 2 LD A,COMVEC AND 0FFH ; LOW-ORDER ADDRESS OUT (UICD1),A OUT (UICD2),A ; ; CLEAR THE IMR BITS FOR ALL RECEIVER DEVICES (ENABLE INTERRUPTS) ; LD A,0B0H ; PRE-SELECT IMR REGISTER OUT (UICC1),A ; UIC DEVICE 1 OUT (UICC2),A ; UIC DEVICE 2 LD A,055H ; IREQ-1,3,5,7 OUT (UICD1),A OUT (UICD2),A ; ENDIF ; INTDC ; ENDIF ; INO288 ; ; ALLOW THE DISK DRIVER TO INITIALIZE. ; CALL INIDVR ; ENTRY POINT ; ; IF BANK SWITCHED MEMORY IS BEING USED, THIS CALL MUST ; BE THE LAST OPERATION BEFORE RETURNING FROM SYSTEMINIT. ; THE FIRST 64 BYTES OF THE DEFAULT PAGE 0 IS COPIED INTO ; EACH OF THE OTHER BANKS. ; IF BNKMEM ; IF BANK SWITCHED MEMORY CALL INITBNK ENDIF ; ; SYSTEM INITIALIZATION SHOULD NOW BE COMPLETE. ; RET ; from SYSTEMINIT ; ; ; ****** INITIALIZATION TABLES FOR SIO DEVICES ****** ; ; CHANNEL A ISIOA: DB 018H ; CHANNEL RESET DB 004H ; WRITE REG 4 DB 044H ; X16 CLOCK, 1 STOP BIT DB 003H ; WRITE REG 3 DB 0C1H ; Rx 8-BIT CHAR, Rx ENABLE DB 005H ; WRITE REG 5 DB 0EAH ; DTR, Tx 8-BIT CHAR, Tx ENABLE, RTS ; IF INTDC DB 001H ; WRITE REGISTER 1 DB 018H ; INT ON ALL Rx CHARACTERS ENDIF ; DB 000H ; READ REG 0 ISIOAL EQU $-ISIOA ; LENGTH OF SEQUENCE ; ; CHANNEL B ISIOB: DB 018H ; CHANNEL RESET DB 004H ; WRITE REG 4 DB 044H ; X16 CLOCK, 1 STOP BIT DB 003H ; WRITE REG 3 DB 0C1H ; Rx 8-BIT CHAR, Rx ENABLE DB 005H ; WRITE REG 5 DB 0EAH ; DTR, Tx 8-BIT CHAR, Tx ENABLE, RTS ; IF INTDC DB 002H ; WRITE REGISTER 2 DB COMVEC AND 0FFH IFF SERLST ; NOT SERIAL PRINTER DB 001H ; WRITE REGISTER 1 DB 018H ; INT ON ALL Rx CHARACTERS ENDIF ENDIF ; DB 000H ; READ REG 0 ISIOBL EQU $-ISIOB ; LENGTH OF SEQUENCE ; IF CPC281 ; ; CHANNEL D ISIOD: DB 018H ; CHANNEL RESET DB 004H ; WRITE REG 4 DB 044H ; X16 CLOCK, 1 STOP BIT DB 003H ; WRITE REG 3 DB 0C1H ; Rx 8-BIT CHAR, Rx ENABLE DB 005H ; WRITE REG 5 DB 0EAH ; DTR, Tx 8-BIT CHAR, Tx ENABLE, RTS ; IF INTDC DB 002H ; WRITE REGISTER 2 DB COMVEC AND 0FFH DB 001H ; WRITE REGISTER 1 DB 018H ; INT ON ALL Rx CHARACTERS ENDIF ; DB 000H ; READ REG 0 ISIODL EQU $-ISIOD ; LENGTH OF SEQUENCE ; ENDIF ; IF BNKMEM ; IF BANKED MEMORY ; INITIALIZE PAGE 0 OF EACH BANK. ; ; COPY PAGE 0 TO LOCAL AREA. ; INITBNK: LD HL,0 ; POINT TO START OF PAGE 0. LD DE,SECBUF ; POINT TO LOCAL STORAGE. LD BC,64 ; SAVE 64 BYTES. LDIR ; ; INITIALIZE ALL DEFINED BANKS OF MEMORY. ; LD A,NOBNKS ; START WITH LAST BANK PUSH AF INITB1: POP AF DEC A JR Z,INITB2 ; JUMP IF ALL BANKS INITIALIZED. PUSH AF CALL SELBNK CALL BNKSET JR INITB1 ; INITB2: ; ; SELECT BANK 0 AGAIN. ; XOR A CALL SELBNK ; RET ; ; ROUTINE TO COPY LOCAL STORAGE TO PAGE 0 OF SELECTED BANK. ; BNKSET: LD HL,SECBUF ; POINT TO LOCAL STORAGE. LD DE,0 ; POINT TO PAGE 0. LD BC,64 LDIR RET ; ENDIF ; BNKMEM ; VAIRABLES ; TICKN: DB 0 ; CLOCK TICKING FLAG PREEMP: DB 0 ; EXIT REGION PRE-EMP FLAG EOTIK: DB 0 ; EVEN/ODD TICK FLAG FOR RTC INTERRUPT. CNTTIK: DB 1 ; TICK COUNTER FOR RTC INTERRUPT. OLDSP: DW 0 ; SP SAVE FOR INTERRUPT. HLSAV: DW 0 ; HL SAVE FOR INTERRUPT. ; ; STACK AREA FOR LOCAL INTERRUPTS. ; DS 50 INTSTK: IF INTDC ; ***** INTERRUPT DRIVEN CONSOLE BUFFERS ***** ; CBUFA: DS CBLEN ; SIO CHANNEL A BUFFER CBUFB: DS CBLEN ; SIO CHANNEL B BUFFER ; IF CPC281 ; if this CPU CBUFC: DS CBLEN ; SIO CHANNEL C BUFFER CBUFD: DS CBLEN ; SIO CHANNEL D BUFFER ENDIF ; IF INO288 CBUF0: DS CBLEN ; UART-0 BUFFER CBUF1: DS CBLEN CBUF2: DS CBLEN CBUF3: DS CBLEN CBUF4: DS CBLEN CBUF5: DS CBLEN CBUF6: DS CBLEN CBUF7: DS CBLEN ; UART 7 BUFFER ENDIF ; INO288 ; ENDIF ; INTDC END