As explained in section 1.1,
the Basic Input/Output Subsystem
is responsible for providing the actual access to I/O devices.
Both the design and implementation of the BIOS is specific to a
given processor and I/O configuration. In this section we will
attempt to specify the nature of BIOS in sufficient detail for an
experienced programmer, in cooperation with IIS personnel, to
write the code for a given processor and set of peripherals.
The general scheme discussed below uses vectors from RSP/IO
to BIOS subroutines for reading, writing and initializing. The
exact vector scheme and means of passing parameters must be worked
out separately for each processor. Arrangements that have already
been worked out for certain processors are given in
Appendix C.
4.1 Design Goals
The speed of the BIOS code is generally of small significance
compared to the speed of the I/O devices which it serves. When
peripherals are changed, which may occur frequently, it will often
prove that only minor changes need be made in an existing BIOS to
service the new hardware. Also, since BIOS is core-resident, each
byte it occupies is one less available to the Pascal user. For
these reasons, we suggest that major design goals be (1) compactness
and (2) clarity.
Like the rest of the Interpreter, the BIOS should be ROM-able.
Obviously it will also require access to some RAM. It
should be possible to easily change the addresses involved using
some equates and thus reassemble the BIOS for a given memory
configuration.
4.2 Completion Codes
All read, write or initialization calls to BIOS must return a
byte to RSP containing status information on the I/O request just
serviced. The value of this byte is the “completion code”
discussed in section 2.2.
Most of the standard completion codes
listed in 2.2
are not relevant to BIOS — they are returned by the
Pascal Operating System for file errors and the like. The
following errors can be returned by BIOS:
Code | Meaning |
0 | No error |
1 | CRC error |
3 | Illegal operation on unit |
9 | Unit not on line |
16 |
Write attempt to write-protected disk |
17 | Illegal Block or Sector number |
18 |
Non-zero byte count (physical sector mode) |
19 | Error in UIR |
100..199 | Hardware dependent |
All other errors are considered hardware-dependent. For
these, BIOS should return codes in the range 100..199. The
selection of appropriate codes is left to the BIOS writer.
Note that any units not implemented must arrange to return a
completion code of 9 (“Unit not on line”) when an attempt is made
to initialize or use them.
4.3 Calling Mechanisms
In this section we discuss the parameters required in the
BIOS calls for each unit. Each unit has three BIOS calls
associated with it: READ, WRITE and INIT. Each unit has varying
needs for information associated with these functions. Remember
that all calls must return the completion code byte. For a
summary of the BIOS calling requirements, see
Appendix B.
4.3.1 Console
Only one parameter is needed For reading and writing,
containing the data byte to be transferred. Initialization of the
console BIOS requires that the identity of a number of special
control characters be provided in the UIR, as well as serial line
interface settings and a BREAK vector. The details of handling
these special characters are discussed in section 4.5.1.5.
4.3.2 Printer
A single parameter is passed: a byte containing the data read
or written. Initializing the printer requires the serial line
interface settings in the UIR. Optional use may be made of the
UIR field UPAGELINES which specifies the number of lines to be
printed per page. If UPAGELINES = 0 then no page breaks should be
made by BIOS.
4.3.3 Disk
The calling mechanism for disk units requires five parameters
for reading and writing:
-
a starting logical block number as described above,
-
a count of the number of bytes to transfer (unsigned 16 bits,
i.e. 0 to 64K),
-
the address of the data area to transfer to or from,
-
a drive number (0..n-1, given n
drives; currently n = 6 is assumed), and
-
the CONTROL word.
It should be noted that, in the case of disk I/O, the data area
address is guaranteed to be on a word boundary (an even byte address)
and the number of bytes to transfer will always be even. On
initialization, the UIR is empty.
4.3.4 Remote
The remote unit requires a single parameter for reading and
writing: a byte containing the data being transferred. When
initializing the remote unite the UIR contains serial line
interface settings.
4.4 Character Codes
The U.C.S.D. Pascal system assumes that the printer and
console units will support the use of ASCII printable characters
and a few standard control codes (CR, LF, SP, NUL and BEL). The
remaining control codes which may be useful (e.g. cursor
positioning and screen erasure) are “soft” characters which may be
changed by the Pascal user (by running the SETUP utility) to suit
the requirements of his current hardware. The reason for
inflicting these hardware dependencies upon the Pascal level is
the simple fact of life that terminals use control codes which
vary widely and we want to be able to change terminals without
installing a new BIOS. The basic issue is one of mapping logical
control symbols into the control codes recognized by the hardware.
Suppose, for example, that there is pre-declared procedure
CURSORBACK which causes the cursor on a screen terminal to move
left one column. Somewhere in the system, CURSORBACK must cause a
control code to be sent to the terminal which will cause the
desired responses whether it's control-U, control-H or an escape
sequence. One wag to do this would be for the Pascal level to
emit a standard code which the BIOS then translates into whatever
is correct for the current terminal. This has the disadvantage of
requiring a new BIOS for every slightly different terminal. The
approach which we have taken sees to it that the correct code is
sent to BIOS for the current terminal on line. The details of how
this is done are irrelevant to the I/O Subsystem and are elsewhere
in the UCSD Pascal System documentation.
Due to the capability of many devices to make use of
eight-bit
control codes, the Pascal system makes no assumptions as to
the relevance of the high-order bit and transfers the whole byte
faithfully. When using [seven-bit] ASCII, the value of the
high-order
bit is defined to be zero. In other words, the code for the
character ‘A’ must be 65 (decimal) rather than 193 (or 41 hex
rather than C1, if you prefer). This has the effect of requiring
BIOS to return ASCII codes with the high-order bit off for all the
standard characters.
RSP will be sending both upper and lower case characters to
BIOS. Thus for upper-case-only display devices that do not
display lower case codes as upper case. BIOS must map lower case
into upper case.
4.5 Semantics
4.5.1 Console
Here we discuss the required and optional features of the
console device. The console device is assumed to be a CRT
terminal in the following discussion, although a typewriter device
may also be used.
4.5.1.1 Output Requirements
As noted in section 4.4, we depend on
the action of certain ASCII control codes. These are the minimum
requirements for a console device:
-
CR <carriage return> (hex OD)
-
Move cursor to the beginning
of the current line (column 0).
-
<LE line feed> (hex OA)
-
Move cursor to the next line down
while the column position remains the same. Starting from any
but the last line on the screen, the contents of the screen should
remain the same while the cursor moves downward. If the cursor is
on the last line when the LF is issued, it should remain in the
same position while the rest of the display scrolls upward one
line and the bottom line clears.
-
DEL <bell> (hex 07)
-
If an audio signal is available, it
should be sounded. If one is not available, the terminal should
do nothing. The delay time required while doing nothing is not
significant.
-
SP <space> (hex 20)
-
Write a space at the current cursor
position (erasing whatever is there) and advance the cursor
position by one column. If the cursor is already at the last
position in a line, the position of the cursor after the SP is
undefined. We prefer that the cursor remain in its prior position
in this case. If the cursor is in the last column of the last
line on the screen, not only is the position of the cursor
undefined after the SP, but so is the state of the screen: maybe
it scrolled and maybe it didn't. As above, we would prefer that
the cursor remain where it was and that the screen not scroll.
-
NUL <null> (00)
-
Delay for the time required to write one
character. The state of the console should not change.
-
Any printable character
-
Same as the discussion for SP,
except, of course, write the character and not SP!
Note that the effect of sending non-printable characters
other than those described above to the screen BIOS is not defined
since it is known to vary from terminal to terminal.
4.5.1.2 Output Options
The following set of cursor and screen functions should be
provided if possible, however they are optional in the sense that
almost all major functions of the UCSD Pascal System will still be
available if they are not provided. The control characters or
sequences of characters which provide these functions are left
unspecified for the reasons described in section 4.4.
-
Reverse Line Feed:
-
Move the cursor to the next line higher
on the screen without changing column or the other contents of the
screen. If the cursor is already on the top lines the result is
undefined. If possible, the screen should reverse-scroll in such
a case, or if that is not feasible, the cursor and screen should
just remain as they were.
-
Non-destructive Forward and Backward Space:
-
Move the cursor
in the direction indicated without changing the contents of the
screen (i.e. move it non-destructively). The position of the
cursor is undefined if an attempt is made to move it beyond the
end of a line. The preferred result is that cursor and screen
remain unchanged in such a case.
-
Cursor Home:
-
Move the cursor to the upper left-hand corner
of the screen without changing the other contents of the screen.
-
Cursor X,Y Positioning:
-
Move the cursor to some absolutely
determined row and column without disturbing the contents of the
screen. The result is undefined if an attempt is made to move the
cursor to a non-existent position.
-
Erase to End of Screen:
-
Erase from the cursor position to
the end of the screen, leaving the cursor where it started and the
other contents of the screen undisturbed.
-
Erase to End of Line:
-
Erase from the cursor position to the
end of the current line, leaving the cursor where it started and
the rest of the screen undisturbed.
4.5.1.3 Input Requirements
Input from the keyboard should not be echoed to the screen by
BIOS; this function will be handled by RSP/IO. Keys which
represent ASCII characters should generate eight bit codes between
0 and 127. Problems were encountered with an implementation in
which an early form of BIOS returned ASCII with the high bit set
(i.e. between 128 and 255). In that instance, the high bit had to
be turned off by RSP/IO before the character was used. Other
[non-ASCII,
e.g. special function] kegs can generate codes between 128
and 255 if desired.
4.5.1.4 Input Options
If possible, we recommend that the console input BIOS be
responsible for the following special functions:
4.5.1.4.1 START/STOP
The START/STOP character is used to control console output.
When START/STOP (a soft character) is received, console output is
suspended until (a) another START/STOP character is received or
(b) the BREAK character is received. Action to take in the latter
case is discussed below. Should the former case occur, the
suspended activities should resume exactly as they left off. The
chief benefit gained through this arrangement is to enable
the user to suspend console output processes which are proceeding
faster than he would like, e.g. a text file scrolling across the
screen at 9600 baud. The suspension process takes place wholly
within BIOS and requires no communication to RSP. Note that the
queueing of keyboard input should continue during the suspension.
4.5.1.4.2 FLUSH
FLUSH is another soft control character; when FLUSH is typed,
the console output BIOS throws away all output characters (i.e.
does not display them now or ever) until FLUSH is typed again,
input is requested from the console BIOS or the console BIOS is
reinitialized. This feature is useful when a long text file is
being displayed on the console and you're tired of looking at it.
Push FLUSH and it terminates rather quickly. It is also useful
when a process is generating console output which significantly
slows the rate at which the process proceeds.
4.5.1.4.3 ALPHALOCK
Keyboards supporting both upper and lower case characters
should have an alpha-lock facility; something which causes all
alphabetic keys to generate upper case without shifting the other
keys. If the hardware does not support such a feature (i.e. an
alphalock key), it should be done by BIOS. It should be
implemented as a “toggle” controlled by the ALPHALOCK soft
character.
4.5.1.4.4 BREAK
The remaining special character to watch for is BREAK, also a
soft character. When BREAK is typed, the console input BIOS
should immediately give control to a special RSP routine. The
vector to this special routine will be passed at console
initialization time. Note that receipt of BREAK should terminate
any START/STOP suspension pending.
4.5.1.4.5 Type-Ahead
When non-special (i.e. not described in the section above)
characters are received from the keyboard with no read request
pending, they should be queued until the next read request, which
should be serviced from the queue. When characters in excess of
the maximum queue size are received, they should be ignored and
the queue remain intact. While a type-ahead of even one
character is better than none at all, we recommend a minimum queue
capacity of about 20 characters, up to a maximum of about 80. If
possible the bell should be sounded for each character entered
from the keyboard after no room remains in the queue.
When operating with a keyboard that is not interrupt-driven,
it is possible to provide type-ahead by polling the console status
at strategic locations elsewhere in the BIOS. This will work
fairly well if the current process is spending a lot of time doing
I/O, however characters may well get lost. For this reason we
suggest that only the BREAK character be sensed in this manner.
Complete type-ahead may be done this way at the user's own risk.
4.5.1.5 Initialization
Initialization of the console BIOS will make use of the
information in the UIR for several purposes:
-
(1) Serial Line Settings
-
If the serial
line interface hardware provides software-selection of any of its
parameters, they should be set in accordance with the UIR.
-
(2) Soft Control Character Recognition
-
The BIOS
should use the character codes in the UIR to set the control
characters it is sensitive to.
-
(3) BREAK vector
-
The UIR contains the address of the
Interpreter subroutine which will recover from user BREAK
requests.
The structure of the console UIR is shown in figure 3.4.
Initialization should also cause any START/STOP and FLUSH flags to
be cleared and any characters currently in the type-ahead queue to
be discarded.
Note that the console display should remain unchanged after
console initialization. Specifically, the BIOS should NOT issue a
clearscrean during initialization. The Pascal system is
responsible for issuing clearscreens when needed.
4.5.2 Printer
The Printer unit is conceived of as being a line printer or
other hard copy device. Any ASCII display device may be used in
actuality.
4.5.2.1 Output Requirements
In order to serve the widest variety of hard copy devices,
RSP/IO does not buffer a line of text and send it all at once.
Rather it sends the printer BIOS a single character at a time.
Since some line printers must buffer a line and then print it all at
once, this becomes a BIOS requirement if such a device is to be
served. Thus, in order to determine when a line is finished, the
BIOS must recognize certain line delimiter characters. These
characters may have additional meaning besides just being line
delimiters. They are summarized:
Line Delimiters
-
CR <carriage return> (hex 0D)
-
Print the line. An
automatic line feed should NOT be done. If the hardware requires
that a line feed be performed, then if the next character is a
line feed it must be ignored.
-
LF <line feed> (hex 0A)
-
In normal operations RSP/IO will
only send LF's to BIOS immediately after a CR. Should a LF be sent
which is NOT preceded by a CR, it must be interpreted as a line
delimiter. If the hardware allows a simple line feed to be
performed (without a return) then this should be done. If, as
would be the case with a line printers a complete “new
line” operation (return and line feed) is all that can be done,
then this may be allowed.
-
FF <form feed> (hex 0C)
-
The printer should advance the
paper to top-of-form if possible and perform a carriage return.
If no such feature is available, the printer may execute a “new
line” operation, i.e. a return followed by a line feed.
4.5.2.2 Input Requirements
The printer is allowed to talk back to the Pascal system in
much the same way as the console or remote units. The printer
BIOS may watch for START/STOP or FLUSH control characters coming
from the printer if desired.
4.5.2.3 Initialization
Initialization of the printer should make sure that it is
ready to print at the beginning of a blank line, thus a “new line”
(return and line feed) operation may be in order. Any
characters which have been buffered but not printed are lost. It
is not desired that the printer perform a form-feed each time it
is initialized.
4.5.3 Disk
4.5.3.1 Mapping Logical Blocks onto Physical
Sectors
4.5.3.1.1 Interleaving
A primary function of the disk BIOS is mapping the 512 byte
Pascal logical blocks onto one or more physical sectors of some
arbitrary size (see section 2.3).
In the simplest possible
schemes the disk has 512 byte sectors and logical block numbers
are identical to physical sector numbers. The most common
situation (IBM format floppy disks) finds us with 128 byte
physical sectors. Here, the simplest mapping would establish the
correspondence between a logical block and four consecutive
sectors. Due to limitations in disk hardware, however, it is
quite common to interleave “logical sectors” on the disk.
When Interleaving is used, the disk driver, when asked for,
say, eight consecutive sectors, may actually transfer sectors
1, 3, 5, ..., 15. Since the same interleaving algorithm is used for
both reading and writing, the interleaving is transparent to the
user (until he tries to use his disk on a system using different
interleaving). The advantage in using interleaving is that the
hardware may not be fast enough to pick up physically contiguous
sectors on a single disk revolution, but, with an appropriate
interleaving algorithm, will be able to pick up sectors that are
logically contiguous, though not physically contiguous, on a
single revolution.
The UCSD Pascal system makes no assumptions about the
interleaving method used by the BIOS, except that it works.
4.5.3.1.2 Bootstrap Location
While bootstrap schemes vary, typical UCSD Pascal
implementations make use of a hardware (usually ROM) bootstrap to
load and execute a primary software bootstrap which, in turn,
loads and executes a secondary software bootstrap. The secondary
bootstrap then loads the Pascal interpreter and operating system,
performs required initialization and starts UCSD Pascal. To be
accessible to the hardware bootstrap, the primary software
bootstrap must reside at a location on the disk which is
predetermined by the hardware vendor. Since these locations can
vary widely, it is necessary for UCSD's physical disk format
requirements to be flexible in this regard.
There are two primary requirements which must be met: (1) The
primary bootstrap area must not overlap disk data structures
maintained by the Pascal system and (2) The primary bootstrap area
must be accessible to the Pascal system to facilitate maintenance
of the bootstrap code.
The Pascal system reserves logical blocks 0 and 1 for
bootstrap code, thus allowing 1024 bytes in the interleaving
format used on the rest of the disk. Thus the simplest solution
is to map the Pascal logical blocks onto the disk so that the
primary and secondary bootstraps are together in blocks 0 and 1.
If 1024 bytes is not enough, or if the interleaving format is
unacceptable to the hardware bootstrap, then the primary bootstrap
area must be outside of the “Pascal disk”. The Pascal logical
blocks must be mapped onto the disk in such a way that the
hardware-defined bootstrap area is inaccessible to the Pascal
system as a logical block (it will still be accessible in
physical sector mode).
The details of the bootstrap procedure are not discussed in
this document.
4.5.3.2 Output Requirements
Nothing fancy here, simply transfer however many physical
sectors are needed to accommodate the data. To make it simple,
after a disk-write in which (BYTESTOTRANSFER mod 512) is not equal
to zero (i.e. the last block is partially written to), the
remaining contents of the last block are undefined. This makes it
possible to write whatever garbage remains in a buffer if that is
convenient to fill up a whole sector. Figure 4.0 illustrates this
situation. The Pascal level is responsible for keeping track (in
logical block numbers and byte counts) of where the good data is.
Example: Write to disk.
Number of bytes to transfer = | 1174 |
Starting logical block number = | 72 |
Data area address = | (irrelevant) |
+-------------------+-------------------+-----:-------------+
| | | : |
| Block 72 | Block 73 | Block 74 |
| (512 bytes) | (512 bytes) | 150 : 362 bytes |
|<====================data===================>: (undefined) |
| | | : |
+-------------------+-------------------+-----:-------------+
:start of data end of data: :
end of last block:
|
Figure 4.0 — State of Blocks on Disk After Being Written To
|
4.5.3.3 Input Requirements
On input from the disk, it is certainly not permissible to
overwrite the end of the assigned data area! Therefore, BIOS is
responsible for transferring exactly the number of bytes
requested. This can probably best be accomplished by buffering
the last sector and then transferring that part of it which was
requested.
4.5.3.4 Initialization
Initializing a disk unit should bring it to a state in which
it is ready to read or write from/to any given track or sector.
For some drives with simple controllers, the head should be
stepped to track 0 to facilitate the BIOS disk driver's
remembering the current track.
4.5.3.5 Physical Sector Mode
When the PHYSSECT bit of the CONTROL word is set, disk access
should be performed in the manner described in section 2.3.1. The
BIOS is responsible for returning a completion code of 18 if the
byte count is not zero.
4.5.4 Remote
This unit is intended to be an RS-232 serial line for
supporting various types of communication.
4.5.4.1 Output Requirements
Output is made a single byte at a time.
4.5.4.2 Input Requirements
If interrupt-driven, input should be captured in a
“type-ahead”
buffer similar to that used for the console unit. The
buffer should be 80 or more bytes long.
4.5.4.3 Initialization
On initialization, the remote BIOS is passed a pointer to a
UIR. The structure of the UIR for the remote unit is shown in
figure 3.4. If software selection of any of these serial
interface settings is possible then it should be done.
4.6 Special BIOS Calls
These functions are provided by the BIOS to make
configuration-specific functions accessible to the Interpreter.
Although these functions are not related to Input/Output, they are
put in the BIOS as the repository for configuration-specific code.
4.6.1 Memory Sizing
Since the Interpreter is designed to run in various sizes of
memory, it must know the address of the last accessible word. A
call to the memory sizing function of BIOS should return this
address. Note that a “word” address should be returned,
i.e. on
an 8080 system with 64k bytes of RAM the last byte address is
‘FFFF’, but the last word address is ‘FFFE’.
In many BIOS implementations, it will be possible to return a
simple assembly-time constant. If, however, dynamic memory sizing
must be performed, the sampling routine should restore the
contents of memory sampled.
4.6.2 System Halt
The system halt routine in BIOS should perform whatever is
necessary to terminate Pascal execution in an orderly fashion,
e.g. eject disks. Note that the Pascal system itself will already
have taken care of Pascal-ish details such as closing files.
4.6.3 Start Clock
If the system is equipped with a real-time clock it should be
started, otherwise this call may be ignored.
This page last regenerated Sun Jul 25 13:37:38 2010.