1 REM Ins{nd av Bert Holgersson <560> 1987-12-12 19.02.35 (DUMP) ; ZPROG Ramdisc ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ; * * U F D - d o s R A M - D i s c Ver. 2.0 * * ; ; RAM-disc routine for ABC 80 and UFD-Dos. ; ; Bert Holgersson <560> 86-03-03 ; Kvarnv{gen 14 ; 454 00 Brastad ; Tel: 0523/40513 ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; PREREQ ; ------ ; Routines are designed for an ABC80 with 64k RAM, built as ; shown in MIKRODATORN. There should, however, be no problem ; in changing the hardware specific part of the code and to ; implement it on 80's expanded in other ways. Of course ; the machine must have ABC-klubben's UFD-dos. ; ; PROGRAM ; ------- ; Program consists of two parts: One installation part and one ; driver part. Installation part reservs space on stack, puts ; driver in reserved space and links driver to DOS. Driver part ; Checks every DOS acces to disc, and takes action when access ; is made to disc choosen to be RAM-drive ; ; INTERRUPTS ; ---------- ; If you mean to use he routine together with interrupt driven ; communication drivers like SOFTSIO and TERM100, then you must ; be aware that interrupts are disabled during block transfers. ; This can (and must probably, will) cause junk characters to ; to be received/transmitted. However, if you have interrupt ; service routines in place during RAM-disc acces, you dont't ; have to turn interrupts off.( This is no problems for me, as ; I have an external SIO-card ) ; ; USE OF RAM-DISC ; --------------- ; RAM-disc is used the same way as ordinary drives. ; Ex:If you select SF0 as RAMDRIVE, then a BASIC line like: ; 10 PREPARE "SF0:FOO.BAR" AS FILE 1 ; would create the file FOO.BAR in RAM. ; Every time you specify "SF0:" as device, DOS will use ; the "RAM-disc". ; ; FORMATTING ; ---------- ; Like other disc:s, RAM has to be formatted before DOS can ; use it. The formatting is, of course, only the logical ; formatting, that inits bitmap,lockoutsector and lib sectors. ; The BASIC program RAMGEN.BAS can do the formatting for you. ; ; ;CALL(0) ; -------- ; The RAM-disc will stay intact between restarts of BASIC/ ; DOS. You only have to install the driver again. ; ; RESET BUTTON ; ------------ ; It might even survive a push of reset button if you ; make it a *VERY SHORT* push.( This is because there is no ; refresh of memory, as long as reset button is pressed ) ; ; EVEN CASETTERS ; -------------- ; There is no need for discdrives for this function ; Even the "casetters" can use this RAM-drive, if ; they install the UFD-Dos. ; ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ; List of select codes known to UFD-dos ; MF0 EQU 8 ; Clustersize 4 MF1 EQU 9 MF2 EQU 10 MO0 EQU 12 ; Clustersize 1 MO1 EQU 13 MO2 EQU 14 SF0 EQU 16 ; Clustersize 4 SF1 EQU 17 SF2 EQU 18 HD0 EQU 4 ; Clustersize 4 HD1 EQU 5 HD2 EQU 6 HD3 EQU 7 ; RAMDRIVE EQU SF0 ; Selectcode for drive simulated in RAM ; ; RAM border definitions ; RAMSTART EQU 256 ; Start adress of "RAM-disc" RAMEND EQU 32767 ; End adress of "RAM-disc" ; ; RAM-disc definitions ; FIRSTSEC EQU 14 ; First adressable sector MINSECT EQU FIRSTSEC-1 ; Value to test with RAMSPAN EQU RAMEND-RAMSTART ; Available RAM space SECTSPAN EQU RAMSPAN/256 ; Number of sectors available MAXSECT EQU SECTSPAN+FIRSTSEC ; Max adressable sector BLOCKSIZ EQU 256  ; RAM sector size ; ; Misc. symbols ; JP EQU 195 ; Instruction "JP" STACK EQU 65063 ; ; DOS-symbols ; DOSBUF0 EQU 62720 ; Adress to DOSBUF0 DRIVBYTE EQU 64769 ; Adress of drive-select byte BCSAVE EQU 64797 ; Place in system DOS-variables DRDWRET EQU 24689 ; Where to find a pointer to link in ram memory DRVMSK EQU 00011111B ; Mask for Drive no i Drive select byte READ EQU 3 ; DOS Read command to controller WRITE EQU 12 ; DOS Wrie command to controller NOT_RDY EQU 10000000B ; Disc error: "Not ready" WRITPROT EQU 01000000B ; "Write protect" NOTFOUND EQU 00010000B ; "Not found" CRC_ERR EQU 00001000B ; "CRC error" COMM_ERR EQU 00000010B ; "Command error" BUSY EQU 00000001B ; "Busy" ; SIM_ERR EQU NOT_RDY ; Simulated disc error if outside sector bounds ; ; External routines definitions ; DR_DWEND EQU 25012 ; Terminating code in DR/DW routine GETBUF EQU 25098 ; Gets adress to DOSBUF B*10H ; ;= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ; ; * * * I N I T I A L I Z A T I O N R O U T I N E ; ORG DOSBUF0 ; Init routine in DOSBUF0. ( Only needed once ! ) INIT JP RAMINIT OSYSTACK DEFW 0 ; Old system stackpointer NSYSTACK DEFW 0 ; New system stackpointer OLDSTACK DEFW 0 ; Old stackpointer NEWSTACK DEFW 0 ; New stackpointer DEPTH DEFW 0 ; Stack depth when routine started ; RAMINIT LD (BCSAVE),BC ; Save BC for BASIC ; ; Calculate new system stackpointer ; LD HL,(STACK) ; Read current stack LD (OSYSTACK),HL ; Save that stack LD DE,DRIVLEN ; Length of RAM-dsic driver AND A ; Clear carry SBC HL,DE ; Resrv space on stack LD (NSYSTACK),HL ; Save that stack LD (STACK),HL ; Set new system stackpointer ; ; Calculate stackdepth and new stackpointer ; LD (OLDSTACK),SP ; Get current stackpointer LD DE,(OLDSTACK) ; into DE LD HL,(OSYSTACK) ; Get old system stackpointer SBC HL,DE ; Old system stack - Old stack = Stackdepth LD (DEPTH),HL ; Save stackdepth LD DE,(NSYSTACK) ; EX DE,HL ; HL:= New system stackpointer, DE:= Stack depth SBC HL,DE ; Make room for stack data LD (NEWSTACK),HL ; Save new stackpointer ; ; Change stackpointer in CPU ; DI ; No interrupts during stack fixing HALT ; Between NMI:s LD SP,HL ; Set new stack ; ; Move stack data to new position ; LD HL,(OLDSTACK) ; Source LD DE,(NEWSTACK) ; Destination LD BC,(DEPTH) ; Number of bytes to move LDIR ; Move stack data to new position EI ; Interrupts are possible to handle again ; ; Put driver in space reserved on top of stack ; PUSH DE ; Save driver start adress LD HL,RAMFLOP ; Start of RAM-driver code ( Source ) LD BC,DRIVLEN ; BC = Number of bytes LDIR ; Put driver where it should be ; ; Link driver into DOS ; LD HL,(DRDWRET) ; Get adress to link LD A,JP ; Instruction "JP" POP DE ; Get adress to our driver INC DE ; Skip save of max sector for RAMGEN LD (HL),A ; Make DOS jump to our routine INC HL LD (HL),E INC HL LD (HL),D LD BC,(BCSAVE) ; Restore BC reg. ; ; Move the first 256 bytes, so that NMI can be running in both bank's ; PUSH BC ; Save register for BASIC DI ; No interrupts during BASIC move HALT ; Can't stop NMI, so i'll do it between them LD HL,0 ; Start adress LD B,0 ; Number of bytes ; LOOP XOR A ; Memory map 0 OUT (7),A LD D,(HL) LD A,3 ; Memory map 3 (All RAM) OUT (7),A LD (HL),D INC HL DJNZ LOOP ; Move 256 bytes ; XOR A ; Set memory map 0 before returning OUT (7),A EI POP BC LD HL,(NEWSTACK) ; Tell operator what new stack will be RET ; Return to whatever called us ; ;= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ; ; * * * R A M D I S C R O U T I N E * * * ; (This is the part that will stay in RAM, on top of stack) ; RAMFLOP DEFB MAXSECT ; RAMGEN can get max sector here. Adress via DOS LD A,(DRIVBYTE) ; Get select code AND DRVMSK ; Mask drive number  CP RAMDRIVE ; Is it RAM drive ? RET NZ ; This call was not for me ; ; Check that sector are within limit ; ; !!NB. Uses only 8 bit arithmetic. If you build a system with ; more than 255 sectors, you must change the calculating routine ; POP AF ; Skip return from link call PUSH DE ; Save registers ( BC already saved ) PUSH HL LD A,D ; Get high part of sector number AND A ; There should be no high part in this system ! JR NZ,ERR LD A,MAXSECT SUB E ; Max - Actual sector, must not give carry ! JR C,ERR ; Jump if sector is to high ; LD A,MINSECT SUB E ; Min sector - Actual sector, must giv carry JR NC,ERR ; ; Calculate SOURCE for LDIR ; LD A,E ; A:=Sectornumber SUB FIRSTSEC ; Logical sector -> Physical sector (i.e. 14->0) LD DE,RAMSTART ; Beginning of RAM-disc ADD A,D ; Offset to wanted sector LD D,A ; DE -> wanted RAM sector ; XOR A ; A = 0 LD L,A ; Low adress part = 0 CALL GETBUF ; Get high adress part to Dosbuf ; LD A,C ; Get wanted operation CP WRITE ; Read or write operation ? JR Z,MOVE ; Source,Dest OK if write EX DE,HL ; If read operation, it's the other way around MOVE LD BC,BLOCKSIZ ; Number of bytes to transfer DI ; No interruptroutines in place while RAM:ing !! LD A,3 ; 64k All RAM ( Map 3 ) OUT (7),A ; LDIR ; Move ; XOR A ; Standard memory map ( 0 ) AND OK indicator OUT (7),A ; Switch back EI ; Now, interrupts are legal again JR OK ; Do an OK exit ; ERR LD A,SIM_ERR ; Simulated error to DOS SCF ; Error indicator OK JP DR_DWEND ; Ret done by DR/DW routine.( Terminating part ) ; ( Necessary POP:s are done by that routine ! ) DRIVLEN EQU $-RAMFLOP ; How much to reserve on stack END INIT D A,SIM_ERR ; Simulated error to DOS SCF ; Error indicator OK JP DR_DWEND ; Ret done by DR/DW routine.( Terminating part ) ; ( Necessary POP:s are done by that routine ! ) DRIVLEN EQU $-RAMFLOP ; How much to reserve on stack END INIA,SIM_ERR ; Simulated error to DOS SCF ; Error indicator OK JP DR_DWEND ; Ret done by DR/DW routine.( Terminating part ) ; ( Necessary POP:s are done by that routine ! ) DRIVLEN EQU $-RAMFLOP ; How much to reserve on stack END INI0RAMDISC.ASM Bert Holgersson <560> 1987-12-12 19.15.23 (DUMP)я яWEND ; Ret done by DR/DW routine.( Terminating part ) ; ( Necessary POP:s are done by that routine ! ) DRIVLEN EQU $-RAMFLOP ; How much to reserve on stack END INIеееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееее