Bondwell 12 Virtual-disk
by M.J. Moene
http://www.eld.leidenuniv.nl/~moene/Home/museum/Bondwell12/bgg-vdisk/
Preface
When using programs that frequently or frequently do disk I/O, such as translators (compilers and assemblers) and programs that use
overlay files (eg WordStar), the relatively slow disk I/O of the floppy - often experience disk drives as annoying. The available
storage capacity of both drives (166 kbyte each) is sometimes too small. These disadvantages of floppy disk drives with respect to
speed and (temporarily) available capacity can be overcome by using a disk simulated in memory: a virtual disk.
In this article I describe how a virtual disk can be implemented in the Bondwell 12-CP/M 2.2 operating system. The memory space
required for the virtual disk can be obtained by expanding the memory with eight 64 kbytes of dynamic RAMs. The hardware of the
Bondwell 12 provides the possibility to add these two additional 32 kbyte memory banks. A small hardware extension makes it possible
to add 32 kbyte (= 256 kbytes) instead of two, eight additional memory banks.
Content
H 1. The CP/M control system
H 2. Expansion of the BIOS with a virtual disk
H 3. Memory bank selection
H 4. 256 kbyte memory expansion
1. The CP/M operating system
1.1. Preface
An operating system is intended to provide control over the peripheral equipment, such as, for example, terminal, disk drives and
printer, in a way that is independent of the hardware structure of that peripheral equipment. CP/M is such an operating system.
CP/M is made up of five parts:
BIOS: Basic Input Output System,
BDOS: Basic Disk Operating System,
CCP: Console Command Processor,
TPA: Transient Program Area,
MWA: Monitor Work Area.
The BIOS takes care of the basic operations needed to control the disk drives and the usual peripherals, such as the terminal and
printer. The BDOS provides disk management and control of the peripherals, using the BIOS. CCP executes the commands that come from
the keyboard. The TPA is the part of the memory that is available for the user programs (possibly extended with the space of CCP and
BDOS). The MWA contains a number of system constants and buffers. Of these five parts, only the BIOS depends on the hardware system
used. Adding a memory disk requires that the BIOS is adjusted.
1.2. The Basic Input/Output System
What needs to be adjusted in the BIOS? To investigate this, here is a description of the most important properties of the BIOS.
The BIOS of the Bondwell 12 is made up of the following parts:
jump-table,
BIOS routines,
disk parameter tables,
function key table.
ad 1.
The jump-table serves to call the BIOS routines. At address $ 0001 and $ 0002 in the MWA you will find the address of the second
jump instruction of the BIOS jump-table. This means that the location of the entire BIOS jump-table is known.
ad 2.
The BIOS routines can be divided into three groups:
system initialization,
ASCII import and export routines,
disk input and output routines.
To add the memory disk, only the disk input and output routines are important.
ad 3.
The physical properties of the used disk drives are fixed in three disk parameter tables:
Disk Parameter Header table (DPH),
Disk Parameter Block table (DPB),
sector translate table (XLT).
ad 4.
The function key table consists of 16 x 16 bytes for the sixteen function keys. The table covers the address area $ F6BF .. $ F7BF.
I will not describe this table further.
The BIOS routines
The data on the floppy disk is organized in tracks and sectors. (see figure 1.2.1.)
\ --- + --- /
| \ - + - / |
|| \ - + - / | o ---- track (circle)
||| \ | / |||
- +++ - O - +++ -
||| / | \ ||| \
|| / - + - \ || ) - sector (circle segment)
| / - + - \ | /
/ --- + --- \
figure 1.2.1. tracks and sectors on a disk
The data transfer to and from disk takes place via a so-called DMA buffer (Direct Memory Access buffer). The data is exchanged per
record of 128 bytes between the DMA buffer and the disk. The records are indicated with a track and sector number.
The BIOS contains the following disk input and output routines:
home: Bring the read head to zero track of the selected drive:
normally on the first tracks is the CP/M operating system
saved.
seldsk: Select the disk drive, indicated by register c
(0 = A:, 1 = B :); if the drive exists, then register pair hl
the address of the Disk Parameter Header, otherwise
register pair hl zero.
settrk: Select the track of the selected disk drive, switched on
give by the number in register pair bc.
setsec: Select the sector of the selected disk drive, switched on
give by the number in register pair bc.
setdma: Use it for subsequent disk read and write operations
address of the DMA buffer as indicated by register pair bc.
read: Read the selected sector of the disk and place the data
in the indicated DMA buffer; if the operation is successful,
register a contains the value zero, otherwise a value is unequal
to zero.
write: Describe the selected sector of the disk with the data
from the indicated DMA buffer; if the operation is successful,
register a contains the value zero, otherwise a value is unequal
to zero.
sectran: Translate a logical sector number in register pair bc to it
physical sector number in register pair hl; register pair the
contains the address of the translation table sector; the difference
between the logical and the physical sector number
used to reduce the time required to successive sectors
to read or describe to shorten (skewing).
For the above routines, with the exception of home, the read/write head only really has to be brought to the selected sector in the
read and write operations.
The disk parameter tables
The physical properties of the used disk drives are recorded in three disk parameter tables in the BIOS:
Disk Parameter Header table (DPH),
Disk Parameter Block table (DPB),
sector translate table (XLT).
The DPH is the link between the BDOS and the BIOS for the use of disk input and output. The DPH contains a draft area and the addresses
of a number of buffers that are used by the BDOS. Furthermore, the DPH contains the addresses of the DPB and the XLT tables. The DPB
describes the physical properties of the drive and the XLT table gives the translation of logical sectors to physical sectors.
There is one DPH per connected drive. DPBASE indicates the start of the list of DPHs. In Figure 1.2.2. the format of the DPHs is shown.
Disk Parameter Header
+ -------------------------------------------- +
DPBASE | XLT | 0 | 0 | 0 | DIRBUF | DPB | CSV | ALV | Drive 0 (A :)
+ -------------------------------------------- +
| :
+ -------------------------------------------- +
| XLT | 0 | 0 | 0 | DIRBUF | DPB | CSV | ALV | Drive n
+ -------------------------------------------- +
16b 16b 16b 16b 16b 16b 16b 16b
figure 1.2.2. list of Disk Parameter Headers
The DPH contains the following data:
XLT: Address of the translation table sector; if there is no skewing
applied XLT has the value zero.
000: Stroke area for the BDOS; the initial value is not of
importance.
DIRBUF: Address of a 128 byte large scratch buffer for directory
operations performed by the BDOS; all DPHs
can refer to the same buffer,
DPB: Address of the Disk Parameter Block for this drive; drives
with the same characteristics can refer to the same
DPB,
CSV: Address of a scratch area used for the off
conduct a software check on changing the
disk; each DPH refers to its own scratch area; if there
not having to be checked, CSV has the value zero.
ALV: Address of a scratch area used by the BDOS to
the occupation of the disk, expressed in allocation-blocks,
to keep up; each bit of the buffer establishes an allocation
block for; a bit that has the value one indicates that
the corresponding allocation block is occupied; every DPH
refers to its own scratch area.
The format of the Disk Parameter Block is shown in Figure 1.2.3.
Disk Parameter Block
+ ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + - ---- + ----- +
A:, B: | SPT | BSH | BLM | EXM | DSM | DRM | AL0 | AL1 | CKS | OFF |
+ ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + - ---- + ----- +
+ ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + - ---- + ----- +
Vdisk | SPT | BSH | BLM | EXM | DSM | DRM | AL0 | AL1 | CKS | OFF |
+ ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + - ---- + ----- +
16b 8b 8b 8b 16b 16b 8b 8b 16b 16b
figure 1.2.3. two Disk Parameter Blocks
The Disk Parameter Block contains the following data:
SPT: Sectors Per Track.
The number of sectors per track.
BSH: Data allocation Block SHIFT factor.
This is a number that depends on the size of it
allocation-block (BLS: allocation BLock Size).
BLM: Data allocation BLock Mask.
The value of this is: 2 ^ (BSH-1).
EXM: EXtent Mask.
The value of EXM depends on the size of it
allocation block and the total number of allocation
blocks from this disk.
DSM: Maximum Data block number.
DSM shows the capacity of the disk in allocation-blocks:
DSM = alloc-blocks -1.
DRM: Maximum number of DiRectory entries -1.
DRM gives the number of directory places -1 of this disk.
AL0, AL1: ALlocated blocks for directory.
AL0 and AL1 give the initial value for the ALV: this is used
indicated which blocks are reserved for the directory.
CKS: Number of directory sectors ChecK Summed.
CKS indicates the size of the buffer for checking it
changing the disk, expressed in sectors; there will be no
control, then CKS has the value zero.
OFF: Number of reserved system tracks (track OFFset).
OFF indicates the number of reserved tracks at the beginning of the
disk; these tracks can, for example, be used for the storage of
the CP / M operating system.
The value of BSH and BLM indirectly determine the size of an allocation block (BLS). The value of BLS is not mentioned in the DPB.
The size of an allocation block is: 128 x 2 ^ (BSH), or 128 x (BLM + 1) [byte]. BSH and BLM depend on BLS as follows:
BLS BSH BLM
1024 byte 3 7
2048 byte 4 15
4096 byte 5 31
8192 byte 6 63
16384 byte 7 127
BSH is used to determine in which allocation block a particular record falls: allocation-block nr = record number >> BSH.
(j >> k: shift number j k-times to the right)
BLM is used to determine the record number within the allocation block: place = record number & BLM. (j & k: bitwise AND of j with k)
DSM shows the capacity of the disk measured in allocation-blocks. This does not include the reserved tracks at the beginning of the
disc (OFF). The capacity of the disk is: BLS x (DSM +1) [bytes].
The value of EXM depends on BLS and DSM as follows:
BLS DSM < 256 DSM >= 256
1024 byte 0 -
2048 byte 1 0
4096 byte 3 1
8192 byte 7 3
16384 byte 15 7
The following considerations apply to the choice of the size of the allocation block (BLS): for the storage of large files, a large
allocation block gives an efficient use of the directory space; for the storage of many small files, a small allocation block
provides an efficient use of the available disk capacity: a file that is only a few bytes in size does use a whole allocation block.
DRM gives the number of directory locations minus one. Al0 and Al1 are used as initial value for the allocation buffer (ALV) to
reserve space for the directory. The value of DRM is decisive for the value AL0 and AL1. The concatenation of AL0 and AL1 can be
onsidered as a list of 16 bits (see figure 1.2.4.).
+ ------------------------------+------------------------------------ +
| AL0 | AL1 |
+ ----------------------------- + ----------------------------------- +
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
+ ----------------------------- + ----------------------------------- +
figure 1.2.4. directory allocation-blocks
Position 0 corresponds to the high-order bit of byte AL0, position 15 corresponds to the low-order bit of byte AL1. Each bit
in this list reserves an allocation block for a number of directory locations, so that sixteen allocation blocks can be used
for the directory. Each directory location covers 32 bytes. The number of allocation blocks required for the directory thus
depends on the size of the allocation block. This dependency can be expressed as follows: number of directory allocation-blocks
= (DRM + 1) / (BLS / 32).
As many allocation-blocks as the directory needs, so many bits of AL0 and AL1 must be '1', starting with AL0 position 0.
The value of OFF determines the number of tracks that will be skipped at the beginning of the physical disk. This value is
automatically added to the track number when calling the routine settrk. This mechanism can be used to skip the tracks reserved
for the operating system, or to divide a large disk into smaller parts.
The explanation of the Disk Parameter Header ends with the CSV and ALV buffers. The size of the buffer for checking the disk
(CSV) is equal to the value of CKS. The value of CKS is determined as follows: in the case of a removable disk, CKS has the
value (DRM + 1) / 4: there are four directory locations per record. If it is a fixed disk, CKS has a value of zero (no check
on changing).
The size of the allocation buffer (ALV) is determined by the maximum number of allocation blocks of the relevant disk. The size
of ALV is: (DSM / 8) +1 [bytes], namely one bit per allocation block.
2. Extend the BIOS with a virtual disk
2.1. Preface
The operation of the BIOS is now sufficiently known to add a virtual disk to the BIOS. The addition requires the following actions:
assign a free letter between A and P to the virtual disk,
program the BIOS disk I/O routines for the virtual disk,
make the virtual disk DPH, DPB and possibly the XLT table.
The sequel describes the way in which the virtual disk is implemented in the existing Bondwell 12 CP/M 2.2 operating system.
2.2. The vdisk program (version 1.5)
2.2.1. Assumptions
When creating a program for the virtual disk, the following assumptions are used:
The CP/M operating system on the system disk must remain unchanged: the installation of the memory disk must be done by
a separate program.
For the memory space required for the virtual disk, the memory banks one and two are used; these are available through the
standard 64 kbyte memory expansion of the Bondwell 12; due to the extra memory expansion of 256 kbytes, the memory banks
one to eight are available for the virtual disk.
The program must be suitable for both the 64 and 256 kbytes of memory space.
2.2.2. Global operation
The operation of the memory disk program can be summarized as follows. The calls from the BIOS disk I/O routines seldsk to
write are redirected to the corresponding memory disk BIOS routines, so that it can be checked whether the memory disk is
concerned. If it concerns the memory disk, the memory disk routine is further processed; if it concerns a different drive,
the program will continue in the original BIOS routine.
For the memory disk BIOS routines and the disk parameter tables, which have to be added to the standard Bondwell 12 BIOS,
some memory space is needed that can not be used by other programs. This memory space is required in the common memory bank
(common bank: address $ 8000 .. $ FFFF), because the other memory banks can only be accessed from this memory bank. This
space for the memory disk BIOS routines is available in the BIOS from address $ F500 to address $ F6BF, where the function
key table begins.
Installing the memory disk includes the following actions:
If desired, format the memory disk directory space.
Overwrite the existing BIOS jump table with the virtual disk jump table as far as the relevant disk I/O routines are concerned.
Copy the virtual disk parameter tables and routines to the free space in the BIOS.
Replace the jump CCP at the end of the original BIOS warm boot routine with jump virtual disk hot-boat, so that it can be
checked whether the default drive is the (now) legal virtual disk; if this is not done, the virtual disk is not considered
legal by the original warm boot routine and replaced by drive A :.
Figure 2.2.2.1. gives an impression of the memory usage of the virtual disk.
$ FFFF + -------------- + 64 kbyte
| video |
$ F800 | -------------- |
| -------------- |
| vdisk buffer |
| vdisk-program |
$ F500 | -------------- |
| -------------- |
| BIOS |
| BDOS |
| CCP |
| -------------- |
| TPA |
$8000 + -------------- + 32 kbyte
common bank
$7FFF + -------------- + 32 kbyte $7FFF + -------------- + 32 kbytes
| | | |
| | | |
| | | |
| | | Vdisk |
| TPA | | track |
| | | |
| | | n-1 |
| | | |
| | | |
$0100 | -------------- | | |
| MWA | | |
$0000 + -------------- + 0 $0000 + -------------- + 0
bank 0 ... bank n
figure 2.2.2.1. memory usage of the virtual disk
2.2.3. Realization
This section describes the structure of the virtual disk program, the operation of the BIOS routines and the content of the disk
parameter tables.
Structure
The memory disk program consists of the following parts:
installation,
formatting,
jump-table,
parameter tables,
BIOS routines.
These parts are explained in more detail below.
Installation
The memory disk installation is as follows.
The installation routine determines whether the memory disk should be formatted ('-f' option). If this is the case, the installation
routine copies the format routine to the available space in the Bondwell 12 BIOS (address $ F500 .. $ F6BF) and then calls it. If
formatting is not required, this section is omitted. Furthermore, the installation routine copies the memory disk parameter tables
and BIOS routines to the available space in the original BIOS. The jump to the CCP at the end of the BIOS hot-boot routine is
replaced by a jump to the memory hot-boot routine. Finally, the installation routine overwrites a part of the original BIOS jump-table
with the memory disk jump-table.
Formatting
The format routine initializes all locations in the memory bank (s) in which the memory disk directory is located with the value $ E5,
which corresponds to an empty directory.
Jump-table
The jump-table ensures that when calling the BIOS routines seldsk to write, you first jump to the corresponding memory disk BIOS
routine. Then, if necessary, the original BIOS routine is followed.
Disk parameter tables
The disk properties are defined in the disk parameter tables. The memory disk has the following properties:
Disk Parameter Header
XLT = 0: No sector translation is applied.
DIRBUF = $ F2CD: Address of the directory buffer of drive A: and B :.
DPB = ....: Disk Parameter Block, see below.
CSV = 0: No check on changing the disk.
ALV = ....: This is the address of the memory allocation buffer.
Disk Parameter Block
SPT = 256: There is exactly one track per memory bank; this gives one
simple calculation of the memory bank number and the
address of the sector in that bank.
BSH = 4: The allocation block size is 2048 bytes.
BLM = 15: The allocation-block size is 2048 byte.
EXM = 1: The allocation-block size is 2048 byte and DSM <256.
DSM = 31: Maximum allocation block number for the 64 kbyte disk.
(127 for the 256 kbyte memory disk.)
DRM = 63: There are 64 directory places.
AL0 = $ 80: One block is reserved for the directory.
AL1 = 0: Idem.
CKS = 0: No check on changing the disk.
OFF = 0: There are no reserved tracks on the disk.
BIOS routines
The CP / M operating system does not need to be present on the memory disk. Furthermore, applying skewing for the memory disk will
not give a speed gain. It follows that the home and sectran routine for the memory disk are not important. The following are the
memory disk BIOS routines.
seldsk: The drive number in register c is copied to the
variable 'drive'; if it concerns the memory disk, then
the register pair hl obtains the address of the memory disk Disk
Parameter Header and the subroutine is terminated; concerns
it is another disk, then the routine jumps to the original one
seldsk routine.
settrk: The track number in register pair bc is copied to the
variable 'track' and the routine jumps to the original
settrk routine.
setsec: The sector number in register pair bc is copied to the
variable 'sector' and the routine jumps to the original
setsec routine.
setdma: The dma address in register pair bc is copied to the
variable 'dma' and the routine jump to the original
setdma routine.
read: The subroutine 'checkd' checks whether
a sector must be read from the memory disk or from
one of the floppy disks; it does not concern the memory disk,
then the routine jumps to the original read routine; if
it concerns the memory disk, the subroutine is 'getadr'
called; this routine selects the correct memory bank
(track of the memory disk) and returns the start address of the
requested sector in said memory bank in register pair h1; the
sector is copied to the local memory disk
data buffer in the 'common bank'; with the routine 'bank' becomes
memory bank zero selected again; then the
memory disk data buffer copied to the dma address; the
read routine ends with a zero in register a to the BDOS
to indicate that the reading operation went well.
write: The operation of the write routine is similar to that of
the read routine; the direction of the data flow is however
other way around.
Other routines
vdwbt: This routine is just after the original BIOS warm boot routine
run through; the vdwbt routine checks the number of the
default drive in the MWA matches the number of the
memory disk. If the numbers match, it will be in register
c the number of the memory disk is given to the CCP.
checkd: This routine indicates whether the memory disk has been selected.
getadr: The routine 'getadr' selects the memory bank in which the
requested sector and gives it in register pair hl
starting address of the sector in that memory bank. The calculation
of memory bank number and sector start address is as follows:
- the sector size is 128 bytes,
- there are 256 sectors per track: 256 x 128 bytes = 32 kbytes,
so that each track covers a memory bank;
the number of the memory bank is: bank = track + 1:
the memory disk starts with a memory bank;
- the first sector of each track starts at address $ 0 of the
memory bank corresponding to that track: the calculation
the starting address of a sector is therefore not dependent
of the track number; the starting address of a sector is:
address = sector x 128, or (sector x 256) / 2:
- load register h with the sector number (sector x 256),
load register l with 0,
- shift the contents of the register pair to a position
right (hl / 2),
bank: The routine 'bank' selects the memory bank according to it
number in register a. This routine is suitable for the
standard 64 kbyte memory expansion of the Bondwell 12 as
for memory expansion of 256 kbytes. The operation of the
memory bank selection is described in chapter 3. The
numbering of the memory banks in the 'bank' routine is different
of the numbering in the Bondwell 12/14 manual: in the routine
'bank' is the numbering as follows:
- 0: Boot ROM,
- 1..9: RAM bank 0..8.