4.0 The Machine Level: BIOS


p.20 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

p.21 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:

CodeMeaning
0No error
1CRC error
3Illegal operation on unit
9Unit not on line
16 Write attempt to write-protected disk
17Illegal Block or Sector number
18 Non-zero byte count (physical sector mode)
19Error in UIR
100..199Hardware 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

p.22 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:
  1. a starting logical block number as described above,
  2. a count of the number of bytes to transfer (unsigned 16 bits, i.e. 0 to 64K),
  3. the address of the data area to transfer to or from,
  4. a drive number (0..n-1, given n drives; currently n = 6 is assumed), and
  5. 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.

p.23 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

p.24

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.

p.25 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.

p.26 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
p.27 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.

p.28 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

p.29 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

p.30 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

p.31 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.

p.32 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

p.33 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’.

p.34 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.