;===================================================================== ; MP/M-80 II Resident Extended Input/Output System, Version 1.0 ;===================================================================== ; ; Copyright (C) 1981 ,by MICROCOSM.All rights reserved.No part may be ; reproduced,transmitted,transcribed ,stored in retrieval system, or ; translated into any language or computer language, in any form or ; by any means,electronic,mechanical,magnetic,optical,chemical,manual ; or otherwise, without the prior written permission of MICROCOSM, ; 3055 Waco St.,Simi Valley,California 93063. ; ; Disclaimer ; ========== ; ; MICROCOSM makes no representation or warranties with respect to the ; contents herof and specifically disclaims any implied warranties of ; merchantability or fitness for any particular purpose. Further , ; MICROCOSM reserves the right to revise and to make changes from ; time to time in the content hereof without obligation of MICROCOSM ; to notify any person of such revision or changes. ; ; ; ; ; THIS MODULE CONTAINS ALL THE INPUT/OUTPUT ROUTINES FOR THE MP/M-80 II SYSTEM ; ; ; CONSOLE PORT #0 I/O PARAMETER EQUATES ; CCTRL EQU 010H ; CONSOLE STATUS PORT CCTRL EQU 010H ; CONSOLE COMMAND PORT CDATA EQU 011H ; CONSOLE DATA PORT CRRDY EQU 001H ; CONSOLE RECEIVER READY BIT CTRDY EQU 002H ; CONSOLE TRANSMITTER READY BIT CNULL EQU 000H ; CONSOLE NULL COUNT ; ; CONSOLE PORT #1 I/O PARAMETER EQUATES ; MCTRL EQU 01AH ; MODEM CONTROL/STATUS PORT MDATA EQU 01BH ; MODEM DATA PORT MRRDY EQU 001H ; MODEM RECEIVER READY BIT MTRDY EQU 002H ; MODEM TRANSMITTER READY BIT CARDET EQU 004H ; DATA CARRIER DETECT MASK ROMBOOT EQU 0F13DH ; ROM BOOT ENTRY ADDRESS ; ; VECTOR INTERRUPT/REAL TIME CLOCK I/O PARAMETER EQUATES ; VICNTRL EQU 0FEH ; 88-VI(RTC) CONTROL PORT FLAGSET EQU 133 DSPTCH EQU 142 ; ; VECTOR INTERRUPT/REAL TIME CLOCK VECTOR LEVEL EQUATES ; VEC1 EQU 0DDH ; VECTOR LEVEL 1 (RST 1), ADDRESS 0008 HEX ; ; DISK I/O PARAMETER EQUATES ; CNTRL EQU 0C0H ; ICOM 3712 DISK CONTROL COMMAND PORT DATAO EQU 0C1H ; ICOM 3712 DISK DATA OUT PORT DATAI EQU 0C0H ; ICOM 3712 DISK DATA IN PORT ; ; LIST DEVICE I/O PARAMETER EQUATES ; LSTAT EQU 002H ; LIST STATUS PORT LCOM EQU 002H ; LIST COMMAND PORT LDATA EQU 003H ; LIST DATA PORT LRBIT EQU 080H ; LISTER READY BIT LNULL EQU 000H ; LIST NULL COUNT LINCNT EQU 66 ; LINES PER PRINTER PAGE ; ; ASCII CHARACTER EQUATES ; RUBOUT EQU 7FH SPACE EQU 20H ; TDISKS EQU 2 ; NUMBER OF AVAILABLE DISKS ; NMBDEV EQU 6 ; NUMBER OF DEVICES IN POLL TABLE ; NMBCNS EQU 2 ; NUMBER OF CONSOLES ; POLL EQU 131 ; XDOS POLL FUNCTION ; PLLPT EQU 0 ; POLL PRINTER PLDSK EQU 1 ; POLL DISK PLCO0 EQU 2 ; POLL CONSOLE OUT #0 PLCO1 EQU 3 ; POLL CONSOLE OUT #1 (MODEM) PLCI0 EQU 4 ; POLL CONSOLE IN #0 PLCI1 EQU 5 ; POLL CONSOLE IN #1 (MODEM) ; RTCNT EQU 10 ; RETRY COUNT ; IOBYTE EQU 3 ; ADDRESS OF I/O BYTE ; OFFSET EQU 2 ; NUMBER OF TRACKS USED BY MP/M-80 II ORG 00000H ; START OF REL-0 XIOS FOR MP/M-80 II ; ; +++ I/O JUMP VECTOR +++ ; ; JMP COMMONBASE ; COMMON BASE, TERMINATE PROCESS WBOOTE: JMP WBOOT ; WARM BOOT, TERMINATE PROCESS JMP CONST ; CONSOLE STATUS JMP CONIN ; CONSOLE CHARACTER IN JMP CONOUT ; CONSOLE CHARACTER OUT JMP LIST ; LIST CHARACTER OUT JMP PUNCH ; PUNCH NOT IMPLEMENTED JMP READER ; READER NOT IMPLEMENTED JMP HOME ; MOVE HEAD TO HOME JMP SELDSK ; SELECT DISK JMP SETTRK ; SET TRACK NUMBER JMP SETSEC ; SET SECTOR NUMBER JMP SETDMA ; SET DMA ADDRESS JMP READ ; READ DISK JMP WRITE ; WRITE DISK JMP POLLPT ; LIST STATUS JMP SECTRAN ; SECTOR TRANSLATE ; ; EXTENDED I/O SYSTEM JUMP VECTOR ; JMP SELMEMORY ; SELECT MEMORY JMP POLLDEVICE ; POLL DEVICE JMP STARTCLOCK ; START CLOCK JMP STOPCLOCK ; STOP CLOCK JMP EXITREGION ; EXIT REGION JMP MAXCONSOLE ; MAXIMUM CONSOLE NUMBER JMP SYSTEMINIT ; SYSTEM INITIALIZATION DB 0,0,0 ; IDLE PROCEDURE, NOT USED ; COMMONBASE: ; TERMINATE PROCESS ; JMP COLDSTART SWTUSER:JMP $-$ SWTSYS: JMP $-$ PDISP: JMP $-$ XDOS: JMP $-$ SYSDAT: DW $-$ ; COLDSTART: WARMSTART: ; MVI C,0 ; SYETM RESET, TERMINATE PROCESS JMP XDOS ; ; MP/M-80 II CONSOLE HANDLERS ; CONST: ; CONSOLE STATUS CALL PTBLJMP ; COMPUTE AND JUMP TO HANDLER DW PT0ST ; CONSOLE #0 STATUS ROUTINE DW PT1ST ; CONSOLE #1 (MODEM) STATUS RT READER: ; READER NOT IMPLEMENTED MVI D,0 ; DEFAULT TO CONIN #0 CONIN: ; CONSOLE INPUT CALL PTBLJMP ; COMPUTE AND JUMP TO HANDLER DW PT0IN ; CONSOLE #0 INPUT DW PT1IN ; CONSOLE #1 (MODEM) INPUT PUNCH: ; PUNCH NOT IMPLEMENTED MVI D,0 ; DEFAULT TO CONOUT #0 CONOUT: ; CONSOLE OUTPUT CALL PTBLJMP ; COMPUTE AND JUMP TO HANDLER DW PT0OUT ; CONSOLE #0 OUTPUT DW PT1OUT ; CONSOLE #1 (MODEM) OUTPUT ; PTBLJMP: ; COMPUTE AND JUMP TO HANDLER ; D = CONSOLE # ; DO NOT DESTROY MOV A,D CPI NMBCNS JC TBLJMP POP PSW ; THROW AWAY TABLE ADDRESS RTNEMPTY: XRA A RET TBLJMP: ; COMPUTE AND JUMP TO HANDLER ; A = TABLE INDEX ADD A ; DOUBLE TABLE INDEX FOR ADR OFFST POP H ; RETURN ADR POINTS TO JUMP TBL MOV E,A MVI D,0 DAD D ; ADD TABLE INDEX * 2 TO TBL BASE MOV E,M ; GET HANDLER ADDRESS INX H MOV D,M XCHG PCHL ; JUMP TO COMPUTED CNS HANDLER ; ; CHECK CONSOLE INPUT STATUS ; ; POLL CONSOLE #0 INPUT POLCI0: PT0ST: ; RETURN 0FFH IF READY, ; 000H IF NOT IN CCTRL ; READ CONSOLE STATUS ANI CRRDY ; LOOK AT RECEIVER READY BIT MVI A,0 ; SET A=0 FOR RETURN RZ ; NOT READY, WHEN 0 MVI A,0FFH ; IF READY A=FF RET ; RETURN FROM POLCI0 ; ; READ A CHARACTER FROM CONSOLE. ; ; CONSOLE #0 INPUT ; PT0IN: ; RETURN CHARACTER IN REG A MVI C,POLL MVI E,PLCI0 CALL XDOS ; POLL CONSOLE #0 INPUT IN CDATA ; READ A CHARACTER ANI 7FH ; MAKE MOST SIG. BIT = 0 CPI RUBOUT ; IS IT A RUBOUT? RNZ ; RETURN IF NOT MVI A,0FFH ; SET NO PRINT FLAG STA CONOTF MVI A,7FH ; RESTORE RUBOUT RET ; RETURN FROM PT0IN ; ; WRITE A CHARACTER TO THE CONSOLE DEVICE ; ; CONSOLE #0 OUTPUT ; PT0OUT: ; REG C = CHARACTER TO OUTPUT PUSH B CALL PT0WAIT ; POLL CONSOLE #0 OUTPUT POP B MOV A,C ; GET CHARACTER OUT CDATA ; PRINT IT RET ; RETURN FROM PT0OUT ; ; WAIT FOR CONSOLE #0 OUTPUT READY ; PT0WAIT: MVI C,POLL MVI E,PLCO0 JMP XDOS ; POLL CONSOLE #0 OUTPUT ; RET ; ; POLL CONSOLE #0 OUTPUT ; POLCO0: ; RETURN 0FFH IF READY, ; 000H IF NOT IN CCTRL ; READ CONSOLE STATUS ANI CTRDY ; IF NOT READY, MVI A,0 ; RETURN WITH ZERO'S RZ ; NOT READY, WHEN 0 MVI A,0FFH RET ; RETURN FROM POLCO0 ; ; WRITE A CHARACTER ON LISTING DEVICE ; LIST: ; LIST OUTPUT PUSH B PUSH D MVI C, POLL MVI E, PLLPT CALL XDOS POP D POP B MOV A,C ; GET DATA BYTE OUT LDATA ; PRINT IT RET ; RETURN FROM LIST ; ; RETURN LIST STATUS ; LISTST: XRA A ; FLAG LISTER NOT READY RET ; ; POLL PRINTER OUTPUT ; POLLPT: ; RETURN 0FFH IF READY, ; 000H IF NOT IN LSTAT ; READ LISTER STATUS. ANI LRBIT ; LOOK AT READY BIT. MVI A,0 ; RETURN WITH ZERO'S IF NOT READY RNZ MVI A,0FFH RET ; ; POLL CONSOLE #1 (MODEM) INPUT ; POLCI1: PT1ST: ; RETURN 0FFH IF READY, ; 000H IF NOT IN MCTRL ; GET MODEM STATUS ANI CARDET ; DATA CARRIER DETECT ON? JNZ RESTART ; EXIT, IF NO CARRIER IN MCTRL ; GET MODEM STATUS ANI MRRDY ; MASK MODEM RECEIVER READY MVI A,0 ; RETURN WITH ZERO'S RZ ; RETURN IF ZERO FLAG SET MVI A,0FFH ; IF READY,A=FFH RET ; RETURN FROM POLCI1 ; ; CONSOLE #1 (MODEM) INPUT ; PT1IN: ; RETURN CHARACTER IN REG A IN MCTRL ; GET MODEM STATUS ANI CARDET ; DATA CARRIER DETECT ON? JNZ RESTART ; EXIT, IF NO CARRIER MVI C,POLL MVI E,PLCI1 CALL XDOS ; POLL CONSOLE #1 INPUT IN MDATA ; GET MODEM DATA BYTE ANI 07FH ; STRIP OFF MSB FOR ASCII RET ; RETURN FROM CONIN ; ; CONSOLE #1 (MODEM) OUTPUT ; PT1OUT: ; REG C = CHARACTER TO OUTPUT IN MCTRL ; GET MODEM STATUS ANI CARDET ; DATA CARRIER DETECT ON? JNZ RESTART ; EXIT, IF NO CARRIER PUSH B CALL PT1WAIT POP B MOV A,C ; GET CHARACTER OUT MDATA ; OUT TO MODEM RET ; RETURN FROM CONOUT ; WAIT FOR CONSOLE #1 (MODEM) OUTPUT READY PT1WAIT: MVI C,POLL MVI E,PLCO1 JMP XDOS ; POLL CONSOLE #1 OUTPUT ; RET ; POLL CONSOLE #1 (MODEM) OUTPUT POLCO1: ; RETURN 0FFH IF READY, ; 000H IF NOT IN MCTRL ; GET MODEM STATUS ANI CARDET ; DATA CARRIER DETECT ON? JNZ RESTART ; EXIT, IF NO CARRIER IN MCTRL ; GET MODEM STATUS ANI MTRDY ; MASK MODEM TRANSMITTER READY MVI A,0 ; RETURN WITH ZERO'S RZ MVI A,0FFH ; IF READY,A=FFH RET ; RETURN FROM POLCO1 ; ; WAIT FOR DATA CARRIER DETECT, THEN RESTART AT "BOOT" ; LIGHTS EQU 0FFH ; IMSAI FRONT PANEL DATA LIGHTS SWITCH EQU 0FFH ; IMSAI FRONT PANEL DATA SWITCHES ; RESTART:MVI B,10 ; SET MAJOR DELAY LOOP XRA A ; RESET FRON PANEL LIGHTS OUT LIGHTS DELAY: LXI H,0FFFFH; SET MINOR DELAY LOOP DELAY1: DCX H MOV A,H ORA L JNZ DELAY1 ; LOOP MINOR DELAY CMA ; SET FRONT PANEL LIGHTS OUT LIGHTS DCR B JNZ DELAY ; LOOP MAJOR DELAY MVI A,003H ; RESET MODEM 2SI/O PORT OUT MCTRL MVI A,011H ; SET 8 DATA BITS,2 STOP, NO PARITY OUT MCTRL CARWAIT:IN MCTRL ; GET MODEM STATUS, AND WAIT FOR CARRIER ANI CARDET ; DATA CARRIER DETECT ON? JNZ RESTART ; LOOP HERE 'TILL IT IS JMP ROMBOOT ; ROM BOOT WHEN READY ; ; MP/M-80 II EXTENDED I/O SYSTEM ; POLLDEVICE: ; REG C = DEVICE # TO BE POLLED ; RETURN 0FFH IF READY, ; 000H IF NOT MOV A,C CPI NMBDEV JC DEVOK MVI A,NMBDEV; IF DEV # >= NMBDEV, ; SET TO NMBDEV DEVOK: CALL TBLJMP ; JUMP TO DEV POLL CODE DW POLLPT ; POLL PRINTER OUTPUT DW POLDSK ; POLL DISK READY DW POLCO0 ; POLL CONSOLE #0 OUTPUT DW POLCO1 ; POLL CONSOLE #1 (MODEM) OUTPUT DW POLCI0 ; POLL CONSOLE #0 INPUT DW POLCI1 ; POLL CONSOLE #1 (MODEM) INPUT DW RTNEMPTY; BAD DEVICE HANDLER ; SELECT / PROTECT MEMORY SELMEMORY: ; REG BC = ADR OF MEM DESCRIPTOR ; BC -> BASE 1 BYTE, ; SIZE 1 BYTE, ; ATTRIB 1 BYTE, ; BANK 1 BYTE. ; THIS HARDWARE DOES NOT HAVE MEMORY PROTECTION OR BANK SWITCHING RET ; START CLOCK STARTCLOCK: ; WILL CAUSE FLAG #1 TO BE SET ; AT EACH SYSTEM TIME UNIT TICK MVI A,0FFH STA TICKN RET ; STOP CLOCK STOPCLOCK: ; WILL STOP FLAG #1 SETTING AT ; SYSTEM TIME UNIT TICK XRA A STA TICKN RET ; EXIT REGION EXITREGION: ; EI IF NOT PREEMPTED LDA PREEMP ORA A RNZ EI RET ; MAXIMUM CONSOLE NUMBER MAXCONSOLE: MVI A,NMBCNS RET ; SYSTEM INITIALIZATION SYSTEMINIT: ; MVI A,003H ; CONSOLE AND MODEM RESET OUT CCTRL OUT MCTRL MVI A,011H ; NO INTERRUPTS,8 DATA BITS,NO PARITY,1 STOP BIT OUT CCTRL OUT MCTRL ; ; CLEAR XIOS VARIABLE AREA ; MVI C,ENDZ-STARTZ ; GET LENGTH OF ZERO AREA LXI H,STARTZ ; POINT TO THE START OF ZERO AREA CLEAR: XRA A ; MAKE ZERO MOV M,A ; JAM INTO MEMORY INX H ; BUMP POINTER DCR C ; DE-BUMP LENGTH JNZ CLEAR ; LOOP UNTIL ALL CLEARED ; ; SETUP RESTART JUMP VECTORS ; MVI A,0C3H STA 1*8 LXI H,INT1HND SHLD 1*8+1 ; JMP INT1HND AT RESTART 1 MVI A,0C9H ; RETURNS FOR ALL REMAINING INTERRUPT VECTORS STA 2*8 STA 3*8 STA 4*8 STA 5*8 STA 6*8 MVI A,0F0H ; ENABLE VI AND RTC, RESET INTERRUPT, CLEAR COUNTERS OUT VICNTRL RET ; MP/M-80 II INTERRUPT HANDLERS INT1HND: ; INTERRUPT 1 HANDLER ENTRY POINT ; ; LOCATION 0008H CONTAINS A JMP ; TO INT1HND. PUSH PSW MVI A,VEC1 ; SET VECTOR LEVEL 1 (RST 1), ADDRESS 0008 HEX OUT VICNTRL LDA SLICE DCR A ; ONLY SERVICE EVERY 2ND SLICE STA SLICE JZ T40MS ; JUMP IF 40MS ELAPSED POP PSW EI RET T40MS: MVI A,4 STA SLICE ; RESET SLICE COUNTER POP PSW SHLD SVDHL POP H SHLD SVDRET PUSH PSW LXI H,0 DAD SP SHLD SVDSP ; SAVE USERS STK PTR LXI SP,INTSTK+48 ; LCL STK FOR INTR HNDL PUSH D PUSH B MVI A,0FFH STA PREEMP ; SET PREEMPTED FLAG LDA TICKN ORA A ; TEST TICKN, INDICATES ; DELAYED PROCESS(ES) JZ NOTICKN MVI C,FLAGSET MVI E,1 CALL XDOS ; SET FLAG #1 EACH TICK NOTICKN: LXI H,CNT25 DCR M ; DEC 25 TICK CNTR JNZ NOT1SEC MVI M,25 MVI C,FLAGSET MVI E,2 CALL XDOS ; SET FLAG #2 @ 1 SEC NOT1SEC: XRA A STA PREEMP ; CLEAR PREEMPTED FLAG POP B POP D LHLD SVDSP SPHL ; RESTORE STK PTR POP PSW LHLD SVDRET PUSH H LHLD SVDHL ; THE FOLLOWING DISPATCH CALL WILL FORCE ROUND ROBIN ; SCHEDULING OF PROCESSES EXECUTING AT THE SAME PRIORITY ; EVERY 40 MILLI-SECONDS. ; ; NOTE: INTERRUPTS ARE NOT ENABLED UNTIL THE DISPATCHER ; RESUMES THE NEXT PROCESS. THIS PREVENTS INTERRUPT ; OVER-RUN OF THE STACKS WHEN STUCK OR HIGH FREQUENCY ; INTERRUPTS ARE ENCOUNTERED. JMP PDISP ; MP/M DISPATCH ; ; FIXED DATA TABLES FOR TWO-DRIVE STANDARD IBM-COMPATIBLE 8" DISKS ; MACLIB DISKDEF ; DISK DEFINITION MACRO LIBRARY DISKS 2 ; TWO DISK SYSTEM DISKDEF 0,1,26,6,1024,243,64,64,OFFSET,(0) DISKDEF 1,0 ; BOOT: WBOOT: MVI C,0 JMP XDOS ; ; ROUTINE TO SELECT GIVEN BY REGISTER C ; SELDSK: MOV A,C ; GET NEW UNIT # LXI H,0 ; RETURN 0000 IN H&L REGS., IF ERROR CPI TDISKS ; BIGGER THAN # OF DISKS AVAILABLE? RNC ; OOPS..... STA UNITNO ; VALID UNIT #, SAVE IT MOV L,C ; L REG =DISK # DAD H ; *2 DAD H ; *4 DAD H ; *8 DAD H ; *16 LXI D,DPBASE; D&E REGS =DISK PARAMETER BASE DAD D ; H&L REGS =BIAS OFFSET INTO TABLE XRA A ; SET A = 0 RET ; RETURN FROM SELDSK ; ; MOVE DISK TO TRACK ZERO ; HOME: MVI A,RTCNT ; GET RETRY COUNT HRETRY: STA SERCNT ; STORE IN SEEK ERROR COUNTER XRA A ; SET TRKNO TO ZERO STA TRKNO CALL XMTUS ; XMIT UNIT/SECTOR # MVI A,00DH ; SET SEEK TRACK ZERO COMMAND CALL XMITW ; XMIT AND WAIT RZ ; RETURN FROM HOME, IF O.K. CALL CLRER ; CLEAR DISK ERROR PUSH H ; SAVE CURRENT DMAADR LXI H,SECNT ; GET SEEK ERR COUNT ADDRESS INR M ; ONE MORE ERROR POP H ; RECOVER CURRENT DMAADR LDA SERCNT ; GET SEEK ERROR COUNT DCR A ; DECREMENT COUNT JNZ HRETRY ; TRY TO HOME AGAIN JMP EREXIT ; OOPS...PERMANENT DISK I/O ERROR ; ; SET TRACK NUMBER TO WHATEVER IS IN REGISTER C ; ALSO PERFORM MOVE TO THE CORRECT TRACK (SEEK) ; SETTRK: MOV A,C ; GET TRACK # INTO A REG CPI 0 ; TRACK ZERO REQUESTED? JZ HOME ; DO SEEK TRACK ZERO, IF SO STA TRKNO ; SAVE TRACK # MVI A,RTCNT ; GET RETRY COUNT SRETRY: STA SERCNT ; STORE IN SEEK ERROR COUNTER CALL XMTUS ; XMIT UNIT/SECTOR # CALL XMTTK ; XMIT TRACK # MVI A,009H ; SET SEEK TRACK COMMAND CALL XMITW ; XMIT AND WAIT RZ ; RETURN FROM SETTRK, IF O.K. CALL CLRER ; CLEAR DISK ERROR PUSH H ; SAVE CURRENT DMAADR LXI H,SECNT ; GET ADDRESS OF SEEK ERROR COUNTER INR M ; ONE MORE SEEK ERROR POP H ; RECOVER CURRENT DMAADR LDA SERCNT ; GET ERROR COUNT DCR A ; DECREMENT COUNT JNZ SRETRY ; RETRY SEEK JMP EREXIT ; ARGH..... ; ; TRANSLATE THE SECTOR GIVEN BY BC USING THE TRANSLATE TABLE GIVEN BY DE ; SECTRAN:MVI B,0 ; DOUBLE PRECISION SECTOR NUMBER XCHG ; TRANSLATE TABLE ADDRESS TO H&L REGS DAD B ; TRANSLATE SECTOR ADDRESS MOV A,M ; TRANSLATE SECTOR # TO A REG MOV L,A ; RETURN SECTOR # IN L REG RET ; RETURN FROM SECTRAN ; ; SET DISK SECTOR GIVEN BY REGISTER C ; SETSEC: MOV A,C ; GET SECTOR NUMBER STA SECNO ; PUT AT SECT # ADDRESS RET ; RETURN FROM SETSEC ; ; SET DISK DMA ADDRESS GIVEN BY REGISTER PAIR B AND C ; SETDMA: MOV H,B ; MOVE B&C TO H&L MOV L,C SHLD DMAADR ; PUT AT DMA ADR ADDRESS RET ; RETURN FROM SETDMA ; ; READ THE SECTOR AT SECT, FROM THE PRESENT TRACK ; USE STARTING ADDRESS AT DMAADR ; READ: MVI A,RTCNT ; GET RETRY COUNT RRETRY: STA ERCNT ; STORE IN ERROR CTR CALL XMTUS ; XMIT UNIT/SECTOR # MVI A,003H ; SET READ SECTOR COMMAND CALL XMITW ; XMIT AND WAIT JZ READOK ; IF READ O.K.,GET DATA FROM BUFFER CALL CLRER ; CLEAR DISK ERROR PUSH H ; SAVE CURRENT DMAADR LXI H,RECNT ; GET READ ERROR COUNT ADDRESS INR M ; ONE MORE ERROR POP H ; RECOVER CURRENT DMAADR LDA ERCNT ; GET ERROR COUNT DCR A ; DECREMENT COUNT JNZ RRETRY ; TRY TO READ AGAIN EREXIT: IN DATAI ; GET DISK STATUS STA IOERR ; SAVE ERROR STATUS MVI A,1 ; INFORM CP/M OF ERROR ORA A ; SET FLAGS RET READOK: LHLD DMAADR ; GET STARTING ADDRESS MVI D,128 ; SET BYTE COUNT MVI A,040H ; SET READ BUFFER COMMAND CALL XMT4X ; XMIT 04XH COMMAND INX H ; BUMP POINTER DCR D ; DE-BUMP BYTE COUNT READL: MVI A,041H ; GET DATA BYTE FROM BUFFER CALL XMT4X ; XMIT 04XH COMMAND INX H ; BUMP POINTER DCR D ; DE-BUMP BYTE COUNT JNZ READL ; LOOP UNTIL ALL BYTES IN RET ; RETURN FROM READ ; ; WRITE THE SECTOR AT SECT, ON THE PRESENT TRACK ; USE STARTING ADDRESS AT DMAADR ; WRITE: MVI A,RTCNT ; GET RETRY COUNT WRETRY: STA ERCNT ; STORE IN ERROR COUNTER LHLD DMAADR ; GET STARTING ADR MVI D,128 ; SET BYTE COUNT WRITEL: MOV A,M ; GET BYTE FROM DMAADR OUT DATAO ; SEND TO CONTROLLER MVI A,031H ; XMIT SHIFT WRITE BUFFER CALL XMIT INX H ; BUMP POINTER DCR D ; DE-BUMP BYTE COUNT JNZ WRITEL ; LOOP UNTIL ALL BYTES OUT CALL XMTUS ; XMIT UNIT/SECTOR # MVI A,005H ; SET WRITE COMMAND CALL XMITW ; XMIT AND WAIT RZ ; RETURN FROM WRITE, IF O.K. CALL CLRER ; CLEAR DISK ERROR PUSH H ; SAVE CURRENT DMAADR LXI H,WECNT ; GET ADR OF WRITE ERR CTR INR M ; ONE MORE WRITE ERROR POP H ; RECOVER CURRENT DMAADR LDA ERCNT ; GET ERROR COUNT DCR A ; DECREMENT COUNT JNZ WRETRY ; TRY TO WRITE AGAIN JMP EREXIT ; ARGH..... ; ; TRANSMIT UNIT AND SECTOR NUMBER ; XMTUS: LDA UNITNO ; GET UNIT NUMBER FOR DISK ANI 003H ; PRESERVE UNIT # ONLY RRC ; POSITION TO BITS 6&7 FOR 3712 CONTROLLER RRC MOV B,A ; SAVE IN B REG LDA SECNO ; GET SECTOR NUMBER ORA B ; MERGE UNIT NUMBER OUT DATAO ; SEND DATA OUT MVI A,021H ; XMIT UNIT/SECTOR NUMBER JMP XMIT ; ; TRANSMIT TRACK NUMBER ; XMTTK: LDA TRKNO ; GET TRACK NUMBER OUT DATAO ; SEND DATA OUT MVI A,011H ; XMIT TRACK NUMBER XMIT: PUSH PSW ; SAVE COMMAND DRCHK: IN DATAI ; GET DISK STATUS ANI 020H ; MASK FOR DRIVE NOT READY JNZ DRCHK ; LOOP UNTILL DISK READY POP PSW ; RECOVER COMMAND OUT CNTRL ; SEND CONTROL XRA A ; RESET CPU0 BIT OUT CNTRL ; SEND CONTROL RET ; ; TRANSMIT "BUSY" TYPE COMMAND, AND WAIT FOR "NOT BUSY" ; XMITW: CALL XMIT ; XMIT COMMAND BUSY: IN DATAI ; GET STATUS RAR ; SET BUSY FLAG JC BUSY ; LOOP IF BUSY IN DATAI ; GET DISK STATUS ANI 028H ; DISK NOT READY OR CRC ERROR? RET ; RETURN FROM XMITW WITH ERROR STATUS ; ; TRANSMIT "4X" (READ BUFFER OR SHIFT READ BUFFER) TYPE COMMAND ; XMT4X: OUT CNTRL ; SEND CONTROL IN DATAI ; GET DATA BYTE MOV M,A ; STUFF DATA BYTE INTO MEMORY XRA A ; RESET CPU0 BIT OUT CNTRL ; SEND CONTROL RET ; RETURN FROM XMT4X CLRER: MVI A,00BH ; CLEAR ERROR FLAGS CALL XMIT RET ; ; POLL DISK READY STATUS ; POLDSK: ; RETURN 0FFH IF READY, ; 000H IF NOT IN DATAI ; GET DISK STATUS ANI 020H ; MASK FOR DISK NOT READY MVI A,0 ; SET A REG. TO ZERO FOR POSSIBLE NOT READY RNZ MVI A,0FFH ; DISK IS READY RET ; ; SCRATCH RAM AREA REQUIRED FOR XIOS VARIABLES ; ; NOTE: AS THERE ARE ONLY SEVEN SECTORS ; AVAILABLE FOR XIOS ON THE SECOND SYSTEM TRACK (1), ; THE LAST ADDRESS BEFORE THIS POINT SHOULD BE NO ; GREATER THAN THE XIOS STARTING ADDRESS + 0380 (HEX). ; ; TRKNO: DS 1 ; CURRENT TRACK NUMBER SECNO: DS 1 ; CURRENT SECTOR NUMBER DMAADR: DS 2 ; DISK TRANSFER ADDRESS. ; ; THE NEXT SEVERAL BYTES, BETWEEN STARTZ AND ; ENDZ, ARE SET TO ZERO AT COLD BOOT TIME. ; STARTZ: ; START OF ZEROED AREA. UNITNO: DS 1 ; DISK NUMBER (TO MP/M) ; ; THESE LOCATIONS KEEP TRACK OF THE NUMBER OF ERRORS THAT OCCUR DURING ; READ, WRITE, OR SEEK OPERATIONS. THEY ARE INITIALIZED ONLY WHEN A ; COLD START IS PERFORMED BY THE BOOT STRAP. ; IOERR: DS 1 ; DISK I/O ERROR TYPE RECNT: DS 1 ; READ ERROR COUNTER WECNT: DS 1 ; WRITE ERROR COUNTER SECNT: DS 1 ; SEEK ERROR COUNTER ; ; SPECIAL FLAGS ; CONOTF: DS 1 ; NO PRINT FLAG (WHEN FF HEX) ; ENDZ: ; END OF ZEROED AREA ; NODSKS: DS 1 ; NUMBER OF DISKS ERCNT: DS 1 ; ERROR COUNTER FOR DISK I/O RETRIES SERCNT: DS 1 ; ERROR COUNTER FOR DISK SEEK RETRIES TEMP: DS 1 ; TEMPORARY DISK UNIT NUMBER ; SLICE: DB 4 ; 4 SLICES = 40MS = 1 TICK CNT25: DB 25 ; 25 TICK CNTR = 1 SEC INTSTK: DS 48 ; LOCAL INTRPT STK SVDHL: DW 0 ; SAVED REGS HL DURING INTERRUPT SVDSP: DW 0 ; SAVED SP DURING INTERRUPT SVDRET: DW 0 ; SAVED RETURN DURING INTERRUPT TICKN: DB 0 ; TICKING BOOLEAN,TRUE = DELAYED PREEMP: DB 0 ; PREEMPTED BOOLEAN ; ENDEF ; DB 0 ; FORCE OUT LAST BYTE IN HEX FIELD FOR RMAC ; END