home *** CD-ROM | disk | FTP | other *** search
- TITLE RAMDRIV5.MAC
- ;
- ;***********************************************************************
- ;
- ; RAMDRIV - A program that permits extended memory to function as
- ; a fast disk drive. This program does not require modification
- ; of the existing BIOS.
- ;
- ; Copyright 1982, by
- ; Herbert B. Shore
- ; Department of Physics
- ; San Diego State University
- ; San Diego, CA 92182
- ; (619) 265-6159
- ;
- ; Released to the public domain for non-commercial use.
- ;
- ; RAMDRIV has been extensively modified by Paul J. Gans. Changes
- ; are copyright (c) by Paul J. Gans, Department of Chemistry, New
- ; York University, New York, NY 10003 (212) 598-2515
- ;
- ; New or modified features include:
- ;
- ; For RAMDRIV5:
- ;
- ; 1. Code has been converted to Z80 code throughout.
- ; 2. The target assembler is now Microsoft's M80.
- ; 3. The code is now self-loading. The original RAMLD program is
- ; no longer required.
- ; 4. It is no longer required to have contiguous memory banks of
- ; the same size. Available memory is controlled by the
- ; BLEN table described below.
- ; 5. Track size is now a variable multiple of 1K and can be
- ; changed through an equate.
- ; 6. The original ALV parameter has been dropped in favor of
- ; TRAKLEN, the number of kilobytes per track.
- ; 7. The DRAM parameter has been dropped. Extended (bank)
- ; addresses are now contained in the BLEN table.
- ; 8. The program now uses both the directory buffer and the host
- ; buffer in the local BIOS instead of its own buffer.
- ; This requires that the user know the addresses of both
- ; of these buffers in his or her BIOS. To accomodate
- ; those who choose not to use the BIOS buffers, two DS
- ; definitions are required a few lines after the label
- ; WBOOT1. The proper spot is commented in the code
- ; below.
- ;
- ;
- ; INSTALLATION of RAMDRIV5:
- ;
- ; RAMDRIV assumes that the user's system has "extra" memory
- ; available beyond the normal 64K maximum directly addressable
- ; in Z80 systems. This memory may be either "bank select" or
- ; S-100 extended addressing.
- ;
- ; RAMDRIV is installed by setting a number of equates and by
- ; properly configuring the BLEN table located near the end of
- ; the code. After the proper values have been set by equates and
- ; the BLEN table has been set up, the code should be assembled
- ; using M80. The commands for so doing are:
- ;
- ; >M80 =RAMDRIV5/L <== /L optionally produces a .PRN file
- ; >L80 /P:100,RAMDRIV5,RAMDRIV5/N/E
- ;
- ; The equates for DIRBUF and RAMBUF must be set to reflect the
- ; location of these buffers in the user's BIOS. If this is not
- ; feasible, see the comments at the label WBOOT1.
- ;
- ; Equates that must be set are defined and explained below.
- ;
- ; In normal use the user must also configure the BLEN table for
- ; his or her system and recompile. There is one BLEN table entry
- ; for each bank of memory to be used by RAMDRIV. It is assumed
- ; that each of these banks starts at address 0000 and proceeds
- ; upward to some value without any holes. It is also assumed that
- ; at least the upper 1K of system memory is global, thus no bank
- ; can exceed 63K.
- ;
- ; A BLEN table entry consists of two bytes for each bank of memory
- ; to be used by RAMDRIV. The first byte is the number of kilo-
- ; bytes available for RAMDRIV in that bank. This value is placed
- ; into the BLEN table as the value divided by TRAKLEN. The actual
- ; number of kilobytes of that bank used by RAMDRIV is the integral
- ; part of the division. For instance a 30K bank of memory would
- ; be indicated to the system as 30/TRAKLEN.
- ;
- ; The second byte in the BLEN table entry is the extended (or
- ; bank) address byte for that bank of memory. There is one such
- ; entry pair for each bank. The table is terminated by a single
- ; zero byte.
- ;
- ; Thus a system with 20K at a bank addressed as 0DEH and 8K at a
- ; bank addressed as 70H could have a BLEN table as:
- ;
- ; BLEN: DB 20/TRAKLN,0DEH
- ; DB 08/TRAKLN,70H
- ; DB 0
- ;
- ; while the same system in which the user wanted to reserve 4K on
- ; the board at 0DEH for some other purpose could have a BLEN table
- ; as:
- ;
- ; BLEN: DB 16/TRAKLN,0DEH
- ; DB 08/TRAKLN,70H
- ; DB 0
- ;
- ;
- ;************************************************************************
- ;
- ; The code and tables in this file will reside in high memory, above the
- ; existing BIOS. The system is self-loading. Typing RAMDRIV3 from the
- ; console is sufficient to initiate RAMDRIV3.
- ;
- .Z80
- ;
- FALSE EQU 0
- TRUE EQU NOT FALSE
- ;
- ; The following equates are system dependent.
- ;
- ; DIRBUF: This is the address of the CP/M directory buffer in the
- ; user's BIOS. CP/M 2.x systems are required to have such a buffer
- ; available. The address will vary in different implementations.
- ;
- ; RAMBUF: This is the address of the CP/M host buffer in the user's
- ; BIOS. In a normal CP/M 2.x system this buffer will be at least 1K
- ; long. The address will vary in different implementations.
- ;
- ; PANEL: If you have an (IMSAI-type) front panel, set PANEL=TRUE. The
- ; lights will display the extended address, simulating the LED on the
- ; door of the disk drive. Flipping switch D0 up will "write protect"
- ; the RAM drive.
- ;
- ; RAMDRIV: Set to a memory location above BIOS. Less than 1K of
- ; GLOBAL memory is required at this location; i.e. the same block
- ; of memory must be accessible independent of the setting of the ex-
- ; tended address bus or any bank byte.
- ;
- ; PRAM: The extended address of regular program RAM. Usually this is
- ; 00H, but need not be.
- ;
- ; XPORT: The output port that sets the extended address bus or bank
- ; byte.
- ;
- ; DNAME: The alphabetic designation of the RAM drive.
- ;
- ; LIGHTS: The output port for front panel lights. This is signif-
- ; icant only if PANEL is TRUE.
- ;
- ; SWITCH: The input port for front panel switches. This is signif-
- ; icant only if PANEL is TRUE.
- ;
- ; TRAKLN: The number of kilobytes per track. This must be a minimum
- ; of 1K and a maximum no greater than the smallest bank of memory to
- ; be made available to RAMDRIV. A good value to use is the greatest
- ; common divisor of each of the memory banks to be used by RAMDRIV.
- ;
- ; DIRECT: The number of directory entries permitted on the RAM drive.
- ; The number specified must be a multiple of 32. I used 32 to leave
- ; the maximum space for program files.
- ;
- .Z80
- ;
- DIRBUF EQU 0F77FH ; CP/M BIOS directory buffer address
- RAMBUF EQU 0F7FFH ; CP/M BIOS host buffer
- PANEL EQU FALSE ;IMSAI FRONT PANEL
- RAMDRIV EQU 0FC00H ;START OF PROGRAM.
- PRAM EQU 00H ;EXTENDED ADDR. OF MAIN RAM
- XPORT EQU 0FDH ;PORT TO SET EXT. ADDR.
- DNAME EQU 'C' ;DRIVE NAME OF RAMDRIV.
- IF PANEL
- LIGHTS EQU 0FFH ;FRONT PANEL LIGHTS.
- SWITCH EQU 0FFH ;FRONT PANEL SWITCHES.
- ENDIF
- TRAKLN EQU 4 ; kilobytes per track
- DIRECT EQU 32 ;NO. OF DIRECTORY ENTRIES.
- ;
- ; These equates will normally not need to be changed.
- ;
- BDOS EQU 5
- DELCHR EQU 0E5H ;DELETED DIRECTORY ENTRY.
- DNUMB EQU DNAME - 'A' ;RAMDRIV DRIVE NUMBER
- CR EQU 0DH
- LF EQU 0AH
- ;
- ;
- ; The code below replaces the original loader code, since that
- ; mechanism will not work on a program compiled under M80. The
- ; M80 .PHASE commands have been used rather than the original
- ; ORG's.
- ;
- LD DE,SIGNON ; print signon message from loader
- LD C,9
- CALL BDOS
- ;
- LD HL,(0001) ; check to see if BIOS modified
- INC HL ; point to jump vector
- LD E,(HL)
- INC HL
- LD D,(HL)
- EX DE,HL
- LD DE,RAMDRIV
- AND A ; clear carry
- SBC HL,DE ; WBOOT minus RAMDRIV
- JP C,CONTIN ; if carry we are OK
- LD DE,NOWAY
- LD C,9
- CALL BDOS
- JP 0
- ;
- SIGNON: DB 'RAMDRIV5'
- DB CR,LF,'$'
- NOWAY: DB 'Cannot load RAMDRIV',CR,LF
- DB 'Cold boot system and try again'
- DB CR,LF,'$'
- ;
- CONTIN: LD HL,SETUP
- LD DE,RAMDRIV
- LD BC,1023
- LDIR
- JP RAMDRIV
- ;
- .PHASE RAMDRIV
- ;
- ; ORIGINAL JUMP TABLE FROM BIOS
- ;
- WBOOT1: DS 48
- WCK: ;END OF BIOS TABLE.
- ;
- CSV: DS DIRECT/4 ; this should probably be zero since no
- ; checking is done
- ALV: DS 72 ; this is allocation vector space which
- ; must have 1 bit available per block.
- ; this value corresponds to 576 1K
- ; blocks.
- ;
- ; If the user does not wish to (or cannot) use the directory and host
- ; buffers in the system BIOS, the buffers can alternatively be defined
- ; here. In this case the following lines should be uncommented and the
- ; corresponding equates above commented.
- ;
- ;DIRBUF: DS 128 ; directory buffer
- ;RAMBUF: DS 128 ; bank communication buffer
- ;
- ENDTBL: ;END OF DATA TABLES.
- ;
- .DEPHASE
- ;
- ; The following code is executed once to set up the RAMDRIV system. In
- ; order to conserve space it will be overwritten by data buffers during
- ; actual access to RAMDRIV.
- ;
- ;
- SETUP:
- ;
- .PHASE RAMDRIV
- ;
- ; Determine the amount of available RAMDRIV memory
- ;
- XOR A
- LD C,A
- LD HL,BLEN ; RAMDRIV memory table
- LD DE,0002 ; table entry increment
- BCHEK0: LD A,(HL) ; get bank kilobytesa
- OR A ; zero means end of table
- JR Z,BCHEK1
- ADD A,C ; accumulate count
- LD C,A ; and save it
- ADD HL,DE ; point to next BLEN entry
- JR BCHEK0
- ;
- BCHEK1: CP C ; is there any ram available at all?
- JR NZ,RAMOK ; jump if there is
- LD DE,NORAM ; no ram, tell the user
- LD C,9
- CALL BDOS
- RET ; avoid warm boots!
- ;
- NORAM: DB 'Cannot activate RAMDRIV. No available RAM.'
- DB CR,LF,'$'
- ;
- RAMOK: XOR A ; clear counter
- LD B,TRAKLN ; the count must be multiplied
- ; by TRAKLN to yeild kilobytes
- RAMOK1: ADD A,C ; multiply by repeated adding
- DJNZ RAMOK1
- ;
- DEC A ; RAMDRIV kilobytes minus 1
- LD (DSM),A ; maximum block number to DPB
- ;
- ; MODIFY BIOS JUMP TABLES
- ;
- IF $ LT WCK ;MAKE SURE THAT WBOOT1 TABLE
- JP BJUMP ;WILL NOT OVERWRITE
- ENDIF ;BJUMP ROUTINE.
- IF $ LT WCK
- DEFS WCK - $
- ENDIF
- ;
- BJUMP: LD HL,(1) ;GET ADDRESS OF WARM BOOT
- LD DE,WBOOT1 ;TRANSFER TABLE FROM BIOS UP HERE
- LD BC,48 ;48 BYTES
- LDIR
- LD HL,WBOOT2 ;TRANSFER OUR TABLE TO BIOS
- LD DE,(0001)
- LD BC,48
- LDIR
- ;
- ; PRINT MESSAGE AND ASK QUESTION
- ;
- LD DE,QUEST
- LD C,9 ;PRINT STRING
- CALL BDOS
- LD C,1 ;GET CHARACTER
- CALL BDOS
- RES 5,A ;CONVERT TO UPPER CASE.
- CP 'Y'
- JP NZ,QUIT
- ;
- ; CLEAR DIRECTORY OF RAMDRIV
- ;
- LD BC,0000 ; directory on track 0 sector 0
- CALL MAP
- OUT (XPORT),A
- IF PANEL
- CPL
- OUT (LIGHTS),A ;TO IMSAI FRONT PANEL
- ENDIF
- EX DE,HL ; HL = base location of directory
- LD DE,32 ;EVERY 32 BYTES
- LD B,DIRECT ;NO. OF ENTRIES.
- LD A,DELCHR
- CLEAR: LD (HL),A
- ADD HL,DE
- DJNZ CLEAR
- LD A,PRAM ;RESET EXT. ADDR.
- OUT (XPORT),A
- IF PANEL
- CPL
- OUT (LIGHTS),A
- ENDIF
- ;
- QUIT: LD DE,CRLF
- LD C,9
- CALL BDOS
- JP 0 ;BACK TO CP/M.
- ;
- QUEST: DB CR,LF
- DB 'RAMDRIV active on drive ',DNAME
- DB CR,LF
- DB 'Should directory of drive ',DNAME
- DB ' be cleared (Y/N)? $'
- CRLF: DB CR,LF,'$'
- ;
- ; NEW TABLE COPIED INTO BIOS
- ;
- WBOOT2: JP WBOOT
- JP WBOOT1+3
- JP WBOOT1+6
- JP WBOOT1+9
- JP WBOOT1+12
- JP WBOOT1+15
- JP WBOOT1+18
- JP HOME ;21
- JP SELDSK ;24
- JP SETTRK ;27
- JP SETSEC ;30
- JP SETDMA ;33
- JP READ ;36
- JP WRITE ;39
- JP WBOOT1+42
- JP SECTRN ;45
- ;
- ; IMPLEMENT BIOS FUNCTIONS
- ;
- IF $ LT ENDTBL ;MAKE SURE THAT BIOS
- DEFS ENDTBL - $ ; FUNCTIONS BEGIN
- ENDIF ; AFTER TABLES.
- ;
- WBOOT: LD HL,80H ;SET INITIAL DMA ADDR.
- LD (DMAADR),HL
- JP WBOOT1 ;BACK TO BIOS
- ;
- ;
- HOME: LD A,(DISK) ;CHECK DISK NUMBER.
- CP DNUMB ;IS IT THE RAMDRIV?
- JP NZ,WBOOT1+21 ;IF NOT, LET BIOS HANDLE IT.
- LD A,0 ;SET "TRACK" TO 0
- LD (XTRAK),A
- RET
- ;
- ;
- SELDSK: LD A,C ;CHECK REQUESTED DISK,
- LD (DISK),A
- CP DNUMB
- JP NZ,WBOOT1+24
- LD HL,DPH ;RETURN DISK PAR. HEADER.
- RET
- ;
- ; DISK PARAMETER HEADER FOR RAMDRIV
- ;
- DPH:
- DW 0 ;NO SECTOR TRANSLATION
- DW 0,0,0 ;SCRATCH
- DW DIRBUF ;LOC. OF SCRATCHPAD AREA.
- DW DPB ;DISK PARAMETER BLOCK
- DW CSV ;DIR. CHECK AREA
- DW ALV ;ALLOC. VECTOR.
- ;
- ; DISK PARAMETER BLOCK
- ;
- DPB:
- DW (1024*TRAKLN)/128 ;SECTORS PER TRACK
- DB 3 ;BSH
- DB 7 ;BLM
- DB 0 ;EXM
- DSM: DW 62 ;MAX BLOCK NO.
- DW DIRECT-1 ;HIGHEST DIRECT. NO.
- ;
- AL0 EQU LOW (0FFH SHL (8-DIRECT/32))
- AL1 EQU 0
- ;
- DB AL0,AL1 ;DIRECTORY BLOCKS.
- ;
- CKS EQU 0 ;CHECK DIRECT. ENTRIES.
- ;
- DW CKS
- DW 0 ;NO SKIPPED TRACKS.
- ;
- ;
- SETTRK: LD A,(DISK)
- CP DNUMB
- JP NZ,WBOOT1+27
- LD A,C ;TRACK NO.
- LD (XTRAK),A
- RET
- ;
- ;
- SETSEC: LD A,(DISK)
- CP DNUMB
- JP NZ,WBOOT1+30
- LD (SECTOR),BC
- RET
- ;
- ;
- SETDMA: LD (DMAADR),BC ;SAVE DMA ADDR. BOTH HERE
- JP WBOOT1+33 ;AND IN BIOS.
- ;
- ;
- READ: LD A,(DISK)
- CP DNUMB
- JP NZ,WBOOT1+36
- LD BC,(SECTOR) ; but we asssume sector fits in one byte
- LD A,(XTRAK) ;SET EXTENDED ADDRESS.
- LD B,A
- CALL MAP ; to compute bank and offset
- OUT (XPORT),A
- IF PANEL
- CPL
- OUT (LIGHTS),A
- ENDIF
- EX DE,HL
- LD DE,RAMBUF ;TEMPORARY BUFFER.
- LD BC,128 ;SECTOR=128 BYTES.
- LDIR
- LD A,PRAM ;RESET ADDR.
- OUT (XPORT),A
- IF PANEL
- CPL
- OUT (LIGHTS),A
- ENDIF
- LD HL,RAMBUF ;MOVE FROM BUFFER
- LD DE,(DMAADR) ; back to main ram
- LD BC,128
- LDIR
- XOR A ; show no errors
- RET
- ;
- ;
- WRITE: LD A,(DISK)
- CP DNUMB
- JP NZ,WBOOT1+39
- IF PANEL
- IN A,(SWITCH) ;CHECK D0 OF FRONT PANEL
- AND 1
- RET NZ ;RETURN IF WRITE PROTECT.
- ENDIF
- LD HL,(DMAADR) ;DMA --> BUFFER
- LD DE,RAMBUF
- LD BC,128
- LDIR
- ;
- LD BC,(SECTOR) ; but we assume sector < 256
- LD A,(XTRAK)
- LD B,A
- CALL MAP
- OUT (XPORT),A
- IF PANEL
- CPL
- OUT (LIGHTS),A
- ENDIF
- LD HL,RAMBUF ;BUFFER --> RAMDRIV.
- LD BC,128
- LDIR
- ;
- LD A,PRAM
- OUT (XPORT),A
- IF PANEL
- CPL
- OUT (LIGHTS),A
- ENDIF
- XOR A ; show no error
- RET
- ;
- ;
- SECTRN: LD A,(DISK)
- CP DNUMB
- JP NZ,WBOOT1+45
- LD H,B
- LD L,C
- RET
- ;
- ;
- ; Subroutine to calculate RAM address and bank
- ;
- ; called with B = track number (starts from 0)
- ; C = sector number (starts from 0)
- ;
- ; returns with A = extended address byte
- ; DE = offset into bank for start of sector
- ;
- MAP: XOR A ; clear A
- LD A,B ; track number to A
- LD DE,2 ; increment for BLEN table
- LD HL,BLEN
- ;
- MAP1: SUB (HL) ; subtract bank length in K's
- JR C,MAP2 ; jump if track in this bank
- ADD HL,DE ; point to next BLEN entry
- JR MAP1 ; repeat till done
- ;
- MAP2: ADD A,(HL) ; A = relative track number in bank
- RLCA ; multiply by 4K
- RLCA
- RLCA
- RLCA
- LD E,D ; clear E
- LD D,C ; multiply sector number by 128
- RR D
- RR E
- ADD A,D ; add to track starting address
- LD D,A ; DE = sector start in bank
- INC HL
- LD A,(HL) ; A = extended (bank) address
- RET
- ;
- BLEN: DB 32/TRAKLN,0FFH ; first bank has 32K at FF
- DB 32/TRAKLN,0FEH ; second bank has 32K at FE
- DB 04/TRAKLN,001H ; third bank has 4K at 01
- DB 0 ; end of table
- ;
- ; DATA STORAGE AREA
- ;
- DISK: DB 0
- XTRAK: DB 0
- DMAADR: DW 80H
- SECTOR: DW 0
- ;
- .DEPHASE
- ;
- END