TITLE 'MEMORY DISK ADDON MODULE VERSION 2.0 OF 2/9/83' ;****************************************************************************** ; MICRO RESOURCES CP/M MEMORY DISK ADDON MODULE ;****************************************************************************** ; ; ; THIS PROGRAM IS A SMALL TRANSIENT PROGRAM BASED BIOS SUBSTITUTE ; THAT ALLOWS FILE TRANSFER UTILITY BETWEEN THE NORMAL CP/M SYSTEM ; DISKS AND A RESIDENT "MEMORY DISK". THIS TRANSIENT PROGRAM IS ; SETUP FOR ANY VERSION 2.2 CP/M RUNNING IN AN S100 COMPUTER WITH ; THE CCS 2065 BANK SWUTCHED DYNAMIC RAM CARDS. ; ; THIS PROGRAM ALLOWS FOR A MEMORY RESIDENT FLOPPY DISK TO BE LOCATED ; IN A SEVERAL CCS BANK SWITCHED BOARDS. THE PROGRAM SUPPORTS UP TO ; EIGHT BOARDS, ONE AS THE MASTER BANK AND UP TO SEVEN AS THE DISK ; DATA STORAGE AREA. THE BANK SWITCHING IS DONE AT THE 48K BYTE ADDRESS ; BOUNDARY ABOVE WHICH ONLY ONE CARD HAS A 16K BANK ENABLED. BELOW THIS ; EACH BOARD CONTAINS 48K BYTES THAT IS BANK SWITCHED IN PLACE OF THE ; TPA FOR THE MEMORY DISK STORAGE SPACE. THE FORMAT OF THE CP/M ; SYSTEM ALLOWS FOR A TOTAL OF 64 DIRECTORY ENTRIES AND USES A 1K ; BYTE BLOCK ALLOCATION SIZE. THIS ALLOWS MAXIMUM FLEXIBILITY OF ; SMALL DIRECTORY SIZE AND SMALL BLOCK SIZE TO CONSERVE MEMORY SPACE ; ON SMALL FILES. ; ; PROGRAM ACCESS TO THE RAM DRIVE IS DONE IN 128 BYTE SECTORS ; THAT ARE DIRECTLY TRANSFERRED FROM/TO THE USER TRANSIENT PROGRAM. ; THE INITIAL LOADING OF THIS SOFTWARE SWAPS OUT THE NORMAL CP/M DISK ; I/O ENTRY POINTS TO THE BIOS WITH A NEW SET OF ENTRY POINTS TO THIS ; MODULE. THIS MODULE THEN CHECKS ALL SELECT DISK ACCESSES FOR LOGICAL ; UNIT M: AND WILL AND WILL STEER I/O REQUESTS FOR THIS DRIVE THROUGH ; DRIVERS CONTAINED WITHIN THIS PROGRAM. NOTE THAT THIS PROGRAM STILL ; DEPENDS UPON THE HOST CP/M SYSTEM BDOS AS THE FILE INTERFACE MEDIUM. ; ; OPERATION OF THE PROGRAM IS DONE TO MOVE THE MODULE UP TO A WORKSPACE ; BELOW THE MEMORY RESIDENT CCP. THE WARM BOOT VECTOR AT THE SYSTEM ; WARM BOOT ENTRY POINT IS SWAPPED TO A NEW ENTRY POINT WITHIN THE ; RELOCATED I/O MODULE. THE NEW WARMBOOT FUNCTION SIMPLY RE-ENTERS ; THE ALREADY PRESENT CCP FOR FURTHER OPERATOR COMMAND PROCESSING. ; THE BDOS ENTRY VECTOR IS ALSO MODIFIED TO PERMIT THE DYNAMIC ; MODIFICATION OF THE USER PROGRAM AREA SIZE SUCH THAT THE CCP AND ; THE RELOCATED I/O MODULE DO NOT GET OVERLAYED BY THE TRANSIENT ; PROGRAM AREA'S BUFFER SPACES. THE UTILITY, WHEN LOADED PERFORMS ; A CHECK TO VERIFY WHETHER A RELOCATED MODULE IS ALREADY PRESENT ; IN MEMORY. THE ALREADY PRESENT CHECK IS DONE VIA A SPECIALLY DEFINED ; BDOS CALL THAT REQUESTS THE OPENING OF A FILE WITH THE SPECIALLY ; DEFINED NAME SEQUENCE OF "A,,,,,,,,.,,," AS THE FILE NAME WHERE (A) ; IS A REQUEST NUMBER FOR PRESENCE CHECKING. AS THIS CHARACTER SEQUENCE ; IS AN ILLEGAL FILE NAME SEQUENCE, THE CHECK PROGRAM WILL TRAP THE NAME ; AND RETURN A ZERO BYTE IN THE (A) REGISTER IF THE MODULE IS PRESENT. ; IF THE ADDRESS BYTE IN THE FIRST BYTE OF THE FCB IS NOT RECOGNIZED, ; THEN THE MODULE PASSES THE OPEN FILE REQUEST ON TO THE NEXT HIGHER ; LEVEL BDOS CALL. IN ANY CASE THE NON PRESENCE OF A FILE BY THE NAME ; OF "A,,,,,,,.,,," IS VIRTUALLY ASSURED TO CAUSE THE BDOS TO RETURN ; A NOT FOUND "0FFH" ERROR CODE IN THE (A) REGISTER. THIS WOULD INDICATE ; THE ABSENSE OF THE MODULE BEING CHECKED FOR. ; ; ; THIS MEMORY DISK DRIVER PACKAGE ; PROGRAM IS COPYRIGHT PROTECTED BY: ; ; COPYRIGHT (C) 1983 ; ; MICRO RESOURCES ; 2468 HANSEN COURT ; SIMI VALLEY, CALIFORNIA 93065 ; (805) 527-7922 ; ;***************************************************************************** ; ; ; ;DEFINE TRUE AND FALSE ASSEMBLY PARAMETERS ; TRUE EQU -1 ;DEFINE TRUE FALSE EQU NOT TRUE ;DEFINE FALSE ; ; HARDSIZ EQU FALSE ;TRUE IF HARD SIZE CODING BDTRKS EQU 8 ;NUMBER OF 48K BANKS (HARD CODED) BIGMEM EQU FALSE ;TRUE IF THE AVAILABLE RAM ABOVE THE ;..TOP OF THE BANK SWITCH AREA CAN ;..ACCOMODATE THIS MEMORY DISK ADDON ;..MODULE. IF NOT, THEN MEMORY ABOVE THE ;..BIOS MUST BE MADE AVAILABLE AS SPECIFIED ;..BY THE "IPPROG" EQUATES BELOW. THE ;..NUMBER OF BYTES NEEDED BY THE RESIDENT ;..DRIVER IS 256 BYTES. MAXTRK EQU 8*3 ;MAXIMUM NUMBER OF POSSIBLE 16K TRACKS ;..ON 8 48K BOARDS DIRTRK EQU 3 ;TRACK NUMBER FOR DIRECTORY START MAXSEC EQU 128 ;NUMBER OF 128 BYTE SECTORS IN A ;..16K TRACK ; ; ;SOME ASCII CHARACTERS ; CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED ; ; ;DEFINE RAMDISK MODULE SELECT ADDRESS AS SPECIAL VALUE ; MODADDR EQU 0CCH ;ADDRESS OF THIS MODULE ; ;..FOR CALIFORNIA COMPUTERS (HA HA) ; ;CP/M BDOS INTERFACE EQUATES ; ASEG BOOT EQU 0000H ;FIXED BOOT ADDRESS BDOS EQU 0005H ;FIXED BDOS ADDRESS DEFFCB EQU 005CH ;DEFAULT FCB LOCATION DEFBUF EQU 0080H ;DEFAULT SYSTEM BUFFER RESET EQU 13 ;RESET DISK SYSTEM OPEN EQU 15 ;OPEN FILE STDMA EQU 26 ;SET DMA ADDRESS ; ; ;CCS 2065 RAM BOARD ACCESS ADDRESS EQUATES ; BANKSEL EQU 040H ;CCS FACTORY DEFAULT BANK SELECT PORT ; IF NOT BIGMEM IPPROG EQU 0F500H ;LOCATION TO BLOCK MOVE PROGRAM TO FOR ;..RESIDENT MEMORY I/O PROGRAM ABOVE BIOS IPBUF EQU IPPROG+080H ;RESIDENT MEMORY PAGE DISK BUFFER ENDIF IF BIGMEM IPPROG EQU RWXFR ;IF PLENTY OF MEMORY LET THE DRIVER ;..RESIDE AT TOP OF ADDON MODULE ENDIF ; BANKTOP EQU 0C000H ;TOP ADDRESS +1 FOR THE 48K BANK AREAS ; ; ;DEFINE MACRO LIBRARY FOR Z80 OPCODES ; MACLIB Z80 ;DRI Z80 OPCODE MACROS ; ; ;DEFINE MACRO LIBRARY FOR DEFINING THE DISK ; MACLIB DISKDEF ;STD DRI PACKAGE ; ; ;CP/M 2.2 TO HOST DISK CONSTANTS ; BLKSIZ EQU 1024 ;CP/M ALLOCATION SIZE HSTSIZ EQU 128 ;HOST DISK SECTOR SIZE ; SECSIZ EQU 128 ;NUMBER OF BYTES IN DISK RECORD ; ; ;***************************************************************************** ; ; CSEG ;SET ORIGIN TO ZERO FOR RELOCATABLE ;ASSEMBLY BY RMAC ; ; ; ;FIRST TIME START UP ENTRY POINT FOR THE SINGLE DENSITY ;AUTO RELOCATING I/O MODULE. ENTRY HERE ASSURES PRESENSE OF ;CP/M 2.2. ; JMP CHKPRES ;GO CHECK IF A MODULE OF ;SAME FUNCTION ADDRESS IS PRESENT ;IN SYSTEM ; ; ;DUMMY SPACE OFFSET TO PUT NEW BDOS ENTRY CODE AT A 06H PAGE ;BOUNDARY OFFSET TO PERMIT DIGITAL RESEARCH DDT AND XSUB TO ;OPERATE WITHOUT A GLITCH ; DS 3 ; ; ;NEWLY DEFINED ENTRY POINT INTO THIS MODULE FOR THE BDOS ;CALL VECTOR FUNCTION. ; L5ENT: JMP BDOS$SCAN ;TO ENTRY POINT TO SCAN BDOS ;FUNCTION CALLS ; ; ;SUBSTITUTE BDOS ENTRY POINT. EXECUTION ADDRESS IS PLACED HERE ;FROM LOCATION 6 & 7 BY THE START UP MODULE PROVIDED THIS ;MODULE IS DETERMINED TO NOT ALREADY BE IN MEMORY. ; TO$BDOS: JMP $-$ ;ENTER ADDRESS AT STARTUP ; ; ;START UP CHECK ROUTINE TO SEE IF THIS SOFTWARE WAS ALREADY ;LOADED BY A PREVIOUS OPERATOR COMMAND. ; CHKPRES: MVI C,OPEN ;ATTEMPT TO OPEN FILE "A,,,,,,,.,,," LXI D,CHKFCB ;POINT AT THE CHECK FCB CALL BDOS ;CALL NORMAL BDOS ADDRESS ORA A JNZ NOT$PRES ;NON ZERO RETURN MODULE IS NOT ;..PRESENT LXI D,PRESMSG ;POINT TO PRESENT MESSAGE MVI C,9 ;PRINT FUNCTION CODE CALL BDOS ;PRINT ALREADY PRESENT MESSAGE RET ;SIMPLE RETURN TO THE CCP ; CHKFCB: DB 0,MODADDR,',,,,,,,,,,',0,0,0,0 DS 16 DB 0 ; PRESMSG: DB CR,LF,'MICRO RESOURCES Memory Disk' DB CR,LF,'Access Already Active','$' ; ; ;HERE IF THIS RELOCATED MODULE IS NOT PRESENT IN MEMORY ; NOT$PRES: POP H ;COMPUTE CCP RE-ENTRY POINT PUSH H LXI D,075CH ;NEGATIVE OFFSET TO CCP ENTRY ;WITH NO AUTO LOAD MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A SHLD CCP$ENT ;SAVE THAT ENTRY ADDRESS ; LHLD BDOS+1 ;GET PREVIOUS BDOS ADDRESS SHLD TO$BDOS+1 ;SET TO LOCAL REFERENCE VECTOR ; LXI H,L5ENT ;SET NEW BDOS ENTRY TO THIS MODULE SHLD BDOS+1 ;BASE+6 ; CALL MOVDN ;MOVE DOWN THE BIOS VECTOR TABLE LHLD BWBOOT+1 SHLD BIOSLD ;SAVE AS BIOS LOAD ADDRESS ; LXI H,BOOTENT ;SET MOVED DOWN TABLE TO LOCAL BOOT HANDLER SHLD BWBOOT+1 ; CALL PRTMSG ;PRINT SIGN ON MESSAGE DB CR,LF,' MICRO RESOURCES Memory Disk Add-On' DB CR,LF,' Version 2.0' DB CR,LF,' COPYRIGHT (C) 1983' DB CR,LF DB CR,LF,' Drive M: becomes active in CCS 64K RAM' DB 0 ; ; ;INITIALIZE ALL ITEMS FOR USE IN THIS I/O HANDLER ; MVI B,ENDZ-STARTZ ;ZERO DATA AREA IN PARAMETER TABLE LXI H,STARTZ ZLP: MVI M,00H ;PUT IN A ZERO PARM BYTE INX H ;POINT TO NEXT BYTE TO BE ZEROED DCR B ;CHECK BYTE COUNT TO SEE IF DONE JNZ ZLP ; ; ;HAVE THIS UTILITY QUEUE BOTH BIOS AND THIS DRIVER TO THE SAME ;CP/M DATA BUFFER ADDRESS ; LXI D,DEFBUF ;USE DEFAULT BUFFER MVI C,STDMA ;SET DMA FUNCTION CODE CALL TO$BDOS ; LXI H,RAMSEL ;DISABLE DRIVE SELECT FOR RAM DISK MVI M,00H XRA A ;SET RESIDENT DRIVER FLAG OFF STA RESFLG ; ; ;FIND OUT THE SIZE OF THE AVAILABLE MEMORY BOARDS FOR THE ;MEMORY RESIDENT DRIVE ; SIZEDRV: IF HARDSIZ MVI B,BDTRKS ;FORCE TRACKS COUNT JMP SIZEGOT ENDIF ; CALL PRTMSG DB CR,LF,'Memory sizing ',0 MVI A,00H STA SEKSEC ;TEST SECTOR ZERO EACH 'TRACK' STA SEKTRK+1 ;ZERO HIGH BYTE OF TRACK NUMBER ; ; ;READ FIRST SECTOR OF EACH "TRACK" TO SAVE EACH FIRST BYTE IN BUFFER ;AND REPLACE THE FIRST BYTE WITH A PATTERN OF TRACK NUMBER ; MVI B,0 ;START TRACK NUMBER GFBYT: PUSH B ;SAVE TRACK NUMBER MOV A,B STA SEKTRK CALL RDSEC ;GET FIRST SECTOR OF TRACK POP B LDA DEFBUF ;GET THE FIRST BYTE LXI H,FBBUF ;POINT AT SAVE BUFFER MVI D,00H MOV E,B DAD D ;INDEX TO BYTE SAVE LOCATION MOV M,A ;SAVE BYTE MOV A,B ;PLACE TRACK NUMBER INTO BYTE STA DEFBUF PUSH B CALL WRTSEC ;WRITE MODIFIED PATTERN BACK OUT POP B INR B ;INCREMENT TRACK COUNTER MOV A,B ;CHECK IF PAST MAX BANK CPI MAXTRK JNZ GFBYT ;MORE BANK "TRACKS" TO DO ; ; ;RESTORE THE FIRST BYTES OF EACH SECTOR TO MAX TRK CNT+1 IN (C) ;BUT CHECK THE FIRST BYTES OF READ BACK IN PATTERN TO SEE EXTENT ;OF AVAILABLE MEMORY ; BYTRST: MVI B,0 ;START TRACK NUMBER PFBYT: PUSH B ;SAVE TRACK/SEC CALL PRTMSG DB '.',0 POP B MOV A,B ;SET TRACK NUMBER STA SEKTRK PUSH B ;SAVE TRK/MAX TRK CALL RDSEC ;GET SECTOR FOR RESTORE POP B LDA DEFBUF ;CHECK BYTE READ BACK CMP B ;DO THEY MATCH? JNZ SIZEGOT PUSH B LXI H,FBBUF ;POINT AT SAVE BUFFER MVI D,00H MOV E,B DAD D ;INDEX TO BYTE SAVE LOCATION MOV A,M ;GET RESTORE BYTE VALUE STA DEFBUF ;RESTORE FIRST BYTE CALL WRTSEC ;WRITE SECTOR BACK POP B INR B ;INCREMENT TRACK COUNTER MOV A,B CPI MAXTRK ;CHECK IF PAST MAX TRACK JNZ PFBYT ;MORE BANK "TRACKS" TO RESTORE ; ; ;HERE IF WE HAVE CURRENT "DISK" SIZE IN 16K TRACKS. TRACKS OR REAL RAM ;BANKS WERE ASSUMED TO BE PRESENT EACH IN ITS ENTIRITY. ENTRY HERE WITH ;THE (B) REGISTER EQUAL TO THE NUMBER OF THE AVAILABLE TRACKS. THE ;MAXIMUM REAL TRACK NUMBER IS (B)-1. ; SIZEGOT: MOV A,B CPI DIRTRK+1 ;CHECK IF NO OTHER BANKS AVAILABLE JNC SG1 ;CONTINUE IF OK ; CALL PRTMSG DB CR,LF,'No Memory Available for RAM Disk',0 LHLD BIOSLD ;TO BIOS WARM BOOT ADDRESS FOR RESTART PCHL ;OFF TO BIOS FOR RELOAD ; SG1: STA NTRKS ;SAVE OFF AS NUMBER OF TRACKS SUI DIRTRK ;SET SIZE OF DISK - RESERVED AREA MOV L,A MVI H,0 DAD H ;SHIFT LEFT FOUR TIMES DAD H DAD H DAD H PUSH H ;SAVE SIZE FOR PARM TABLE UPDATE ; LXI D,RSIZE ;POINT TO RAM SIZE STRING AREA CALL BINASC ;CONVERT RAM SIZE TO DEC ASCII LXI H,RSIZE ;FIXUP TO PRINT LEADING ZEROS MVI B,4 ;NUMBER OF ZERO STRIP LOCS TO CHECK SSTRP: MOV A,M ;GET A CHARACTER CPI '0' JNZ STDONE ;NON ZERO SO EXIT MVI M,' ' ;SUBSTITUTE A SPACE INX H DCR B JNZ SSTRP ;CONTINUE CHARACTER STRIP ? ; STDONE: CALL PRTMSG ;PRINT RAM SIZE MESSAGE DB CR,LF,'RAM Available for ' RSIZE: DB '00000 Kbyte Disk',0 ; ; ;PLUG DISK SIZE INTO THE DISK PARAMETER TABLE ; LXI H,DPBASE ;INDEX TO DRIVE PARAMETER LXI D,5 ;..TABLE POINTER DAD D DAD D MOV E,M ;GET POINTER INX H MOV D,M LXI H,5 ;INDEX TO DISK SIZE DAD D POP D ;POP DISK SIZE INTO THE (DE) DCX D ;-1 FOR BIOS TABLE MOV M,E ;MOVE SIZE INTO TABLE INX H MOV M,D ; ; ;INITIALIZE THE RAM BUFFER TO LOOK LIKE FRESH FORMATTED DRIVE ;THIS FORMAT PROCESS IS OF COURSE OPTIONAL ; FORMAT: CALL PRTMSG ;PRINT FORMAT MESSAGE DB CR,LF DB CR,LF,'Should RAM be FORMATTED (Y/N): ',0 CALL BCIN ;GET RESPONSE PUSH PSW MOV C,A ;ECHO CALL BCOUT CALL PRTMSG DB CR,LF,0 POP PSW ;GET INPUT CHAR ANI 05FH ;CONVERT TO UPPER CASE CPI 'Y' JNZ CCPGO ;SKIP FORMAT IN NOT 'Y' ; LXI H,DEFBUF ;MAKE PATTERN FOR FORMAT LXI B,SECSIZ E5LP: MVI M,0E5H ;FILL IN AN E5 CHAR FOR FORMAT INX H ;BUMP POINTER DCX B ;DEBUMP BYTE COUNTER MOV A,B ;CHECK IF DONE ORA C JNZ E5LP ;MUST BE MORE TO DO ; CALL PRTMSG DB CR,LF,'Formatting ',0 ; LDA NTRKS ;GET TRACK COUNT FOR FORMAT MOV L,A ;(L)=TRACK COUNT ; MVI B,DIRTRK ;START TRACK NUMBER FOR FORMAT MVI C,00H ;START SECTOR NUMBER FOR FORMAT FMTLP: PUSH H PUSH B MOV A,B STA SEKTRK MOV A,C STA SEKSEC CALL WRTSEC ;WRITE FORMAT SECTOR POP B ;GET BACK TRACK/SECTOR POP H INR C ;BUMP SECTOR NUMBER MVI A,MAXSEC ;AT MAXIMUM SECTOR NUMBER? CMP C JNZ FMTLP ;GO ON TRACK TILL LAST SECTOR ; MVI C,00H ;RESET SECTOR TO TRACK START INR B ;BUMP TRACK NUMBER ; FMTCK: PUSH H ;SAVE TRACK COUNT PUSH B ;SAVE TRACK/SEC CALL PRTMSG DB '.',0 ;PRINT ACTIVITY PERIOD POP B POP H DCR L ;DEBUMP TRACK COUNTER JNZ FMTLP ;GO START NEXT TRACK ; CALL PRTMSG DB CR,LF,0 ; ; ;RETURN TO CCP VIA THE OLD DEFINED REENTRY POINT ; CCPGO: LXI H,L5ENT ;RESET NEW BDOS ENTRY TO THIS MODULE SHLD BDOS+1 ;BASE+6 LHLD CCP$ENT ;GET THE CCP ENTRY POINT LDA 004H ;GET CURRENTLY LOGGED DRIVE MOV C,A PCHL ; ; ;NEW WARM BOOT ENTRY LOCATION THAT RESETS THE DISK SYSTEM ;AND TRANSFERS CONTROL BACK TO THE ALREADY PRESENT CCP ; BOOTENT: JMP CCPGO ;NOW GO BACK TO THE CCP ; ; ;HERE FROM A BDOS ENTRY TO TRAP FILE OPEN I/O TO CHECK FOR ;MODULE PRESENT CHECK. ; BDOS$SCAN: PUSH D ;SAVE CALLERS PARAMETERS PUSH B MOV A,C ;GET FUNCTION CODE TO A CPI OPEN ;SEE IF THIS IS AN OPEN FUNCTION JNZ CHKFAIL INX D ;POINT TO FCB CHECK BYTE LXI H,10 ;SET SCAN COUNTER TO FAKE FILE NAME END DAD D MVI B,10 ;NUMBER OF "," TO CHECK FOR SCAN$LOOP: MOV A,M ;GET FILE NAME CHARACTER CPI ',' JNZ CHKFAIL ;PASS ON IF CHECK FAIL DCX H ;DECREASE BUFFER POINTER DCR B JNZ SCAN$LOOP ;CHECKED ALL POSSIBLE CHARS YET MOV A,M ;CHECK IF ADDRESS BYTE IS OURS CPI MODADDR JNZ CHKFAIL ;BALE OUT IF NOT XRA A ;RETURN ZERO BYTE IF ALL CHECK VALID POP B POP D RET ;BACK TO PRESENT CHECKER ; CHKFAIL: ;PROPER OPEN CHECK FAIL POP B POP D JMP TO$BDOS ;OFF TO THE NORMAL BDOS ROUTINE ; ; XFRTAB: ; ; SUBSTITUTE BIOS VECTOR TABLE. THIS JUMP TABLE VECTORS ALL CP/M ; DISK I/O TO THIS TRANSIENT MODULE FIRST. TABLE IS PUT INTO THE ; BIOS VECTOR TABLE POSITION BY A CALL TO THE SUBROUTINE "MOVDN" ; ; JMP BCBOOT ;TO NORMAL BIOS COLD BOOT ROUTINE JMP BOOTENT ;TO LOCAL WARM BOOT HANDLER JMP BCSTAT ;TO NORMAL BIOS CONSOLE STATUS CHECK JMP BCIN ;TO NORMAL BIOS CONSOLE INPUT JMP BCOUT ;TO NORMAL BIOS CONSOLE OUTPUT JMP BLOUT ;TO NORMAL BIOS LPT OUTPUT JMP BPUN ;TO NORMAL BIOS PUNCH OUTPUT JMP BRDR ;TO NORMAL BIOS READER INPUT JMP HOME ;MOVE DISK TO TRACK ZERO JMP SELDSK ;SELECT DISK DRIVE JMP SETTRK ;SEEK TO TRACK IN REG A JMP SETSEC ;SET SECTOR NUMBER JMP SETDMA ;SET DISK STARTING ADR JMP READ ;READ SELECTED SECTOR JMP WRITE ;WRITE SELECTED SECTOR JMP BLSTST ;GO RIGHT TO NORMAL BIOS FOR THIS I/O JMP SECTRAN ;SECTOR TRANSLATE ; ; LOCTAB: ; ; LOCAL COPY OF THE ORIGINAL BIOS DISK I/O VECTOR TABLE ; INITIALIZED BY CALLING THE "MOVDN" SUBROUTINE. ; BCBOOT: JMP $-$ ;TO BIOS COLD BOOT ROUTINE BWBOOT: JMP $-$ ;TO BIOS WARM BOOT ROUTINE BCSTAT: JMP $-$ ;TO BIOS CONSOLE STATUS CHECK BCIN: JMP $-$ ;TO BIOS CONSOLE INPUT BCOUT: JMP $-$ ;TO BIOS CONSOLE OUTPUT BLOUT: JMP $-$ ;TO BIOS LPT OUTPUT BPUN: JMP $-$ ;TO BIOS PUNCH OUTPUT BRDR: JMP $-$ ;TO BIOS READER INPUT BHOME: JMP $-$ ;TO BIOS HOME DISK ROUTINE BSELDSK: JMP $-$ ;TO BIOS SELECT DISK ROUTINE BSETTRK: JMP $-$ ;TO BIOS SET TRACK ROUTINE BSETSEC: JMP $-$ ;TO BIOS SET SECTOR ROUTINE BSETDMA: JMP $-$ ;TO BIOS SET DMA ADDRESS ROUTINE BREAD: JMP $-$ ;TO BIOS SECTOR READ ROUTINE BWRITE: JMP $-$ ;TO BIOS SECTOR WRITE ROUTINE BLSTST: JMP $-$ ;TO BIOS LIST STATUS ROUTINE BSTRAN: JMP $-$ ;TO BIOS SECTOR TRANSLATE ROUTINE ; ; ;SUBROUTINE TO INTERCHANGE BIOS DISK I/O VECTOR TABLE ENTRIES WITH ;THOSE CONTAINED LOCALLY. ; TABSIZ EQU 17*3 ;TABLE SIZE TO INITIALIZE WITH 17 JMP'S ; ; MOVDN: LHLD BOOT+1 ;GET ORIGINAL WARM BOOT VECTOR POINTER DCX H ;ADJUST TO BASE OF COLD BOOT VECTOR DCX H DCX H MVI A,TABSIZ ;SET BYTE COUNT TO MOVE STA BYTCNT LXI D,LOCTAB ;POINT TO LOCAL TABLE FILL FROM ABOVE LXI B,XFRTAB ;POINT TO TABLE TO MOVE UP MDLP: MOV A,M ;GET A BIOS TABLE BYTE STAX D ;PUT IN LOCAL COPY TABLE LDAX B ;GET BYTE OF PATCH TABLE MOV M,A ;PUT PATCH BYTE INTO BIOS POSITION INX H ;MOVE UP TO NEXT BYTE INX D INX B LDA BYTCNT ;SEE IF DONE YET DCR A STA BYTCNT JNZ MDLP ;CONTINUE IF NOT DONE YET RET ; BYTCNT: DB 0 ;LOCAL MOVE BYTE COUNTER ; ; ;INLINE PRINT OF MESSAGE TILL A ZERO ; PRTMSG: XTHL ;SAVE HL, GET MSG POINTER ; PRTMLP: MOV C,M ;GET CHARACTER INX H ;INCREMENT POINTER TO NEXT CHAR ;..OR RETURN ADDRESS MOV A,C ;CHECK IF ZERO END ORA A JZ PMXIT ;EXIT IF ZERO ; PUSH H ;SAVE MSG PTR. CALL BCOUT ;OUTPUT IT POP H ;RESTORE MSG PTR. JMP PRTMLP ;GO CHECK/DO NEXT CHAR ; PMXIT: XTHL ;RESTORE HL, RET ADDR RET ;RET PAST MSG ; ; ; ;ROUTNE TO CONVERT A TWO BYTE BINARY VALUE TO ASCII IN A STRING. ;ASCII IS IN THE DECIMAL NOTATION FAMILIAR TO ALL US HUMANS. ; ; (HL) = BINARY NUMBER UPON ENTRY ; (DE) = POINTER TO START OF STRING ON ENTRY ; BINASC: PUSH PSW ;SAVE REGISTERS PUSH B PUSH D LXI B,004H ;FIX DE TO POINT TO END OF BUFFER XCHG DAD B XCHG PUSH D ;SAVE ASCII POINTER MVI A,05H ;GET A DIGIT COUNT STA DIGCNT NDIG: LXI B,-10 ;RADIX FOR CONVERSION LXI D,-1 ;THIS BECOMES NO DIVIDED BY RADIX DX: DAD B ;SUBTRACT 10 INX D JC DX LXI B,10 DAD B ;ADD RADIX BACK IN ONCE XCHG MOV A,E ADI '0' ;CONVERT FROM BCD TO ASCII POP D ;GET ASCII BUFFER POINTER STAX D ;STORE ASCII CHARACTER DCX D ;ADJUST ASCII POINTER LDA DIGCNT ;CHECK IF CONVERSION DONE DCR A JZ DDIG ;EXIT IF DONE STA DIGCNT PUSH D ;SAVE ASCII POINTER JMP NDIG ;GO DO NEXT DIGIT DDIG: POP D ;RESTORE REGISTERS POP B POP PSW RET ; ; ;BINASC ROUTINE STORAGE ALLOCATIONS ; DIGCNT DB 00 ;PLACE TO STORE ASCII DIGIT COUNT ; ; ;******************************************************************** ; ;PARAMETER TABLE FOR CCS 2065 BOARDS RESIDENT RAM DRIVE ; DISKS 1 ;ONE LOGICAL DRIVE SUPPORTED DISKDEF 0,1,128,,1024,336,64,0,DIRTRK ;M: RAM DRIVE ;SET FOR 64 NON CHECKED DIR ENTRIES ;336 ALLOCATABLE BLOCKS OF 1K (FOR SEVEN ;..48K BANK SWITCHED BOARDS) MODIFIED AT ;..BOOTUP. ;OFFSET OF THREE TRACKS TO PERMIT FIRST BANK ;..TO BE RESERVED FOR CP/M RESIDENT SYSTEM ;128 SECTORS PER TRACK (128 RECORDS PER 16K ;..MEMORY BANK). ; SELDSK: MOV A,C ;GET NEW UNIT NUMBER CPI 'M'-041H ;IS THIS OUR DRIVE? JZ SDSK1 ;IF SO THEN GIVE THEM A PARAMETER POINTER ; XRA A ;IF NOT CLEAR THE RAM DRIVE SELECT FLAG STA RAMSEL JMP BSELDSK ;IF NOT FOR US THEN LET BIOS HAVE SELECT ; ; ;HERE IF DRIVE SELECT WAS FOR THIS PIECE OF SOFTWARE ; SDSK1: MVI A,0FFH ;SET THE RAM DRIVE SELECT FLAG STA RAMSEL ; LXI H,DPBASE ;PASS BACK DISK PARAMETER BASE XRA A ;SET A REG. = 00 RET ;RETURN FROM SELDSK ; ; HOME: LDA RAMSEL ;SEE IF RESTORE FOR US ORA A JZ BHOME ;NO MUST BE FOR BIOS DRIVE ; LXI H,00H SHLD SEKTRK ;ZERO SEK TRK ON HOME RET ; ; ;SET TRACK NUMBER SPECIFIED BY B&C REGS. ; SETTRK: LDA RAMSEL ;SEE IF TRACK FOR US ORA A JZ BSETTRK ;TO PROM IF NOT LOCAL ; MOV H,B MOV L,C SHLD SEKTRK ;TRACK TO EMULATE RET ; ; ; ;TRANSLATE THE SECTOR GIVEN BY B&C REGS. ; ; NO TRANSLATE DONE AT THIS TIME. WE WILL NOT NEED TO TRANSLATE ; RAM DISK SECTOR BECAUSE RAM HAS NO ROTATIONAL LATENCY ; SECTRAN: LDA RAMSEL ;SEE IF SECTRAN FOR US ORA A JZ BSTRAN ;TO BIOS IF NOT LOCAL ; MOV H,B MOV L,C RET ;RETURN FROM SECTRAN ; ; ;SET DISK SECTOR NUMBER ; SETSEC: LDA RAMSEL ;SEE IF SECTOR FOR US ORA A JZ BSETSEC ;TO PROM IF NOT LOCAL ; MOV A,C ;GET SECTOR NUMBER STA SEKSEC ;SECTOR TO EMULATE RET ;RETURN FROM SETSEC ; ; ;SET DISK DMA ADDRESS ; SETDMA: PUSH H MOV H,B ;MOVE B&C TO H&L MOV L,C SHLD DMAADR ;PUT AT DMA ADR ADDRESS POP H JMP BSETDMA ;TELL BIOS DMA ADDRESS ; ; ;READ THE SELECTED CP/M 2.2 128 BYTE SECTOR ; READ: LDA RAMSEL ;SEE IF OPERATION FOR US ORA A JZ BREAD ;GO READ IN BIOS IF NOT FOR US LOCAL ; RDSEC: CALL SWAP ;GO INSTALL DRIVER IF NECESSARY CALL RIOPB ;SET RAM DISK IOPB MVI B,00H ;SET (B) MSB = 0 FOR READ SECTOR CALL IPPROG ;GO READ SECTOR AT RESIDENT LOCATION ; LDA DMAADR+1 ;GET USER DMA ADDRESS ;.. TO CHECK IF IN BANK SWITCH AREA CPI (BANKTOP SHR 8) JNC RDS1 ;USED USER BUFFER DIRECTLY FOR SPEED ; LXI D,IPBUF ;BUFFER IN IO PAGE LHLD DMAADR ;POINT AT USER DMAADR AS USUAL XCHG ;MOVE FROM IOPAGE TO USER BUFFER LXI B,SECSIZ ;SIZE OF CP/M SECTOR LDIR ;BLOCK MOVE THE DATA ; RDS1: XRA A ;DEFAULT NO READ ERROR STA ERFLAG RET ; ; ;WRITE THE SELECTED CP/M 2.2 128 BYTE SECTOR ; WRITE: LDA RAMSEL ;IS THIS WRITE FOR HERE ORA A JZ BWRITE ;TO BIOS IF SO ; WRTSEC: LDA DMAADR+1 ;GET USER DMA ADDRESS ;.. TO CHECK IF IN BANK SWITCH AREA CPI (BANKTOP SHR 8) JNC WSEC1 ;USE USER BUFFER DIRECTLY FOR SPEED ; LXI D,IPBUF ;BUFFER IN IO PAGE LHLD DMAADR ;POINT AT USER DMAADR AS USUAL LXI B,SECSIZ ;SIZE OF CP/M SECTOR LDIR ;BLOCK MOVE THE DATA ; WSEC1: CALL SWAP ;GO INSTALL DRIVER IF NECESSARY CALL RIOPB ;SETUP RAM DISK IOPB MVI B,080H ;SET (B) MSB FOR WRITE DATA XFR CALL IPPROG ;GO WRITE SECTOR AT RESIDENT LOCATION XRA A STA ERFLAG ;RESET ERROR FLAG RET ; ; ;ROUTINE TO INITAILLY INSTALL THE BANK SWITCH MEMORY DRIVER ;SOFTWARE INTO TE CP/M I/O CONFIGURATION PAGE. ; SWAP: LDA RESFLG ;IS DRIVER ALREADY RESIDENT ORA A RNZ ;RETURN FROM SWAP IF ALREADY PRESENT ; IF NOT BIGMEM ;BLOCK MOVE ONLY REQUIRED IF TO PUT ;..DRIVER ABOVE BIOS LXI H,RWXFR ;BLOCK MOVE PROGRAM FROM HERE LXI D,IPPROG ;IN I/O CONFIG PAGE LXI B,ENDRWX-RWXFR ;AMOUNT OF PROGRAM CODE TO MOVE LDIR ;BLOCK MOVE THE PROGRAM ENDIF ; MVI A,0FFH ;MARK DRIVER RESIDENT STA RESFLG RET ; ; ;ROUTINE TO SETUP THE RAM DISK SOFTWARE ADDRESS VALUES ;BASED UPON THE CP/M LOGICAL VALUES. SETS UP THE (A) REGISTER ;TO THE CCS BOARD BANK NUMBER FROM THE CP/M TRACK NUMBER. FIRST ;THREE TRACK NUMBERS ARE ON BANK 0, SECOND THREE ON BANK 1 ETC. ;THE CORRESPONDING BANK NUMBERS ARE LINEAR BIT SELECTS AS 01H FOR ;BANK 0 AND 02H FOR BANK 1. THE SETUP ALSO INCLUDES THE (HL) PAIR ;SET TO THE PROPERLY INDEXED 128 BYTE SECTOR BASE ADDRESS IN ;THE 48K BANK ENABLED. (DE) IS SET TO THE APPROPIATE DATA BUFFER ;POINTER DEPENDING UPON IF THE USER DMA ADDRESS IS IN THE BANK ;SWITCH AREA OR NOT. ; RIOPB: LDA SEKTRK ;GET TRACK NUMBER TO COMPUTE ;BANK NUMBER MOV L,A ;SAVE IN H&L MVI H,00H DAD H ;* 4 FOR FOUR BYTE TABLE ENTRIES DAD H LXI D,PTABL ;INDEX TO DECODING TABLE DAD D ;(HL) IS OFFSET IN TABLE MOV C,M ;GET BANK NUMBER TO (C) INX H INX H MOV E,M ;GET BANK ADDRESS OFFSET TO TRACK INX H MOV D,M ; LDA SEKSEC ;GET THE LOGICAL SECTOR NUMBER ORA A ;CLEAR CARRY RAR ;LSB OF SECTOR TO CARRY MOV H,A ;SAVE UPPER SECTOR ADDRESS IN (H) RAR ;MOVE LSB TO UPPER BIT OF LOWER ANI 080H ;MASK LOWER BITS TO ZERO MOV L,A ;AND PUT INTO (L) DAD D ;(HL) IS THE SECTOR ADDRESS IN BANK ; XCHG LHLD DMAADR ;GET USER DMA ADDRESS XCHG ;..TO (DE) MOV A,D ;CHECK IF IN BANK SWITCH AREA CPI (BANKTOP SHR 8) JNC RIOPB1 ;USE HIS POINTER LXI D,IPBUF ;NO; ..NEED IOPAGE BUFFER RIOPB1: MOV A,C ;GET BANK TO (A) RET ; ; ;TRACK NUMBER TO BANK AND ADDRESS BASE DECODE TABLE ; BANK SET 01H ;START BANK NUMBER PTABL: REPT 8 ;BUILD FOR EIGHT BOARDS ADDR SET 0000H ;TRACK BASE ADDRESS ON BOARD REPT 3 ;BUILD FOR THREE BANKS PER BOARD DW BANK,ADDR ;TWO WORDS PER ENTRY ADDR SET ADDR+04000H ;BUMP UP BY 16K ENDM BANK SET (BANK SHL 1) ;SETUP NEW BANK NUMBER ENDM ; ; ;************************************************************************* ; ; STORAGE AREA FOR VARIABLES BEGINS HERE... ; ; ;RELOCATION POINTER STORAGE AREA ; CCP$ENT: DS 2 ;STORE CCP RE-ENTRY POINTER HERE ;TABLE POINTER HERE ; BIOSLD: DS 2 ;PLACE TO SAVE BIOS RELOAD ADDRESS ; ; ;THE NEXT SEVERAL BYTES, BETWEEN STARTZ AND ;ENDZ, ARE SET TO ZERO AT MODULE INITIALIZATION ; STARTZ EQU $ ;START OF ZEROED AREA ; ; ;MEMORY DISK DATA AREA ; SEKTRK: DS 2 ;SEEK TRACK NUMBER SEKSEC: DS 1 ;SEEK SECTOR NUMBER ; ERFLAG: DS 1 ;ERROR REPORTING ; DMAADR: DS 2 ;DISK DMA TRANSFER ADDRESS ; RAMSEL: DS 1 ;LOCAL DISK SELECTED FLAG ; RESFLG: DS 1 ;SET IF DRIVER CODE IS RESIDENT IN ;..IN I/O PAGE OF Z80 MEMORY ; NTRKS: DS 1 ;STORAGE TO SAVE NUMBER OF TRACKS ; FBBUF: DS MAXTRK ;FIRST WORD OF TRACKS BUFFER ;..FOR DISK SIZING CHECK ; ; ;SCRATCH RAM AREA FOR BDOS USE ; ENDEF ;LET DISKDEF FIXUP BDOS BUFFERS ; ENDZ EQU $ ; ; ;************************************************************************ ; ; ; ;POSITION INDEPENDENT ROUTINE THAT MOVES DATA FROM MEMORY DRIVE ;BANKS TO THE EXECUTION PAGE DATA BUFFER. THIS ROUTINE IS DESIGNED TO ;RUN AT THE SOME ARBITRARY BASE PAGE ADDRESS XX00H. THE DATA IS PASSED ;IN 128 BYTE BLOCKS AS THE UPPER HALF OF THE ARBITRARY PAGE IF THE USER ;DMA ADDRESS WAS IN OR ABOVE THE BANK SWITCH AREA. XX80H BEING THE BASE ;OF THE BUFFER. IF THE DMA ADDRESS WAS HIGHER THAN THE BANKSWITCH TOP ;ADDRESS THEN THE TRANSFER BUFFER IS THE CALLERS DMA ADDRESS DIRECTLY ; ; ENTRY PARAMETERS ARE AS FOLLOWS: ; ; (A) = BANK NUMBER OF THE CCS 2065 ; IN FOUR LSB'S ; (B) = DIRECTION OF TRANSFER ; MSB = 0 READ EXPANSION MEMORY TO (BC) BUFFER ; MSB = 1 WRITE (BC) BUFFER TO EXPANSION RAM ; (DE) = ADDRESS OF TRANSFER DATA BUFFER ; (HL) = ADDRESS WITHIN BANK SWITCH AREA FROM/TO WHERE ; DATA BUFFER IS TO BE MOVED. ; RWXFR: OUT BANKSEL ;SELECT THE APPROPIATE BANK NUMBER MOV A,B ;GET DIRECTION BIT ANI 080H ;TEST TRANSFER DIRECTION JRZ XFR ;SKIP DIRECTION SWITCH XCHG ;SWAP MOVE POINTERS XFR: LXI B,SECSIZ ;MOVE ONE SECTOR OF DATA LDIR ;MOVE THE DATA WITH BLOCK MOVE MVI A,01H ;RESELECT CCS BANK 0 FOR CP/M OUT BANKSEL RET ;BACK TO THE ADD-ON MODULE ; ENDRWX EQU $ ;END MARKER FOR READ/WRITE ROUTINE ; ; ;LOCAL DATA TRANSFER BUFFER IF DRIVER IS ABOVE BANK SWITCH TOP ; IF BIGMEM IPBUF: DS SECSIZ ;DATA BUFFER IF RAM IS BIG ENOUGH ENDIF ; END ; ; ;+++...END OF FILE