.TITLE "< GSR COMPUTERS MONITOR >" .SBTTL 'VERSION III.8 10-22-83' ; ***************************************** ; * THE GSR MONITOR, VERSION III.8 * ; * REQUIRES SBC-880 CPU BOARD * ; * AND UFDC-1 FLOPPY DISK CONTROLLER * ; * PROVIDES FOR USE OF CT256K-1 * ; * DYNAMIC MEMORY BOARD * ; * PROVIDES MULTIPLE FORMAT CAPABILITY * ; * IBM COMPATIBLE FORMATS * ; * 8" OR 5 1/4" DISK * ; * SINGLE OR DOUBLE DENSITY * ; * SINGLE OR DOUBLE SIDE * ; * 128, 256, 512, OR 1024 BYTE SECTORS * ; * 1K, 2K, OR 4K ALLOCATION BLOCK SIZE * ; * VARIABLE SECTOR SKEW * ; * REQUIRES 2.2 CPM * ; * CONFIGURED FOR 60K OF RAM * ; * 2.2 CPM BIOS CONTAINED IN ROM AND * ; * DISK PARAMETERS ARE OBTAINED FROM * ; * TABLES ON DISK * ; * PRINT DRIVER FOR CENTRONIX PARALLEL * ; * INTERFACE AND CONSOLE DRIVER FOR * ; * 9600 BAUD TERMINAL ARE IN BIOS * ; * WRITTEN BY R. D. CATILLER * ; * COPYRIGHT 1983 (C) COMPUTIME & GSR * ; ***************************************** ; ; ; PATCH LOG ;------------------------------------------------------- ; ;CTVIII.2 - 9/19/82 ; FIRST RELEASE OF TESTED MONITOR ; ;CTVIII.3 - 10/13/82 ; BIOS VECTORS ARE NO LONGER AFFECTED ; DURING A WARM BOOT OF CPM. VERSION ; III.2 WOULD TRANSFER A COPY OF THE ; COLD START VECTORS DURING A WARM ; BOOT OPERATION. THIS VERSION WILL ; RETAIN THE VECTORS THAT WERE PRESENT ; AT THE TIME OF A WARM START. THIS ; ALLOWS THE MONITOR TO RUN PROPERLY ; WITH PROGRAMS THAT MODIFY THE BIOS ; VECTORS. ; ;CTVIII.4 - 11/ 4/82 ; ALLOWS DISKS TO START WITH SECTOR ADDRESS ; ZERO, (NORMALLY THE STARTING SECTOR ; ADDRESS IS ONE). THIS ALLOWS THE MONITOR ; TO HANDLE THE XEROX 820 KAYPRO II FORMATS. ; ;CTVIII.5 - 11/16/82 ; ALLOWS SIDE 1 OF DOUBLE SIDE DISKS TO ; HAVE SECTOR ADDRESSES THAT ARE LESS THAN ; 128, (SECTOR ADDRESSES ON SIDE 1 ARE ; NORMALLY EXPECTED TO BE GREATER THAN 128). ; THIS ALLOWS THE MONITOR TO HANDLE ; CALLAN SYSTEM FORMATS. ; ;CTVIII.6 - 2/ 1/83 ; FIXED INTERMITTENT BDOS ERROR PROBLEM. ; PROBLEM WAS CAUSED BY DISK HEAD BEING ; ON UNEXPECTED TRACK WHEN CHANGING DISKS. ; VERSION III.5 WAS RESYNCHRONIZING TRACK ; REGISTER ON THE CONTROLLER BEFORE THE ; DISKNO WAS LOGGED ON. MOVED THE TRACK ; REGISTER SYNCHRONIZING CODE INTO THE ; END OF THE LOGDSK ROUTINE, (INSURES THE ; DISK IS LOGGED ON BEFORE SYNCHRONIZING ; OCCURS). ALSO PATCHED THE READ/WRITE ; RETRY CODE TO WRITE ALL 1'S TO THE LUNIT ; VALUE DURING RETRY OPERATIONS. THIS ; FORCES A RESYNCHRONIZATION BEFORE ; EACH RETRY OPERATION. ADDED THE PATCH ; LOG TO THE MONITOR SOURCE FILE. ; ;CTVIII.7 - 5-15-83 ; ADDED CAPABILITY TO HANDLE INVERTED DISK ; DATA AND NON-CYLINDER MODE DOUBLE SIDED ; DISKS. THESE TWO FEATURES PROVIDE ; COMPATIBILITY WITH THE SUPER BRAIN SYSTEM ; FORMATS. YOU MUST USE VERSION 6 OF THE ; FORMAT PROGRAM TO INITIALIZE THESE DISKS ; FOR USE ON THE SYSTEM, (PROGRAM NAME IS ; FMTIII6.COM). ; ADDED BIOS VECTORS AND EXTRA DRIVERS ; TO PROVIDE COMPATIBILITY WITH MP/M II.0. ; MOVED ALL JUMP VECTORS TO THE START ; OF THE MONITOR FOR EASY ACCES TO MONITOR ; ROUTINES FROM USER PROGRAMS. ; THE ADDED BIOS DRIVERS ; PROVIDE MEMORY MANAGEMENT FOR A FULLY ; LOADED CT256K RAM BOARD RUNNING ; UNDER MP/M. FIVE 48K MEMORY BANKS ; ARE AVAILABLE ALONG WITH 16K OF ; COMMON MEMORY WHEN RUNNING MP/M. ; THE MONITOR WILL NOW TRY TO AUTO-BOOT ; AT RESET AND POWER-ON. IF A DISK IS ; NOT PRESENT IN DRIVE A WITH A READABLE ; 2.2 CPM IMAGE, THE SYSTEM WILL BRANCH ; TO THE MONITOR. ; ALL DIAGNOSTICS ARE REMOVED FROM THE ; STANDARD MONITOR. ; A SEPERATE VERSION OF THE MONITOR WILL ; CONTAIN DIGNOSTIC ROUTINES. ; A ROUTINE HAS BEEN ADDED THAT WILL ALLOW ; THE MONITOR TO RUN FROM A PHANTOMED ; EPROM. THIS ADDITION IS COMPATIBLE WITH ; SYSTEMS THAT DO NOT HAVE A PHANTOM OPTION ; AVAILABLE. THE ADDITIONAL ROUTINE WILL ; TRANSFER A COPY OF THE MONITOR CODE ; TO MEMORY PRIOR TO JUMPING TO THE CODE ; AND INVOKING THE PHANTOM OPTION. ; THE PHANTOM EPROM OPTION ON THE ; COMPUTIME/GSR Z80 CPU BOARD IS ENABLED ; BY CUTTING THE TRACE BETWEEN JUMPER ; PADS Q AND R. ; ADDED A DEFAULT DISK PARAMETER TABLE ; THAT IS INVOKED AT COLD START TIME IF ; THE DISK IN DRIVE A DOES NOT CONTAIN ; A VALID PARAMETER TABLE ON SECTOR 1 ; OF TRACK 0. THE DEFAULT TABLE IS FOR ; AN 8" SINGLE DENSITY, SINGLE SIDE DISK. ; A USER DISK PARAMETER TABLE HAS BEEN ; ADDED TO ALLOW READING DISKS THAT DO ; NOT HAVE PARAMETER TABLES ON SECTOR 1 ; OF TRACK 0. A USER FLAG MUST BE ACTIVATED ; BY STORING 0FFH AT ADRESS 0F480H AND ; THEN THE USER TABLE (AT ADDRESS 0F080H) ; MUST BE LOADED. A BDOS ; CALL (CALL TO ADDRESS 0005H) WITH THE ; C REGISTER = 0EH AND THE E REGISTER ; = THE SELECTED DISK (0 = DRIVE A, 1 = ; DRIVE B, 2 = DRIVE C, AND 3 = DRIVE D) ; WILL CAUSE THE SELECTED ; DISK TO BE LOGGED ON, AND THE USER TABLE ; WILL BE TRANSFERRED TO THAT DRIVES ; DISK PARAMETER BLOCK. ; THE SAME USER TABLE MAY BE TRANSFERRED TO ; MULTIPLE DRIVE TABLES BY SETTING THE USER ; FLAG (AT ADDRESS 0F480H) TO 0FFH AND ; REPEATING THE BDOS CALL. NOTE THAT THE ; BDOS CALL WILL RESET THE USER FLAG EACH ; TIME BUT WILL NOT DISTURB THE CONTENTS ; OF THE USER TABLES. ; ;CTVIII.8 - 10/22/83 ; FIXED A PROBLEM WITH THE WARM BOOT ROUTINE. ; THE CPM JUMP VECTORS AT THE BEGINNING OF MEMORY ; WERE NOT BEING RESTORED DURING A WARM BOOT ; OPERATION. THEY WILL NOW BE PROPERLY RESTORED. ; ; .PHEX .XLINK .PABS ; ; MEMORY USED BY MONITOR ; BASE = 0F800H ;MONITOR BASE ADDRESS. STACK = BASE-1 ;MONITOR STACK ; ; CONSTANTS FOR MONITOR ; CR = 0DH ;ASCII CARRIAGE RET LF = 0AH ;ASCII LINE FEED ; ; I/O PORTS ON CPU BOARD ; T0 = 028H T1 = T0+1 T2 = T0+2 TCTL = T0+3 INOUT = T0+4 CONDTA = T0+6 CONCTL = T0+7 CONSTS = CONCTL ; ; ; I/O PORTS ON CT256K MEMORY BOARD ; MAP0 = 88H ;MEMORY MAP REGISTERS MAP1 = 89H MAP2 = 8AH MAP3 = 8BH MEMSTS = 88H ;MEMORY STATUS PORT ; ; ; DISK DEFINES ; VERS = 22 ;CP/M VERSION NUMBER MSIZE = 60 ;CP/M MEMORY SIZE BIAS = (MSIZE-20)*1024 CCP = 3400H+BIAS ;BASE OF CCP BDOS = CCP+806H ;BASE OF BDOS BIOS = CCP+1600H ;BASE OF BIOS WRALL = 0 ;WRT TO ALOC BLK WRDIR = 1 ;WRT TO DIRECTORY WRUAL = 2 ;WRT TO UNALOC BLK WBOOTE = BIOS+3 ;WARM BOOT ENTRY ; ; ;DISK I/O PORTS ; DSTAT = 9CH ;DISK STATUS PORT DCMMD = DSTAT ;DISK COMMAND PORT DTRCK = DSTAT+1 ;DISK TRACK PORT DSCTR = DSTAT+2 ;DISK SECTOR PORT DDATA = DSTAT+3 ;DISK DATA PORT DFLAG = 9BH ;STATUS REGISTER 1 DCNTL = DFLAG ;CONTROL REGISTER 1 ; ; ;MEMORY USED BY CPM ; CURDSK = 4 ;CURRENT DISK DRIVE TBUF = 80H ;DEFAULT CPM BUFFER ; ; ; PROGRAM CODE BEGINS: ; .LOC BASE ; ; ;MONITOR BIOS JUMP VECTORS ; ; ; THE FOLLOWING CODE TRANSFERS A COPY OF THE ; MONITOR INTO RAM AND THEN PHANTOMS THE EPROM ; THAT ORIGINALLY CONTAINED THE CODE. ; ; LXI H,BIOSCD-BASE ;START OF CODE LXI D,BIOSCD ;DESTINATION FOR CODE LXI B,0FFFFH-BIOSCD ;LEGNTH OF CODE LDIR ;MOVE CODE ; ; THE JUMP INSTRUCTION FOLLOWING THIS CODE ; WILL CAUSE THE EPROM TO BE PHANTOMED AND ; THE MONITOR WILL BEGIN EXECUTING FROM RAM. ; BIOSCD: JMP BOOT ;COLD BOOT JMP WBOOT ;WARM BOOT JMP CSTS ;CONSOLE STATUS JMP CI ;CONSOLE INPUT JMP CO ;CONSOLE OUTPUT JMP PRINT ;LIST DEVICE JMP CO ;PUNCH DEVICE JMP CI ;READER DEVICE JMP HOME ;MOVE HEAD TO TRK 0 JMP SELDSK ;SELECT DISK JMP SETTRK ;SET TRACK NUMBER JMP SETSEC ;SET SECTOR NUMBER JMP SETDMA ;SET DMA ADDRESS JMP HREAD ;READ DISK JMP HWRITE ;WRITE DISK JMP PSTS ;LIST STATUS JMP SECTRN ;SECTOR TRANSLATE ; ; THE FOLLOWING VECTORS ARE USED BY MP/M ; JMP SELMEM ;MEMORY BANK SELECT JMP POLDEV ;DEVICE POLLING ROUTINE JMP STRTCK ;START SYSTEM CLOCK JMP STOPCK ;STOP SYSTEM CLOCK JMP EXITRG ;EXIT REGION ROUTINE JMP MAXCON ;MAX CONSOLE ROUTINE JMP SYSINT ;SYSTEM INITIALIZE .BYTE 0,0,0 ;USE MP/M IDLE PROC BCDL = .-BIOSCD ; ; MP/M BIOS ROUTINES ; SELMEM: RET ; POLDEV: MOV A,C CPI 2 ;BAD DEVICE #? JRC DEVOK ;GOOD DEVICE # MVI A,2 ;BAD DEVICE # DEVOK: CALL TBLJMP ;JUMP TO POLL ROUTINE DEVTBL: .WORD PSTS ;POLL PRINTER .WORD CSTS ;POLL CONSOLE .WORD RTNEMP ;BAD DEVICE # RTNEMP: XRA A RET TBLJMP: ADD A ;DOUBLE TABLE INDEX POP H ;RET ADR = TBL ADR MOV E,A ;ADD INDEX MVI D,0 DAD D MOV E,M ;GET ADR OF ROUTINE INX H MOV D,M XCHG PCHL ;JUMP TO ROUTINE ; STRTCK: RET ; STOPCK: RET ; EXITRG: RET ; MAXCON: MVI A,1 ;# OF CONSOLES IS 1 RET ; SYSINT: RET ; ; MONITOR SIGN-ON MESSAGE ; MSG: .BYTE CR,LF .ASCII 'GSR COMPUTERS III.8' MSGL = .-MSG ; ; MEMORY PARITY ERROR MESSAGE ; MSG1: .BYTE CR,LF .ASCII 'PAR ERR' MSG1L = .-MSG1 ; START: LXI SP,STACK ;RESTORE STACK CALL CRLF CALL CI ;WAIT FOR INPUT JMP WBOOT ;TRY BOOTING AGAIN ; ;MESSAGE OUTPUT ROUTINE. ; MESG: LXI H,MSG MESG1: MOV C,M ;GET A CHARACTER INX H ;MOVE POINTER CALL CO ;OUTPUT IT DJNZ MESG1 ;KEEP GOING TILL B=0 RET ; ; ;CRLF BEFORE HLBLK ROUTINE ; CRLFHL: CALL CRLF ; ;PRINT THE CURRENT VALUE OF H&L, ;AND A SPACE. ; HLBLK: CALL DISPHL ; ;PRINT A SPACE ON THE CONSOLE ; SPACE: MVI C,' ' ; ;THIS IS THE MAIN CONSOLE ;OUTPUT ROUTINE. ; CO: IN CONCTL ANI 01H JRZ CO MOV A,C OUT CONDTA RET ; ; CONVERT HEX TO ASCII ; HTA: ANI 0FH ;LOW NIBBLE ONLY ADI 90H DAA ACI 40H DAA MOV C,A RET ; ; ; CONSOLE CARRIAGE RETURN & ; LINE FEED ROUTINE. ; CRLF: PUSH H ;SAVE HL MVI B,2 ;CRLF LENGTH CALL MESG ;SEND CRLF POP H RET ; ;CONSOLE STATUS TEST ROUTINE. ; CSTS: IN MEMSTS ;TEST FOR PAR ERR ANI 0C0H CPI 80H JRNZ CSTS1 ;NO PAR ERR LDA PARFLG ;1ST PAR ERR? CPI 0 JRNZ CSTS1 ;NOT 1ST INR A ;SET PAR FLG STA PARFLG PUSH H PUSH B LXI H,MSG1 ;DISPLAY PAR ERR MVI B,MSG1L CALL MESG1 POP B POP H CSTS1: IN CONCTL ANI 02H MVI A,0FFH RNZ CMA RET ; ; ;PRINT H&L ON CONSOLE ; DISPHL: MOV A,H CALL DISPB MOV A,L DISPB: PUSH PSW RRC RRC RRC RRC CALL HTA2 POP PSW HTA2: CALL HTA JMPR CO ; ;MAIN CONSOLE INPUT ROUTINE ; CI: CALL CSTS ;TEST FOR INPUT ORA A JRZ CI IN CONDTA ANI 7FH RET ; ; ;PRINTER OUTPUT ROUTINE ; PRINT: IN INOUT ANI 1 JRNZ PRINT MOV A,C ORI 80H OUT INOUT ANI 7FH OUT INOUT ORI 80H OUT INOUT RET ; ; PRINTER STATUS ROUTINE ; PSTS: IN INOUT ANI 1 MVI A,0FFH RZ CMA RET ; ; ;GET READY TO MOVE BIOS VECTORS ; BIOSMV: LXI H,DIRBF BIOSM1: LXI D,BIOS BIOSM2: LXI B,BCDL RET ; ; ;BOOT CPM AND RUN ; BOOT: LXI SP,STACK ;SET UP STACK MVI A,80H ;SET UP PRINTER OUT INOUT MVI A,1 ;RESET TO MODE WORD OUT CONCTL OUT CONCTL MVI A,40H OUT CONCTL MVI A,0FAH ;SET USART MODE OUT CONCTL MVI A,36H ;SET TIMER MODE OUT TCTL MVI A,13 ;SET BAUD RATE TO 9600 OUT T0 XRA A STA SECTOR STA PARFLG OUT T0 MOV B,A ;SET UP TO PURGE RAM MOV C,A MOV D,A MOV E,A MOV H,A MOV L,A OUT MAP0 ;SET MAP REGS INR A OUT MAP1 INR A OUT MAP2 INR A OUT MAP3 LDIR ;PURGE RAM OUT MAP3 ;RESET PARITY FLAG MVI A,37H ;ENABLE XMT & REC OUT CONCTL STA RFLAG HELLO: MVI B,MSGL ;SAY HELLO CALL MESG BBOOT: LXI H,BIOSCD ;SET UP BIOS VECTORS CALL BIOSM1 LDIR WBOOT: LXI SP,STACK ;RESTORE STACK LXI H,TPLT ;MOVE DOWN JMP VECTORS LXI D,0 LXI B,8 LDIR LXI H,BEGDAT ;CLEAR SCRATCH RAM LXI D,BEGDAT+1 LXI B,DATSIZ MVI M,0 LDIR CALL BIOSMV ;SAVE BIOS VECTORS XCHG LDIR LXI H,EPBASE ;SET UP CPM TABLES LXI D,DPBASE LXI B,EPLGTH LDIR LXI H,CCP ;SET DMA ADR SHLD DMAAD MVI A,2 ;SECTOR = 2 STA SECTOR STA LUNIT XRA A CALL LOGDS2 ;LOG ON DRIVE A JNZ START ;LOG ON ERROR LIXD CTBLP ;GET TBL POINTER MVI A,49 ;NO OF SECS STA BTSEC MVI D,1 ;# OF 128 BYTE SECS MVI A,25 ;8" SECS ON TRK 0 STA SECCNT IN DFLAG ANI 4 ;8" OR 5 1/4" ? JRZ WBOOT8 ;8" MVI A,17 STA SECCNT WBOOT8: LDA BTSEC ;SUBTRACT SECTORS SUB D STA BTSEC MVI B,10 BRWAGN: PUSH B CALL TST128 ;ADJUST SECTOR ADR OUT DSCTR CALL SETUP PUSH D ;SAVE FOR RETRY LHLD DMAAD ;GET DMA ADR BOOTRD: LDA SECTOR ;TEST FOR SIDE 1 ANI 80H MVI A,88H ;READ COMMAND JRZ BTRW3 ;SIDE 0 MVI A,8AH ;SELECT SIDE 1 BTRW3: STA CMND OUT DCMMD BTRW1: LXI B,(128*256)+DDATA INIR DCR D ;LOOP CONTROL JRNZ BTRW1 POP D ;RESTORE LENGTH CALL EOJ ANI 9CH POP B JRZ WBOOTA ;DONE, NO ERRORS DJNZ BRWAGN ;RETRY DERROR: CALL DERR1 ;DISPLAY ERROR JMP START WBOOTA: SHLD DMAAD ;UPDATE DMAAD LDA SECTOR ;SECTOR + 1 INR A STA SECTOR LDA BTSEC ;ALL SECS DONE? ORA A JZ GOCPM ;DONE LDA SECCNT ;TEST FOR END OF TRK DCR A STA SECCNT JRNZ WBOOT8 ;NOT END OF TRK MOV L,15(X) ;BYTES PER SEC MOV H,16(X) DAD H ;ADJUST VALUE MOV D,H ;# 128 BYTE SECS BIT 1,18(X) ;TEST FOR DOUBLE SIDE JRZ WBOOTB ;SINGLE SIDE BIT 5,18(X) ;CYLINDER MODE? MVI A,81H ;SIDE 1 SELECT JRZ WBOOT9 ;CYLINDER MODE WBOOTB: MVI B,58H ;STEP IN 1 TRACK CALL EOJA LXI H,TRACK ;TRK + 1 INR M MVI A,1 ;SECTOR = 1 WBOOT9: STA SECTOR MOV A,19(X) ;SECS PER TRK STA SECCNT JMP WBOOT8 ;DO NEXT TRK GOCPM: CALL BIOSMV ;RESTORE BIOS VECTORS LDIR LXI H,TBUF ;DEFAULT CPM BUFFER SHLD SEKDMA ;SET DMA ADDRESS LDA CURDSK ;LOG-ON DSK MOV C,A ;SEND TO CPM JMP CCP ;GO TO CP/M ; ;JUMPS AT START OF MEMORY AND IOBYTE ; TPLT: JMP WBOOTE IOBYT: .BYTE 0BDH .BYTE 0 JMP BDOS ; ; DERRM: .ASCII 'DSKTRKSCTSTSCMDDMA' ; ; ;DISPLAYS ALL DISK PARAMETERS ; DERR1: PUSH B ;SAVE REGISTERS PUSH D PUSH H LXI H,DERRM ;POINT TO NAMES LXI D,DISKNO ;POINT TO PARAMETERS CALL CRLF ;DISPLAY CRLF MVI C,5 ;SET TALLY DERR2: MVI B,3 PUSH B ;SAVE BC CALL MESG1 ;DISPLAY NAME CALL SPACE ;DISPLAY SPACE PUSH H ;SAVE HL LDAX D ;GET DATA INX D ;STEP TO NEXT CALL DISPB ;DISPLAY DATA CALL SPACE ;DISPLAY SPACE POP H ;GET HL POP B ;GET BC DCR C ;TALLY - 1 JRNZ DERR2 ;CONTINUE MVI B,3 ;DISPLAY NAME CALL MESG1 CALL SPACE ;DISPLAY SPACE LHLD DMAAD ;LAST PARAMETER CALL DISPHL ;DISPLAY IT POP H ;RESTORE REGISTERS POP D POP B LDA STATUS ORA A RET ; ; ; ;SELECT DISK GIVEN BY REGISTER C ; SELDSK: LXI H,0 ;ERROR RETURN CODE MOV A,C STA SEKDSK ;STORE DSK NO. CPI 4 ;MUST BE 0,1,2,OR 3 RNC ;INVALID DSK NO. PUSH X ;LOG ON DISK PUSH H CALL LOGDS2 POP H RNZ ;ERROR RETURN POP X LDA SEKDSK ;GET DISK NO. MOV L,A MOV H,B DAD H ;*2 DAD H ;*4 DAD H ;*8 DAD H ;*16 XCHG LXI H,DPBASE DAD D ;HL=DPBASE+(DISKNO*16) RET ; LOGDSK: LDA DISKNO LOGDS2: MOV C,A ;SAVE DSK NO IN C INR A LXI X,DP0 ;BUILD TBL ADR IN X LXI D,128 DABLD1: DCR A JRZ DABLD2 DADX D JMPR DABLD1 DABLD2: SIXD CTBLP MVI A,0C0H ORA C STA HSELCD ;STORE SELECT CODE LXI H,DSKSEL ;SEE IF NEW DISK MVI B,0 DAD B LDA SELFLG ;LOAD USER TABLE? CPI 0 JRZ DABLD3 ;USE DISK TABLES XRA A ;RESET FLAG STA SELFLG CMA ;MARK DISK AS USED MOV M,A LXI H,UTABLE ;LOAD USER TABLE JMPR VALID2 DABLD3: MOV A,M ORA A JRNZ DBPARM ;NOT NEW DISK CMA MOV M,A ;MARK AS USED LDA HSELCD ;GET SEL CODE OUT DCNTL ;SEL DRIVE CALL EOJB ;RESTORE DRIVE ANI 80H ;TEST FOR NOT READY JNZ DERR1 ;NOT RDY ERROR MVI B,10 ;RETRY COUNT NTAGN: PUSH B MVI A,1 ;SELECT SEC 1 OUT DSCTR MOV D,A ;SEC SIZE=128 LHLD CTBLP LDA HSELCD ;GET SELECT CODE OUT DCNTL MVI A,8CH ;READ OP CALL RDAT ;READ TABLES POP B ;RETRY COUNT ORA A ;TEST FOR ERRORS JRZ VALID ;DONE, NO ERRORS DJNZ NTAGN ;RETRY JMP DERR1 ;DISP PARAMETERS VALID: MOV L,15(X) ;BYTES PER SECTOR MOV H,16(X) PUSH H ;COPY TO DE POP D MOV B,19(X) ;PHYSICAL SEC/TRK DCR B VALID1: DAD D ;BYTES/SEC X SEC/TRK DJNZ VALID1 DAD H ;DIVIDE BY 128 BIT 1,18(X) ;DOUBLE SIDE ? JRZ VALID3 ;SINGLE SIDE BIT 5,18(X) ;CYLINDER MODE ? JRNZ VALID3 ;CYLINDER MODE DAD H ;DBL SIDE, TIMES 2 VALID3: MOV A,H CMP 0(X) ;EQUAL SEC/TRK ? JRZ DBPARM ;VALID TABLE LXI H,DEFLT ;LOAD DEFAULT TABLE VALID2: PUSH X POP D LXI B,128 LDIR DBPARM: MOV L,15(X) ;GET BYTES/SEC MOV H,16(X) DAD H MOV A,H STA HSTBLK ;CPM SEC/PHY SEC DCR A STA SECMSK ;SECTOR MASK MOV B,2(X) ;GET BLK SHIFT FACTOR MVI A,1 ;CPM ALOC SIZE/128 BLKCAL: RLC DJNZ BLKCAL STA BLKCNT LDA DISKNO ;GET DISK NO LXI H,LUNIT ;POINT TO LAST UNIT CMP M ;SEE IF SAME MOV M,A ;SAVE THIS UNIT RZ CALL SETUP LXI H,IDSV MVI D,1 MVI A,0C4H ;READ ADR COMMAND OUT DCMMD STA CMND LXI B,(6*256)+DDATA CALL READ2 IDRD1: LDA IDSV OUT DTRCK ;SET THE TRACK XRA A ;RET, NO ERRORS RET ; ; ;SET TRACK GIVEN BY REGISTER C ; SETTRK: MOV A,C STA SEKTRK RET ; ; ;SET SECTOR GIVEN BY REGISTER C ; SETSEC: MOV A,C STA SEKSEC RET ; ; ;TRANSLATE THE SECTOR GIVEN BY BC USING THE ;TRANSLATE TABLE GIVEN BY DE ; SECTRN: PUSH X ;SAVE X LXI H,0FFECH ;TBL POINTER-20 DAD D PUSH H ;POINTER TO X POP X XRA A BIT 1,18(X) ;TEST FOR DBL SIDE JRZ SECTR1 ;SINGLE SIDE BIT 5,18(X) ;CYLINDER MODE? JRNZ SECTR1 ;NON-CYLINDER MODE MOV L,0(X) ;GET CPM SEC/TRK MOV H,A SRLR L ;DIVIDE BY 2 DCR L ;SUBTRACT 1 DSBC B ;SEC ON SD 0 OR 1? JRNC SECTR1 ;SECTOR ON SIDE 0 MOV A,L ;BUILD ADR FOR SD 1 CMA MOV C,A MVI A,80H ;SIDE SELECT = SD 1 SECTR1: XCHG ;HL=TRANS TBL DAD B ;ADD SEC INDEX ORA M ;OR SIDE SELECT MOV L,A ;HL = TRANS(SECTOR) MVI H,0 POP X ;RESTORE X RET ; ; ;SET DMA ADDRESS GIVEN BY REGISTERS B AND C ; SETDMA: SBCD SEKDMA ;SAVE THE ADDRESS RET ; ; ;MOVE TO THE TRACK 00 POSITION OF CURRENT DRIVE ; HOME: LDA HSTWRT ;TEST FOR WRITE PEND ORA A RNZ STA HSTACT ;CLEAR HSTACT FLAG RET ; ; ;DEBLOCKING ROUTINES ; HREAD: MVI A,1 ;SET READOP=READ STA READOP INR A STA WRTYPE ;TREAT AS UNALOC JMP ALLOC HWRITE: XRA A ;SET READOP=WRITE STA READOP MOV A,C ;SAVE WRITE TYPE STA WRTYPE CPI WRUAL ;UNALOC WRITE? JRNZ CHKUNA ;NOT UNALOC WRT LHLD SEKDSK ;UNADSK=SEKDSK SHLD UNADSK ;UNATRK=SEKTRK LDA BLKCNT ;RECORDS/CPM BLOCK STA UNACNT LDA SEKSEC ;UNASEC=SEKSEC STA UNASEC LHLD CTBLP ;SAVE TBL ADR SHLD UTBLP CHKUNA: LDA UNACNT ;ANY UNALOC REMAIN? ORA A JRZ ALLOC ;NONE REMAIN DCR A ;UNACNT-1 STA UNACNT LHLD UNADSK ;SEK = UNA? LDA SEKSEC MOV C,A LDA UNASEC CALL CMP3 JRNZ ALLOC ;NOT EQUAL LHLD UTBLP ;GET TBL ADR MOV C,M ;CPM SEC/TRK MVI B,0 LXI D,20 ;SEC TRANSL TBL DAD D LDA UNASEC ;SEARCH FOR UNASEC CCIR ;END OF TRK? JO NOOVF ;NOT END LXI H,UNATRK ;UNATRK + 1 INR M MVI A,1 ;UNASEC = 1 JMPR OVF NOOVF: MOV A,M ;GET NEXT SECTOR OVF: STA UNASEC ;STORE NEXT UNASEC XRA A ;RESET RSFLAG JMPR ALLOC2 ALLOC: XRA A ;SET UNACNT=0 STA UNACNT INR A ;SET RSFLAG ALLOC2: STA RSFLAG ;NEED PREREAD LXI H,DBUF ;SET DMA ADR SHLD DMAAD RWOPER: PUSH X LDA SEKDSK ;LOG ON SEKDSK CALL LOGDS2 BIT 5,18(X) ;CYLINDER MODE? JRZ CYLN ;YES LDA SEKTRK CMP 17(X) ;TRK > TRKS PER SIDE? JRC CYLN ;NOT GREATER SUB 17(X) ;ADJUST TRACK STA SEKTRK ;SAVE IT LDA SEKSEC ;SELECT SIDE 1 ORI 80H STA SEKSEC CYLN: LDA SEKSEC ;COMPUTE PHY SEC ADR MOV C,A ANI 80H ;GET SIDE SELECT STA SIDSEL ;SAVE IT MOV A,C ;MASK OFF SIDE SEL ANI 7FH MOV C,A LDA HSTBLK DCR C PSEC1: RAR JRC SECDN SRLR C JMPR PSEC1 SECDN: INR C LDA SIDSEL ;GET SIDE SELECT ORA C ;OR IT WITH SECTOR STA SEKHST ;SAVE IT LXI H,HSTACT ;TEST & SET HSTACT FLG MOV A,M MVI M,1 ;SET FLAG ORA A ;TEST FLAG JRZ FILHST ;NOT SET LHLD DISKNO ;SEEK=HOST? LDA SEKHST MOV C,A LDA SECTOR CALL CMP3 JRZ MATCH ;SAME LDA HSTWRT ;HOST WRITTEN? ORA A CNZ DWRITE ;WRITE HOST BUF FILHST: LHLD SEKDSK ;GET SET TO FILL BUF SHLD DISKNO LDA SEKHST ;PHYSICAL SEC ADR BIT 2,18(X) ;1ST SEC = 0? JRZ FLHST2 ;1ST SEC = 1 DCR A ;1ST SEC = 0 FLHST2: STA SECTOR LDA RSFLAG ;RSFLAG SET? ORA A CNZ DREAD ;YES DO READ XRA A STA HSTWRT ;NO PENDING WRT MATCH: LDA SEKSEC ;MASK BUF SEL BITS DCR A MOV L,A LDA SECMSK ANA L MOV H,A ;BUF SEL BITS X 128 MVI L,0 SRLR H RARR L LXI D,DBUF ;ADD BUFFER INDEX DAD D LDED SEKDMA ;GET SEEK DMA ADR LXI B,128 ;SIZE OF MOVE LDA READOP ;READOP=1? ORA A JRNZ RWMOVE ;YES MOVE READ DATA MVI A,1 STA HSTWRT ;SET HOST WRITTEN XCHG ;MOVE WRITE DATA RWMOVE: BIT 4,18(X) ;INVERTED DATA? JRZ NOINV ;NON-INVERTED DATA MOV B,C ;MOVE LENGTH TO B INVRT: MOV A,M ;GET DATA CMA ;INVERT DATA STAX D ;MOVE TO DESTINATION INX H ;INCREMENT ADDRESSES INX D DJNZ INVRT ;DO 128 BYTES JMPR INVDN ;DONE NOINV: LDIR ;MOVE NON-INVERTED DATA INVDN: LDA WRTYPE ;WRITE TO DIRECTORY? CPI WRDIR LDA ERFLAG ;GET ERROR FLAG JRNZ RWD ;NOT DIR WRT ORA A ;ERRORS? JRNZ RWD ;DONE IF ERRORS XRA A STA HSTWRT ;RESET HSTWRT FLAG CALL DWRITE ;WRITE TO DIRECTORY LDA ERFLAG ;GET ERROR FLAG RWD: POP X RET ;DONE CMP3: LDED SEKDSK ;GET SEKDSK & SEKTRK ORA A DSBC D ;COMPARE HL & DE RNZ ;RETURN NOT EQUAL CMP C ;COMPARE A & C RET ;DONE ; ; ;DISK READ AND WRITE ROUTINES ; DREAD: MVI A,1 ;SET READ FLAG JMPR STRFLG DWRITE: XRA A ;SET WRITE FLAG STRFLG: STA RWFLG ;SAVE IT FOR LATER USE DORDWT: MVI B,10 ;NUMBER OF RETRIES AGN: PUSH B ;SAVE BC CALL SEEK ;SEEK THE TRACK CZ RDWR ;NO ERROR STA ERFLAG ;STORE ERROR FLAG READ3: POP B ;GET ERROR RETRY COUNT RZ ;RETURN IF NO ERRORS MVI A,0FFH ;CAUSE IDRD ON RETRY STA LUNIT DJNZ AGN ;DO A RETRY JMP DERR1 ;DISP PARAMETERS ; RDWR: MOV E,A ;SAVE COMMAND LDA RWFLG ORA A MOV A,E ;REGET THE COMMAND JRZ WRDAT ;WRITE IF ZERO RDAT: OUT DCMMD ;DISK COMMAND PORT STA CMND READ1: LXI B,(128*256)+DDATA READ2: INIR DCR D ;LOOP CONTROL JRNZ READ1 CALL EOJ ANI 9CH ;ISOLATE READ ERROR BITS RET ; WRDAT: ORI 20H ;ADD WRITE COMMAND OUT DCMMD ;DISK COMMAND PORT STA CMND WRT1: LXI B,(128*256)+DDATA OUTIR DCR D ;LOOP CONTROL JRNZ WRT1 JMPR EOJ EOJB: MVI B,8 ;BASIS OF RESTORE COMMAND EOJA: IN DFLAG ;STEP RATE BITS ANI 3 ORA B ;ADD ON THE COMMAND STA CMND OUT DCMMD ;DO THE COMMAND MVI B,128 ;DELAY SKDLY: DJNZ SKDLY EOJ: IN DSTAT ;TEST FOR INTRQ ANI 1 JRNZ EOJ ;WAIT FOR INTRQ CALL DWAIT ;DISABLE WAITS EOJ1: IN DSTAT ;GET THE DISK STATUS STA STATUS ANI 0FCH RET ; SEEK: CALL LOGDSK ;LOG ON DISKNO RNZ ;ERROR RETURN CALL TST128 ;ADJUST SECTOR ADR OUT DSCTR ;DISK SECTOR PORT SEEK2: IN DTRCK ;DISK TRACK PORT MOV C,A ;SAVE IT LDA TRACK ;GET DESIRED TRACK CMP C JRZ RDWRT ;NO SEEK NEEDED OUT DDATA ;SET THE TRACK MVI B,18H ;SEEK COMMAND CALL EOJA ;DO THE SEEK ANI 80H ;ERROR MASK RNZ ;SEEK ERROR RDWRT: CALL SETUP ;GET READY IN DFLAG ANI 10H ;HEAD LOADED? MVI A,4 JRZ RDWRT1 ;JUMP IF NOT XRA A ;RESET HEAD LD FLAG RDWRT1: ADI 88H ;READ COMMAND MOV C,A ;SAVE IT LDA TRACK ;TEST FOR TRK 0 ORA A JRNZ RDWRT4 ;NOT TRACK 0 LDA SECTOR ;TEST FOR SIDE 1 BIT 7,A MVI D,1 JRZ RDWRT2 ;TRK 0, SIDE 0 = SD RDWRT4: MOV L,15(X) ;GET SECTOR SIZE MOV H,16(X) DAD H MOV D,H RDWRT2: LHLD DMAAD ;GET DMA ADDRESS RDWRT3: LDA SECTOR ;TEST FOR SIDE 1 ANI 80H MOV A,C ;REGET COMMAND RZ ;SIDE 0 ORI 2 ;SELECT SIDE 1 CMP A ;CLEAR THE FLAGS RET TST128: LDA SECTOR BIT 3,18(X) ;SD 1 < 128? RZ ;SD 1 > 128 ANI 7FH ;SD 1 < 128 RET ; ; ;SELECTS DRIVE ; SETUP: LXI H,SECTOR ;POINT TO SECTOR IN DFLAG ANI 40H ;TEST FOR TRK 0 LDA HSELCD ;GET SEL CODE JRNZ SETUP2 ;NOT TRK 0 BIT 7,M ;TEST FOR SIDE 1 JRZ SETUP3 ;TRK 0, SIDE 0 IS SD SETUP2: BIT 7,18(X) ;TEST FOR DD/SD JRZ SETUP4 ;THIS DSK IS SD RES 6,A ;SET DD SETUP4: BIT 7,M ;TEST FOR SIDE 1 JRZ SETUP3 ;SIDE 0 SET 5,A ;SELECT SIDE 1 SETUP3: OUT DCNTL RET ; ; ;DISABLE WAIT STATES ; DWAIT: LDA HSELCD ;RESET AUTO-WAIT ANI 7FH OUT DCNTL RET ; ; ; EPBASE: ;DISK PARAMETER HEADER FOR DISK 00 .WORD TD0,0 .WORD 0,0 .WORD DIRBF,DP0 .WORD CHK00,ALL00 ;DISK PARAMETER HEADER FOR DISK 01 .WORD TD1,0 .WORD 0,0 .WORD DIRBF,DP1 .WORD CHK01,ALL01 ;DISK PARAMETER HEADER FOR DISK 02 .WORD TD2,0 .WORD 0,0 .WORD DIRBF,DP2 .WORD CHK02,ALL02 ;DISK PARAMETER HEADER FOR DISK 03 .WORD TD3,0 .WORD 0,0 .WORD DIRBF,DP3 .WORD CHK03,ALL03 EPLGTH = .-EPBASE ; ; ; THE FOLLOWING TABLE IS THE DEFAULT ; DISK PARAMETER TABLE. IT WILL CONTAIN ; AN 8" SINGLE SIDE SINGLE DENSITY TABLE ; AT COLD START TIME, (RESET OR POWER ON). ; ANY TIME A VALID TABLE IS NOT FOUND ON ; A DISK BEING LOGGED-IN, THIS TABLE ; WILL BE LOADED INSTEAD. ; DEFLT: .WORD 26 ;SECTORS PER TRACK .BYTE 3 ;BLOCK SHIFT FACTOR .BYTE 7 ;BLOCK MASK .BYTE 0 ;EXTENT MASK .WORD 242 ;BLOCKS PER DISKETTE .WORD 63 ;# DIRECTORY ENTRIES .BYTE 0C0H ;ALLOC 0 .BYTE 0 ;ALLOC 1 .WORD 16 ;DIR CHECK VECTOR SIZE .WORD 2 ;SYSTEM TRACK OFFSET .WORD 128 ;BYTES PER SECTOR .BYTE 77 ;TRACKS PER DISK ; CONTROL BYTE .BYTE 00000001B ; BIT 0 = 8"/5" ; BIT 1 = DS/SS ; BIT 2 = SEC 0/SEC 1 ; BIT 3 = SD 1 < 128 ; BIT 4 = INV DATA ; BIT 5 = NON-CYLINDER ; BIT 6 = UNDEFINED ; BIT 7 = DD/SD .BYTE 26 ;PHYSICAL SEC/TRK ; ; SECTOR TRANSLATE TABLE ; T8S4: .BYTE 1,7,13,19,25 .BYTE 5,11,17,23 .BYTE 3,9,15,21 .BYTE 2,8,14,20,26 .BYTE 6,12,18,24 .BYTE 4,10,16,22 ; ; ;SCRATCH RAM AREA FOR BDOS USE ; BEGDAT = BIOS+128;BEGINNING OF DATA AREA .LOC BEGDAT DBUF: .BLKB 1024 ;DEBLOCK BUFFER DP0: .BLKB 20 ;DISK PARMETER TABLES TD0: .BLKB 108 DP1: .BLKB 20 TD1: .BLKB 108 DP2: .BLKB 20 TD2: .BLKB 108 DP3: .BLKB 20 TD3: .BLKB 108 UTABLE: .BLKB 128 ;USER DISK PARAMETER TABLE DIRBF: .BLKB 128 ;SCRATCH DIRECTORY AREA ALL00: .BLKB 128 ;ALLOCATION VECTOR 0 ALL01: .BLKB 128 ;ALLOCATION VECTOR 1 ALL02: .BLKB 128 ;ALLOCATION VECTOR 2 ALL03: .BLKB 128 ;ALLOCATION VECTOR 3 CHK00: .BLKB 64 ;CHECK VECTOR 0 CHK01: .BLKB 64 ;CHECK VECTOR 1 CHK02: .BLKB 64 ;CHECK VECTOR 2 CHK03: .BLKB 64 ;CHECK VECTOR 3 SELFLG: .BLKB 1 ;USER TABLE FLAG DSKSEL: .BLKB 4 ;DISK ACCESS TABLE DISKNO: .BLKB 1 ;DISK PARAMATERS TRACK: .BLKB 1 SECTOR: .BLKB 1 STATUS: .BLKB 1 CMND: .BLKB 1 RWFLG: .BLKB 1 DMAAD: .BLKB 2 PARFLG: .BLKB 1 ;PAR ERROR FLAG HSELCD: .BLKB 1 ;HOST SELECT CODE HSTBLK: .BLKB 1 ;CPM SEC/PHY SEC BLKCNT: .BLKB 1 ;REC/CPMBLK SECMSK: .BLKB 1 ;SECTOR MASK WRTYPE: .BLKB 1 ;WRITE TYPE UNACNT: .BLKB 1 ;UNALOC REC COUNT UNADSK: .BLKB 1 ;LAST UNALOC DISK UNATRK: .BLKB 1 ;LAST UNALOC TRACK UNASEC: .BLKB 1 ;LAST UNALOC SECTOR SEKDSK: .BLKB 1 ;SEEK DISK SEKTRK: .BLKB 1 ;SEEK TRACK SEKSEC: .BLKB 1 ;SEEK SECTOR SEKHST: .BLKB 1 ;PHYSICAL SEC ADR SIDSEL: .BLKB 1 ;SIDE SELECT STORAGE HSTWRT: .BLKB 1 ;HOST WRITTEN FLAG HSTACT: .BLKB 1 ;HOST ACTIVE FLAG RSFLAG: .BLKB 1 ;READ SECTOR FLAG READOP: .BLKB 1 ;1=READ, 0=WRITE LUNIT: .BLKB 1 ;LAST SELECTED DRIVE ERFLAG: .BLKB 1 ;ERROR FLAG RFLAG: .BLKB 1 ;CPM READ FLAG BTSEC: .BLKB 1 ;NO OF BOOT SECS SEKDMA: .BLKB 2 ;SEEK DMA ADDRESS CTBLP: .BLKB 2 ;CURRENT TBL ADR UTBLP: .BLKB 2 ;UNALOC TBL ADR SECCNT: .BLKB 1 ;SECS/TRK FOR BOOT DPBASE: .BLKB EPLGTH ;CPM DISK PARAMETER HEADERS IDSV: .BLKB 6 DATSIZ = .-BEGDAT ;SIZE OF SCRATCH RAM ; ; ;END OF PROGRAM ; ; ; .END A ADDRESS CTBLP: .BLKB 2 ;CURRENT TBL ADR UTBLP: .BLKB 2 ;UNALOC TBL ADR SECCNT: