TITLE '<< MYBIOS FOR GSR BOARD VERSION OF 21 APR 84 RHP>>' ; ***************************************** ; * THE GSR MONITOR, VERSION III.8 * ; * UFDC-1 FLOPPY DISK CONTROLLER * ; * 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 * ; ***************************************** ; ; ; 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. ; MACLIB Z80 ; ; MEMORY USED BY MONITOR ; BASE EQU 0F800H ;MONITOR BASE ADDRESS. STACK EQU BASE-1 ;MONITOR STACK ; ; CONSTANTS FOR MONITOR ; CR EQU 0DH ;ASCII CARRIAGE RET LF EQU 0AH ;ASCII LINE FEED ; ; I/O PORTS ON CPU BOARD ; INOUT EQU 01H CONDTA EQU 03H CONCTL EQU 02H CONSTS EQU 02H ; ; ; DISK DEFINES ; VERS EQU 22 ;CP/M VERSION NUMBER MSIZE EQU 60 ;CP/M MEMORY SIZE BIAS EQU (MSIZE-20)*1024 CCP EQU 3400H+BIAS ;BASE OF CCP BDOS EQU CCP+806H ;BASE OF BDOS BIOS EQU CCP+1600H ;BASE OF BIOS WRALL EQU 0 ;WRT TO ALOC BLK WRDIR EQU 1 ;WRT TO DIRECTORY WRUAL EQU 2 ;WRT TO UNALOC BLK WBOOTE EQU BIOS+3 ;WARM BOOT ENTRY ; ; ;DISK I/O PORTS ; DSTAT EQU 9CH ;DISK STATUS PORT DCMMD EQU DSTAT ;DISK COMMAND PORT DTRCK EQU DSTAT+1 ;DISK TRACK PORT DSCTR EQU DSTAT+2 ;DISK SECTOR PORT DDATA EQU DSTAT+3 ;DISK DATA PORT DFLAG EQU 9BH ;STATUS REGISTER 1 DCNTL EQU DFLAG ;CONTROL REGISTER 1 ; ; ;MEMORY USED BY CPM ; CURDSK EQU 4 ;CURRENT DISK DRIVE TBUF EQU 80H ;DEFAULT CPM BUFFER ; ; ; PROGRAM CODE BEGINS: ; ORG BASE ; ; ;MONITOR BIOS JUMP VECTORS ; ; 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 DB 0,0,0 ;USE MP/M IDLE PROC BCDL EQU $-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: DW PSTS ;POLL PRINTER DW CSTS ;POLL CONSOLE DW 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 ; MAXCON: MVI A,1 ;# OF CONSOLES IS 1 STRTCK: STOPCK: EXITRG: SYSINT: RET ; ; MONITOR SIGN-ON MESSAGE ; MSG: DB CR,LF DB 'GSR COMPUTER BOARD FOR RH PETERS' MSGL EQU $-MSG ; ; MEMORY PARITY ERROR MESSAGE ; MSG1: DB CR,LF DB 'PAR ERR' MSG1L EQU $-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: MOV A,C CALL 0F803H 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 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 JR 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 XRA A STA SECTOR STA PARFLG MVI A,37H ;ENABLE XMT & REC 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 LDX L,15 ;BYTES PER SEC LDX H,16 DAD H ;ADJUST VALUE MOV D,H ;# 128 BYTE SECS BIT 1,(IX+18) ;TEST FOR DOUBLE SIDE JRZ WBOOTB ;SINGLE SIDE BIT 5,(IX+18) ;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 LDX A,19 ;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: DB 0BDH DB 0 JMP BDOS ; ; DERRM: DB '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 IX ;LOG ON DISK PUSH H CALL LOGDS2 POP H RNZ ;ERROR RETURN POP IX 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 LXIX DP0 ;BUILD TBL ADR IN X LXI D,128 DABLD1: DCR A JRZ DABLD2 DADX D JR 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 JR 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: LDX L,15 ;BYTES PER SECTOR LDX H,16 PUSH H ;COPY TO DE POP D LDX B,19 ;PHYSICAL SEC/TRK DCR B VALID1: DAD D ;BYTES/SEC X SEC/TRK DJNZ VALID1 DAD H ;DIVIDE BY 128 BIT 1,(IX+18) ;DOUBLE SIDE ? JRZ VALID3 ;SINGLE SIDE BIT 5,(IX+18) ;CYLINDER MODE ? JRNZ VALID3 ;CYLINDER MODE DAD H ;DBL SIDE, TIMES 2 VALID3: MOV A,H CP (IX+0) ;EQUAL SEC/TRK ? JRZ DBPARM ;VALID TABLE LXI H,DEFLT ;LOAD DEFAULT TABLE VALID2: PUSH IX POP D LXI B,128 LDIR DBPARM: LDX L,15 ;GET BYTES/SEC LDX H,16 DAD H MOV A,H STA HSTBLK ;CPM SEC/PHY SEC DCR A STA SECMSK ;SECTOR MASK LDX B,2 ;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 IX ;SAVE X LXI H,0FFECH ;TBL POINTER-20 DAD D PUSH H ;POINTER TO X POP IX XRA A BIT 1,(IX+18) ;TEST FOR DBL SIDE JRZ SECTR1 ;SINGLE SIDE BIT 5,(IX+18) ;CYLINDER MODE? JRNZ SECTR1 ;NON-CYLINDER MODE LDX L,0 ;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 IX ;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? JPO NOOVF ;NOT END LXI H,UNATRK ;UNATRK + 1 INR M MVI A,1 ;UNASEC = 1 JR OVF NOOVF: MOV A,M ;GET NEXT SECTOR OVF: STA UNASEC ;STORE NEXT UNASEC XRA A ;RESET RSFLAG JR 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 IX LDA SEKDSK ;LOG ON SEKDSK CALL LOGDS2 BIT 5,(IX+18) ;CYLINDER MODE? JRZ CYLN ;YES LDA SEKTRK CP (IX+17) ;TRK > TRKS PER SIDE? JRC CYLN ;NOT GREATER SUBX 17 ;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 JR 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,(IX+18) ;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,(IX+18) ;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 JR 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 IX 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 JR 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 JR 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: LDX L,15 ;GET SECTOR SIZE LDX H,16 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,(IX+18) ;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,(IX+18) ;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 SETB 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 DW TD0,0 DW 0,0 DW DIRBF,DP0 DW CHK00,ALL00 ;DISK PARAMETER HEADER FOR DISK 01 DW TD1,0 DW 0,0 DW DIRBF,DP1 DW CHK01,ALL01 ;DISK PARAMETER HEADER FOR DISK 02 DW TD2,0 DW 0,0 DW DIRBF,DP2 DW CHK02,ALL02 ;DISK PARAMETER HEADER FOR DISK 03 DW TD3,0 DW 0,0 DW DIRBF,DP3 DW CHK03,ALL03 EPLGTH EQU $-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: DW 26 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DB 7 ;BLOCK MASK DB 0 ;EXTENT MASK DW 242 ;BLOCKS PER DISKETTE DW 63 ;# DIRECTORY ENTRIES DB 0C0H ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;DIR CHECK VECTOR SIZE DW 2 ;SYSTEM TRACK OFFSET DW 128 ;BYTES PER SECTOR DB 77 ;TRACKS PER DISK ; CONTROL BYTE DB 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 DB 26 ;PHYSICAL SEC/TRK ; ; SECTOR TRANSLATE TABLE ; T8S4: DB 1,7,13,19,25 DB 5,11,17,23 DB 3,9,15,21 DB 2,8,14,20,26 DB 6,12,18,24 DB 4,10,16,22 ; ; ;SCRATCH RAM AREA FOR BDOS USE ; BEGDAT EQU BIOS+128;BEGINNING OF DATA AREA ORG BEGDAT DBUF: DS 1024 ;DEBLOCK BUFFER DP0: DS 20 ;DISK PARMETER TABLES TD0: DS 108 DP1: DS 20 TD1: DS 108 DP2: DS 20 TD2: DS 108 DP3: DS 20 TD3: DS 108 UTABLE: DS 128 ;USER DISK PARAMETER TABLE DIRBF: DS 128 ;SCRATCH DIRECTORY AREA ALL00: DS 128 ;ALLOCATION VECTOR 0 ALL01: DS 128 ;ALLOCATION VECTOR 1 ALL02: DS 128 ;ALLOCATION VECTOR 2 ALL03: DS 128 ;ALLOCATION VECTOR 3 CHK00: DS 64 ;CHECK VECTOR 0 CHK01: DS 64 ;CHECK VECTOR 1 CHK02: DS 64 ;CHECK VECTOR 2 CHK03: DS 64 ;CHECK VECTOR 3 SELFLG: DS 1 ;USER TABLE FLAG DSKSEL: DS 4 ;DISK ACCESS TABLE DISKNO: DS 1 ;DISK PARAMATERS TRACK: DS 1 SECTOR: DS 1 STATUS: DS 1 CMND: DS 1 RWFLG: DS 1 DMAAD: DS 2 PARFLG: DS 1 ;PAR ERROR FLAG HSELCD: DS 1 ;HOST SELECT CODE HSTBLK: DS 1 ;CPM SEC/PHY SEC BLKCNT: DS 1 ;REC/CPMBLK SECMSK: DS 1 ;SECTOR MASK WRTYPE: DS 1 ;WRITE TYPE UNACNT: DS 1 ;UNALOC REC COUNT UNADSK: DS 1 ;LAST UNALOC DISK UNATRK: DS 1 ;LAST UNALOC TRACK UNASEC: DS 1 ;LAST UNALOC SECTOR SEKDSK: DS 1 ;SEEK DISK SEKTRK: DS 1 ;SEEK TRACK SEKSEC: DS 1 ;SEEK SECTOR SEKHST: DS 1 ;PHYSICAL SEC ADR SIDSEL: DS 1 ;SIDE SELECT STORAGE HSTWRT: DS 1 ;HOST WRITTEN FLAG HSTACT: DS 1 ;HOST ACTIVE FLAG RSFLAG: DS 1 ;READ SECTOR FLAG READOP: DS 1 ;1=READ, 0=WRITE LUNIT: DS 1 ;LAST SELECTED DRIVE ERFLAG: DS 1 ;ERROR FLAG RFLAG: DS 1 ;CPM READ FLAG BTSEC: DS 1 ;NO OF BOOT SECS SEKDMA: DS 2 ;SEEK DMA ADDRESS CTBLP: DS 2 ;CURRENT TBL ADR UTBLP: DS 2 ;UNALOC TBL ADR SECCNT: DS 1 ;SECS/TRK FOR BOOT DPBASE: DS EPLGTH ;CPM DISK PARAMETER HEADERS IDSV: DS 6 DATSIZ EQU $-BEGDAT ;SIZE OF SCRATCH RAM ; ; ;END OF PROGRAM ; ; ; END