home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
kaypro
/
kpramdsk.lbr
/
RAMDRIVE.MZC
/
RAMDRIVE.MAC
Wrap
Text File
|
1987-12-25
|
16KB
|
593 lines
TITLE RAMDRIVE.MAC
;
;***********************************************************************
;
; RAMDRIVE - 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.
;
;***********************************************************************
;
; RAMDRIVE 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 RAMDRIVE5:
;
; 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.
;
;***********************************************************************
;
; June 1986 - Minor modifications to RAMDRIVE to facilitate its
; use with 83 series Kaypro computers fitted with 256K RAM chips.
; These changes (trivial as they are!) are hereby released to
; the public domain for non-commercial use.
;
; Dr Michael Liddle,
; 21 The Frostings,
; Grenoside, SHEFFIELD,
; England, S30 3NZ.
;
; The main changes in version 6 are as follows :-
;
; 1. Bank switching is carried out by a new routine 'SWAP'. This
; makes porting RAMDRIVE to different systems easier by further
; isolating hardware dependencies from the main code.
;
; 2. Initially set to install on a pre 84 series Kaypro II with
; the 256K RAM modification described by me in MicroCornucopia
; issue ??? and the CP/M relocated to 63K using MOVCPM.
;
; 3. References to the IMSAI Panel have been removed as few
; micros today have a hardware front panel!
;
; 4. RAMDRIVE assumes that no interrupts will occur and take
; control away - if your system uses interrupts them insert
; DI and EI opcodes as needed.
;
;***********************************************************************
; 8/25/86
; Configured for '84 Kaypro machines using an overlay NEW PIO
; chip on ports 029H and 02BH. If used with the internal PIO,
; set ports to 021H and 023H. The ???BUF values are for a
; Turbo-Rom 62.75K system, and must be set if different!
;
; Charles McHan - AMY <> BBS Multi-System - (904) 725-7461
;***********************************************************************
;
; INSTALLATION of RAMDRIVE6:
;
; RAMDRIVE 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.
;
; RAMDRIVE 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 =RAMDRIVE6/L <== /L optionally produces a .PRN file
; >L80 /P:100,RAMDRIVE6,RAMDRIVE6/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 RAMDRIVE. 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 RAMDRIVE. The first byte is the number of kilo-
; bytes available for RAMDRIVE 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 RAMDRIVE 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 RAMDRIVE6 from the
; console is sufficient to initiate RAMDRIVE6.
;
.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.
;
; RAMDRIVE: 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.
;
; DNAME: The alphabetic designation of the RAM drive.
;
; 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 RAMDRIVE. A good value to use is the greatest
; common divisor of each of the memory banks to be used by RAMDRIVE.
;
; 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 0FEE5H ; CP/M BIOS directory buffer address
RAMBUF EQU 0F5ADH ; CP/M BIOS host buffer
RAMDRIVE EQU 0F363H ;START OF PROGRAM ABOVE BIOS.
PRAM EQU 07H ;EXTENDED ADDR. OF MAIN RAM
DNAME EQU 'D' ;DRIVE NAME OF RAMDRIVE.
TRAKLN EQU 4 ; kilobytes per track
DIRECT EQU 64 ;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' ;RAMDRIVE 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,RAMDRIVE
AND A ; clear carry
SBC HL,DE ; WBOOT minus RAMDRIVE
JP C,CONTIN ; if carry we are OK
LD DE,NOWAY
LD C,9
CALL BDOS
JP 0
;
SIGNON: DB 'RAMDRIVE Version 6 - Mike Liddle June 1986'
DB CR,LF,'$'
NOWAY: DB 'Cannot load RAMDRIVE',CR,LF
DB 'Cold boot system and try again'
DB CR,LF,'$'
;
CONTIN: LD HL,SETUP
LD DE,RAMDRIVE
LD BC,ENDRAM-RAMDRIVE ; 1023
LDIR
JP RAMDRIVE
;
.PHASE RAMDRIVE
;
; 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 RAMDRIVE system. In
; order to conserve space it will be overwritten by data buffers during
; actual access to RAMDRIVE.
;
;
SETUP:
;
.PHASE RAMDRIVE
;
; Determine the amount of available RAMDRIVE memory
;
XOR A
LD C,A
LD HL,BLEN ; RAMDRIVE memory table
LD DE,0002 ; table entry increment
BCHEK0: LD A,(HL) ; get bank kilobytes a
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 RAMDRIVE. 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 ; RAMDRIVE 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 RAMDRIVE
;
LD BC,0000 ; directory on track 0 sector 0
CALL MAP
CALL SWAP
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.
CALL SWAP
;
QUIT: LD DE,CRLF
LD C,9
CALL BDOS
JP 0 ;BACK TO CP/M.
;
QUEST: DB CR,LF
DB 'RAMDRIVE 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 RAMDRIVE?
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 RAMDRIVE
;
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
CALL SWAP
EX DE,HL
LD DE,RAMBUF ;TEMPORARY BUFFER.
LD BC,128 ;SECTOR=128 BYTES.
LDIR
LD A,PRAM ;RESET ADDR.
CALL SWAP
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
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
CALL SWAP
LD HL,RAMBUF ;BUFFER --> RAMDRIVE.
LD BC,128
LDIR
;
LD A,PRAM
CALL SWAP
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
;
;*******************************************************************
;
; This is where banks are switched. Register A contains the
; bank to be selected.
;
;*******************************************************************
;
PIOData EQU 029H ; '84 NEW PIO PORT (DATA)
PIOCtrl EQU 02BH ; '84 NEW PIO PORT (CONTROL)
Mode3 EQU 0CFH ; Mode3 = Control
IOMask EQU 0F8H ; Bits 0,1,2 as output. Rest as input.
SWAP: LD C,A ; Save bank
LD A,Mode3 ; Set up PIO for bank select
OUT (PIOCtrl),A ; Mode 3
LD A,IOMask
OUT (PIOCtrl),A ; Bits 0,1,2 are output
LD A,C ; Bank 7 selected for TPA
OUT (PIOData),A
RET
;
;*******************************************************************
;
BLEN:
DB 32/TRAKLN,00H
DB 32/TRAKLN,01H
DB 32/TRAKLN,02H
DB 32/TRAKLN,03H
DB 32/TRAKLN,04H
DB 32/TRAKLN,05H
DB 0 ; end of table
;
; DATA STORAGE AREA
;
DISK: DB 0
XTRAK: DB 0
DMAADR: DW 80H
SECTOR: DW 0
;
ENDRAM EQU $
;
.DEPHASE
;
END