;15 MAY 85 RHP TITLE 'MEMORY DISK ADDON MODULE VERSION 2.0 OF 2/9/83' ; ;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 MBDTRKS 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 "MIPPROG" 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 MBDOS EQU 0005H ;FIXED BDOS ADDRESS MDEFFCB EQU 005CH ;DEFAULT FCB LOCATION MDEFBUF EQU 0080H ;DEFAULT SYSTEM BUFFER MRESET EQU 13 ;RESET DISK SYSTEM MOPEN EQU 15 ;OPEN FILE MSTDMA EQU 26 ;SET DMA ADDRESS ; ; ;CCS 2065 RAM BOARD ACCESS ADDRESS EQUATES ; MBANKSEL EQU 040H ;CCS FACTORY DEFAULT BANK SELECT PORT ; IF NOT BIGMEM MIPPROG EQU 0F500H ;LOCATION TO BLOCK MOVE PROGRAM TO FOR ;..RESIDENT MEMORY I/O PROGRAM ABOVE BIOS MIPBUF EQU MIPPROG+080H ;RESIDENT MEMORY PAGE DISK BUFFER ENDIF IF BIGMEM MIPPROG EQU MRWXFR ;IF PLENTY OF MEMORY LET THE DRIVER ;..RESIDE AT TOP OF ADDON MODULE ENDIF ; MBANKTOP 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 ; MSECSIZ 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 MCHKPRES ;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. ; ML5ENT: JMP MBDOS$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. ; MTO$BDOS: JMP $-$ ;ENTER ADDRESS AT STARTUP ; ; ;START UP CHECK ROUTINE TO SEE IF THIS SOFTWARE WAS ALREADY ;LOADED BY A PREVIOUS OPERATOR COMMAND. ; MCHKPRES: MVI C,MOPEN ;ATTEMPT TO OPEN FILE "A,,,,,,,.,,," LXI D,MCHKFCB ;POINT AT THE CHECK FCB CALL MBDOS ;CALL NORMAL BDOS ADDRESS ORA A JNZ MNOT$PRES ;NON ZERO RETURN MODULE IS NOT ;..PRESENT LXI D,MPRESMSG ;POINT TO PRESENT MESSAGE MVI C,9 ;PRINT FUNCTION CODE CALL MBDOS ;PRINT ALREADY PRESENT MESSAGE RET ;SIMPLE RETURN TO THE CCP ; MCHKFCB: DB 0,MODADDR,',,,,,,,,,,',0,0,0,0 DS 16 DB 0 ; MPRESMSG: DB CR,LF,'MICRO RESOURCES Memory Disk' DB CR,LF,'Access Already Active','$' ; Š; ;HERE IF THIS RELOCATED MODULE IS NOT PRESENT IN MEMORY ; MNOT$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 MCCP$ENT ;SAVE THAT ENTRY ADDRESS ; LHLD MBDOS+1 ;GET PREVIOUS BDOS ADDRESS SHLD MTO$BDOS+1 ;SET TO LOCAL REFERENCE VECTOR ; LXI H,ML5ENT ;SET NEW BDOS ENTRY TO THIS MODULE SHLD MBDOS+1 ;BASE+6 ; CALL MOVDN ;MOVE DOWN THE BIOS VECTOR TABLE LHLD WBOOT+1 SHLD MBIOSLD ;SAVE AS BIOS LOAD ADDRESS ; LXI H,MBOOTENT ;SET MOVED DOWN TABLE TO LOCAL BOOT HANDLER SHLD WBOOT+1 ; CALL MESSAGE ;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,MENDZ-STARTZ ;ZERO DATA AREA IN PARAMETER TABLE LXI H,STARTZ MZLP: 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 MZLP ; ; ;HAVE THIS UTILITY QUEUE BOTH BIOS AND THIS DRIVER TO THE SAME ;CP/M DATA BUFFER ADDRESS ; LXI D,MDEFBUF ;USE DEFAULT BUFFER MVI C,MSTDMA ;SET DMA FUNCTION CODE CALL MTO$BDOS Š; LXI H,MRAMSEL ;DISABLE DRIVE SELECT FOR RAM DISK MVI M,00H XRA A ;SET RESIDENT DRIVER FLAG OFF STA MRESFLG ; ; ;FIND OUT THE SIZE OF THE AVAILABLE MEMORY BOARDS FOR THE ;MEMORY RESIDENT DRIVE ; MSIZEDRV: IF HARDSIZ MVI B,MBDTRKS ;FORCE TRACKS COUNT JMP MSIZEGOT ENDIF ; CALL MESSAGE DB CR,LF,'Memory sizing ',0 MVI A,00H STA MSEKSEC ;TEST SECTOR ZERO EACH 'TRACK' STA MSEKTRK+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 MGFBYT: PUSH B ;SAVE TRACK NUMBER MOV A,B STA MSEKTRK CALL MRDSEC ;GET FIRST SECTOR OF TRACK POP B LDA MDEFBUF ;GET THE FIRST BYTE LXI H,MFBBUF ;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 MDEFBUF PUSH B CALL MWRTSEC ;WRITE MODIFIED PATTERN BACK OUT POP B INR B ;INCREMENT TRACK COUNTER MOV A,B ;CHECK IF PAST MAX BANK CPI MAXTRK JNZ MGFBYT ;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 ; MBYTRST: Š MVI B,0 ;START TRACK NUMBER MPFBYT: PUSH B ;SAVE TRACK/SEC CALL MESSAGE DB '.',0 POP B MOV A,B ;SET TRACK NUMBER STA MSEKTRK PUSH B ;SAVE TRK/MAX TRK CALL MRDSEC ;GET SECTOR FOR RESTORE POP B LDA MDEFBUF ;CHECK BYTE READ BACK CMP B ;DO THEY MATCH? JNZ MSIZEGOT PUSH B LXI H,MFBBUF ;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 MDEFBUF ;RESTORE FIRST BYTE CALL MWRTSEC ;WRITE SECTOR BACK POP B INR B ;INCREMENT TRACK COUNTER MOV A,B CPI MAXTRK ;CHECK IF PAST MAX TRACK JNZ MPFBYT ;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. ; MSIZEGOT: MOV A,B CPI DIRTRK+1 ;CHECK IF NO OTHER BANKS AVAILABLE JNC MSG1 ;CONTINUE IF OK ; CALL MESSAGE DB CR,LF,'No Memory Available for RAM Disk',0 LHLD MBIOSLD ;TO BIOS WARM BOOT ADDRESS FOR RESTART PCHL ;OFF TO BIOS FOR RELOAD ; MSG1: STA MNTRKS ;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,MRSIZE ;POINT TO RAM SIZE STRING AREA CALL MBINASC ;CONVERT RAM SIZE TO DEC ASCII LXI H,MRSIZE ;FIXUP TO PRINT LEADING ZEROS MVI B,4 ;NUMBER OF ZERO STRIP LOCS TO CHECK MSSTRP: MOV A,M ;GET A CHARACTER CPI '0' JNZ MSTDONE ;NON ZERO SO EXIT MVI M,' ' ;SUBSTITUTE A SPACE INX H DCR B JNZ MSSTRP ;CONTINUE CHARACTER STRIP ? ; MSTDONE: CALL MESSAGE ;PRINT RAM SIZE MESSAGE DB CR,LF,'RAM Available for ' MRSIZE: 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 ; MFORMAT: CALL MESSAGE ;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 CONOUT CALL MESSAGE DB CR,LF,0 POP PSW ;GET INPUT CHAR ANI 05FH ;CONVERT TO UPPER CASE CPI 'Y' JNZ MCCPGO ;SKIP FORMAT IN NOT 'Y' Š; LXI H,MDEFBUF ;MAKE PATTERN FOR FORMAT LXI B,MSECSIZ ME5LP: 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 ME5LP ;MUST BE MORE TO DO ; CALL MESSAGE DB CR,LF,'Formatting ',0 ; LDA MNTRKS ;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 MFMTLP: PUSH H PUSH B MOV A,B STA MSEKTRK MOV A,C STA MSEKSEC CALL MWRTSEC ;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 MFMTLP ;GO ON TRACK TILL LAST SECTOR ; MVI C,00H ;RESET SECTOR TO TRACK START INR B ;BUMP TRACK NUMBER ; MFMTCK: PUSH H ;SAVE TRACK COUNT PUSH B ;SAVE TRACK/SEC CALL MESSAGE DB '.',0 ;PRINT ACTIVITY PERIOD POP B POP H DCR L ;DEBUMP TRACK COUNTER JNZ MFMTLP ;GO START NEXT TRACK ; CALL MESSAGE DB CR,LF,0 ; ; ;RETURN TO CCP VIA THE OLD DEFINED REENTRY POINT ; MCCPGO: LXI H,ML5ENT ;RESET NEW BDOS ENTRY TO THIS MODULE Š SHLD MBDOS+1 ;BASE+6 LHLD MCCP$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 ; MBOOTENT: JMP MCCPGO ;NOW GO BACK TO THE CCP ; ; ;HERE FROM A BDOS ENTRY TO TRAP FILE OPEN I/O TO CHECK FOR ;MODULE PRESENT CHECK. ; MBDOS$SCAN: PUSH D ;SAVE CALLERS PARAMETERS PUSH B MOV A,C ;GET FUNCTION CODE TO A CPI MOPEN ;SEE IF THIS IS AN OPEN FUNCTION JNZ MCHKFAIL 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 MSCAN$LOOP: MOV A,M ;GET FILE NAME CHARACTER CPI ',' JNZ MCHKFAIL ;PASS ON IF CHECK FAIL DCX H ;DECREASE BUFFER POINTER DCR B JNZ MSCAN$LOOP ;CHECKED ALL POSSIBLE CHARS YET MOV A,M ;CHECK IF ADDRESS BYTE IS OURS CPI MODADDR JNZ MCHKFAIL ;BALE OUT IF NOT XRA A ;RETURN ZERO BYTE IF ALL CHECK VALID POP B POP D RET ;BACK TO PRESENT CHECKER ; MCHKFAIL: ;PROPER OPEN CHECK FAIL POP B POP D JMP MTO$BDOS ;OFF TO THE NORMAL BDOS ROUTINE ; ; MXFRTAB: ; ; 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 MBOOTENT ;TO LOCAL WARM BOOT HANDLER JMP BCSTAT ;TO NORMAL BIOS CONSOLE STATUS CHECK JMP BCIN ;TO NORMAL BIOS CONSOLE INPUT JMP CONOUT ;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 MHOME ;MOVE DISK TO TRACK ZERO JMP MSELDSK ;SELECT DISK DRIVE JMP MSETTRK ;SEEK TO TRACK IN REG A JMP MSETSEC ;SET SECTOR NUMBER JMP MSETDMA ;SET DISK STARTING ADR JMP MREAD ;READ SELECTED SECTOR JMP MWRITE ;WRITE SELECTED SECTOR JMP BLSTST ;GO RIGHT TO NORMAL BIOS FOR THIS I/O JMP MSECTRAN ;SECTOR TRANSLATE ; ; MLOCTAB: ; ; LOCAL COPY OF THE ORIGINAL BIOS DISK I/O VECTOR TABLE ; INITIALIZED BY CALLING THE "MOVDN" SUBROUTINE. ; BCBOOT: JMP $-$ ;TO BIOS COLD BOOT ROUTINE WBOOT: JMP $-$ ;TO BIOS WARM BOOT ROUTINE BCSTAT: JMP $-$ ;TO BIOS CONSOLE STATUS CHECK BCIN: JMP $-$ ;TO BIOS CONSOLE INPUT CONOUT: JMP $-$ ;TO BIOS CONSOLE OUTPUT BLOUT: JMP $-$ ;TO BIOS LPT OUTPUT BPUN: JMP $-$ ;TO BIOS PUNCH OUTPUT BRDR: JMP $-$ ;TO BIOS READER INPUT HOME: JMP $-$ ;TO BIOS HOME DISK ROUTINE SETDRV: JMP $-$ ;TO BIOS SELECT DISK ROUTINE SETTRK: JMP $-$ ;TO BIOS SET TRACK ROUTINE SETSEC: JMP $-$ ;TO BIOS SET SECTOR ROUTINE SETDMA: JMP $-$ ;TO BIOS SET DMA ADDRESS ROUTINE READ: JMP $-$ ;TO BIOS SECTOR READ ROUTINE WRITE: JMP $-$ ;TO BIOS SECTOR WRITE ROUTINE BLSTST: Š JMP $-$ ;TO BIOS LIST STATUS ROUTINE SECTRAN: 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 MBOOT+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 MBYTCNT LXI D,MLOCTAB ;POINT TO LOCAL TABLE FILL FROM ABOVE LXI B,MXFRTAB ;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 MBYTCNT ;SEE IF DONE YET DCR A STA MBYTCNT JNZ MDLP ;CONTINUE IF NOT DONE YET RET ; MBYTCNT: DB 0 ;LOCAL MOVE BYTE COUNTER ; ; ;INLINE PRINT OF MESSAGE TILL A ZERO ; MESSAGE: XTHL ;SAVE HL, GET MSG POINTER ; MPRTMLP: 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 MPMXIT ;EXIT IF ZERO ; PUSH H ;SAVE MSG PTR. CALL CONOUT ;OUTPUT IT POP H ;RESTORE MSG PTR. JMP MPRTMLP ;GO CHECK/DO NEXT CHAR Š; MPMXIT: 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 ; MBINASC: 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 MDIGCNT MNDIG: LXI B,-10 ;RADIX FOR CONVERSION LXI D,-1 ;THIS BECOMES NO DIVIDED BY RADIX MDX: DAD B ;SUBTRACT 10 INX D JC MDX 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 MDIGCNT ;CHECK IF CONVERSION DONE DCR A JZ MDDIG ;EXIT IF DONE STA MDIGCNT PUSH D ;SAVE ASCII POINTER JMP MNDIG ;GO DO NEXT DIGIT MDDIG: POP D ;RESTORE REGISTERS POP B POP PSW RET ; ; ;BINASC ROUTINE STORAGE ALLOCATIONS ; MDIGCNT 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). ; MSELDSK: MOV A,C ;GET NEW UNIT NUMBER CPI 'M'-041H ;IS THIS OUR DRIVE? JZ MSDSK1 ;IF SO THEN GIVE THEM A PARAMETER POINTER ; XRA A ;IF NOT CLEAR THE RAM DRIVE SELECT FLAG STA MRAMSEL JMP SETDRV ;IF NOT FOR US THEN LET BIOS HAVE SELECT ; ; ;HERE IF DRIVE SELECT WAS FOR THIS PIECE OF SOFTWARE ; MSDSK1: MVI A,0FFH ;SET THE RAM DRIVE SELECT FLAG STA MRAMSEL ; LXI H,DPBASE ;PASS BACK DISK PARAMETER BASE XRA A ;SET A REG. = 00 RET ;RETURN FROM SELDSK ; ; MHOME: LDA MRAMSEL ;SEE IF RESTORE FOR US ORA A JZ HOME ;NO MUST BE FOR BIOS DRIVE ; LXI H,00H SHLD MSEKTRK ;ZERO SEK TRK ON HOME RET ; ; ;SET TRACK NUMBER SPECIFIED BY B&C REGS. ; MSETTRK: LDA MRAMSEL ;SEE IF TRACK FOR US ORA A JZ SETTRK ;TO PROM IF NOT LOCAL ; Š MOV H,B MOV L,C SHLD MSEKTRK ;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 ; MSECTRAN: LDA MRAMSEL ;SEE IF SECTRAN FOR US ORA A JZ SECTRAN ;TO BIOS IF NOT LOCAL ; MOV H,B MOV L,C RET ;RETURN FROM SECTRAN ; ; ;SET DISK SECTOR NUMBER ; MSETSEC: LDA MRAMSEL ;SEE IF SECTOR FOR US ORA A JZ SETSEC ;TO PROM IF NOT LOCAL ; MOV A,C ;GET SECTOR NUMBER STA MSEKSEC ;SECTOR TO EMULATE RET ;RETURN FROM SETSEC ; ; ;SET DISK DMA ADDRESS ; MSETDMA: PUSH H MOV H,B ;MOVE B&C TO H&L MOV L,C SHLD MDMAADR ;PUT AT DMA ADR ADDRESS POP H JMP SETDMA ;TELL BIOS DMA ADDRESS ; ; ;READ THE SELECTED CP/M 2.2 128 BYTE SECTOR ; MREAD: LDA MRAMSEL ;SEE IF OPERATION FOR US ORA A JZ READ ;GO READ IN BIOS IF NOT FOR US LOCAL ; MRDSEC: CALL MSWAP ;GO INSTALL DRIVER IF NECESSARY CALL MRIOPB ;SET RAM DISK IOPB Š MVI B,00H ;SET (B) MSB = 0 FOR READ SECTOR CALL MIPPROG ;GO READ SECTOR AT RESIDENT LOCATION ; LDA MDMAADR+1 ;GET USER DMA ADDRESS ;.. TO CHECK IF IN BANK SWITCH AREA CPI (MBANKTOP SHR 8) JNC MRDS1 ;USED USER BUFFER DIRECTLY FOR SPEED ; LXI D,MIPBUF ;BUFFER IN IO PAGE LHLD MDMAADR ;POINT AT USER DMAADR AS USUAL XCHG ;MOVE FROM IOPAGE TO USER BUFFER LXI B,MSECSIZ ;SIZE OF CP/M SECTOR LDIR ;BLOCK MOVE THE DATA ; MRDS1: XRA A ;DEFAULT NO READ ERROR STA MERFLAG RET ; ; ;WRITE THE SELECTED CP/M 2.2 128 BYTE SECTOR ; MWRITE: LDA MRAMSEL ;IS THIS WRITE FOR HERE ORA A JZ WRITE ;TO BIOS IF SO ; MWRTSEC: LDA MDMAADR+1 ;GET USER DMA ADDRESS ;.. TO CHECK IF IN BANK SWITCH AREA CPI (MBANKTOP SHR 8) JNC MWSEC1 ;USE USER BUFFER DIRECTLY FOR SPEED ; LXI D,MIPBUF ;BUFFER IN IO PAGE LHLD MDMAADR ;POINT AT USER DMAADR AS USUAL LXI B,MSECSIZ ;SIZE OF CP/M SECTOR LDIR ;BLOCK MOVE THE DATA ; MWSEC1: CALL MSWAP ;GO INSTALL DRIVER IF NECESSARY CALL MRIOPB ;SETUP RAM DISK IOPB MVI B,080H ;SET (B) MSB FOR WRITE DATA XFR CALL MIPPROG ;GO WRITE SECTOR AT RESIDENT LOCATION XRA A STA MERFLAG ;RESET ERROR FLAG RET ; ; ;ROUTINE TO INITIALLY INSTALL THE BANK SWITCH MEMORY DRIVER ;SOFTWARE INTO THE CP/M I/O CONFIGURATION PAGE. ; MSWAP: LDA MRESFLG ;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,MRWXFR ;BLOCK MOVE PROGRAM FROM HERE LXI D,MIPPROG ;IN I/O CONFIG PAGE LXI B,MENDRWX-MRWXFR ;AMOUNT OF PROGRAM CODE TO MOVE LDIR ;BLOCK MOVE THE PROGRAM ENDIF ; MVI A,0FFH ;MARK DRIVER RESIDENT STA MRESFLG 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. ; MRIOPB: LDA MSEKTRK ;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,MPTABLE ;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 MSEKSEC ;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 MDMAADR ;GET USER DMA ADDRESS XCHG ;..TO (DE) MOV A,D ;CHECK IF IN BANK SWITCH AREA CPI (MBANKTOP SHR 8) Š JNC MRIOPB1 ;USE HIS POINTER LXI D,MIPBUF ;NO; ..NEED IOPAGE BUFFER MRIOPB1: MOV A,C ;GET BANK TO (A) RET ; ; ;TRACK NUMBER TO BANK AND ADDRESS BASE DECODE TABLE ; MBANK SET 01H ;START BANK NUMBER MPTABLE: REPT 8 ;BUILD FOR EIGHT BOARDS MADDR SET 0000H ;TRACK BASE ADDRESS ON BOARD REPT 3 ;BUILD FOR THREE BANKS PER BOARD DW MBANK,ADDR ;TWO WORDS PER ENTRY MADDR SET ADDR+04000H ;BUMP UP BY 16K ENDM MBANK SET (MBANK SHL 1) ;SETUP NEW BANK NUMBER ENDM ; ; ;************************************************************************* ; ; STORAGE AREA FOR VARIABLES BEGINS HERE... ; ; ;RELOCATION POINTER STORAGE AREA ; MCCP$ENT: DS 2 ;STORE CCP RE-ENTRY POINTER HERE ;TABLE POINTER HERE ; MBIOSLD: DS 2 ;PLACE TO SAVE BIOS RELOAD ADDRESS ; ; ;THE NEXT SEVERAL BYTES, BETWEEN STARTZ AND ;MENDZ, ARE SET TO ZERO AT MODULE INITIALIZATION ; STARTZ EQU $ ;START OF ZEROED AREA ; ; ;MEMORY DISK DATA AREA ; MSEKTRK: DS 2 ;SEEK TRACK NUMBER MSEKSEC: DS 1 ;SEEK SECTOR NUMBER ; MERFLAG: DS 1 ;ERROR REPORTING ; MDMAADR: DS 2 ;DISK DMA TRANSFER ADDRESS ; ŠMRAMSEL: DS 1 ;LOCAL DISK SELECTED FLAG ; MRESFLG: DS 1 ;SET IF DRIVER CODE IS RESIDENT IN ;..IN I/O PAGE OF Z80 MEMORY ; MNTRKS: DS 1 ;STORAGE TO SAVE NUMBER OF TRACKS ; MFBBUF: DS MAXTRK ;FIRST WORD OF TRACKS BUFFER ;..FOR DISK SIZING CHECK ; ; ;SCRATCH RAM AREA FOR BDOS USE ; ENDEF ;LET DISKDEF FIXUP BDOS BUFFERS ; MENDZ 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. ; MRWXFR: OUT MBANKSEL ;SELECT THE APPROPIATE BANK NUMBER MOV A,B ;GET DIRECTION BIT ANI 080H ;TEST TRANSFER DIRECTION JRZ MXFR ;SKIP DIRECTION SWITCH XCHG ;SWAP MOVE POINTERS MXFR: LXI B,MSECSIZ ;MOVE ONE SECTOR OF DATA LDIR ;MOVE THE DATA WITH BLOCK MOVE MVI A,01H ;RESELECT CCS BANK 0 FOR CP/M Š OUT MBANKSEL RET ;BACK TO THE ADD-ON MODULE ; MENDRWX EQU $ ;END MARKER FOR READ/WRITE ROUTINE ; ; ;LOCAL DATA TRANSFER BUFFER IF DRIVER IS ABOVE BANK SWITCH TOP ; IF BIGMEM MIPBUF: DS MSECSIZ ;DATA BUFFER IF RAM IS BIG ENOUGH ENDIF ; END ; ; ;+++...END OF FILE