.he
.bp odd
.mt 5
.mb 6
.pl 66
.ll 65
.po 10
.hm 2
.fm 2
.ft All Information Presented Here is Proprietary to Digital Research
.sp 3
.sh
.ce 2
.tc 5  Creating a BIOS
Section 5
.SP
.sh
Creating a BIOS
.sp 3
.sh
5.1  Overview
.tc    5.1  Overview
.pp
The BIOS provides a standard interface to the physical input/output devices
in your system.  The BIOS interface is defined by the functions
described in Section 4.  Those functions, taken together, constitute a model
of the hardware environment.  Each BIOS is responsible for mapping that 
model onto the real hardware.
.ix BIOS, creating
.ix BIOS interface
.pp
In addition, the BIOS contains disk definition tables which define 
the characteristics of the
disk devices which are present, and provides some storage for use by the BDOS
in maintaining disk directory information.
.pp
Section 4 describes the functions which must be performed by the BIOS, and the
external interface to those functions.  This Section contains additional
information describing the structure and significance of the disk definition
tables and information about sector blocking and deblocking.  Careful choices
of disk parameters and disk buffering methods are necessary if you are to
achieve the best possible performance from CP/M-8000.  Therefore, this section
should be read thoroughly before writing a custom BIOS.  
.sp 2
.sh
5.2  Disk Definition Tables
.he CP/M-8000 System Guide                 5.2  Disk Definition Tables
.tc    5.2  Disk Definition Tables
.ix disk definition tables
.ix CP/M-8000 configuration
.pp
As in other CP/M systems, CP/M-8000 uses a set of tables to define disk
device characteristics.  This section describes each of these tables
and discusses choices of certain parameters.
.bp
.sh
5.2.1  Disk Parameter Header
.tc         5.2.1  Disk Parameter Header
.ix Disk Parameter Header (DPH)
.ix scratchpad area
.pp
Each disk drive has an associated 26-byte Disk Parameter Header (DPH) 
which both contains information about the disk drive and
provides a scratchpad area for certain BDOS operations.  Each drive must
have its own unique DPH.  The format of a Disk Parameter Header is shown in 
Figure 5-1. 
.sp 3
.ce 100
.nf
     XLT    0000   0000   0000  DIRBUF   DPB     CSV     ALV
.sp
     32b     16b    16b    16b    32b    32b     32b     32b
.sp
.sh
Figure 5-1.  Disk Parameter Header 
.sp 2 
.ce 0
.fi
.ix word (16-bit) value
.ix longword (32-bit) value
.pp
Each element of the DPH is either a word (16-bit) or longword (32-bit) 
value.  The meanings of the Disk Parameter Header (DPH) elements are given
in Table 5-1.
.sp 2
.ce
.sh
Table 5-1.  Disk Parameter Header Elements
.qs
.ix Disk Parameter Header elements
.sp
.nf
   Element                       Description
.sp 
.fi
.ll 62
.in 15
.ti -10
XLT       Address of the logical-to-physical sector translation table, if used 
for this particular drive, or the value 0 if there is no translation table 
for this drive (i.e, the physical and logical sector numbers are the same).  
Disk drives with identical sector translation may share the same translate 
table.  The sector translation table is described in Section 5.2.2.
.ix XLT
.sp
.ti -10
0000      Three scratchpad words for use within the BDOS. 
.sp
.ix scratchpad words
.ix 0000
.ti -10
DIRBUF    Address of a 128-byte scratchpad area for directory operations 
within BDOS.  All DPHs address the same scratchpad area.
.ix DIRBUF
.sp
.ti -10
DPB       Address of a disk parameter block for this drive.  Drives with 
identical disk characteristics may address the same disk parameter block.
.ix DPB
.bp
.ll 65
.in 0
.ce
.sh
Table 5-1.  (continued)
.sp
.nf
   Element                       Description
.fi
.sp
.ll 62
.in 15
.ti -10
CSV       Address of a checksum vector.  The BDOS uses this area to maintain 
a vector of directory checksums for the disk.  These checksums are used in 
detecting when the disk in a drive has been changed.  If the disk is not 
removable, then it is not necessary to have a checksum vector.  Each DPH must 
point to a unique checksum vector.  The checksum vector should contain 1 byte 
for every four directory entries (or 128 bytes of directory).  In other words: 
length (CSV) = (DRM+1) / 4.  (DRM is discussed in Section 5.2.3.)
.ix CSV
.ix checksum vector
.sp
.ti -10
ALV       Address of a scratchpad area used by the BDOS to keep disk storage 
allocation information.  The area must be different for each DPH.  There must 
be 1 bit for each allocation block on the drive, requiring the following: 
length (ALV) = (DSM/8) + 1.  (DSM is discussed below.)
.ix ALV
.ix Disk Parameter Header elements
.in 0
.ll 65
.sp 3
.sh
5.2.2  Sector Translate Table
.tc         5.2.2  Sector Translate Table
.pp
Sector translation in CP/M-8000 is a method of logically renumbering
the sectors on each disk track to improve disk I/O performance.  A frequent 
situation is that a program needs to access disk sectors
sequentially.  However, in reading sectors sequentially, most programs
lose a full disk revolution between sectors because there is not
enough time between adjacent sectors to begin a new disk operation.  To 
alleviate this problem, the traditional CP/M solution is to create a logical 
sector numbering scheme in which logically sequential sectors are physically 
separated.  Thus, between two logically contiguous sectors, there is a 
several sector rotational delay.  The sector translate table defines
the logical-to-physical mapping in use for a particular drive, if a
mapping is used.
.ix logical sector numbering
.ix mapping, logical to physical
.ix rotational latency
.pp
Sector translate tables are used only within the BIOS.  Thus the table
may have any convenient format.  (Although the BDOS is aware of the
sector translate table, its only interaction with the table is to get the
address of the sector translate table from the DPH and to pass that address
to the Sector Translate Function of the BIOS.)  The most common form for a
sector translate table is an n-byte (or n-word) array of physical sector 
numbers, where n is the number of sectors per disk track.  Indexing into 
the table with the logical sector number yields the corresponding physical 
sector number.
.ix sector translate table
.pp
Although you may choose any convenient logical-to-physical mapping, there is
a nearly universal mapping used in the CP/M community for single-sided, 
single-density, 8-inch diskettes.  That mapping is shown in Figure 5-2.  
Because your choice of mapping affects diskette compatibility between 
different systems, the mapping of Figure 5-2 is strongly recommended.
.sp 3
.nf
.sp
     Logical  Sector   0  1  2  3  4  5  6  7  8  9 10 11 12
     Physical Sector   1  7 13 19 25  5 11 17 23  3  9 15 21
.sp
     Logical  Sector  13 14 15 16 17 18 19 20 21 22 23 24 25
     Physical Sector   2  8 14 20 26  6 12 18 24  4 10 16 22
.sp 2
.ce
.sh
Figure 5-2.  Sample Sector Translate Table
.fi
.sp 2
.sh
5.2.3  Disk Parameter Block
.tc         5.2.3  Disk Parameter Block
.pp
A Disk Parameter Block (DPB) defines several characteristics associated
with a particular disk drive.  Among them are the size of the drive, the
number of sectors per track, the amount of directory space, and others.
.ix Disk Parameter Block (DPB)
.pp
A Disk Parameter Block can be used in one or more DPH's if the disks are 
identical in definition.  A discussion of the fields of the DPB follows the 
format description.  The format of the DPB is shown in Figure 5-3.
.cp 6
.sp 2
.nf
.sp
  SPT   BSH   BLM   EXM   0   DSM   DRM   Reserved    CKS   OFF
.sp
  16b   8b     8b    8b   8b  16b   16b      16b      16b   16b
.sp
.ce
.sh
Figure 5-3.  Disk Parameter Block
.sp 2
.fi
.sp
Each field is a word (16 bit) or a byte (8 bit) value.  The description of 
each field is given in Table 5-2.
.ix byte (8 bit) value
.ix word (16 bit) value
.sp 2
.ix Disk Parameter Block fields
.ce 
.sh
Table 5-2.  Disk Parameter Block Fields
.sp
.nf
    Field                      Definition
.fi
.ll 62
.in 15
.sp
.ti -10
SPT       Number of 128-byte logical sectors per track.
.ix SPT
.sp
.ti -10
BSH       The block shift factor, determined by the data block allocation 
size, as shown in Table 5-3.
.ix BSH
.ix Block Shift Factor
.bp
.ce
.ll 65
.in 0
.sh
Table 5-2.  (continued)
.sp
.nf
    Field                      Definition
.sp
.fi
.in 15
.ll 62
.ti -10
BLM       The block mask which is determined by the data block allocation 
size, as shown in Table 5-3.
.ix BLM
.ix Block Mask
.sp
.ti -10
EXM       The extent mask, determined by the data block allocation
size and the number of disk blocks, as shown in Table 5-4.
.ix BLM
.ix Extent Mask
.sp
.ti -10
0         Reserved byte.
.sp
.ti -10
DSM       Determines the total storage capacity of the disk drive and
is the number of the last block, counting from 0.  That is,
the disk contains DSM+1 blocks.
.ix DSM
.ix disk drive, total storage capacity
.sp
.ti -10
DRM       Determines the total number of directory entries which can be
stored on this drive.  DRM is the number of the last directory entry,
counting from 0.  That is, the disk contains DRM+1 directory entries.
Each directory entry requires 32 bytes, and for maximum efficiency, the
value of DRM should be chosen so that the directory entries exactly fill
an integral number of allocation units.
.ix DRM
.sp
.ti -10
CKS       The size of the directory check vector, which is zero if the disk
is permanently mounted, or length (CSV) = (DRM) / 4 + 1 for removable
media.
.ix CKS
.ix directory check vector
.sp
.ti -10
OFF       The number of reserved tracks at the beginning of a logical
disk.  This is the number of the track on which the directory begins.
.ix OFF
.ix reserved tracks, number of
.ll 65
.in 0
.sp 
.pp
To choose appropriate values for the Disk Parameter Block elements, you must 
understand how disk space is organized in CP/M-8000.  A CP/M-8000
disk has two major areas:  the boot or system tracks, and the file system
tracks.  The boot tracks are usually used to hold a machine-dependent
bootstrap loader for the operating system.  They consist of tracks 0 to OFF-1.
Zero is a legal value for OFF, and in that case, there are no boot tracks.  The
usual value of OFF for 8-inch floppy disks is two.
.ix file system tracks
.ix boot tracks
.ix Disk Parameter Blocks
.ix bootstrap loader, machine dependent
.pp
The tracks after the boot tracks (beginning with track number OFF) 
are used for the disk directory and disk files.  Disk space in this area
is grouped into units called allocation units or blocks.  The block size
for a particular disk is a constant, called BLS.  BLS may take on any
one of these values: 1024, 2048, 4096, 8192, or 16384 bytes.  No other
values for BLS are allowed.  (Note that BLS does not appear explicitly in
any BIOS table.  However, it determines the values of a number of other
parameters.)  The DSM field in the Disk Parameter Block is one less than
the number of blocks on the disk.  Space is allocated to a file 
or to the directory in 
whole blocks.  No fraction of a block can be allocated.
block size
.ix BLS
.ix DSM
.pp
The choice of BLS is very important, because it effects the efficiency of
disk space utilization, and because for any disk size there is a minimum
value of BLS that allows the entire disk to be used.
Each block on the disk has a block number ranging from 0 to DSM.  The largest
block number allowed is 32767.  Therefore, the largest number of bytes that
can be addressed in the file system space is 32768 * BLS.  Because the largest
allowable value for BLS is 16384, the biggest disk that can be accessed by
CP/M-8000 is 16384*32768 = 512 Mbytes.  
.ix block number, largest allowed
.pp
Each directory entry may contain either 8 block numbers (if DSM >= 256) 
or 16 block
numbers (if DSM < 256).  Each file needs enough directory entries to hold
the block numbers of all blocks allocated to the file.  Thus a large value 
for BLS implies that fewer directory entries are needed.  Since fewer 
directory entries are used, the directory search time is decreased.
.pp
The disadvantage of a large value for BLS is that since files are allocated
BLS bytes at a time, there is potentially a large unused portion of a block
at the end of the file.  If there are many small files on a disk, the waste
can be very significant.  
.pp
The BSH and BLM parameters in the DPB are functions of BLS.  Once you have
chosen BLS, you should use Table 5-3 to determine BSH and BLM.  The EXM 
parameter of the DPB is a function of BLS and DSM.  You should use Table 5-4
to find the value of EXM for your disk.
.ix ESM
.sp 3
.nf
.sh
                 Table 5-3.   BSH and BLM Values
.sp
                  BLS          BSH          BLM

                  1024          3             7
                  2048          4            15
                  4096          5            31
                  8192          6            63
                 16384          7           127
.in 0
.fi
.bp
.sh
                     Table 5-4.  EXM Values
.sp
.nf
              BLS          DSM <= 255       DSM > 255
.sp
              1024              0               N/A
              2048              1                0
              4096              3                1
              8192              7                3
             16384             15                7
.in 0
.fi
.ll 65
.sp
.pp
The DRM entry in the DPB is one less than the total number of directory
entries.  DRM should be chosen large enough so that you do not run
out of directory entries before running out of disk space.  It is not
possible to give an exact rule for determining DRM, since the number
of directory entries needed will depend on the number and sizes of the
files present on the disk.  
.pp
The CKS entry in the DPB is the number of bytes in the CSV (checksum vector)
which was pointed to by the DPH.  If the disk is not removable, a checksum
vector is not needed, and this value may be zero.
.sp 2
.sh
5.3  Disk Blocking System Guide
.tc    5.3  Disk Blocking Guide
.he CP/M-8000 System Guide                          5.3  Disk Blocking
.ix sector, 128-byte
.pp
When the BDOS does a disk read or write operation using the BIOS, the unit
of information read or written is a 128-byte sector.  This may or may not
correspond to the actual physical sector size of the disk.  If not, the BIOS
must implement a method of representing the 128-byte sectors used by CP/M-8000
on the actual device.  Usually if the physical sectors are not 128 bytes long,
they will be some multiple of 128 bytes.  Thus, one physical sector can hold
some integer number of 128-byte CP/M sectors.  In this case, any disk I/O 
will actually consist of transferring several CP/M sectors at once.  
.pp
It might also be desirable to do disk I/O in units of several 128-byte sectors
in order to increase disk throughput by decreasing rotational latency.  
(Rotational latency is the average time it takes for the desired position on 
a disk to rotate around to the read/write head.  Generally this averages 1/2
disk revolution per transfer.)  Since a great deal of disk I/O is sequential,
rotational latency can be greatly reduced by reading several sectors at a
time, and saving them for future use.
.ix rotational latency
.ix read/write head
.pp
In both the cases above, the point of interest is that physical I/O 
occurs in units larger than the expected sector size of 128 bytes.
Some of the problems in doing disk I/O in this manner are discussed below.
.bp
.sh
5.3.1  A Simple Approach
.pp
This section presents a simple approach to handling a physical sector size
larger than the logical sector size.  The method discussed in this section
is not recommended for use in a real BIOS.  Rather, it is given as a 
starting point for refinements discussed in the following sections.  
Its simplicity also makes it a logical choice for a first BIOS on new
hardware.  However, the disk throughput that you can achieve with this method 
is poor, and the refinements discussed later give dramatic improvements.
.ix disk throughput
.pp
Probably the easiest method for handling a physical sector size which
is a multiple of 128 bytes is to have a single buffer the size of the
physical sector internal to the BIOS.  Then, when a disk read is to be
done, the physical sector containing the desired 128-byte logical sector 
is read into the buffer, and the appropriate 128 bytes are copied to the
DMA address.  Writing is a little more complicated.  You only want to
put data into a 128-byte portion of the physical sector, but you can
only write a whole physical sector.  Therefore, you must first read the
physical sector into the BIOS's buffer; copy the 128 bytes of output data
into the proper 128-byte piece of the physical sector in the buffer; and
finally write the entire physical sector back to disk.  
.sp
.sh
Note:  \c
.qs
this operation involves two rotational latency delays in addition to the time 
needed to copy the 128 bytes of data.  In fact, the second rotational wait
is probably nearly a full disk revolution, since the copying is usually
much faster than a disk revolution.  
.sp 2
.sh
5.3.2  Some Refinements
.tc         5.3.2  Some Refinements
.ix disk access, sequential
.pp
There are some easy things that can be done to the algorithm of Section 5.2.1 
to improve its performance.  The first is based on the fact that disk
accesses are usually done sequentially.  Thus, if data from a certain physical
sector is needed, it is likely that another piece of that sector will be
needed on the next disk operation.  To take advantage of this fact, the BIOS
can keep information with its physical sector buffer as to which disk, 
track, and physical sector (if any) is represented in the buffer.  Then, when
reading, the BIOS need only do physical disk reads when the information needed
is not in the buffer.  
.pp
On writes, the BIOS still needs to preread the physical sector for the same 
reasons discussed in Section 5.2.1, but once the physical sector is in the 
buffer, subsequent writes into that physical sector do not require additional 
prereads.  An additional saving of disk accesses can be gained by not 
writing the sector to the disk until absolutely necessary.  The conditions 
under which the physical sector must be written are discussed in 
Section 5.3.4.
.ix physical sector
.bp
.sh
5.3.3  Track Buffering
.tc         5.3.3  Track Buffering
.pp
Track buffering is a special case of disk buffering where the I/O is done
a full track at a time.  When sufficient memory for several full track
buffers is available, this method is quite good.  The method is essentially
the same as discussed in Section 5.3.2, but there are some interesting
features.  First, transferring an entire track is much more efficient than
transferring a single sector.  The rotational latency is incurred only once
for the entire track, whereas if the track is transferred one sector at a
time, the rotational latency occurs once per sector.  On a typical diskette
with 26 sectors per track, rotating at 6 revolutions per second, the difference
in rotational latency per track is about 2 seconds versus a twelfth of a 
second.  Of course, in applications where the disk is accessed purely 
randomly, there is no advantage because there is a low probability that
more than one sector will be used from a given track.  However, such 
applications are extremely rare.
.ix rotational latency
.sp 2
.sh
5.3.4  LRU Replacement
.tc         5.3.4  LRU Replacement
.pp
With any method of disk buffering using more than one buffer, it is necessary
to have some algorithm for managing the buffers.  That is, when should buffers
be filled, and when should they be written back to disk.  The first question
is simple, a buffer should be filled when there is a request for a disk sector
that is not presently in memory.  The second issue, when to write a buffer
back to disk, is more complicated.  
.ix buffer, writing to disk
.pp
Generally, it is desirable to defer writing a buffer until it becomes 
necessary.  Thus, several transfers can be done to a buffer for the cost of
only one disk access, two accesses if the buffer had to be preread.  
However, there are several reasons why buffers must be written.  The following 
list describes the reasons:
.sp 2
.in 8
.ti -3
1) A BIOS Write operation with mode=1 (write to directory sector).  To maintain
the integrity of CP/M-8000's file system, it is very important that directory
information on the disk is kept up to date.  Therefore, all directory writes
should be performed immediately.
.ix BIOS write operation
.sp
.ti -3
2) A BIOS Flush Buffers operation.  This BIOS function is explicitly intended
to force all disk buffers to be written.  After performing a Flush Buffers, 
it is safe to remove a disk from its drive.
.ix BIOS flush buffers operation
.sp
.ti -3
3) A disk buffer is needed, but all buffers are full.  Therefore some
buffer must be emptied to make it available for reuse.
.sp
.ti -3
4) A Warm Boot occurs.  This is similar to number 2 above.
.ix warm boot
.ix boot, warm
.sp
.in 0
.pp
Case three above is the only one in which the BIOS writer has any discretion
as to which buffer should be written.  Probably the best strategy is to 
write out the buffer which has been least recently used.  The fact that
an area of disk has not been accessed for some time is a fairly good 
indication that it will not be needed again soon.  
.ix LRU buffers
.sp 2
.sh
5.3.5  The New Block Flag
.tc         The New Block Flag
.pp
As explained in Section 5.2.2, the BDOS allocates disk space to files
in blocks of BLS bytes.  When such a block is first allocated to a file,
the information previously in that block need not be preserved.  To
enable the BIOS to take advantage of this fact, the BDOS uses a special
parameter in calling the BIOS Write Function.  If register D1.W contains
the value 2 on a BIOS Write call, then the write being done is to the
first sector of a newly allocated disk block.  Therefore, the BIOS need
not preread any sector of that block.  If the BIOS does disk buffering
in units of BLS bytes, it can simply mark any free buffer as corresponding
to the disk address specified in this write, because the contents of the 
newly allocated block are not important.  If the BIOS uses a buffer size
other than BLS, then the algorithm for taking full advantage of this
information is more complicated.  
.ix BLS bytes
.pp
This information is extremely valuable in reducing disk delays.  Consider
the case where one file is read sequentially and copied to a newly created
file.  Without the information about newly allocated disk blocks, every 
physical write would require a preread.  With the information, 
no physical write requires a preread.  Thus, the number of physical disk
operations is reduced by one third.
.sp 2
.ce
End of Section 5
.nx six

 
