BK Complete

You might also like

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 703

Introduction to AutoBios

1. About AutoBios
This section introduces AutoBios, lists some reasons for creating your own customized Bios, explains
Ownership and License information, and provides an Overview of the structure of the Bios.

1.1 Introduction to AutoBios


Unseen and unnoticed, the Bios (Basic input/output system) of a personal computer takes control when
power is switched on, setting up the hardware devices, running tests, and booting up the operating system
from disk. Without a Bios the machine is an unusable, non-operating collection of hardware
components. Yet the Bios is a mysterious component for the majority of users. The Bios is a collection
of programs stored on a read-only memory chip and is usually considered to be part of the hardware set,
but these routines are like any other software. They can be analyzed, understood, modified and re-created
as desired.

1.1.1 This Book


This book is a guide to analyzing and understanding what a Bios is, how it works, and how one goes
about creating a Bios. The descriptions of the Bios functions are augmented with listings of the
programs required to perform those functions. The auxiliary tools and utility programs which are used to
create the Bios are also included with an explanation of their purpose and function.

1.1.2 What is the Bios?


Bios is an acronym for Basic input/output system. It is a set of programs that reside in non-volatile
memory (often called firmware; programs that are implemented in hardware memory chip(s) and are not
lost when power is turned off). The Bios includes the power-on diagnostics, a boot-up program, and
device drivers for the keyboard, disk, display, serial ports, printer port, and miscellaneous functions. A
Bios is usually written in assembly language, but AutoBios is done in the C language wherever possible.
Some low-level operations require assembly language for memory allocation reasons and some
operations are done in assembly language for efficiency. But by providing the bulk of AutoBios in C, it
is much easier to understand, modify, and maintain the code.

1.1.3 Why do your own Bios?


You may want special features, such as special interface card support, SysVue capability, faster bootup,
equipment status displays, and so forth. Some of these features are difficult to implement with a supplied
Bios since you do not have the capability to modify it. Additionally, a standard Bios may not have the
compatibility that you desire. You may also wish to upgrade your machine to newer capabilities that are
included in later generations of compatible computers.
If you are a manufacturer or systems integrator, you may have found that your own Bios requires
expensive long-term commitments to a Bios vendor that may not be able to respond to your needs in a
timely manner. Once you have control of your Bios in your own hands, you will be able to modify and
maintain your Bios at your own discretion.
If you are a manufacturer of systems for use in government or commercial applications which require
delivery of source code for all software included in a system, AutoBios allows you to easily meet these

1
Configuring a Bios

requirements without cumbersome escrow agreements or additional payment to a Bios Supplier to obtain
source code. By including AutoBios Documentation as part of your product, you may satisfy your
project requirements. If your project requires special verification or certification activities, AutoBios not
only gives you access to source code, it also allows you to configure it as you desire.

1.1.4 Intended Audience


This book is intended for various groups of people:
 Those who have an unsatisfied curiosity about the internal workings of their personal computer.
 Those who are involved in the hardware and system design details of PC's and need to understand the
workings of a Bios.
 Those who are creating special applications of PC systems and find that the typical PC Bios may
have some shortcomings or omissions.
 Those who just want to make their own Bios so they can enjoy the satisfaction of having done it.
 And especially for those people that are in more than one just one of the above groups.

1.1.5 About AutoBios


This book and the magnetic media included with it provide you with the source code and explanations
needed for you to customize your own Bios for an AT type compatible computer. The majority of the
source code is in the C language with supporting routines in assembly language. C was chosen for a
variety of reasons, including:
 It is well suited to systems level programs because it permits access to machine features.
 It is widely used, understood, and a de-facto standard among system level programmers.
 There are many publications available for reference, tutorials, as well as periodical publications for
alternate information.
 It is supported by a variety of affordable compilers.
 Its architecture and structure encourage good programming practices which help to minimize the
frustrating aspects of debugging and error-correction.
Because of some restrictive aspects of a Bios program, some of the programs are written in assembly
language, as you might expect with systems-level C programs. This is required because:
 Certain locations in the completed program need to be fixed at absolute memory locations (the reset
jump).
 Constants need to reside in read-only memory and be allocated to the code segment in fixed
locations.
 Some operations such as block moves (used in CRT scrolling, for instance) are much faster than the
C counterparts.

1.1.6 Recommended Tools

2
Introduction to AutoBios

Building and customizing the Bios requires some tools. Knowledge is the basic tool. Then you will
need the physical tools; the hardware and software described below.

1.1.7 Knowledge Tools


Readers should have or be prepared to acquire some degree of skill in the following areas to comprehend
and become proficient in the creation and enhancement of a Bios:
 operation of DOS
 operation of a text editor
 assembly language understanding
 understanding of the C language
 understanding of the PC architecture

There are many excellent publications available on these subjects in addition to the manuals that are
supplied with the software tools listed below. By visiting your library and book store, and by reading
computer periodicals, and especially by talking to computer-interested acquaintances, you will find ways
to augment your knowledge. For those who may be apprehensive about tackling a Bios project,
remember that knowledge is acquired by bits and pieces. Curiosity, patience, and a positive attitude will
be your best ally.

1.1.8 Software Tools


To build the Bios you will need the following tools:
 C Compiler - Microsoft Visual C/C++ Version 1.0/1.5
 Macro-Assembler - Microsoft V 6.11
 Linker - Microsoft (included with MASM or Compiler)
 Debug program (included with MASM)
 Nmake Utility (included with MASM or Compiler)
 An Archive or backup utility is also recommended.
You may chose alternate tools, but they may require some modification of the source code to build and
execute successfully.

1.1.9 Development Tools


Bigger and faster are good guidelines for your development system! At a minimum, use a 386 system (at
least 4 Mbytes RAM - more is more better) to support running the compiler under 386MAX or Windows
(or other DPMI support). Allow 20-25 Mbytes hard disk space for the tools, and 5-10 Mbytes for the
working space for AutoBios files.
Our development lab uses 8-12 PCs (mostly 486s) running Windows for WorkGroups with a collective
2+ Gbyte to share the load, (compiling, documenting, BBS, business programs, multimedia, desktop
publishing, graphics, test-beds, etc.).

3
Configuring a Bios

1.1.10 Prom Programming Tools


To program Eproms for your computer you will need a Prom programmer. The one we use is from
Needhams in Sacramento, CA (916-924-8037). The cost is approximately $150 and has been reliable,
fast, and easy to use. Since it is software driven, device capabilities are periodically updated, and
includes generic Flash chips.
If Flash proms are used, the programmer can perform the erase function. For UV proms, a Walling
Datarase UVProm Eraser is suggested ($35 to $55).
During the development test phase, we usually use Prom Emulators from Technical Solutions.

1.1.11 Target Tools


The programs in this book were designed for use with an "PC" compatible hardware set. This means that
the original PC/XT/AT or the truly compatible "clone/compatibles" will require little or no Bios
modification to operate successfully. There are some areas of difference, however, that may affect your
Bios details. Some of these are described below.
Prom/Rom chip types - Some high volume AT's use masked Rom chips for the Bios. These chips may
or may not have the same electrical characteristics and pinout as the Prom chips you would normally use
for your Bios. You should verify that the pinout of the original Bios chip you intend to replace is
compatible with the chip you will be using. If it is not pin compatible, you may be able to replace it by
using an appropriate adapter.
The next consideration is the addressing capability of the original Bios Socket(s) in your target system.
Depending on the original design, the address mapping may be hard-wired or jumper (or decoding
device) selectable to accommodate the Bios Proms you create. You should have the range of F0000-
FFFFF available for your Bios. This will probably require two Proms, one for even bytes and one for
odd bytes in your target system.
Turbo machines generally interpret a special combination of keystrokes to enter/leave the turbo mode.
This decoding may be added to the keyboard handler (keyboard.c ) in the scan code conversion section of
the hardware interrupt service routine. Turbo-AT's may use one of the spare output pins of the 8042
keyboard controller chip to change the CPU clock speed. To determine if this method is used, you may
manually toggle these bits using Sysvue (Port In and Out commands) to see if this scheme is used to
control the Turbo switching. If you include a Turbo switching feature and subsequently have floppy disk
failures, the DMA clock speed is to be suspected. Some Turbo motherboards switch the DMA clock to
high speed along with the CPU clock. It may be necessary to include an "Unturbo" and "Returbo"
sequence in the floppy disk module (Disk.c) to insure that the DMA is operated at the slow clock speed
during disk transfers. To do this, save the state of the signal used to implement the speed switch upon
entry to the Disk_io handler, and restore it to its previous condition upon exit. A Turbo machine may
have a "Turbo" mode display (typically an LED) to show when it is in turbo mode. This indicator is
usually driven from the same speed switch signal that controls the clock.
One method of investigating compatibility is to attempt to run the standard version of DOS on a
computer. If a given computer operates only with its customized version of DOS, some hardware
incompatibility might be expected.
AT system boards are commonly implemented with an LSI chip-set, which may have special
configuration requirements, although most chip-sets will default to an AT like mode, if no special
configuration is done.

4
Introduction to AutoBios

1.1.12 SysVue
Bonus - AutoBios includes the source code for SysVue, a Prom resident program that provides many of
the features of disk resident Debug programs. SysVue is always available with a keystroke sequence. It
is extremely handy for checking custom features of your Bios. Configuration options in Common.Plt file
let you specify many SysVue options.
Once you have successfully built the standard version of Bios, you will be ready to consider special
versions for your particular application.

1.2 License, Ownership, and Warranty


The following paragraphs explain the ownership (right of title) of the Source Code and of the Binary
Code generated from it, the license granted to you to duplicate the object code, and the warranty of this
published information. This information is important to you. Please read it carefully.
1.2.1 Ownership of Source Code
The Source Code for AutoBios is an intellectual work covered under the copyright laws of the United
States and other countries. Your purchase of the publication "AutoBios" includes a license to use the
Source Code, but does not convey right of title of said Source Code to you. You may use the Source
Code in accordance with the License Agreement as described in the following paragraph(s).

1.2.2 License to Duplicate


With the purchase of AutoBios, The Software Farm has waived the $4.00 per copy license fee for the
first ten (10) copies of AutoBios Binary code for your own use, or for sale in your product. This waiver
DOES NOT permit you to copy, reproduce, distribute, the "Source Code", which must be treated as any
other copyrighted material. For additional authorization to use the "binary code", contact The Software
Farm for the "AutoBios License Agreement"
During the build/customization phases, you may program an unlimited number of "Proms" (or equivalent
device) until you have completed the Bios. Once you place the Proms in a computer used to run
programs, the Proms are included in the ten (10) quantity covered by this license to duplicate.
Any Bios built from AutoBios must include the original copyright information included with the original
source code. You may add additional information, but you shall not delete any copyright information
included in the standard AutoBios.
The Source Code for AutoBios is available only in authorized publications (and electronic media) under
the terms of a publishers agreement. Unauthorized copies of the Source Code (on printed or any other
media) are expressly prohibited

1.2.3 DISCLAIMER AND LIMITED WARRANTY


The information contained in this book and on the diskette is believed to be factual and accurate;
however, no claim of such, nor of fitness to purchaser's intended use, is implied. Although the programs
described in this book (and contained on the diskette) are believed to be compatible in function and
operation with the normal operation of an "PC" class computer, no warranty as to the completeness of
compatibility to any other Bios is implied or expressed. Prudence dictates that the user must verify
fitness, correctness, and applicability of the information contained in this publication. The diskette(s) are
warranted to be readable when installed in a compatible computer. Warranty is limited to the

5
Configuring a Bios

replacement of unreadable diskette(s) within 90 days of purchase. The Diskette(s) are not copy-protected
and should be used only to make working copies, and then archived for backup purposes. Liability under
this warranty is limited to the replacement of the diskette(s) even if claims otherwise have been made by
purchaser or any user of the information contained in this publication. This statement of warranty
constitutes the full and complete agreement between seller and buyer, and may not be modified by oral
representation or written instrument without the permission of The Software Farm.

1.3 Organization of AutoBios


This chapter is intended to acquaint you with the major functions and parts of the Bios. To do this, we
will follow the flow of the Bios from the power-on hardware reset point and summarize what happens as
the computer is turned on. Descriptions of detailed operations will follow in later sections and be
correlated with the Source Code Listings.

1.3.1 Power On -
The processor starts operation at segment:offset address FFFFF:0000. This means that program
execution begins at the last paragraph (16 bytes) at the top of address space. This location normally will
have a far jump to a lower address where the Bios will start to initialize and check-out hardware features
of the system.

1.3.2 Diagnostics -
This usually starts at a label called 'reset' and includes checking of the CPU chip registers, tests and
initialization of the peripheral chips, and ends up by invoking a bootstrap routine.

1.3.3 Bootstrap -
The function of the bootstrap routine is to load DOS from a floppy disk. If you have a hard disk in the
system, a failure to boot from a floppy is usually followed by an attempt to boot from the hard disk. If
no disk is available, you may wish to default to SysVue or some other Prom resident program you may
elect.

1.3.4 Drivers -
The Bios contains the low-level drivers for a variety of devices. DOS normally assumes these drivers are
present in the Bios and makes calls to them to perform peripheral access. The drivers correspond to the
Bios Interrupts documented in various publications about PC's and DOS. To fully support DOS, these
drivers must be included, and their devices initialized by the Bios.

1.3.5 Bios Structure


This description of the Bios structure is intended to clarify some of the characteristics of the Bios.
The processor starts executing code (from a power-up reset) at the highest paragraph in the memory map.
This is at Segment:Offset FFFFF:0000. To properly respond to the hardware reset, valid executable code
must be stored at this location in the Bios Prom. To insure that the instruction intended for this location
is assembled and linked correctly, the final module of the Bios is manipulated in such a way that the

6
Introduction to AutoBios

normal linker utilities (such as Microsoft's Linker which links programs in an ascending address
sequence), can achieve this result. The top module of the Bios is written in Assembly language, so that
programmer control is maintained over the location of certain instructions. Additionally, the top module
provides a place to include various table structures and assembly language subroutines, which are C
functions.
From the power-on reset, a jump is executed (at FFFFF:0000) to an assembly language initialization code
sequence which initializes the DMA controller, the Ram Refresh, and the first 64 Kbytes of System Ram.
Once this has been accomplished, the C language POD (Power On Diagnostic) module is executed. This
module continues the power-up and diagnostic checks of the system, and also calls setup (initialization)
routines in the various device driver modules. When the system has been completely initialized, the
bootstrap function is called.

The POD process includes:


 loading the interrupt vector locations,
 initializing the display adapter,
 determining the size of the system Ram,
 testing the system Ram,
 reading the equipment configuration CMOS Ram,
 performing a checksum test on the Bios prom,
 identifying and initializing COM and LPT ports,
 calling any executable Rom option modules,
 initializing the floppy disk drive(s),
 and finally calling the bootstrap procedure.

1.3.6 Why Link is Done Twice


During the linking process when building the Bios, a trial link is performed. This trial link determines
how far short the Bios falls of filling a complete segment (64 Kbytes). This shortfall in length is
calculated, and a filler module is built which will compensate for the shortfall. The Bios is then linked
again with the filler module to produce a Bios in which the required locations are fixed at the correct
addresses. This file is then converted from an .EXE format file to a .BIN binary image file suitable for
transfer to a Prom programmer. Specialized linkers which offer absolute fixup values (such as Link &
Locate) can perform a final link in one step. If you have access to such a tool, the makefile may be
modified accordingly. In the author's opinion, the time required to perform the extra link is generally
inconsequential balanced against the extra cost for a special linker.

1.3.7 How to develop and test a Bios


The simplest way, of course, is to build a Bios, program a Prom, install the Prom in the system, and see
how the system runs. This method is time consuming and debugging can be difficult, particularly if the
system doesn't run at all.

7
Configuring a Bios

The preferred method is to use a Prom Emulator to eliminate the need to remove and reprogram prom
chips. The emulator may be connected to a "host" machine downloads the Bios-under-Test.
An additional aid to testing is to add debug mode display statements to track the activity of the Bios.
These may be included in your C modules by using the printf("args") statement. The printf function
(printf.c) is similar in usage to the standard C function, but has some variation on argument types to
support the requirements of the Bios and SysVue.
Another test aid is a "PostCode" adapter which responds to Port I/O commands (usually at I/O Port 80),
and displays a two-character Hex code. For those systems with ISA bus connectors, a ready-made board
may be obtained. For other systems, the decoding logic may be added to the system board design.
When you have verified the operation of your modified Bios, the debug-mode statements may be
removed, and the Bios rebuilt.

1.3.8 Driver Structure


By examining the structure of the Driver modules, you will see that they are essentially self-contained.
They may call common assembly language functions in BiosJump.asm and common C functions in
Misc.c, but they seldom will call other modules except through the Interrupt structure. This helps to
isolate interaction and serves to make testing easier.
Drivers have the general structure of a Setup routine followed by the Driver itself. Some drivers may
also have a service routine for its associated hardware interrupt. The Setup routines are called from
BiosPod to initialize the drivers during the Power-On-Diagnostics.

1.3.9 Programming Style


As you work with the source code, you will begin to apply your particular style of programming to re-
writes, additions, and changes. This is normal and it is a sign of your increasing understanding of the
programs. Don't be afraid to analyze the program structure and experiment. There are at least as many
ways to code a function as there are programmers! Since this book deals with each topic only once, we
had to present each example in a particular manner. You have a different perspective and style, and you
will probably see it in a slightly different manner. Remember there are many right ways to code a
function. It is sometimes difficult to find one of those right ways; it is usually easier to find one of the
wrong ways!

1.3.10 Structure Overview

1.3.11 Build Hierarchy


The build hierarchy addresses the method of using top-level files to direct and specify how a particular
version of a Bios is constructed.
Most of the source code modules used in a Bios require very few, and mostly standardized, variations to
support many Bios applications. By using conditional compilation and assembly directives, these
variations can be selected at build time to create a specific Bios. The directives to select these options are

8
Introduction to AutoBios

consolidated in a top-level file used to direct both the "make" process and the individual module
configuration.
This top-level file (Myfile.Job) is the primary device by which configuration is specified. By
maintaining project specific information in this file, a particular Bios can be re-created as desired. Lower
level modules may be updated independently, without creating regression. This hierarchy allows the
Bios to evolve (as software is known to do) with a minimum impact on the developer.

1.3.12 Output Files


The product of a Bios build is a set of binary image files which are to be programmed into suitable prom
chip(s). Some system boards may be configured to accept one prom containing the Bios, and the
AutoBios output file Bios.Bin contains the binary image for this prom. Other system boards may require
two proms, an even (Low) and an odd (High), and AutoBios will produce these files; Bios.Evn and
Bios.Odd.
A Cfg equate in the .Job file may be used to specify whether the Evn and Odd files are produced from the
normal Bios.Bin file.
Many programmers will accept binary image files directly, so these files need no further conversion. A
Bin2Hex conversion utility is provided with AutoBios should you need the Intel Hexadecimal Format.
This utility is provided in the form of a filter:

Bin2Hex <input stream >output stream

where the input filename is specified for the input stream, and the output stream may be another file, the
console device, a printer, or a serial channel, as shown in the examples below:

Bin2Hex <Bios.Bin >Bios.Hex


Bin2Hex <Bios.Bin >con
Bin2Hex <Bios.Bin >LPT1
Bin2Hex <Bios.Bin >Com1

9
Introduction to AutoBios

2. The Utility Programs


These programs are used during the building process to add the date-stamp, calculate the checksum and
to fix some locations at absolute addresses.

2.1 Utilities used during the Nmake process

2.1.1 The Extract Utility


Because of the great variety of chipsets used in system boards, the concept of Chip-specific personality
modules (.Chp) provides an easy way to provide chip support on an ongoing basis. As new chipset
support is created, it may be added to the "library" of .Chp modules, without requiring modifications in
the core-set of AutoBios programs.
This chipset support may have multiple components; the original chip control register initialization,
memory controller configuration, enhanced feature support, diagnostic dumps, chip identification
information, etc.
To allow these functions to be written in the most appropriate form would normally require multiple
source files (typically .C, .H, .ASM) which would require creating, naming, and maintaining three
modules, rather than just one module.
In order to permit the use of only one support module per chipset, a convention has been implemented to
allow the one module to contain multiple language types. The Makefile then reads this module and
extracts the desired language portions and creates a temporary module(s) to be used during build. An
inspection of a .Chp module will show the use of the "[Extract]" and the "[Break]" keywords. These
keywords define the portion of the source file to be extracted to the appropriate temporary file.
The line containing the [Extract] keyword also has a following keyword ([C], [H], [ASM]) to specify the
particular language type being extracted. The line(s) following the keyword will be copied until the
[Break] keyword is encountered.
//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] The Mixed Source Extraction Program
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] EXTRACT.C
//
// [Description] This program reads a mixed-source file, looking for
// [Description] looking for the keyword argument.
// [Description] When it finds a keyword, it copies the following lines
// [Description] until a [break] keyword is found, to an output file.

11
Configuring a Bios

// [Description] Example: keywords are [h], [c], [asm].


//
// [Usage] Extract files.vrs "keyword" OutputFilename <enter>
//
// [Arguments] MixedFileName "Keyword" OutputFilename
//
// [Return] Creates file(s) with extracted data
//
// [Notes] None
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

enum { False,True };

// I N C L U D E F I L E S

#include <stdio.h>
#include <string.h>
#include <process.h>
#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <dos.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>

// F U N C T I O N P R O T O T Y P E S

// V A R I A B L E S

// This is the input line string


char line[255];
char * charptr;

// these are the temp saves for file time and date
unsigned FileDate;
unsigned FileTime;

unsigned BreakFlag = False;

char ExtractKeyword[] = "[Extract]";

unsigned Date,Time;
int fh;

unsigned DotCounter = 10;

FILE *instream,*outstream;

void main(int argc,char *argv[])


{
printf("\nMixed Source Extraction Program Version 1.00 5-25-93");
printf("\nCopyright 1994 John O. Foster - All Rights Reserved.\n");

12
Introduction to AutoBios

if (argc < 3)
{
printf("\nUsage is Extract MixedFileName \"[Keyword]\" OutputFile <enter>");
exit(0);
}

// Open the MixedSourceFile for Input


if((instream = fopen(argv[1],"r")) == 0)
{
printf("\nInput file not found"); exit(1);
};

printf("\nScanning File: %s for Keywords [Extract] ...


%s\n",argv[1],argv[2]);
// Open a OutputFile for output

if(!(outstream = fopen(argv[3], "w" )))


{ printf("\nCould not open output file"); exit(1); };

// Read each line of the input file, and scan for keywords
while (fgets(line,255,instream))
{

// Remove the newline char, if present


if(charptr = strrchr(line,(int)'\n')) *charptr = 0;

// if [Extract] [keyword] found, start copying lines


if(strstr(line,ExtractKeyword) && strstr(line,argv[2]))
{
printf("\nExtracting ");
// advance to next line
if(!fgets(line,255,instream)) BreakFlag = True;

while((!strstr(line,"[Break]")) && !BreakFlag)


{
fputs(line,outstream);
if(!--DotCounter) { DotCounter = 10; printf("."); };
if(!fgets(line,255,instream)) BreakFlag = True;
};
};
};
fcloseall();
printf(" Done\n\n");
};

2.1.2 The Touch Utility


This utility "touches" the time/date stamp of a file, and sets it to the current system time. It is commonly
used to alter a file's time/date stamp so that a make utility such as NMAKE will be forced to rebuild
certain files upon finding a dependent is "newer" than a target. AutoBios uses touch to force rebuilding
when there is a change in the Job, Chip, or Platform specifications since the previous build.

13
Configuring a Bios

Touch may also be used to re-stamp a group of files when desired to align them with a major milestone
event, such as a product release, etc. Wildcard specifiers are allowed with Touch.
//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] The File Time/Date Stamp Touch Utility
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] TOUCH.C
//
// [Description] This program updates the time/date stamp(s)
// [Description] for the specified files.
//
// [Usage] Touch filespec <enter>
//
// [Return] Sets time/date stamp on files to current value.
//
// [Notes] None
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

enum { False,True };

// I N C L U D E F I L E S

#include <process.h>
#include <stdio.h>
#include <dos.h>
#include <sys\types.h>
#include <sys\utime.h>

//---------------------------------------------------------------

void main(int argc,char *argv[])


{
struct _find_t c_file;
printf("\nFile Touch Program Version 1.00 5-25-93");
printf("\nCopyright 1993 John O. Foster - All Rights Reserved.");
if (argc < 1)
{
printf("\nUsage is Touch filespec <enter>"); exit(0);
}

// find first .c file in current directory


if(_dos_findfirst( argv[1], _A_NORMAL, &c_file ) == 0)

14
Introduction to AutoBios

{
printf("\nTouching %s",c_file.name);
if( _utime( c_file.name, NULL ) == -1 ) exit(1);
}

while( _dos_findnext( &c_file ) == 0 )


{
printf("\nTouching %s",c_file.name);
if( _utime( c_file.name, NULL ) == -1 ) exit(1);
};
printf("\n");
}

2.1.3 The BookMark Utility


This utility extracts sections of a named file which are enclosed by the [BookMark] and [EndBookMark]
keywords. The BookMark keywords allow modules to be written in a complete compilable module, and
also permit the body of these programs to be extracted and included in a superior program module.
//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Indent Utility
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 07/15/94
//
// [File Name] INDENT.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This program is a utility which is used to indent C
// [Description] source code lines according to the nesting level of
// [Description] the left and right bracket characters ( { } ). It
// [Description] improves readability of the souce file, but does not
// [Description] affect the logic flow. It is useful when a general
// [Description] purpose editor is being used to prepare source files.
//
// [Arguments] Indent File name <enter>
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//

15
Configuring a Bios

//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include <stdio.h>
#include <process.h>
#include <io.h>
#include <string.h>

/* G L O B A L V A R I A B L E S */

enum { False, True, };

FILE *instream;
FILE *outstream;
unsigned long length;
unsigned int i,numread,numwritten, tab = 0;
#define blen 512
unsigned char instring[blen], outstring[blen], buffer[16384];

unsigned write_ok = True;

/* L O C A L D E F I N I T I O N S */

#define tabchar 9
#define rt_brace 125
#define lf_brace 123
#define indent_level 1 /* # of columns to indent */

/* P R O G R A M */

/* indent c programs according to {} characters */

void main(int argc, char *argv[])


{
printf("\nIndent Source Utility Version 3.00 05-25-93");
printf("\nCopyright 1993 John O. Foster - All Rights Reserved.\n");
if (argc <2)
{
printf("Usage is Indent filename <enter>\n");
exit(0);
}

if ((instream = fopen(argv[1],"r")) == NULL)


printf("Could not open file for reading\n");
else
{
length = filelength(fileno(instream));
if (length == -1) printf("Bad Length on input file\n");
else
{
if ((outstream = fopen("$id.$$$","w")) == NULL)
printf("Could not open file for writing\n");
else
{
tab=0;

16
Introduction to AutoBios

while (fgets(instring,blen,instream) != 0)
{
// skip over leading spaces
i=0; while (instring[i++] == ' '); i--;
// check for right brace here so we de-indent the current line
if ((instring[i] == rt_brace) && (tab >= indent_level))
tab -= indent_level;

// pad front of output string with required # of spaces


strnset(outstring,' ',tab);outstring[tab] = 0;

// now copy instring[i] to outstring[tab]


strcat(&outstring[tab],&instring[i]);

// write to the temp file and mark any errors


if(fputs(outstring,outstream) != 0) write_ok = False;;
// check for left braces here so we indent the following line
if (instring[i] == lf_brace)
{
tab += indent_level;
// check for closing brace on same line
for(; i<strlen(instring);i++)
{
if ((instring[i] == rt_brace) && (tab >= indent_level))
{
tab -= indent_level;
break;
}
}
}
}
}
}
fclose(instream);
fclose(outstream);

if(!write_ok)
{
printf("Error in writing temporary file, processing aborted.\n");
printf("Original file %s remains unchanged.\n",argv[1]);
}
else
{
// now copy the $id.$$$ to the original file
if (((instream = fopen("$id.$$$","r+b")) != NULL) &&
((outstream=fopen(argv[1],"w+b")) != NULL))
{
do
{
numread = fread((char *)buffer, sizeof(char),16384,instream);
numwritten = fwrite((char *)buffer, sizeof(char),numread,outstream);
if (numwritten != numread)
{
printf("Transfer error on file %s. Use $ID.$$$ as recovery
file./n",argv[1]);
write_ok = False;

17
Configuring a Bios

}
}
while (numread > 0);
fclose(instream);
fclose(outstream);
if(write_ok)
if ((numread = remove ("$id.$$$")) != 0)
printf("Error deleting temp file $ID.$$$\n");
}
}
}
}

2.1.4 The Job 2 H Translator


The Job2H Translator is a Software Farm created utility that greatly simplifies the construction process
for the Bios. The original plan for AutoBios called for the use of "Master" configuration files to be used
for defining the personality of a Bios, hence the abbreviation "M" for Master. The .Job and .Plt files are
constructed in a format acceptable the Nmake utility, allowing them to specify options in the Make
process itself, as well as being translatable by Job2H into .H files for the C compiler. The H2INC utility
provided as part of the MASM toolset further translates the files into .INC files which are used by the
Assembly language portions of AutoBios.
This approach creates a coordinated synchronized construction process, and permits a wide variety of
personalization by editing one master file. By minimizing the need to customize or modify individual
modules, periodic source updates are easily handled.
//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] .job (include) file to C.H File Converter
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 08/05/94
//
// [File Name] Job2H.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This utility program will read an NMAKE description
// [Description] file and convert it into a C recognizable .H file.
// [Description] The purpose is to allow a top level description
// [Description] which provides conditional settings to act as an .h
// [Description] file for C modules. The H2INC translator may be
// [Description] used to further convert the .H to a usable masm.INC
// [Description] file for assembly language modules.
//
// The translation rules will:

18
Introduction to AutoBios

// 1. Ignore comment lines beginning with a '#' sign


// 2. Convert '!' conditional prefixes to pragma '#' prefixes
// 3. Translate the expression form <name = string> to
// <#define name string>
//
//
// [History] 2.00 08/05/94 Original
//
//---------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include <stdio.h>
#include <string.h>
#include <process.h>
#include <io.h>

/* G L O B A L V A R I A B L E S */

FILE *instream;
FILE *outstream;

#define blen 512


char InString[blen],OutString[blen];
char InName[16], OutName[16];

char *EqLoc;
unsigned DotCounter = 10;

/* L O C A L D E F I N I T I O N S */

//#define NULL ((void *) 0)


#ifndef True
#define True -1
#endif

#ifndef False
#define False 0
#endif

/* MAIN Program */

void main(int argc, char *argv[])


{
printf("\njob.tmp to .H file converter Version 2.00 08-05-94");
printf("\nCopyright (c) 1994 John O. Foster - All Rights Reserved.");

if ((argc <3) || (stricmp(argv[1],"/?") == 0))


{
printf("\nUsage is Job2H infilename.ext outfilename(.H) <enter>");
printf("\nThe output file extension does not need to be specified.");
printf("\nThe syntax will be converted to .H #pragma syntax.");
exit(1);
}

19
Configuring a Bios

/*----- build the assumed filenames ---------*/

strcpy(InName,argv[1]);
strcpy(OutName,argv[2]); strcat(OutName,".H");

/*---- Now Start the Process -----------*/

if ((instream = fopen(InName,"r")) == NULL)


{
printf("\nCould not open file %s for reading\n",InName);
fclose(instream);
exit(1);
}

if (filelength(fileno(instream))== -1)
{
printf("\nBad Length on input file %s\n",InName);
fclose(instream);
exit(1);
}

if ((outstream = fopen(OutName,"w")) == NULL)


{
printf("=nCould not open file %s for writing\n",OutName);
fclose(instream);
fclose(outstream);
exit(1);
}

/*-------------------------------------------------------------*/
/*
** Now we have both files open, and we can start translating line by line
*/

printf("\nTranslating ");

while (fgets(InString,blen,instream) != NULL)


{
OutString[0] = 0; /* Null out the OutString */
if(strncmp(InString,"#",1) != 0) /* ignore comment lines */
{
if(strncmp(InString,"!",1) == 0) /* found a '!' */
{
InString[0] = '#'; /* replace with a '#' */
strcpy(OutString,InString); /* copy it to the OutString */
}

EqLoc = InString + strcspn(InString,"=");


if(*EqLoc == '=') /* Just in case no find occurred */
{
*EqLoc = ' '; /* replace with a space */
/* build the form "#define x y" */
strcat(OutString,"#define "); strcat(OutString,InString);
};

/* write the string out */

20
Introduction to AutoBios

if(strlen(OutString) != 0)
{
fputs(OutString,outstream);
if(!--DotCounter) { DotCounter = 10; printf("."); };
}
}
}
printf(" Done\n\n");
fclose(instream);
fclose(outstream);
exit(0);
}

2.1.5 The BiosGen Program


One of the characteristics of the x86 family of processors is that code execution after reset begins at the
highest paragraph memory address. To insure that a valid executable instruction resides at this high
paragraph address, certain code modules need to be located at explicit addresses. Most code module's
locations may be left to the Linker for inclusion and placement. One specific module of the Bios
(BiosJump.asm) is intended to be explicitly placed. Normal Linker operation is to include module-after-
module, starting at segment offset 0000 and including modules at ascending addresses. The total space
used is a function of the total size of the modules involved, and the highest location may be at various
locations for different build sessions, depending on the actual code generated by the compiler and
assembler.
Specialized Linkers provide specific locating directives for selected modules, and provide for explicitly
locating modules. The standard Linker included with the Microsoft Toolset does not provide this degree
of control, so an alternate method evolved to perform the explicit locating function.
This methods consists of two-pass linking, with the sequence described below:

1. A zero-length Fill .Obj module is created, which will require 0 bytes of space on the 1st pass.
2. The linking order is specified so that the Fill module will be linked prior to the explicit module
(BiosJump).
3. The modules are linked, the total (highest address) being a function of the combined amount of code
(including the zero-length fill module).
4. The highest address used is subtracted from the top of the segment (offset FFFF) and the resulting
value (indicating the shortage) is translated into a text string directive. This evaluation is done by the
BiosGen Utility.
5. A new Fill.Obj module is constructed, using the adjustment value created by BiosGen.
6. A second link is done, in which the Fill module uses the calculated "padding" to occupy sufficient
space to cause to explicit module (BiosJump) to be located at the top of the image.
7. The resulting image (starting usually at offset 0000) contains code for the main Bios modules, Filled
space, then finally the explicit module at the end (top) of the segment, resulting in the power-on reset
code, (as well as other explicit locations) to appear in the correct locations.
The description below summarizes the method by which the Fill value is detected and calculated.

21
Configuring a Bios

The Biosgen.c file is used during the build process to sense the size of the Bios code and calculate a
value which will be used to upward justify the BiosJump module so that it resides in the highest portion
of the Bios segment. Biosgen reads the Bios.Map file from the first link, and detects the actual location
of the calculated position of offset E000. It then creates a filler file (BiosFill.Inc) which is used during
the second link to relocate the BiosJump.Asm modules code to the top of the Bios space.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios filler generator
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] BIOSGEN.C
//
// [Language] MSVC 1.0/1.5
//
// [Category] Bios Build Utility
//
// [Description] This program reads the map file (bios.map) and
// [Description] calculates how far short it falls from ending at
// [Description] the top of the segment. Then it builds a biosfill.inc
// [Description] file that pads out enough to complete the segment
// [Description] (64k bytes). The .inc file is used in a second linking
// [Description] of the .obj files. This produces a full 64k byte file
// [Description] with the power-on reset jumps fixed at offset FFF0 in
// [Description] the binary image file.
//
// [Arguments] biosgen bios.map biosfill.inc
//
// [Return] Creates a biosfill.inc file
//
// [History] 2.00 04/11/94 Original
//
//-------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include <stdio.h>
#include <string.h>
#include <process.h>
#include <stdlib.h>

/* F U N C T I O N P R O T O T Y P E S */

unsigned int hval(unsigned char);

/* G L O B A L V A R I A B L E S */

22
Introduction to AutoBios

FILE *stream;
int radix = 10;
char first[20],second[20],third[20];
char *p;

unsigned int i;
unsigned int diff;
unsigned int find; /* find/no find flag */
unsigned int find_string;
unsigned long int numread;
unsigned char line[255], *result;

/* P R O G R A M */

void main(int argc,char *argv[]) /* sourcefile.map,destfile.inc */


{

/* this is the label we will search for */


char *estring = "_ORG_FFF0";

/* this is where we move the offset value of the label*/

char *vstring = "0000";


printf("\nBiosGen Utility version 1.00 05-25-93");
printf("\nCopyright 1993 John O. Foster - All Rights reserved.\n");
if ((argc <3) || (stricmp(argv[1],"/?") == 0))
{
printf("\nUsage is Biosgen xx.map xxfill.inc <enter>");
printf("\n where xx.map is the map file for the bios, and");
printf("\n xxfill.inc is the fill include file to create");
exit(0);
}
if ((stream = fopen(argv[1],"r+b")) == NULL)
printf("Could not open file for reading\n");
else
{
find = 0;
/* check each line of the .map file for the wanted label*/
do
{
if((result = fgets(line,255,stream)) != NULL);
{
/* check for the label */
if (strstr(result,estring) != NULL)
{
find_string = 0xfff0;
strncpy(vstring,&line[6],4);
diff = 0;
for(i=0;i<4;i++)
{
diff = (diff << 4) + hval(vstring[i]);
}
find = 1;
}
}
}

23
Configuring a Bios

while ((result != NULL) && (find == 0));

fclose(stream);

if (find == 0) /* no find */
{
printf("Could not find ORG_FFF0 label in .MAP file\n\r");
printf("Aborting operation.\n\r");
printf(" 1. Check command line argument specifies .MAP file\n\r");
printf(" 2. Check .MAP file for proper labels.\n\r");
}
else
{
printf(" File size = %5u\n\r",diff+(0x10000-find_string));
if (diff >= find_string)
{
printf(".EXE file is to large to process - aborting fill generation\n\r");
}
else
{
numread = find_string - diff; /* num to write */

printf(" Free Space = %5u\n\r",numread);

/* now build the text line for the biosfill.inc file */


strcpy(first," db ");
strcpy(second,ultoa(numread,second,radix));
strcpy(third," dup(0ffh)");
strcat(first,second);
strcat(first,third);

if ((stream = fopen(argv[2],"w")) == NULL)


printf("Could not open file for writing\n");
else
{
fwrite((char *)first,sizeof(char),strlen(first),stream);
}
}
fclose(stream);
}
}
}

/* convert hex ascii to val */

unsigned hval(unsigned char cval) {


unsigned val;
cval -= '0';
if (cval > 9) cval -= 7;
val = cval;
return(val);
}

24
Introduction to AutoBios

2.1.6 The BiosDate Program

The Biosdate.c file is the program which inserts the current date value as the date-stamp in the Bios
module. This date is determined from the current date in your development machine. It will obviously
affect the overall checksum of the Bios module, if you re-build on different days.
//-------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios date routine
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] BIOSDATE.C
//
// [Language] MSVC 1.0/1.5
//
// [Category] Bios Build Utility
//
// [Description] Insert date string into bios binary file. This program
// [Description] inserts the current date information into the date
// [Description] field in the Bios at location FFF5
//
// [Arguments] Filename
//
// [Return] Writes date field in bios.bin file
//
// [History] 2.00 04/11/94 Original
//
//-------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include <stdio.h>
#include <process.h>
#include <time.h>
#include <string.h>

/* G L O B A L V A R I A B L E S */

FILE *stream;
char date_buffer[9];

/* P R O G R A M */

void main(argc,argv)
int argc;
char *argv[];

25
Configuring a Bios

{
printf("\nBiosDate Utility Ver. 1.00 05-25-93");
printf("\nCopyright 1993 John O. Foster - All Rights Reserved.\n");
if ((argc <2) || (stricmp(argv[1],"/?") == 0))
{
printf("\nUsage is - Biosdate xx.bin <enter>");
printf("\n where xx.bin is name of bios image file");
printf("\n Biosdate inserts today's date string at offset ");
printf("\n FFF5 of the bios image");
exit(0);
}
if ((stream = fopen(argv[1],"r+b")) == NULL)
printf("\nCould not open file for reading\n");
else
{
fseek(stream,-11,SEEK_END); /* find date field */
_strdate(date_buffer);
fwrite((char *)date_buffer,sizeof(char),8,stream);
printf("\nToday's date inserted into file\n");
}
fclose(stream);
}

2.1.7 The BiosSum Utility


The Biossum.c file is used during the Bios Build process to calculate the additive checksum of the Bios
and to insert the checksum value into the last byte of the Bios. It looks for the first non-FF location and
treats it as the start of the block. If the Bios is padded with FF's at the front of the file, the program will
scan forward every 512 bytes to look for the start. This allows you to reserve space in 512 byte blocks at
the front for your own special programs. The Rom-Scan routine will determine where the Bios starts and
scan up to that point.
An internal routine in AutoBios scans the Bios, from the BiosStartLocation Label in the BiosPad.asm
module, to the ending offset of the Bios (FFFF). Space for other functions may be reserved at the front
of the Bios by adjusting the CfgPad definition in the project's .Job file.
Due to a "feature" of the original XT bios, the scan boundaries were 2048 bytes, although the block-
length specifier was modulo 512. A CfgScanBoundaries definition in Common.Plt may be set to specify
either 2048 or 512 byte boundaries. For complete compatibility, the 2048 is preferred, but in projects
under close control, the 512 byte option may provide more efficient use of the scan area. Should you
decide to pad with 512 byte boundaries, insure that any other rom-scan modules in the system (VGA,
Networks, etc.) operate correctly.
//-------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Checksum calculator
//
// [Version] 2.00

26
Introduction to AutoBios

//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] BIOSSUM.C
//
// [Language] MSVC 1.0/1.5
//
// [Category] Bios Build Utility
//
// [Description] This program calculates a checksum and inserts it
// [Description] into the last byte location of the Bios.
//
// [Arguments] Filename
//
// [Return] None
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include <stdio.h>
#include <process.h>
#include <string.h>

/* G L O B A L V A R I A B L E S */

unsigned numread,i;
char sum,buffer[32768];
FILE *stream;

/* P R O G R A M */

void main(argc,argv)
int argc;
char *argv[];
{
printf("\nBiosSum Bios Checksum Utility Version 1.00 05-25-93");
printf("\nCopyright 1993 John O. Foster - All Rights Reserved.\n");
if ((argc <2) || (stricmp(argv[1],"/?") == 0))
{
printf("\nUsage is Biossum xx.bin <enter>");
printf("\n where xx.bin is the binary bios image file.");
exit(0);
}
if ((stream = fopen(argv[1],"r+b")) == NULL)
printf("Could not open file for reading\n");
else
{
sum=0;
numread = fread((char *)buffer,sizeof(char),32768,stream);

//

27
Configuring a Bios

// Scan for the first "CfgEnd" string and advance to the next paragrap mark
the
// start of the checksummed bios code. Reserve the prior cells for rom
module
// integration later when customizing the bios prom
// with extensions.
//

for (i=0;(i < numread) && (strcmp(buffer[i],"CfgEnd") != 0); i += 16);

/* i is advanced to beginning of actual bios code */


for (;i<numread;i +=16) sum += buffer[i];

numread = fread((char *)buffer,sizeof(char),32767,stream);


for (i=0;i<numread;i++) sum += buffer[i];
sum = 0 -sum;
buffer[i] = sum;
fseek(stream,-1L,SEEK_END);
fwrite(&sum,1,1,stream);
}
fclose(stream);
}

2.1.8 The Version Information Utility


One objective of AutoBios, right from the start, was to provide a means to easily allow future expansion,
updating, and maintenance for source code files which would allow the structure to support a lengthy
lifetime. Knowing well from past experience that platforms, chipsets, tools, features and applications
would be subject to change, modules were (are will be) intentionally reduced in size and scope, using the
library concept to build a configurable set of modules which could be adapted with minimum interaction
to existing modules. This caused the quantity of modules to grow to (at present) 150+. To simplify the
task of tracking module status, the idea of in integrated version status reporting utility was implemented.
On the premise that, if version description could be included in the source code module (hopefully easing
the nuisance of keeping the status current) and a simple method of extracting this information were
available in a flexible form, keeping track of the current version, revision level, etc. would be welcome.
As future needs arise, the data may be manipulated to produce useful summaries.
To make this possible, a simple method of tagging descriptive information was designed, consisting of a
bracketed keyword followed by its associated text. These keywords are be placed in text or comment
fields of a module, most forms of which have some Remark or Comment capability.
The Version.c module is the result of this objective. It scans a selection of files (selected by the file
extension) for a selection of bracketed keywords. Since it was desired to allow flexibility in the
selection of file types, the Version program reads a text file containing a list of file extensions, and also
reads a text file containing a list of keywords. This allows easy changes in both the file list and the
keyword list, permitting extreme flexibility in the information extracted. In fact, Version can be run
specifying different file and keyword lists to extract almost any data subset of interest.
Examination of the Makefile will show the instance of Version, and its arguments describe the standard
file and keyword lists, as well as the created output file.

28
Introduction to AutoBios

The output file is written in standard comma-separated-values, which can be used as input to database or
spreadsheet programs, as well as listed in its raw form.
Following the listing of the Version.C module, are listings of the VrsFiles.Def and the VrsWords.Def
modules which are used in the standard Makefile.
//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] The Version Reporting Extraction Program
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] VERSION.C
//
// [Description] This program reads the extension list file (files.vrs)
// [Description] and the keyword file (keywords.vrs) to build a list
// [Description] of file types to scan. If the keywords are found,
// [Description] then the line is written to an output file.
// [Description] The output file may then be used as an input file to
// [Description] a database manager to generate desired reports.
// [Description] An Index value is also written for each output line,
// [Description] This value serves to associate lines with a particular
// [Description] file which is being scanned.
// [Description] The standard delimiter character is the ".
// [Description] The [Delimiter] decimal-value keyword may be used to
// [Description] specifiy an alternate delimiter character. This keyword
// [Description] should be placed after the [Keyword List] keyword in the
// [Description] keyword.vrs file.

//
// [Usage] Version files.vrs keywords.vrs outputfile.txt <enter>
//
// [Arguments] ExtensionList KeywordList OutputFileSpec
//
// [Return] Creates a comma delimited ASCII text file
//
// [Notes] None
//
// [History] 2.00 04/11/94 Original
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

enum { True,False };

// I N C L U D E F I L E S

#include <stdio.h>

29
Configuring a Bios

#include <string.h>
#include <process.h>
#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <dos.h>
#include <errno.h>
#include <stdlib.h>

// F U N C T I O N P R O T O T Y P E S

void ScanFile(void);

// V A R I A B L E S

unsigned Delimiter = 34; // Default delimiter is "


char FileTypeList[50][80];
unsigned FilesListFound = False;
unsigned NumberOfFileTypes = 0;

char KeywordList[50][80];
unsigned KeywordListFound = False;
unsigned NumberOfKeywords = 0;
// This is the input line string
char line[255];
char * charptr;
// This is the string used to construct the wildcard string
char Wildcard[32];
// This is the structure used for the findfirst/findnext
struct _find_t c_file;
// These are the temp strings used by the scanner to write the outstream
char FileCountString[255];
char KeywordString[255];
char DataString[255];
char *DataPtr;
char WhiteSpace[] = " ";

FILE *keystream, *typestream, *instream,*outstream;

unsigned FileIndex;
unsigned KeywordIndex;
unsigned FileCount; // written to output file for Database Key
// This is the column header string dfor the output file
char HeaderString[] =
"\"FileCount\",\"ActualFileName\",\"Keyword\",\"Data\"\n";
char ActualFileNameKeyword[] = "[ActualFileName]";

void main(int argc,char *argv[])


{
printf("\nVersion Control Extraction Program Version 1.00 4-23-93");
printf("\nCopyright 1994 John O. Foster - All Rights Reserved.");
if (argc < 3)
{
printf("\nUsage is Version ExtensionListFile KeywordListFile OutputFile
<enter>");
exit(0);

30
Introduction to AutoBios

if((typestream = fopen(argv[1], "r" )) == NULL )


{
printf( "\nThe ExtensionFileList was not opened\n");
exit(1);
};

printf("\nFiles Types to be scanned are:\n");


while (fgets(line,80,typestream) != NULL)
{
// Remove the newline char, if present
if(charptr = strrchr(line,(int)'\n')) *charptr = 0;

// Look for the start of the fileslist


if(strstr(line,"[File List]") != NULL)
{
// if found, mark found, and skip to the next line
FilesListFound = True;
fgets(line,80,keystream);
// Remove the newline char, if present
if(charptr = strrchr(line,(int)'\n')) *charptr = 0;
}
// If not a null string, save it
if(strlen(line) && strstr(line,".") && FilesListFound != False)
{
strcpy(&FileTypeList[NumberOfFileTypes++][0],line);
printf(" %s \n",line); // optional
}
}
// make the last filetype a null
strcpy(&FileTypeList[NumberOfFileTypes][0],0);
printf("\nNumber of File Types is %d",NumberOfFileTypes);

if((keystream = fopen(argv[2], "r" )) == NULL )


{
printf( "\nThe KeywordList was not opened\n");
exit(1);
};

printf("\nKeywords to be scanned are:\n");


while (fgets(line,80,keystream) != NULL)
{

// Remove the newline char, if present


if(charptr = strrchr(line,(int)'\n')) *charptr = 0;

// Look for the start of the keywordlist


if(strstr(line,"[Keyword List]") != NULL)
{
// if found, mark found, and skip to the next line
KeywordListFound = True;
fgets(line,80,keystream);
// Remove the newline char, if present
if(charptr = strrchr(line,(int)'\n')) *charptr = 0;
}

31
Configuring a Bios

// If not a null string, save it


if(strlen(line) && KeywordListFound != False)
{
// Truncate line after ']'
if(charptr = strrchr(line,(int)']'))
{
// if the keyword is delimiter, then get the definition following
if(strstr(line,"[Delimiter]"))
{
charptr = strrchr(line,(int)']');
Delimiter = atoi(++charptr);
printf("\nUser defined delimiter is %c\n",Delimiter);
// discard the keyword
}
else
{
// truncate it
*++charptr = 0;
strcpy(&KeywordList[NumberOfKeywords++][0],line);
printf(" %s \n",line); // optional
};
};
};
};
// make the last keyword a null
strcpy(&KeywordList[NumberOfKeywords][0],0);
printf("\nNumber of Keywords is %d",NumberOfKeywords);

// now do the extractions

// Open the output file


outstream = fopen(argv[3],"w");

// Write the Table Field Names


fputs(HeaderString,outstream);

// The major loop is for the file type extensions

for(FileIndex = 0; FileIndex < NumberOfFileTypes; FileIndex++)


{
printf("\nScanning File Type %s",&FileTypeList[FileIndex][0]);
strcpy(Wildcard,"*"); strcat(Wildcard,&FileTypeList[FileIndex][0]);

//open the findfirst, then the findnext files here


//printf("\nLooking for first file %s",Wildcard);
if(_dos_findfirst(Wildcard,_A_NORMAL,&c_file)==0)
{
ScanFile();
}
else printf("\nWildcard file not found");

while(_dos_findnext(&c_file)==0)
{
//printf("\nLooking for next file %s",c_file.name);
ScanFile();

32
Introduction to AutoBios

}
}

fcloseall();
printf("\n");
};

void ScanFile(void)
{

// Open the file


instream = fopen(c_file.name,"r");
FileCount++;
printf("\nScanning File: %s",&c_file.name);
// write the actual filename of the file being scanned
// This is done to record a file even if any of the specified
// keywords are not found in the file.
// Write the FileCount
fputc(Delimiter,outstream); // delimiter character
fputs(itoa(FileCount,FileCountString,10),outstream);
fputc(Delimiter,outstream); // delimiter character
fputc(44,outstream); // ,

// Write the Actual File Name


fputc(Delimiter,outstream); // delimiter character
DataPtr = strchr(line,']') + 1;
fputs(c_file.name,outstream);
fputc(Delimiter,outstream); // delimiter character
fputc(10,outstream); // \n

// Read each line of the input file, and scan for keywords
while (fgets(line,255,instream) != NULL)
{
// Remove the newline char, if present
if(charptr = strrchr(line,(int)'\n')) *charptr = 0;
for(KeywordIndex = 0; KeywordIndex < NumberOfKeywords; KeywordIndex++)
{
//printf("\nScanning Keyword %s",&KeywordList[KeywordIndex][0] );
if(strstr(line,&KeywordList[KeywordIndex][0]))
{
//printf("\nFound %s",line);

// Write the FileCount


fputc(Delimiter,outstream); // delimiter character
fputs(itoa(FileCount,FileCountString,10),outstream);
fputc(Delimiter,outstream); // delimiter character
fputc(44,outstream); // ,

// Write the Actual File Name


fputc(Delimiter,outstream); // delimiter character
DataPtr = strchr(line,']') + 1;
fputs(c_file.name,outstream);
fputc(Delimiter,outstream); // delimiter character
fputc(44,outstream); // ,

33
Configuring a Bios

// Write the Keyword


fputc(Delimiter,outstream); // delimiter character
fputs(&KeywordList[KeywordIndex][0],outstream);
fputc(Delimiter,outstream); // delimiter character
fputc(44,outstream); // ,

// Write the Data


fputc(Delimiter,outstream); // delimiter character
DataPtr = strchr(line,']') + 1;
// Remove any leading white space
while(DataPtr == strchr(DataPtr,' ')) { DataPtr++; };
fputs(DataPtr,outstream);
fputc(Delimiter,outstream); // delimiter character
fputc(10,outstream); // \n

}
}
}
fclose(instream);
}

2.2 Ancillary Files used by Nmake utilites


2.2.1 The VrsFiles.Def File
This is the list of file extensions to be scanned by the Version Utility program. Since these are easily
adapted to the types of files involved in a project, the Version utility is also used in other Software Farm
publications.
It should be noted that "nonsense" scanning, such as .Csv, .Cod, .Lst files, may create large amounts of
redundant and/or wasteful data.
//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1993 John O. Foster - All Rights Reserved.
//
// [Module] The Version Reporting Program Files List
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 07/22/93
//
// [File Name] VRSFILES.DEF
//
// [Description] This is the list of the file extensions to be scanned by
// [Description] version.exe when building a version report.
//
// [Usage] Used as input to version.exe
//
// [History] 1.00 07/19/93 Original

34
Introduction to AutoBios

//
//---------------------------------------------------------------------

[File List]
.
.bas
.bat
.asm
.c
.chp
.h
.inc
.job
.plt
.ini
.inp
.def

2.2.2 The VrsWords.Def File


This is the list of keywords to be scanned by the Version Utility program. Since these are easily adapted
to the types of files involved in a project, the Version utility is also used in other Software Farm
publications.
Bracketed keyword scanning is (and intended to be) case sensitive, allowing extra selectivity in the
selection of keywords. If, for instance, both [Module] and [module] detection were desired, then both
forms of the keyword could be specified in the keywords file.
Since the VrsWords.Def file also contains a descriptive header, the special keyword [Keyword List] is
required to denote the start of the intended keyword definitions. It should not be removed or used as a
general keyword.
//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Module] The Version Reporting Program Keyword List
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] VRSWORDS.DEF
//
// [Language] MSC 8
//
// [Purpose] Provides keywords for Version.EXE
//
// [Description] This is the list of the keywords to be scanned by
// [Description] version.exe when building a version report.

35
Configuring a Bios

//
// [Usage] Used as input to version.exe
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

[Keyword List] Denotes Start of Keyword List for Version.Exe


[Module Name] Name of this module
[File Name] VRSWORDS.DEF
[File Status] Released, Prototype, Being Updated, New, etc.
[Copyright] Copyright (c) 1994 John O. Foster
[Version] 2.00
[Author] John O. Foster
[Date] 04/11/94
[Language] Language (and Version) to process this module
[Purpose] Purpose of this module
[Description] Optional multi-line description of this module
[Arguments] Input arguments
[Return] Return parameters
[Usage] Where used
[History] Summary of Revisions
[Category] Optional Category of Module
[Text] General Text
[//] General Comments or Text
[Help] Reserved for future use

2.3 General Purpose Utilities


Using a Prom Emulator
Probably the most productive method of testing AutoBios is to replace the system board Proms with a
Prom Emulator device. This emulator can be downloaded from the software development machine, and
the code can then be executed in the target machine. Our favorite emulator is provided by Technical
Solutions, (Listed in the appendices) which is available in a variety of configurations at a reasonable
price.
These emulators may be used in multibyte wide configurations, and are loaded through a parallel printer
port adapter on the development machine. The emulator includes a reset strobe signal which may be
connect to the target board's reset line to cause a clean restart after loading the emulator.
We prefer this method of testing, for the following reasons:
1. No residual previous Bios effects.
2. Quick edit, compile, download, and test cycle.
3. Reasonable cost.

2.3.1 The Binary to Hex Filter


The Bin2Hex filter is used to convert a binary image file into Intel Hexadecimal Format. This is a
common format used by many prom programmers such as Data I/O, etc. Since this is a filter, the output
may be directed to a file, an output port, or the screen. Since this filter is generic, and used in other

36
Introduction to AutoBios

programs, it actually creates the Extended Intel format, which includes segment records, making possible
conversions on image files greater than 64K bytes.
This utility may be run by stand-alone batch files as needed, or included in a PostMake directive in a .Job
file.
;****************************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] Binary to Intel hexadecimal filter
;
; [Version] 3.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] BIN2HEX.ASM
;
;
; [Description] This program converts the contents of a file to Intel
; [Description] hexadecimal format. Since many Prom Programmers will
; [Description] accept an Intel Hex download format, .BIN files may
; [Description] be converted.
; Filter outputs can be directed as shown in the examples below.
;
; [Usage] bin2hex <infile.bin >outfile.hex
; [Usage] bin2hex <infile.bin >COM1
; [Usage] bin2hex <infile.bin >CON
;
; [History] 2.00 04/11/94 Original
;
;****************************************************************************

; P R O G R A M

.model compact,c

stack segment word stack 'stack'


stack ends

stdin equ 0
stdout equ 1

.data
ibuff db 16 dup(0)
obuff db 32 dup(0)
line_count dw 0
char_count db 0
checksum db 0
ochar db 0
eof db 13,10,':00000001FF'
byte_counter dw 0 ; whenever this rolls over, we want to send

37
Configuring a Bios

; the next segment record


segment_counter dw 0 ; this is the index to which segment record we send
; every 64K
segment_record_pointer_table label word
dw seg0
dw seg1
dw seg2
dw seg3

; segment address canned records


seg0 db 13,10,':020000020000FC' ; set segment 0000
seg1 db 13,10,':020000021000EC' ; set segment 1000
seg2 db 13,10,':020000022000DC' ; set segment 2000
seg3 db 13,10,':020000023000CC' ; set segment 3000
.code

bin2hex proc
mov ax,DGROUP
mov ds,ax

mov bx,0
mov bx,segment_record_pointer_table[bx]
; now bx points to the canned record
call write_seg_record
mov line_count,0
.WHILE (ax == ax)
mov bx,stdin ; get stdin
mov cx,16
mov dx,offset ibuff
mov ah,3fh
int 21h
.BREAK .IF(Carry?) ; done if error or no more bytes
.BREAK .IF (ax == 0)
mov char_count,al
call write_line
add byte_counter,16 ; count up lines (16 bytes per line)
.IF (byte_counter == 0)
add segment_counter,2 ; this requires a segment change
; since this is a word index, we
; just add 2 now instead of later
push bx
mov bx,segment_counter
mov bx,segment_record_pointer_table[bx]
; now bx points to the canned record
call write_seg_record
pop bx
.ENDIF
.ENDW
call write_eof ; write eof
mov ax,4c00h
int 21h ; return to dos
bin2hex endp

write_line proc
mov checksum,0
mov cl,char_count

38
Introduction to AutoBios

xor ch,ch
mov al,13 ; carriage return
call putc
mov al,10 ; line feed
call putc
mov al,":"
call putc
mov al,char_count
sub checksum,al
call convert
mov ax,line_count
mov al,ah
sub checksum,al
call convert
mov ax,line_count
sub checksum,al
call convert
mov al,00
sub checksum,al
call convert
add line_count,16
mov si,offset ibuff
.REPEAT
lodsb
sub checksum,al
call convert
.UNTILCXZ
mov al,checksum
call convert
ret
write_line endp

convert proc uses ax


push ax
shr al,1
shr al,1
shr al,1
shr al,1
and al,0fh
add al,'0'
.IF (al > '9')
add al,7
.ENDIF
call putc
pop ax
and al,0fh
add al,'0'
.IF (al > '9')
add al,7
.ENDIF
call putc
ret
convert endp

putc proc uses ax bx cx dx


mov ochar,al

39
Configuring a Bios

mov bx,stdout
mov cx,1
mov dx,offset ochar
mov ah,40h
int 21h
ret
putc endp

write_eof proc uses ax bx cx dx


mov bx,stdout
mov cx,13
mov dx,offset eof
mov ah,40h
int 21h
ret
write_eof endp

write_seg_record proc uses ax bx cx dx


mov dx,bx ; the pointer to the seg record should be
; placed in dx !!
mov cx,17 ; count of chars in record ???
mov bx,stdout
mov ah,40h
int 21h
ret
write_seg_record endp

end bin2hex

2.3.2 The Binary Image Splitter


The Splitbin Program is used to Split the bios.bin file into an bios.evn and bios.odd file for programming
the two Proms normally needed for a Bios.
Some of the newer Chipsets used in AT clones may allow you to use a 64k x 8 prom for the complete
Bios. These Chipsets are based on the idea that the Bios would be moved to Shadow Ram which usually
operates with fewer wait states than Prom, allowing higher performance operation. This may provide
you with a design advantage if you are designing your own CPU board. Check with the VLSI chipset
vendor for more information on this possible feature, and what additional software that might be
required. If your AT motherboard has this feature, then the Splitbin won't be needed.
The Splitbin command line argument is the filename without the extension ("bios" not "bios.bin").
Splitbin adds the ".bin" to the input filename argument and the ".evn" and ".odd" extensions to the output
files.
//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Binary file splitter to even/odd
//
// [Version] 2.00

40
Introduction to AutoBios

//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] SPLITBIN.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This program reads the .bin file specified by the
// [Description] argument, and splits it into an .evn and a .odd file.
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include <stdio.h>
#include <string.h>
#include <process.h>

/* G L O B A L V A R I A B L E S */

#define blen 8192


FILE *instream,*evenstream,*oddstream;
unsigned char inbuffer[2*blen], evenbuffer[blen], oddbuffer[blen];
unsigned char inname[16], oddname[16],evenname[16];
unsigned numread,i,j;

/* P R O G R A M */

void main(int argc, char *argv[])


{
printf("\nBinary Image Split Utility Version 1.00 05-25-93");
printf("\nCopyright 1994 John O. Foster - All Rights Reserved.\n");
if ((argc !=2) || (stricmp(argv[1],"/?") == 0))
{
printf("Usage is Splitbin xx <enter>\n");
printf(" where xx is the binary image file (xx.bin) to split,\n");
printf(" creating xx.odd and an xx.evn output files.\n");
exit(0);
}
strcpy(inname,argv[1]); strcat(inname,".bin");
strcpy(evenname,argv[1]); strcat(evenname,".evn");
strcpy(oddname,argv[1]); strcat(oddname,".odd");
if((instream = fopen(inname,"rb")) != NULL)
if((evenstream = fopen(evenname,"wb")) != NULL)
if((oddstream = fopen(oddname,"wb")) != NULL)
{
while((numread = fread((char *)inbuffer,sizeof(char),2*blen,instream))
!= (unsigned)NULL)
{
for(i=0,j=0; j < numread; i++,j+=2)
{

41
Configuring a Bios

evenbuffer[i] = inbuffer[j];
oddbuffer[i] = inbuffer[j+1];
}
fwrite((char *)evenbuffer,sizeof(char),numread/2,evenstream);
fwrite((char *)oddbuffer,sizeof(char),numread/2,oddstream);
}
}
}

2.3.3 The Binary Image Merger


The Mergebin Program is the companion to the Splitbin Program and may be used to combine ".evn" and
".odd" files to a ".bin" file. The command line argument is the filename (without extension). Mergebin
looks for the ".evn" and ".odd" files and creates a ".bin" file. Mergebin is handy if you want to read
existing Bios proms and create a complete image, as well as providing a means to verify the even/odd
conversion process (Splitbin) by merging a split and comparing results.
//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Merge evn/odd files to a bin file
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MERGEBIN.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This program merges the .evn and .odd file into a
// [Description] combined .bin file.
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include <stdio.h>
#include <string.h>
#include <process.h>

/* G L O B A L V A R I A B L E S */

#define blen 8192


FILE *outstream,*evenstream,*oddstream;
unsigned char outbuffer[2*blen], evenbuffer[blen], oddbuffer[blen];
unsigned char outname[16], oddname[16],evenname[16];

42
Introduction to AutoBios

unsigned numread,i,j;

/* P R O G R A M */

void main(int argc, char *argv[])


{
printf("\nBinary Image Merge Utility Version 1.00 05-25-93");
printf("\nCopyright 1993 John O. Foster - All Rights Reserved.");
if ((argc !=2) || (stricmp(argv[1],"/?") == 0))
{
printf("\nUsage is Mergebin xx <enter>\n");
printf(" where xx is the name of the xx.evn and xx.odd files.\n");
printf(" Merged output is placed in xx.bin file.\n");
exit(0);
}
strcpy(outname,argv[1]); strcat(outname,".bin");
strcpy(evenname,argv[1]); strcat(evenname,".evn");
strcpy(oddname,argv[1]); strcat(oddname,".odd");
if((outstream = fopen(outname,"wb")) != NULL)
if((evenstream = fopen(evenname,"rb")) != NULL)
if((oddstream = fopen(oddname,"rb")) != NULL)
{
while(
((numread = fread((char *)evenbuffer,sizeof(char),blen,evenstream)) !=
(unsigned)NULL) &&
((numread = fread((char *)oddbuffer,sizeof(char),blen,oddstream)) !=
(unsigned)NULL)
)
{
for(i=0,j=0; i < numread; i++,j+=2)
{
outbuffer[j] = evenbuffer[i];
outbuffer[j+1] = oddbuffer[i];
}
fwrite((char *)outbuffer,sizeof(char),numread*2,outstream);
}
}
}

2.3.4 The Indent Utility


This utility was written to assist in keeping C source files neat and readable. When using an editor which
does not provide automatic indenting for C curly-braces (such as MS-DOS Edit), the indentation level of
source code lines often becomes "ragged" and makes readability difficult. Uniform indentation helps to
quickly spot instances of unmatched "{" and "}" bracket usage. Indent processes a source file by re-
indenting the lines according to curly-brace occurrence. Indent simply re-adjusts the number of leading
spaces per line to position the text of the line according to its depth. Tabs are not changed, so if the
indentations on specific lines appear grossly un-adjusted, presume that tabs rather than spaces are present
in the source file. They may be replaced with spaces as appropriate to allow Indent to then perform the
desired indenting. Although indenting is purely cosmetic, and does not affect the compilers processing
of the code, it is to be recommended for programmer convenience,
//---------------------------------------------------------------------

43
Configuring a Bios

//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Indent Utility
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 07/15/94
//
// [File Name] INDENT.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This program is a utility which is used to indent C
// [Description] source code lines according to the nesting level of
// [Description] the left and right bracket characters ( { } ). It
// [Description] improves readability of the souce file, but does not
// [Description] affect the logic flow. It is useful when a general
// [Description] purpose editor is being used to prepare source files.
//
// [Arguments] Indent File name <enter>
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include <stdio.h>
#include <process.h>
#include <io.h>
#include <string.h>

/* G L O B A L V A R I A B L E S */

enum { False, True, };

FILE *instream;
FILE *outstream;
unsigned long length;
unsigned int i,numread,numwritten, tab = 0;
#define blen 512
unsigned char instring[blen], outstring[blen], buffer[16384];

unsigned write_ok = True;

/* L O C A L D E F I N I T I O N S */

#define tabchar 9
#define rt_brace 125

44
Introduction to AutoBios

#define lf_brace 123


#define indent_level 1 /* # of columns to indent */

/* P R O G R A M */

/* indent c programs according to {} characters */

void main(int argc, char *argv[])


{
printf("\nIndent Source Utility Version 3.00 05-25-93");
printf("\nCopyright 1993 John O. Foster - All Rights Reserved.\n");
if (argc <2)
{
printf("Usage is Indent filename <enter>\n");
exit(0);
}

if ((instream = fopen(argv[1],"r")) == NULL)


printf("Could not open file for reading\n");
else
{
length = filelength(fileno(instream));
if (length == -1) printf("Bad Length on input file\n");
else
{
if ((outstream = fopen("$id.$$$","w")) == NULL)
printf("Could not open file for writing\n");
else
{
tab=0;
while (fgets(instring,blen,instream) != 0)
{
// skip over leading spaces
i=0; while (instring[i++] == ' '); i--;
// check for right brace here so we de-indent the current line
if ((instring[i] == rt_brace) && (tab >= indent_level))
tab -= indent_level;

// pad front of output string with required # of spaces


strnset(outstring,' ',tab);outstring[tab] = 0;

// now copy instring[i] to outstring[tab]


strcat(&outstring[tab],&instring[i]);

// write to the temp file and mark any errors


if(fputs(outstring,outstream) != 0) write_ok = False;;
// check for left braces here so we indent the following line
if (instring[i] == lf_brace)
{
tab += indent_level;
// check for closing brace on same line
for(; i<strlen(instring);i++)
{
if ((instring[i] == rt_brace) && (tab >= indent_level))
{
tab -= indent_level;

45
Configuring a Bios

break;
}
}
}
}
}
}
fclose(instream);
fclose(outstream);

if(!write_ok)
{
printf("Error in writing temporary file, processing aborted.\n");
printf("Original file %s remains unchanged.\n",argv[1]);
}
else
{
// now copy the $id.$$$ to the original file
if (((instream = fopen("$id.$$$","r+b")) != NULL) &&
((outstream=fopen(argv[1],"w+b")) != NULL))
{
do
{
numread = fread((char *)buffer, sizeof(char),16384,instream);
numwritten = fwrite((char *)buffer, sizeof(char),numread,outstream);
if (numwritten != numread)
{
printf("Transfer error on file %s. Use $ID.$$$ as recovery
file./n",argv[1]);
write_ok = False;
}
}
while (numread > 0);
fclose(instream);
fclose(outstream);
if(write_ok)
if ((numread = remove ("$id.$$$")) != 0)
printf("Error deleting temp file $ID.$$$\n");
}
}
}
}

46
Introduction to AutoBios

3. The Build Programs


These programs are used to assemble, compile and link the Bios modules. The process is automated to
permit a complete build with just a few keystrokes.

3.1 The Make file


The Makefile is used by Nmake to direct the build process. It supplies Nmake with the information it
needs to check dependencies, invoke the compiler, assembler and linker as needed. The AutoBios
MakeFile uses information from the .Job file and the Tools.Ini file to determine the personality of the
build.
A build includes various elements which in addition to creating a prom image of the target Bios,
produces additional reports and tools, including:
 A chipset configuration register dump routine that may be used to dump chip configuration on
system boards which already have an existing operating Bios. This simplifies determining the
configuration of an existing system.
 A set of text-file reports which provide data useful in further analysis steps such as optimizing the fit
in included (bookmarked) routines into the fragmented slots in the biosjump.asm module
(findfree.txt, findused.txt, findsize.txt).
 A list of the checkpoints included in the Bios (Check.Pnt).
 A list of modules which have ‘include’ statements to assist determining dependencies.
 A ‘Version.Rpt’ file which may be used to extract module header information for user-implemented
configuration control information.
 A chip configuration information help summary file for reference to the chip options (CfgHelp.Rpt).
 A chip directory showing the available chip support modules.
 A text file showing a Hard Disk Parameter summary for the Hard Drive parameter Table
(HardType.txt).
 A set of StandAlone TSR files which may be used to implement post-boot driver service overlay
functions. These are also helpful to perform test & debug in Virtual DOS Machines.
 A set of Rom-Scan Bios installable driver service modules which may be used to extend existing
Bios’, without the need for complete Bios replacement.

#**************************************************************************
#
# [Copyright] Copyright (c) 1997 John O. Foster - All Rights reserved.
#
# [Product Name] AutoBios
#
# [Module Name] MakeFile
#
# [Version] 3.00
#

47
Configuring a Bios

# [Author] John O. Foster


#
# [Date] 01/21/94
#
# [File Name] MAKEFILE.
#
# [Language] NMAKE Version 1.30
#
# [Description] This is the Make file to build the Bios
# [Description] To Build the Bios, type 'nmake' <enter>
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************

True = 1
False = 0

LibOperator=nul

#------- Define the dependents for the top build ------

all:: Bios.bin
all:: chiphelp.txt
all:: SaDisk.exe
all:: SaSysVue.exe
all:: SaVideo.exe
all:: SaHard.exe
all:: SaComm.exe
all:: SaLpt.exe
all:: SaPrtScr.exe
all:: SaKb.exe
all:: SaSysSrv.exe
all:: SaEquip.exe
all:: SaMem.exe
all:: SaTimer.exe
all:: SaTOD.exe
all:: SaBoot.exe
all:: PostMake.bat
all:: $(objs)
all:: i386Boot.bin

#----------- Force a rebuild on any utilities needed --------

!MESSAGE Checking for Up to Date Utilities


!if [nmake /F makeutil]
!endif
!MESSAGE Utility Check Complete
!MESSAGE

#----------- Get the Current Configuration Directives -----------

# Lastmake.txt holds the information on the last configuration built.


!INCLUDE LastMake.txt # get the last build information
# Display it for operator information.
!MESSAGE Retrieving info about last build.

48
Introduction to AutoBios

! if [type lastmake.txt]
!endif

# If nmake <enter> is used without a Job=nnnn spec, use the last


# saved .Job description.
!ifndef Job # either use new argument or lastjob
Job=$(LastJob)
!endif

# Copy the job information into a temp file

! MESSAGE Copying $(Job).job to job.tmp


! if [copy $(Job).job job.tmp]
! endif

# If the Job changed, touch the time/date to force a re-build


! if "$(Job)" != "$(LastJob)"
!MESSAGE Job selection has changed, touch to force complete rebuild.
! if [type job.tmp > job.xxx]
! endif
! if [type job.xxx > job.tmp]
! endif
! endif

!include job.tmp

Platform=$(CfgPlatform)

# Copy the Platform info into a temp file


! MESSAGE Copying $(Platform).Plt to Platform.Tmp
! if [copy $(Platform).Plt Platform.Tmp]
! endif

# If the platform changed, touch the time/date to force a re-build


! if "$(Platform)" != "$(LastPlatform)"
!MESSAGE Platform selection has changed, touch5 to force complete rebuild.
! if [type platform.tmp > platform.xxx]
! endif
! if [type platform.xxx > platform.tmp]
! endif
! endif

#-------------------------------------------------

!include Platform.tmp

# Copy the Common to a temp file


!MESSAGE Copying Common.Plt Common.Tmp
!if [copy common.plt common.tmp]
!endif

!include common.tmp

#------- Update the Chip Personality file -------------

Chip = $(CfgChip)

49
Configuring a Bios

# Copy the Chip file into a temp file


! MESSAGE Copying $(Chip).Chp to Chip.Tmp
! if [copy $(Chip).Chp Chip.Tmp]
! endif

# If the Chip has changed, touch the time/date to force a re-build


! if "$(Chip)" != "$(LastChip)"
!MESSAGE Chip selection has changed, touch to force complete rebuild.
! if [type chip.tmp > chip.xxx]
! endif
! if [type chip.xxx > chip.tmp]
! endif
! endif

# If the chip is newer, force a re-build


chipasm.tmp: Chip.Tmp
command /cextract $(Chip).chp [MASM] chipasm.tmp

chipc.tmp: Chip.Tmp
command /cextract $(Chip).chp [C] chipc.tmp

chiph.tmp: Chip.Tmp
command /cextract $(Chip).chp [H] chiph.tmp

chiphelp.txt: Chip.Tmp
command /cextract $(Chip).chp [HELP] chiphelp.txt

chipdump.h: Chip.Tmp
command /cextract $(Chip).chp [DUMP] chipdump.h

!MESSAGE

#--------- Set the target CPU type --------

cpulevel = $(CfgCompiler)

#------------ Select the Debug/Release Mode --------

!if $(CfgCodeView)
!MESSAGE Selecting build options to generate CodeView information files.
adebug =-Fl -Sg -Zi -Sn
cdebug =-Fc -Zi
ldebug = /CO
!endif

!if $(CfgListings)
!MESSAGE Selecting build options to generate listing files.
alist =-Fl -Sg -Sn
clist =-Fc
ldebug =
!endif

#------ Check the following files for possible BookMark updates

50
Introduction to AutoBios

# Run Job2H and H2INC as needed to generate updated .H and .INC files.

job.h: job.tmp tools.ini platform.tmp


job2h job.tmp job

Platform.h: Platform.tmp job.tmp


job2h platform.tmp platform

common.h: common.tmp platform.tmp job.tmp


job2h common.tmp common

Bios.h: job.h Platform.h common.h chiph.tmp product.h \


stddefs.h objects.h lowram.h intregs.h \
sysvue.h virtual.h Bios8042.h lang.h

Bios.inc: Bios.h

BiosPrfx.inc: Bios.inc

#--- Build a standalone ChipDump Utility for this Chipset ---

all:: $(Chip).exe

$(Chip).exe: $(Chip).Chp chipdump.h chiph.tmp chipdump.c


@echo Building a Stand-Alone ChipSet Dump Utility: $(Chip).exe
CL /G0 /W3 /AS /O /Oi /Fc$*.cod /Fe$*.exe chipdump.c

#---------- These are the Bios Modules --------------

# Build the bios front-end stratup module

BiosStart.obj: BiosPrfx.inc $*.asm

# Build the absolutized high location module

BiosJump.obj: BiosPrfx.inc $*.asm

# Build the bios configuration module

Bioscfg.obj: BiosPrfx.inc $*.asm

#-------- These are the library modules ----------

object.obj: Bios.h object.c

CmdChip.obj: Bios.h chipc.tmp

Printf.obj: Bios.h $*.c

Pause.obj: Bios.h $*.c

KbHit.obj: Bios.h $*.c

GetStr.obj: Bios.h $*.c

CmdSnap.obj: Bios.h $*.c

51
Configuring a Bios

Typing.obj: BiosPrfx.inc $*.asm

Keyboard.obj: Bios.h $*.c

SysVue.obj: Bios.h $*.c

Lists.obj: Bios.h $*.c

Tod.obj: Bios.h $*.c

Equi.obj: Bios.h $*.c

SysSrv.obj: Bios.h $*.c

Bios8042.obj: Bios.h $*.c

Disk.obj: Bios.h $*.c

Hard.obj: Bios.h $*.c

Pod.obj: Bios.h $*.c

PrtScr.obj: Bios.h $*.c

Mem.obj: Bios.h $*.c

Misc.obj: Bios.h $*.c

Boot.obj: Bios.h $*.c

Comm.obj: Bios.h $*.c

Lpt.obj: Bios.h $*.c

Crt.obj: Bios.h $*.c

Tmr.obj: Bios.h $*.c

CmdCalc.obj: Bios.h $*.c

CmdChksm.obj: Bios.h $*.c

CmdCLS.obj: Bios.h $*.c

CmdCmos.obj: Bios.h $*.c

CmdComp.obj: Bios.h $*.c

CmdDate.obj: Bios.h $*.c

CmdDevic.obj: Bios.h $*.c

CmdDrive.obj: Bios.h $*.c

CmdDump.obj: Bios.h $*.c

52
Introduction to AutoBios

CmdEnter.obj: Bios.h $*.c

CmdFill.obj: Bios.h $*.c

CmdHelp.obj: Bios.h $*.c

CmdInOut.obj: Bios.h $*.c

CmdInt.obj: Bios.h $*.c

CmdMem.obj: Bios.h $*.c

CmdMove.obj: Bios.h $*.c

CmdNpx.obj: Bios.h $*.c

CmdOdump.obj: Bios.h $*.c

CmdPipe.obj: Bios.h $*.c

CmdRegs.obj: Bios.h $*.c

CmdRhex.obj: Bios.h $*.c

CmdSrch.obj: Bios.h $*.c

CmdSI.obj: Bios.h $*.c

CmdScan.obj: Bios.h $*.c

CmdTime.obj: Bios.h $*.c

CmdTrace.obj: Bios.h $*.c

CmdTypes.obj: Bios.h $*.c

CmdVideo.obj: Bios.h $*.c

CmdWhex.obj: Bios.h $*.c

CmdVctrs.obj: Bios.h $*.c

buildarg.obj: Bios.h $*.c

prnnames.obj: Bios.h $*.c

prnlist.obj: Bios.h $*.c

getvalue.obj: Bios.h $*.c

namexist.obj: Bios.h $*.c

valuexst.obj: Bios.h $*.c

getname.obj: Bios.h $*.c

53
Configuring a Bios

reboots.obj: Bios.h $*.c

sysbreak.obj: Bios.h $*.c

conslbrk.obj: Bios.h $*.c

loaduser.obj: Bios.h $*.c

parsedig.obj: Bios.h $*.c

asc2dec.obj: Bios.h $*.c

asc2hex.obj: Bios.h $*.c

IsDeciml.obj: Bios.h $*.c

IsHex.obj: Bios.h $*.c

CalcCmos.obj: Bios.h $*.c

InCmos.obj: Bios.h $*.c

OutCmos.obj: Bios.h $*.c

RstCmos.obj: Bios.h $*.c

SetCmos.obj: Bios.h $*.c

TglCmos.obj: Bios.h $*.c

CmosType.obj: Bios.h $*.c

DsplyVid.obj: Bios.h $*.c

DsplyDrv.obj: Bios.h $*.c

DsplyDte.obj: Bios.h $*.c

DsplyTme.obj: Bios.h $*.c

DsplyNpx.obj: Bios.h $*.c

DsplyUsr.obj: Bios.h $*.c

DsplyHrd.obj: Bios.h $*.c

DsplyReg.obj: Bios.h $*.c

StrChr.obj: Bios.h $*.c

StrCmp.obj: Bios.h $*.c

StrMatch.obj: Bios.h $*.c

StrLen.obj: Bios.h $*.c

54
Introduction to AutoBios

StrStr.obj: Bios.h $*.c

StrTok.obj: Bios.h $*.c

ReadSwit.obj: Bios.h $*.c

RomScan.obj: Bios.h $*.c

XMemText.obj: Bios.h $*.c

Virtual.obj: BiosPrfx.inc $*.asm

Chip.obj: BiosPrfx.inc chipasm.tmp $*.asm

CmosTble.obj: BiosPrfx.inc $*.asm

DskReset.obj: BiosPrfx.inc $*.asm

DskRead.obj: BiosPrfx.inc $*.asm

DskDiag.obj: BiosPrfx.inc $*.asm

DskInit.obj: BiosPrfx.inc $*.asm

DskRecal.obj: BiosPrfx.inc $*.asm

DskChain.obj: BiosPrfx.inc $*.asm

GetBios.obj: BiosPrfx.inc $*.asm

GetSys.obj: BiosPrfx.inc $*.asm

GetVirt.obj: BiosPrfx.inc $*.asm

GetCfg.obj: BiosPrfx.inc $*.asm

PutChVid.obj: BiosPrfx.inc $*.asm

Delay.obj: BiosPrfx.inc $*.asm

GetRegs.obj: BiosPrfx.inc $*.asm

CTypes.obj: BiosPrfx.inc $*.asm

RepInOut.obj: BiosPrfx.inc $*.asm

HardTble.obj: BiosPrfx.inc $*.asm

Beep.obj: BiosPrfx.inc $*.asm

DummyIrt.obj: BiosPrfx.inc $*.asm

SysCfgTb.obj: BiosPrfx.inc $*.asm

GetChar.obj: BiosPrfx.inc $*.asm

55
Configuring a Bios

VidFuns.obj: BiosPrfx.inc $*.asm

VidMoves.obj: BiosPrfx.inc $*.asm

VidFont.obj: BiosPrfx.inc $*.asm

ScanCall.obj: BiosPrfx.inc $*.asm

KbTable.obj: BiosPrfx.inc $*.asm

PutChar.obj: Bios.h $*.c

SendEOI.obj: Bios.h $*.c

SetTmCnt.obj: Bios.h $*.c

SetTimer.obj: Bios.h $*.c

SaPrefix.obj: BiosPrfx.inc $*.asm

SaSuffix.obj: BiosPrfx.inc $*.asm

ClrObjct.obj: BiosPrfx.inc $*.asm

StrCpy.obj: BiosPrfx.inc $*.asm

ClkMisc.obj: BiosPrfx.inc $*.asm

CalcSize.obj: BiosPrfx.inc $*.asm

IDstring.obj: BiosPrfx.inc $*.asm

MainDisk.obj: Bios.h MainBody.c $*.c

MainVue.obj: Bios.h MainBody.c $*.c

MainCrt.obj: Bios.h MainBody.c $*.c

MainHard.obj: Bios.h MainBody.c $*.c

MainComm.obj: Bios.h MainBody.c $*.c

MainLpt.obj: Bios.h MainBody.c $*.c

MainPrSc.obj: Bios.h MainBody.c $*.c

MainKb.obj: Bios.h MainBody.c $*.c

MainSySr.obj: Bios.h MainBody.c $*.c

MainEqui.obj: Bios.h MainBody.c $*.c

MainMem.obj: Bios.h MainBody.c $*.c

MainTOD.obj: Bios.h MainBody.c $*.c

56
Introduction to AutoBios

MainTmr.obj: Bios.h MainBody.c $*.c

MainBoot.obj: Bios.h MainBody.c $*.c

MainTone.obj: Bios.h MainBody.c $*.c

#---------- These are the Bios Library Modules --------------

objs = chip.obj \
object.obj \
Printf.obj \
CmdCalc.obj \
CmdChip.obj \
CmdChksm.obj \
CmdCLS.obj \
Cmdcmos.obj \
CmdComp.obj \
CmdDate.obj \
CmdDevic.obj \
lists.obj \
CmdDrive.obj \
CmdDump.obj \
CmdEnter.obj \
CmdFill.obj \
CmdHelp.obj \
GetStr.obj \
CmdInOut.obj \
CmdInt.obj \
CmdMem.obj \
CmdMove.obj \
CmdNpx.obj \
CmdoDump.obj \
CmdPipe.obj \
CmdRegs.obj \
CmdSrch.obj \
CmdSI.obj \
CmdScan.obj \
CmdTrace.obj \
CmdTime.obj \
CmdTypes.obj \
CmdVideo.obj \
CmdSnap.obj \
PrtScr.obj \
Mem.obj \
Misc.obj \
Boot.obj \
SysVue.obj \
Comm.obj \
Keyboard.obj \
Disk.obj \
Hard.obj \
Lpt.obj \
Crt.obj \
Tmr.obj \
Tod.obj \

57
Configuring a Bios

Equi.obj \
SysSrv.obj \
Typing.obj \
Bios8042.obj \
Pause.obj \
KbHit.obj \
CmdVctrs.obj \
CmdRhex.obj \
CmdWhex.obj \
Virtual.obj \
Pod.obj \
buildarg.obj \
prnnames.obj \
prnlist.obj \
getvalue.obj \
namexist.obj \
valuexst.obj \
getname.obj \
reboots.obj \
sysbreak.obj \
conslbrk.obj \
loaduser.obj \
parsedig.obj \
asc2dec.obj \
asc2hex.obj \
isdeciml.obj \
ishex.obj \
CalcCmos.obj \
InCmos.obj \
OutCmos.obj \
RstCmos.obj \
SetCmos.obj \
TglCmos.obj \
CmosType.obj \
DsplyVid.obj \
DsplyDrv.obj \
DsplyDte.obj \
DsplyTme.obj \
DsplyNpx.obj \
DsplyUsr.obj \
DsplyHrd.obj \
DsplyReg.obj \
StrChr.obj \
StrCmp.obj \
StrMatch.obj \
StrLen.obj \
StrStr.obj \
StrTok.obj \
ReadSwit.obj \
RomScan.obj \
CmosTble.obj \
XMemTest.obj \
DskReset.obj \
DskRead.obj \
DskDiag.obj \
DskInit.obj \

58
Introduction to AutoBios

DskRecal.obj \
DskChain.obj \
GetBios.obj \
GetSys.obj \
GetCfg.obj \
GetVirt.obj \
PutChar.obj \
PutChVid.obj \
SetTmCnt.obj \
SetTimer.obj \
Delay.obj \
GetRegs.obj \
CTypes.obj \
RepInOut.obj \
HardTble.obj \
Beep.obj \
SendEOI.obj \
DummyIrt.obj \
SysCfgTb.obj \
GetChar.obj \
VidFuns.obj \
VidMoves.obj \
VidFont.obj \
ScanCall.obj \
SaPrefix.obj \
SaSuffix.obj \
ClrObjct.obj \
StrCpy.obj \
ClkMisc.obj \
CalcSize.obj \
IDstring.obj \
KbTable.obj

#----- This is the library maintenance directives --------

BiosLib.lib : $(objs)
lib /PAGE:32 Bioslib.lib @<<BiosLib.lrf
-+$(?: = &^
-+)
BiosLib.lst;
<<KEEP

#---- option for 386EX Flash loader ----------

i386Boot.bin: $*.asm
ml /Fl$*.lst $*.asm
debug <i386Boot.inp

#--- This is the link and build process ---------

#-------- make binary file of bios -------

Bios.bin: Virtual.obj \
BiosLink \
BiosCut.inp \

59
Configuring a Bios

biosstart.obj \
bioscfg.obj \
Pod.obj \
BiosJump.obj \
BiosStart.obj \
BiosLib.lib \
biossum.exe \
biosdate.exe \
biosgen.exe \
version.exe \
$(Chip).exe \
tools.ini
copy Blank.inc BiosFill.inc
$(asm) -c -Cp $(ADEBUG) BiosFill.asm
link $(lflags) @BiosLink
biosgen Bios.map BiosFill.inc
$(asm) -c -Cp $(ADEBUG) BiosFill.asm
link $(lflags) @BiosLink
debug <BiosCut.inp
biosdate Bios.bin
biossum Bios.bin
copy Bios.bin $(Job).bin
type <<LastMake.txt
# LastMake Parameters
LastJob=$(Job)
LastChip=$(Chip)
LastPlatform=$(Platform)
<<KEEP
@echo Building Checkpoint List To File Check.Pnt
@erase check.pnt
@-find /I "checkpointcode" Bios.h > $*.pnt
@copy *.pnt check. >NUL
@rename check. check.pnt
@echo Building Include File List To File Include.ncl
@erase include.ncl
@-find /I "#include" Bios.h > $*.ncl
@copy *.ncl include. >NUL
@-rename include. include.ncl
@echo Building ModuleSize List File to FindSize.txt
@-copy *.rpt findsize.tmp >NUL
@-find /I "Module Size" findsize.tmp >findsize.txt
@echo Building Version.Txt file for Optional Version Analysis
@-version vrsfiles.def vrswords.def version.txt >version.rpt
@echo Building CfgHelp.Txt file for Configuration Options Summary
@-version cfgfiles.def cfgwords.def CfgHelp.Txt ?>cfghelp.rpt
@echo Building an Updated Chip Directory File (Chip.Dir).
@dir *.chp >chip.dir
@-find "CHP" chip.dir >chip.xxx
@-sort <chip.xxx >chip.dir
@echo Building an Updated HardType.Txt Information File.
@-extract BiosStart.asm [HELP] hardtype.txt
@echo Building a Current Configuration List ("JobName".Cfg)
@-findcfg Bios.inc >CfgList.xxx
@-sort <Cfglist.xxx >$(Job).Cfg
@echo Building Optional PostMake Sequence
postmake.bat: Bios.bin

60
Introduction to AutoBios

<<postmake.bat
$(CfgPostMake)
$(CfgPostMake0)
$(CfgPostMake1)
$(CfgPostMake2)
$(CfgPostMake3)
$(CfgPostMake4)
$(CfgPostMake5)
<<KEEP
#@echo Running Optional PostMake Sequence
#@postmake.bat
@echo on
@echo.

SaDisk.exe: maindisk.obj saprefix.obj sasuffix.obj Disk.obj BiosLib.lib


@echo Building StandAlone Disk Driver (SaDisk.exe)
@link /m /CO /NOE saprefix.obj+\
maindisk.obj+\
Disk.obj+\
sasuffix.obj,SaDisk,,BiosLib.lib ;

SaDisk.bin: SaDisk.exe
@debug <SaDisk.inp
@biossize SaDisk.Tmp SaDisk.Bin

SaHard.exe: mainhard.obj saprefix.obj sasuffix.obj Disk.obj BiosLib.lib


@echo Building StandAlone Hard Disk Driver (SaHard.exe)
@link /m /CO /NOE saprefix.obj+\
mainhard.obj+\
Hard.obj+\
sasuffix.obj,SaHard,,BiosLib.lib ;

SaHard.bin: SaHard.exe
@debug <SaHard.inp
@biossize SaHard.Tmp SaHard.Bin

SaSysVue.exe: mainvue.obj saprefix.obj sasuffix.obj Disk.obj BiosLib.lib


@echo Building StandAlone SysVue (SaSysVue.exe)
@link /m /CO /NOE saprefix.obj+\
mainvue.obj+\
SysVue.obj+\
idstring.obj+\
sasuffix.obj,SaSysVue,,BiosLib.lib ;

SaSysVue.bin: SaSysVue.exe
@debug <SaSysVue.inp
@biossize SaSysVue.Tmp SaSysVue.Bin

SaVideo.exe: maincrt.obj saprefix.obj sasuffix.obj Crt.obj BiosLib.lib


@echo Building StandAlone Video Driver (SaVideo.exe)
@link /m /CO /NOE saprefix.obj+\
maincrt.obj+\
Crt.obj+\
sasuffix.obj,SaVideo,,BiosLib.lib ;

SaVideo.bin: SaVideo.exe

61
Configuring a Bios

@debug <SaVideo.inp
@biossize SaVideo.Tmp SaVideo.Bin

SaComm.exe: maincomm.obj saprefix.obj sasuffix.obj Comm.obj BiosLib.lib


@echo Building StandAlone Comm Driver (SaComm.exe)
@link /m /CO /NOE saprefix.obj+\
maincomm.obj+\
Comm.obj+\
sasuffix.obj,SaComm,,BiosLib.lib ;

SaComm.bin: SaComm.exe
@debug <SaComm.inp
@biossize SaComm.Tmp SaComm.Bin

SaLpt.exe: mainLpt.obj saprefix.obj sasuffix.obj Lpt.obj BiosLib.lib


@echo Building StandAlone Lpt Driver (SaLpt.exe)
@link /m /CO /NOE saprefix.obj+\
mainLpt.obj+\
Lpt.obj+\
sasuffix.obj,SaLpt,,BiosLib.lib ;

SaLpt.bin: SaLpt.exe
@debug <SaLpt.inp
@biossize SaLpt.Tmp SaLpt.Bin

SaPrtScr.exe: mainprsc.obj saprefix.obj sasuffix.obj PrtScr.obj BiosLib.lib


@echo Building StandAlone PrintScreen Driver (SaPrtScr.exe)
@link /m /CO /NOE saprefix.obj+\
mainprsc.obj+\
PrtScr.obj+\
sasuffix.obj,SaPrtScr,,BiosLib.lib ;

SaPrtScr.bin: SaPrtScr.exe
@debug <SaPrtScr.inp
@biossize SaPrtScr.Tmp SaPrtScr.Bin

SaKb.exe: mainkb.obj saprefix.obj sasuffix.obj Keyboard.obj BiosLib.lib


@echo Building StandAlone Keyboard Driver (SaKb.exe)
@link /m /CO /NOE saprefix.obj+\
mainkb.obj+\
Keyboard.obj+\
sasuffix.obj,SaKb,,BiosLib.lib ;

SaKb.bin: SaKb.exe
@debug <SaKb.inp
@biossize SaKb.Tmp SaKb.Bin

SaSysSrv.exe: mainSySr.obj saprefix.obj sasuffix.obj SysSrv.obj BiosLib.lib


@echo Building StandAlone System Services Driver (SaSysSrv.exe)
@link /m /CO /NOE saprefix.obj+\
mainSySr.obj+\
SysSrv.obj+\
sasuffix.obj,SaSysSrv,,BiosLib.lib ;

SaSysSrv.bin: SaSysSrv.exe
@debug <SaSysSrv.inp

62
Introduction to AutoBios

@biossize SaSysSrv.Tmp SaSysSrv.Bin

SaEquip.exe: mainEqui.obj saprefix.obj sasuffix.obj Equi.obj BiosLib.lib


@echo Building StandAlone Equipment Call (SaEquip.exe)
@link /m /CO /NOE saprefix.obj+\
mainEqui.obj+\
Equi.obj+\
sasuffix.obj,SaEquip,,BiosLib.lib ;

SaEquip.bin: SaEquip.exe
@debug <SaEquip.inp
@biossize SaEquip.Tmp SaEquip.Bin

SaMem.exe: mainMem.obj saprefix.obj sasuffix.obj Mem.obj BiosLib.lib


@echo Building StandAlone Memory Size Call (SaMem.exe)
@link /m /CO /NOE saprefix.obj+\
mainMem.obj+\
Mem.obj+\
sasuffix.obj,SaMem,,BiosLib.lib ;

SaMem.bin: SaMem.exe
@debug <SaMem.inp
@biossize SaMem.Tmp SaMem.Bin

SaTOD.exe: mainTOD.obj saprefix.obj sasuffix.obj Tod.obj BiosLib.lib


@echo Building StandAlone Time Of Day Driver (SaTOD.exe)
@link /m /CO /NOE saprefix.obj+\
mainTOD.obj+\
Tod.obj+\
sasuffix.obj,SaTOD,,BiosLib.lib ;

SaTOD.bin: SaTOD.exe
@debug <SaTOD.inp
@biossize SaTOD.Tmp SaTOD.Bin

SaTimer.exe: mainTmr.obj saprefix.obj sasuffix.obj Tmr.obj BiosLib.lib


@echo Building StandAlone Timer Driver (SaTimer.exe)
@link /m /CO /NOE saprefix.obj+\
MainTmr.obj+\
Tmr.obj+\
sasuffix.obj,SaTimer,,BiosLib.lib ;

SaTimer.bin: SaTimer.exe
@debug <SaTimer.inp
@biossize SaTimer.Tmp SaTimer.Bin

SaBoot.exe: mainBoot.obj saprefix.obj sasuffix.obj Boot.obj BiosLib.lib


@echo Building StandAlone BootStrap Driver (SaBoot.exe)
@link /m /CO /NOE saprefix.obj+\
mainboot.obj+\
Boot.obj+\
sasuffix.obj,SaBoot,,BiosLib.lib ;

SaBoot.bin: SaBoot.exe
@debug <SaBoot.inp
@biossize SaBoot.Tmp SaBoot.Bin

63
Configuring a Bios

all:: cleanup
cleanup:
@echo.
@echo Make Complete

64
Introduction to AutoBios

3.2 The Tools.ini File


The Tools.Ini file is a "standard" filename used by Nmake to determine the default build rules. If a
Tools.ini file is not found in the AutoBios directory, the Tools.Ini file found in the environment path is
used. In order to provide a consistent Tools Rule Set, AutoBios includes a specific Tools.Ini file which
is kept in the project directory. AutoBios's Tools.Ini file is structured to provide the build option
capability desired to create a specific Bios.
#**************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios NMAKE TOOLS.INI File
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] TOOLS.INI
#
# [Language] NMAKE 1.30
#
# [Description] This module defines the rules for the NMAKE utility
# [Description] to use in creating the Bios. NMAKE will look for this
# [Description] file in the current directory, which should be the
# [Description] DarmBios directory.
#
# These are the built in rules and path definitions used by the new MS Make
# Utility (NMAKE). The following variables are set externally (i.e. set in
# the individual makefiles).
#
# extasw = The 'extra assembly switch' variable is optionaly used in the
# makefile to specify special MASM command line switches.
#
# extcsw = The 'extra C switch' variable is optionally used in the makefile
# to specify special C compiler command line switches.
#
# inc = The include file search path from the utility being built to the
# INC directory. Used if needed.
#
# hinc = The include file search path from the utility being built to the
# H directory. Used if needed for C source compilation.
#
# [History] 2.00 04/11/94 Original
#
#*************************************************************************/

[NMAKE]

#--------- Definitions for the Assembler -----------------


#-- awarn can be overridden by placing the new

65
Configuring a Bios

#-- warning level in extasw in the makefile

asm =ML
awarn =-W0
adebug =
alist =
ainc =
astd =-c -Cp
extasw =
aflags =$(awarn) $(alist) $(adebug) $(ainc) $(astd) $(extasw)

#--------- Definitions for C compiler -------------------


#-- cwarn can be overridden by placing the new
#-- warning level in extcsw in the makefile

cc =CL
cwarn =-W0
cdebug =
clist =
cinc =
cpulevel=
cstd =-c -Gs -Ox -Zp1 -J -Zl -Asfw
extcsw =
cflags =$(cwarn) $(clist) $(cdebug) $(cinc) -G$(cpulevel) $(cstd) $(extcsw)

#--------- Definitions for linker ---------

link =link
lstd =
ldebug =
exelink =/E
lflags = $(lstd) $(ldebug)

# Documntation aids rules

asmdocpnt = find /I "checkpoint(" $*.asm > $*.pnt


asmdocncl = find /I "include" $*.asm > $*.ncl

cdocpnt = find /I "checkpoint(" $*.c > $*.pnt


cdocncl = find /I "#include" $*.c > $*.ncl

#--------- Built-in rules ----------

.SUFFIXES:

.SUFFIXES: .c .tmp .h .inc .asm .obj .exe

.asm.obj:
$(asm) $(aflags) -FR$*.sbr $*.asm
$(asm) $(aflags) $*.asm >$*.rpt
-find /I "checkpoint(" $*.asm > $*.pnt
-find /I "include" $*.asm > $*.ncl

.c.obj:

66
Introduction to AutoBios

$(cc) $(cflags) -FR$*.sbr -Fo$*.obj $*.c


-find /I "checkpoint(" $*.c > $*.pnt
-find /I "#include" $*.c > $*.ncl

.obj.exe:
$(link) $(lflags) $*;

.tmp.h:
Job2h $*.tmp $*

.h.inc:
h2inc /W0 /Cp /Zp1 /G2 /Ht /J /Fc $*.h

.c.exe:
$(cc) -FR$*.sbr $*.c

67
Introduction to AutoBios

3.3 The Link File


The BiosLink. file is used as input data to the linker during the build process. The combination of the
BiosLink. file and the BiosPrfx.Inc file specify the segment ordering. The BiosLink. file also directs
the linker to create a Bios.MAP file (required by BiosGen.C) and to use the BiosLib.Lib file (created by
the running the Makefile.
BiosCfg+
IDString+
BiosStart+
BiosFill+
BiosJump,
Bios,
Bios/m,BiosLib.lib /NOE;

Note: The Linker ignores all lines after the semi-colon, so the
module description information is placed at the end of the file

#*************************************************************************
#
# [Copyright] Copyright (c) 1997 John O. Foster - All Rights reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Linker Response file
#
# [Version] 3.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] BiosLink.
#
# [Language] Link Version 5.50
#
# [Description] This is the Linker response file used by the
# [Description] Bios makefile.
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************

69
Introduction to AutoBios

3.4 The Cut File


The BiosCut.Inp file is used as input data for performing the .EXE -> .BIN function. Typical DOS-
provided EXE2BIN.EXE utilities encounter problems handling 64KByte files, so this alternative method
uses the DOS-DEBUG program instead. Although this Exe -> Bin function is a candidate for a dedicated
conversion routine, the simplicity of this method proves highly effective.
nBios.exe
l
rbx
1
rcx
0
nBios.bin
w cs:0
q

71
Introduction to AutoBios

4. Configuring a Bios
4.1 The Configuration Strategy
AutoBios uses a "project' oriented structure to simplify the creation of a Bios customized to a particular
system board. The structure is shown below:

Sample.Job
|---------- ------------------ NoChip.Chp
| Acer.Chp
| VLSI.Chp
| C&T.Chip
| Opti.Chp
|
XT.Plt At.Plt At386.Plt
|
Common.Plt

The fundamental definition file is the Common Platform (Common.Plt) file. This file specifies the
standard default configuration options for all Bios combinations. This file allows easy expansion and
updating of AutoBios, since added features can be specified by modifying the Common.Plt file.
The next level of Platform Files, (typically for each class of system, XT, AT, etc.) permit redefining the
default configuration options, customizing the Bios for a general class of system board.
The highest level of configuration information is contained in the .job file. This is where board specific
options are defined, including the inclusion of support for a particular chipset which may be on the
system board. The chipset definition is specifies by including a .Chp support module from a library of
support modules. Register initialization information needed for a chipset is normally defined in the .Job
module, allowing the .Chp modules to be generalized with default chip initialization information.
The .Job, .Chp, and .Plt modules are processed by the MakeFile in a top-down order as shown above, so
that an default option definition may be over-ridden by a higher precedence module. Any unspecified
options will use the next-lower found definition. The Common.Plt definitions are the lowest-level, and
provide defaults for any otherwise unspecified options.
This precedence allows the .Job files to be minimized for a a particular Job/ Project/System Board. By
examining the following Job, Chip, and Platform files, one can notice the structure involved.
Since these files may be created and updated as required for system board and architecture changes, a
more complete listing of available files is shown in the Appendices.

73
Introduction to AutoBios

4.2 Job Files

4.2.1 The Sample.Job


This file shows a sample job and may be used as a template for a specific .Job file. Any options left
undefined will use default values specified in the .Plt files. If a value is not defined in a platform-specific
.Plt file, then the values in the Common.Plt will be used. If no .Plt file is specified in the .Job file, the
Common.Plt definitions will be used for all default values.
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Sample Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] SAMPLE.JOB
#
# [Description]
#
# [//] If 'NMAKE <enter>' is run without a 'Job = xxx' argument,
# [//] this file is used for the default configuration.
#
# [//] To create a specific project, use this file as a sample,
# [//] and create a 'myname.job' file for a specific project
# [//] configuration. Run 'NMAKE Job=myname <enter>' to
# [//] create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#---------- Primitive Definitions --------------------

#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

# The text strings below are variable length, although I wouldn't

75
Configuring a Bios

# recommend anything extremely long as they do take up space.


# If they try to overwrite a fixed origin directive in BiosTop.asm,
# a warning will be displayed during assembly of BiosTop
# This can be your personal version number
CfgProjectVersion = "0.99"
CfgProjectCustomer= "Sample"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "No Chip"

CfgPromSingle = True
CfgDisk1Type = 1440
CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 384
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors=28

CfgBootSysVue = True
CfgBootOrder = 1

CfgKeyboardIntercept = False

CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

# If anything other than No-Chip is desired, use a valid xxx.Chp


# filename here.
CfgChip = NoChip

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

CfgMaxMem = 640
CfgMemTestGranularity = 64
CfgMemTestPatternBias = 0x0000
CfgKeyboardStyleAT = True

CfgPlatform = AT386

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process.

# [PostMake]
#------ Use the following template for a PostMake Definition ---
# To create a PostMake Sequence, define CfgPostMake.
# If CfgPostMake is not defined, a default sequence will be used.
# To create an active and and alternate PostMake (useful for
# debugging) in this file, define CfgPostMake as True/False.

#CfgPostMake = False

76
Introduction to AutoBios

!ifdef CfgPostMake

postmake.bat:
<<postmake.bat
@rem --------------------------------------------------------------
@rem - You may add a post-make sequence to the end of the Bios
@rem - build process to create the actual prom image files you need.
@rem - This may include concatenating the Bios to other file images
@rem - for larger prom sizes, running the "bin2hex <infile >outfile"
@rem - converter, or for downloading the prom image to a prom
@rem - programmer. You may wish to run an audio "beep" routine to
@rem - alert you to completion of the build.
@rem - The commands may end with the "^" caret to specify a "newline"
@rem - continuation character.
@rem -------- Insert PostMake Command below ------------------------
rem -- Optional -- PostMake file defined ---
pause
@rem -------- Insert PostMake Commands above -----------------------
<<KEEP
!endif
#---- End Of PostMake template -----------------------------------

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

77
Introduction to AutoBios

4.2.2 Typical Job Files


Here are some examples of .Job files to use as guidelines to creating your specific .Job file. These show
some cases of using different platforms and chipsets. They use a variety of configuration features, some
being modified to use some of the more recent capabilities of AutoBios. Consider these examples for
information only, as they may work in only one specific application, since system board configurations
may exhibit specific board designs, and not operate in general cases.
4.2.2.1 AstDel.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Dal's Bios Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] DAL.JOB
#
# [Description]
#
#
# [//] To create a specific project, use this file as a sample,
# [//] and create a 'myname.job' file for a specific project
# [//] configuration. Run 'NMAKE Job=myname <enter>' to
# [//] create a bios.
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

# The detailed flags for a particular target may be specified below

# The text strings below are variable length, although I wouldn't


# recommend anything extremely long as they do take up space.
# If they try to overwrite a fixed origin directive in BiosTop.asm,
# a warning will be displayed during assembly of BiosTop
# This can be your personal version number
CfgProjectVersion = "0.99"
CfgProjectCustomer= "AST HandHeld X01"
CfgProjectPartNr = "930203000000-00001"

79
Configuring a Bios

CfgProjectOption = "386SX-C&T NEAT Chip"

CfgPromSingle = False
CfgDisk = True
CfgHard = False
CfgBootSysVue = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 3072

CfgTypeByte = 0fah
CfgTypeParms = 08h,00h,0fah,00,0b0h,0,0,0,0,0

# If anything other than No-Chip is desired, use a valid xxx.Chp


# filename here.
CfgChip = C_TNEAT

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "xxxxxx".exe <enter>


# (where xxxxxx = # the name of the .Chp file you are using) on
# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgChipData = RA0, 042h, RA1, 0c5h, RA2, 01ah


CfgChipData0 = RB0, 03fh
CfgChipData1 = RB1, 00eh, RB2, 0eeh, RB3, 0, RB4, 0, RB5, 0
CfgChipData2 = RB6, 0e0h, RB7, 083h, RB8, 03h, RB9, 040h
CfgChipData3 = RB10, 0, RB11, 06h

CfgDisk1Type = 1200

CfgMaxMem = 640
CfgMemTestGranularity = 64
CfgMemTestPatternBias = 0x0000
CfgKeyboardStyleAT = True

# For MSC 8.0 (Visual C/C++) this is defined as "G3" in the at386.plt
# file to create true 386 code. If using C6 or C7, edit AT386.Plt
# and change G3 to G2.

CfgPlatform = AT386

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process.

# [PostMake]
#------ Use the following template for a PostMake Definition ---

80
Introduction to AutoBios

# To create a PostMake Sequence, define CfgPostMake.


# If CfgPostMake is not defined, a default sequence will be used.
# To create an active and and alternate PostMake (useful for
# debugging) in this file, define CfgPostMake as True/False.

#CfgPostMake = True

!ifdef CfgPostMake

postmake.bat:
<<postmake.bat
@rem --------------------------------------------------------------
@rem - You may add a post-make sequence to the end of the Bios
@rem - build process to create the actual prom image files you need.
@rem - This may include concatenating the Bios to other file images
@rem - for larger prom sizes, running the "bin2hex <infile >outfile"
@rem - converter, or for downloading the prom image to a prom
@rem - programmer. You may wish to run an audio "beep" routine to
@rem - alert you to completion of the build.
@rem - The commands may end with the "^" caret to specify a "newline"
@rem - continuation character.
@rem -------- Insert PostMake Command below ------------------------
rem -- Optional -- PostMake file defined ---
splitbin c_tneat
@rem -------- Insert PostMake Commands above -----------------------
<<KEEP
!endif
#---- End Of PostMake template -----------------------------------

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

81
Introduction to AutoBios

4.2.2.2 Banjo.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] banjo.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Onabanjo"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "386SX TI 82S411"
CfgPromSingle = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgDisk1Type = 1440

83
Configuring a Bios

CfgDisk2Type = 1200
CfgVideoType = VGA
CfgBaseMem = 640
CfgExtMem = 3200
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors=28

CfgBootSysVue = True
CfgBootOrder = 1

CfgKeyboardIntercept = False

CfgPlatform = AT386
CfgChip = TI411

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgChipData0 = PeripheralControl, 002h


CfgChipData1 = WaitState, 00ch

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

84
Introduction to AutoBios

4.2.2.3 Barry.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 10/10/93
#
# [File Name] Barry.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Barry"
CfgProjectPartNr = "93101000000-00001"
CfgProjectOption = ""
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgDisk1Type = 1440
#CfgDisk2Type = 360

85
Configuring a Bios

CfgVideoType = VGA
CfgBaseMem = 640
CfgExtMem = 1920
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors= 28

CfgBootSysVue = True
CfgBootOrder = 1

CfgKeyboardIntercept = False

CfgPlatform = AT386
CfgChip = SYMPH461

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgChipData0 = RX01,SizeIsByte, 028h


CfgChipData1 = RX02,SizeIsByte, 001h
CfgChipData2 = RX06,SizeIsByte, 006h
CfgChipData3 = RX07,SizeIsByte, 004h
CfgChipData4 = RX08,SizeIsByte, 00eh
CfgChipData5 = RX20,SizeIsByte, 0b4h
CfgChipData6 = RX22,SizeIsByte, 008h
CfgChipData7 = RX23,SizeIsByte, 010h
CfgChipData8 = RX24,SizeIsByte, 010h
CfgChipData9 = RX25,SizeIsByte, 010h
CfgChipData10 = RX27,SizeIsByte, 040h
CfgChipData11 = RX2D,SizeIsByte, 080h
CfgChipData12 = RX32,SizeIsByte, 0ddh
CfgChipData13 = RX33,SizeIsByte, 068h
CfgChipData14 = RX43,SizeIsByte, 010h
CfgChipData15 = RX45,SizeIsByte, 001h

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

86
Introduction to AutoBios

4.2.2.4 Bob.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] Bob.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Bob"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = ""
CfgPromSingle = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgDisk1Type = 1440

87
Configuring a Bios

CTomfgDisk2Type = 360
CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 1920
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors= 28

CfgBootSysVue = True
CfgBootOrder = 0

CfgKeyboardIntercept = False

CfgPlatform = AT386
CfgChip = VLSI315

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

#CfgChipData0 = DramBankConfiguration, 006h

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

88
Introduction to AutoBios

4.2.2.5 Brent.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] Brent.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Brent"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "Headland HT22"
CfgPromSingle = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgDisk1Type = 1440

89
Configuring a Bios

CfgDisk2Type = 1200
CfgVideoType = VGA
CfgBaseMem = 640
CfgExtMem = 3200
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors=28

CfgBootSysVue = True
CfgBootOrder = 1

# This should eliminate conflict with the Phoenic Bios


CfgSysObjectPtrPrimary =CfgSysObjectPtrAlternate

CfgKeyboardIntercept = False

CfgPlatform = AT386
CfgChip = Hland22

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgChipData0 = ControlReg0,ControlReg0Default
CfgChipData1 = ControlReg1,ControlReg1Default
CfgChipData2 = ControlReg2,ControlReg2Default
CfgChipData3 = ControlReg3,ControlReg3Default
CfgChipData4 = ControlReg4,ControlReg4Default
CfgChipData5 = ControlReg5,ControlReg5Default
CfgChipData6 = ControlReg6,ControlReg6Default

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

90
Introduction to AutoBios

4.2.2.6 Dal.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Dal's Bios Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] DAL.JOB
#
# [Description]
#
#
# [//] To create a specific project, use this file as a sample,
# [//] and create a 'myname.job' file for a specific project
# [//] configuration. Run 'NMAKE Job=myname <enter>' to
# [//] create a bios.
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

# The detailed flags for a particular target may be specified below

# The text strings below are variable length, although I wouldn't


# recommend anything extremely long as they do take up space.
# If they try to overwrite a fixed origin directive in BiosTop.asm,
# a warning will be displayed during assembly of BiosTop
# This can be your personal version number
CfgProjectVersion = "0.99"
CfgProjectCustomer= "Dal"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "386SX-C&T SCAT Chip"

CfgPromSingle = True
CfgDisk = False
CfgHard = False
CfgBootSysVue = True
CfgCmos = True
CfgCmosInit = True

91
Configuring a Bios

CfgCmosInitAlways = True

CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 0

CfgTypeByte = 0fah
CfgTypeParms = 08h,00h,0fah,00,0b0h,0,0,0,0,0

# If anything other than No-Chip is desired, use a valid xxx.Chp


# filename here.
CfgChip = C_TSCAT

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "xxxxxx".exe <enter>


# (where xxxxxx = # the name of the .Chp file you are using) on
# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgChipData0 = ChipPeripheralControl, 001h


CfgChipData1 = ChipPowerManagement, 041h
CfgChipData2 = ChipDramConfiguration, 0c2h

CfgMaxMem = 640
CfgMemTestGranularity = 64
CfgMemTestPatternBias = 0x0000
CfgKeyboardStyleAT = True

# For MSC 8.0 (Visual C/C++) this is defined as "G3" in the at386.plt
# file to create true 386 code. If using C6 or C7, edit AT386.Plt
# and change G3 to G2.

CfgPlatform = AT386

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process.

# [PostMake]
#------ Use the following template for a PostMake Definition ---
# To create a PostMake Sequence, define CfgPostMake.
# If CfgPostMake is not defined, a default sequence will be used.
# To create an active and and alternate PostMake (useful for
# debugging) in this file, define CfgPostMake as True/False.

#CfgPostMake = False

!ifdef CfgPostMake

postmake.bat:
<<postmake.bat
@rem --------------------------------------------------------------

92
Introduction to AutoBios

@rem - You may add a post-make sequence to the end of the Bios
@rem - build process to create the actual prom image files you need.
@rem - This may include concatenating the Bios to other file images
@rem - for larger prom sizes, running the "bin2hex <infile >outfile"
@rem - converter, or for downloading the prom image to a prom
@rem - programmer. You may wish to run an audio "beep" routine to
@rem - alert you to completion of the build.
@rem - The commands may end with the "^" caret to specify a "newline"
@rem - continuation character.
@rem -------- Insert PostMake Command below ------------------------
rem -- Optional -- PostMake file defined ---
pause
@rem -------- Insert PostMake Commands above -----------------------
<<KEEP
!endif
#---- End Of PostMake template -----------------------------------

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

93
Introduction to AutoBios

4.2.2.7 Ep.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] EP.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Ep"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "386SX-25 Acer 1217"
CfgPromSingle = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

#CfgSysVueConsole = True

95
Configuring a Bios

CfgCodeView = $(True)

#CfgSysObjectPtrPrimary = CfgSysObjectPtrAlternate

CfgDisk1Type = 1440
#CfgDisk2Type = 1200
CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 3456
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors=28

CfgBootSysVue = True
CfgBootOrder = 1

CfgKeyboardIntercept = False

CfgPlatform = AT386
CfgChip = ACER1217

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgChipData0 = ChipRomSize, 0A0h


CfgChipData1 = ChipDramController, 024h
CfgChipData2 = ChipSplitAddress, 040h
CfgChipData3 = ChipSpeedPassword, 0fah
CfgChipData4 = ChipCacheControl, 015h
CfgChipData5 = ChipHighSpeedControl, 010h
CfgChipData6 = ChipRecoveryPort, 040h
CfgChipData7 = ChipVersion, 090h

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

96
Introduction to AutoBios

4.2.2.8 Jeff.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] Jeff.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Jeff"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "386SX Acer 1217"
CfgPromSingle = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgDisk1Type = 1440

97
Configuring a Bios

CfgDisk2Type = 1200
CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 384
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors=28

CfgBootSysVue = True
CfgBootOrder = 1

CfgKeyboardIntercept = False

CfgPlatform = AT386
CfgChip = ACER1217

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgChipData0 = ChipRomSize, 010h


CfgChipData1 = ChipDramController, 005h
CfgChipData2 = ChipSplitAddress, 040h
CfgChipData3 = ChipSpeedPassword, 0fah
CfgChipData4 = ChipCacheControl, 015h
CfgChipData5 = ChipHighSpeedControl, 010h
CfgChipData6 = ChipRecoveryPort, 040h
CfgChipData7 = ChipVersion, 090h

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

98
Introduction to AutoBios

4.2.2.9 Lynn.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] Lynn.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Ep"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "C&T 4031"
CfgPromSingle = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

#CfgSysVueConsole = True

99
Configuring a Bios

CfgCodeView = $(True)

#CfgSysObjectPtrPrimary = CfgSysObjectPtrAlternate

CfgDisk1Type = 1440
#CfgDisk2Type = 1200
CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 3456
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors=28

CfgBootSysVue = True
CfgBootOrder = 1

CfgKeyboardIntercept = False

CfgPlatform = AT386
CfgChip = C_T4031

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

#CfgChipData0 = ChipRomSize, 0A0h


#CfgChipData1 = ChipDramController, 024h
#CfgChipData2 = ChipSplitAddress, 040h
#CfgChipData3 = ChipSpeedPassword, 0fah
#CfgChipData4 = ChipCacheControl, 015h
#CfgChipData5 = ChipHighSpeedControl, 010h
#CfgChipData6 = ChipRecoveryPort, 040h
#CfgChipData7 = ChipVersion, 090h

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

100
Introduction to AutoBios

4.2.2.10 NoChip.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] nochip.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Nochip"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = ""
CfgPromSingle = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgDisk1Type = 1440

101
Configuring a Bios

CfgDisk2Type = 360
CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 3200
CfgHard1Type = 47
CfgHard47Cyls = 978
CfgHard47Heads = 14
CfgHard47Sectors= 35

CfgBootSysVue = True
CfgBootOrder = 0

CfgKeyboardIntercept = False

CfgPlatform = AT286
CfgChip = NOCHIP

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

#CfgChipData1 = WaitState, 00ch

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

102
Introduction to AutoBios

4.2.2.11 Pars.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] PARS Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] PARS.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#

#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgPlatform = AT386

CfgChip = UMC481_2

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on

103
Configuring a Bios

# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.
#CfgChipData0 = ChipEmsControl, 01h, ChipRomEnable, 03h
#CfgChipData1 = ChipMiscStatus, 02h, ChipRomEnable, 03h
#CfgChipData2 = ChipRomEnable, 03h, ChipMiscStatus, 02h

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Pars"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "386DX-40 UMC"
CfgPromSingle = True
CfgDisk = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True
CfgCmosData = 10h,40h,14h,21h
CfgHard1Type = 47

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process.

# [PostMake]
#------ Use the following template for a PostMake Definition ---
# To create a PostMake Sequence, define CfgPostMake.
# If CfgPostMake is not defined, a default sequence will be used.
# To create an active and and alternate PostMake (useful for
# debugging) in this file, define CfgPostMake as True/False.

#CfgPostMake = False

!ifdef CfgPostMake

postmake.bat:
<<postmake.bat
@rem --------------------------------------------------------------
@rem - You may add a post-make sequence to the end of the Bios
@rem - build process to create the actual prom image files you need.
@rem - This may include concatenating the Bios to other file images
@rem - for larger prom sizes, running the "bin2hex <infile >outfile"
@rem - converter, or for downloading the prom image to a prom
@rem - programmer. You may wish to run an audio "beep" routine to
@rem - alert you to completion of the build.
@rem - The commands may end with the "^" caret to specify a "newline"
@rem - continuation character.
@rem -------- Insert PostMake Command below ------------------------
rem -- Optional -- PostMake file defined ---
pause
@rem -------- Insert PostMake Commands above -----------------------
<<KEEP
!endif
#---- End Of PostMake template -----------------------------------

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

104
Introduction to AutoBios

105
Introduction to AutoBios

4.2.2.12 Paul.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] PAUL.JOB
#
# [Description]
#
# [//] If 'NMAKE <enter>' is run without a 'Job = xxx' argument,
# [//] this file is used for the default configuration.
#
# [//] To create a specific project, use this file as a sample,
# [//] and create a 'myname.job' file for a specific project
# [//] configuration. Run 'NMAKE Job=myname <enter>' to
# [//] create a bios.
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

# The text strings below are variable length, although I wouldn't


# recommend anything extremely long as they do take up space.
# If they try to overwrite a fixed origin directive in BiosTop.asm,
# a warning will be displayed during assembly of BiosTop
# This can be your personal version number
CfgProjectVersion = "0.99"
CfgProjectCustomer= "Paul"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "OPTi 82C499 Chip"

CfgPromSingle = True
CfgDisk = False

107
Configuring a Bios

CfgCmos = True
#CfgCmosInit = True
#CfgCmosInitAlways = True
#CfgCmosData = 10h,40h,14h,21h
CfgTypeByte = 0fah
CfgTypeParms = 08h,00h,0fah,00,0b0h,0,0,0,0,0

# If anything other than No-Chip is desired, use a valid xxx.Chp


# filename here.
CfgChip = OPTI499

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.
#CfgChipData0 = ChipEmsControl, 01h, ChipRomEnable, 03h
#CfgChipData1 = ChipMiscStatus, 02h, ChipRomEnable, 03h
#CfgChipData2 = ChipRomEnable, 03h, ChipMiscStatus, 02h

CfgMaxMem = 640
CfgMemTestGranularity = 64
CfgMemTestPatternBias = 0x0000
CfgKeyboardStyleAT = True

# For MSC 8.0 (Visual C/C++) this is defined as "G3" in the at386.plt
# file to create true 386 code. If using C6 or C7, edit AT386.Plt
# and change G3 to G2.

CfgPlatform = AT386

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process.

# [PostMake]
#------ Use the following template for a PostMake Definition ---
# To create a PostMake Sequence, define CfgPostMake.
# If CfgPostMake is not defined, a default sequence will be used.
# To create an active and and alternate PostMake (useful for
# debugging) in this file, define CfgPostMake as True/False.

#CfgPostMake = False

!ifdef CfgPostMake

postmake.bat:
<<postmake.bat
@rem --------------------------------------------------------------
@rem - You may add a post-make sequence to the end of the Bios
@rem - build process to create the actual prom image files you need.
@rem - This may include concatenating the Bios to other file images

108
Introduction to AutoBios

@rem - for larger prom sizes, running the "bin2hex <infile >outfile"
@rem - converter, or for downloading the prom image to a prom
@rem - programmer. You may wish to run an audio "beep" routine to
@rem - alert you to completion of the build.
@rem - The commands may end with the "^" caret to specify a "newline"
@rem - continuation character.
@rem -------- Insert PostMake Command below ------------------------
rem -- Optional -- PostMake file defined ---
pause
@rem -------- Insert PostMake Commands above -----------------------
<<KEEP
!endif
#---- End Of PostMake template -----------------------------------

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

109
Introduction to AutoBios

4.2.2.13 RoyShay.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] RoyShay.JOB
#
# [Description]
#
#
# [//] To create a specific project, use this file as a sample,
# [//] and create a 'myname.job' file for a specific project
# [//] configuration. Run 'NMAKE Job=myname <enter>' to
# [//] create a bios.
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

# The detailed flags for a particular target may be specified below

# The text strings below are variable length, although I wouldn't


# recommend anything extremely long as they do take up space.
# If they try to overwrite a fixed origin directive in BiosTop.asm,
# a warning will be displayed during assembly of BiosTop
# This can be your personal version number
CfgProjectVersion = "0.99"
CfgProjectCustomer= "Roy's Project"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "Headland HT18"

# This should eliminate conflict with the Future Domain SCSI Board
CfgSysObjectPtrPrimary =CfgSysObjectPtrAlternate

CfgPromSingle = False
CfgDisk = True

111
Configuring a Bios

CfgHard = False
CfgBootSysVue = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 3072

CfgTypeByte = 0fah
CfgTypeParms = 08h,00h,0fah,00,0b0h,0,0,0,0,0

# If anything other than No-Chip is desired, use a valid xxx.Chp


# filename here.
CfgChip = Hland18

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "xxxxxx".exe <enter>


# (where xxxxxx = # the name of the .Chp file you are using) on
# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgDisk1Type = 1200

CfgMaxMem = 640
CfgMemTestGranularity = 64
CfgMemTestPatternBias = 0x0000
CfgKeyboardStyleAT = True
CfgKeyboardIntercept = False

# For MSC 8.0 (Visual C/C++) this is defined as "G3" in the at386.plt
# file to create true 386 code. If using C6 or C7, edit AT386.Plt
# and change G3 to G2.

CfgPlatform = AT386

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process.

# [PostMake]
#------ Use the following template for a PostMake Definition ---
# To create a PostMake Sequence, define CfgPostMake.
# If CfgPostMake is not defined, a default sequence will be used.
# To create an active and and alternate PostMake (useful for
# debugging) in this file, define CfgPostMake as True/False.

#CfgPostMake = True

112
Introduction to AutoBios

!ifdef CfgPostMake

postmake.bat:
<<postmake.bat
@rem --------------------------------------------------------------
@rem - You may add a post-make sequence to the end of the Bios
@rem - build process to create the actual prom image files you need.
@rem - This may include concatenating the Bios to other file images
@rem - for larger prom sizes, running the "bin2hex <infile >outfile"
@rem - converter, or for downloading the prom image to a prom
@rem - programmer. You may wish to run an audio "beep" routine to
@rem - alert you to completion of the build.
@rem - The commands may end with the "^" caret to specify a "newline"
@rem - continuation character.
@rem -------- Insert PostMake Command below ------------------------
rem -- Optional -- PostMake file defined ---
@rem -------- Insert PostMake Commands above -----------------------
<<KEEP
!endif
#---- End Of PostMake template -----------------------------------

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

113
Introduction to AutoBios

4.2.2.14 Sample.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Sample Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] SAMPLE.JOB
#
# [Description]
#
# [//] If 'NMAKE <enter>' is run without a 'Job = xxx' argument,
# [//] this file is used for the default configuration.
#
# [//] To create a specific project, use this file as a sample,
# [//] and create a 'myname.job' file for a specific project
# [//] configuration. Run 'NMAKE Job=myname <enter>' to
# [//] create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#---------- Primitive Definitions --------------------

#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

# The text strings below are variable length, although I wouldn't


# recommend anything extremely long as they do take up space.
# If they try to overwrite a fixed origin directive in BiosTop.asm,
# a warning will be displayed during assembly of BiosTop
# This can be your personal version number
CfgProjectVersion = "0.99"
CfgProjectCustomer= "Sample"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = "No Chip"

115
Configuring a Bios

CfgPromSingle = True
CfgDisk1Type = 1440
CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 384
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors=28

CfgBootSysVue = True
CfgBootOrder = 1

CfgKeyboardIntercept = False

CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

# If anything other than No-Chip is desired, use a valid xxx.Chp


# filename here.
CfgChip = NoChip

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

CfgMaxMem = 640
CfgMemTestGranularity = 64
CfgMemTestPatternBias = 0x0000
CfgKeyboardStyleAT = True

CfgPlatform = AT386

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process.

# [PostMake]
#------ Use the following template for a PostMake Definition ---
# To create a PostMake Sequence, define CfgPostMake.
# If CfgPostMake is not defined, a default sequence will be used.
# To create an active and and alternate PostMake (useful for
# debugging) in this file, define CfgPostMake as True/False.

#CfgPostMake = False

!ifdef CfgPostMake

postmake.bat:
<<postmake.bat
@rem --------------------------------------------------------------
@rem - You may add a post-make sequence to the end of the Bios
@rem - build process to create the actual prom image files you need.

116
Introduction to AutoBios

@rem - This may include concatenating the Bios to other file images
@rem - for larger prom sizes, running the "bin2hex <infile >outfile"
@rem - converter, or for downloading the prom image to a prom
@rem - programmer. You may wish to run an audio "beep" routine to
@rem - alert you to completion of the build.
@rem - The commands may end with the "^" caret to specify a "newline"
@rem - continuation character.
@rem -------- Insert PostMake Command below ------------------------
rem -- Optional -- PostMake file defined ---
pause
@rem -------- Insert PostMake Commands above -----------------------
<<KEEP
!endif
#---- End Of PostMake template -----------------------------------

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

117
Introduction to AutoBios

4.2.2.15 Tom.Job
#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Bios Default Project Configuration FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] Tom.JOB
#
# [Functional Description]
#
# If "NMAKE <enter>" is run without a "Project = xxx" argument,
# this file is used for the default configuration.
#
# To create a specific project, use this file as a sample,
# and create a "myname.prj" file for a specific project
# configuration. Run "NMAKE Project=myname <enter>" to
# create a bios.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
#--------------------------------------------------------------------
# These flags may be defined to specify the target project.
# They provide a preset description for popular combinations.
# They are intended to provide the first-highest-level choice.
# They may then set up standard conditions for that target
# Note: These Project Flags should be placed at the beginning
# so that the default expansions come last.

#[Projects]

# The detailed flags for a particular target may be specified below

CfgProjectVersion = "0.99"
CfgProjectCustomer= "Tom"
CfgProjectPartNr = "930203000000-00001"
CfgProjectOption = ""
CfgPromSingle = True
CfgCmos = True
CfgCmosInit = True
CfgCmosInitAlways = True

CfgDisk1Type = 1440

119
Configuring a Bios

CTomfgDisk2Type = 360
CfgVideoType = Mono
CfgBaseMem = 640
CfgExtMem = 1920
CfgHard1Type = 47
CfgHard47Cyls = 733
CfgHard47Heads = 4
CfgHard47Sectors= 28

CfgBootSysVue = True
CfgBootOrder = 0

CfgKeyboardIntercept = False

CfgPlatform = AT386
CfgChip = Eteq390

# You may define CfgChipData0 thru CfgChipData9


# See the "CfgChip".chp file for the chip definitions
# Refer to ChipHelp.Txt (created during make) for reference.

# The defines below are examples. Run "CfgChip".exe <enter> on


# a working board (with the OEM bios) to see how registers are
# originally set up. The register names can be found in the
# "CfgChip".Chp file for your selected chipset.

CfgChipData0 = DramBankConfiguration, 006h


CfgChipData1 = ShadowRam16kMap1, 0f0h

# If a "postmake" file exists, then it will be appended to


# the end of the standard makefile. Use this for any special
# finishing touches to the build process. See Common.Plt for
# the postmake template

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

120
Introduction to AutoBios

4.3 The Chip Files

4.3.1 The Chip Directory


The Listing File is generated and updated during the make process to create a text file containing the
names of the existing chip support modules. As more support is added, this list will change.

---------- CHIP.DIR
02/13/95 08:53a 2,803 SUNTAC.CHP
02/13/95 08:53a 2,951 NOCHIP.CHP
02/13/95 08:53a 5,531 WILDCARD.CHP
02/13/95 08:53a 7,537 VLSI310.CHP
02/13/95 08:53a 8,659 HLAND18.CHP
02/13/95 08:53a 9,019 VLSI486.CHP
02/13/95 08:53a 10,498 HLAND22.CHP
02/13/95 08:53a 10,794 VLSI315.CHP
02/13/95 08:53a 10,845 AMD286LX.CHP
02/13/95 08:53a 11,891 HLAND12.CHP
02/13/95 08:53a 16,303 ACER1217.CHP
02/13/95 08:53a 16,362 C_TNEAT.CHP
02/13/95 08:53a 17,480 C_TF8680.CHP
02/13/95 08:53a 18,022 ETEQ390.CHP
02/13/95 08:53a 18,119 C_TSCAT.CHP
02/13/95 08:53a 18,448 OPTI499.CHP
02/13/95 08:53a 19,890 TI411.CHP
02/13/95 08:53a 20,541 SARC2016.CHP
02/13/95 08:53a 20,838 UMC481_2.CHP
02/13/95 08:53a 21,169 ACER1207.CHP
02/13/95 08:53a 23,816 C_T4031.CHP
02/13/95 08:53a 27,548 SYMPH461.CHP
02/13/95 08:53a 51,912 I386EX.CHP

121
Introduction to AutoBios

4.3.2 The Default Chip


4.3.2.1 The NoChip.Chp File
This file is used when no specific chips support is needed for a particular system board. It is the default
support used unless a specific .Chp file is specified. Although it may be used as a general template for
a .Chp file, examples shown in the Appendices will provide more information as to typical pieces of code
involved in initializing chip registers, performing memory typing, and providing extra advanced features.

[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] No Glue Chip Dummy Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] NOCHIP.CHP

[File Status] Prototype, Complete

[Language] Mixed MSVC 1.0/1.5 MASM6.1x

[Description] This module is used to provide the default support when


[Description] no glue chip is specified in the .Job file.

[History] 2.00 04/11/94 Original

A Mixed language .Chp module contains support for:


1. Loading the chip configuration registers, if required.
2. Memory typing (chip size determination), if supported.
3. Chip enhancement support, Fast A20, Fast Reset, etc., if supported.
4. Chip type Identification text string
5. SysVue's DumpChip registers command, if enabled.
6. Other support as added.

This module provides a single-module for all the chip-specific


routines involved with a particular chip.

**********************************************************************

-------------------------------------------------------------------

[Extract] [H]

#define ChipID "NoChip"

[Break]

123
The C Programs

-----------------------------------------------------------

[Extract] [C] [DUMP]

struct ItemList DumpList[] =


{
{"","",0,SizeIsByte,0 },
};

unsigned ReadChipRegister(unsigned q, unsigned size)


{
return(q);
};

[Break]

-------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;--- Dummy References Template for Chip Initializing routines ---


;
; This module has 2 standard hooks from the main Bios -
; 1. to preconfigure the chip
; 2. to determine memory configuration (optional)
;
; For pre-configure, use this model
;
ChipHook1 LABEL NEAR
jmp NEAR PTR ResumeChipHook1
;
; For memory configuration, use this model
;
ChipHook2 LABEL NEAR
jmp NEAR PTR ResumeChipHook2
;

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

-------------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)

124
Introduction to AutoBios

{
unsigned Results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(Results);
};

[Break]

;--------------------------------------------------------------------

125
Introduction to AutoBios

4.3.3 The Specific Chips


4.3.3.1 Acer1207
[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] ACER M1207 Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] ACER1207.CHP

[File Status] Being Updated

[Language] Mixed MSVC 1.0/1.5 MASM6.11

[Description] This module is used to Initialize the Acer AM1207 chip.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "Acer 1207"

#define ChipClockWaitStateRegister 0xfc80


#define ChipClockWaitStateRegisterDefault 0x32
// FC80 - Clock and Wait State Register - Default 32h
// Bit 7, Reserved
// Bit 6-5, 8-bit AT cycle wait state generator
// 00 = 5 wait states
// 01 = 4 wait states*
// 10 = 3 wait states
// 11 = 2 wait states
// Bit 4-3, 16-bit AT cylce wait state generator
// 00 = 3 wait states
// 01 = 2 wait states
// 10 = 1 wait state *
// 11 = 0 wait state
//
// Bit 2-0, Processor/System Clock source select
// ProClk SysClk
// 0XX = Note A CLK2IN/4
// 101 = CLK2IN CLK2IN/2
// 110 = CLK2IN CLK2IN/4
// 111 = CLK2IN ATCLK/2

127
The C Programs

// Bit 2 selects the CPU clock. Bit2 = 0 = low (normal) speed,


// Bit2 = 1 = high speed. If low speed is selected, page-
// interleave is disabled.
// Note A: PROCLK is CLK2IN/2 if -DACK7 is pulled up.
// PROCLK is ATCLK/2 if -DACK7 is not pulled up.
//
//DefaultValue 0fc80h,0
//
#define ChipRomWaitRamTypeReg 0xfc81
#define ChipRomWaitRamTypeRegDefault 0x00
// FC81 - ROM Wait state and DRAM type - Default 00h
// Bit 7, Page/interleave mode interleave
// 0 = Disable *
// 1 = Enable
// Bit 6, 640K to 1M RAM relocation bit
// 0 = DRAM Types 1 & 8 should not remap RAM area *
// 1 = DRAM Types 2-7 should relocate RAM area 0A0000h-0FFFFh
// Bit 5-3, DRAM Type
// 1 000 = 1-bank 512K *
// 2 001 = 1-bank 2M
// 3 010 = 2-bank 1M
// 4 011 = 2-bank 4M
// 5 100 = 4-bank 2M
// 6 101 = 4-bank 5M
// 7 110 = 4-bank 8M
// 8 111 = 2-bank 640K
// Bit 2, Conventional mode RAM wait states
// 0 = 1 wait state *
// 1 = 0 wait state
// Bit 1-0, ROM wait states
// 00 = 3 waits states *
// 01 = 2 wait states
// 10 = 1 wait state
// 11 = 0 wait state
//
//DefaultValue 0fc81h,0
//
#define ChipConfigurationStatus 0xfc82
#define ChipConfigurationStatusDefault 0x00
// FC82 - Configuration Status (Read Only)
// Bit 7, Reserved (low, refer to -DACK6)
// Bit 6, 8/16 Bit ROM BIOS Select (refer to -DACK5)
// 0 = 16-bit *
// 1 = 8 bit
// Bit 5, Page mode timeout enable (refer to -DACK3)
// 0 = enable *
// 1 = disable
// Bit 4, Extend 1/2 CLK2 for RAS during conventional memory access
// (refer to -DACK2)
// 0 = OFF *
// 1 = ON
// Bit 3, reserved (high, refer to -DACK1)
// Bit 2-1, Bank Parity Check Error. Read this register during a
// parity error to determine the error source.
// 00 = bank 0
// 01 = bank 1

128
Introduction to AutoBios

// 10 = bank 2
// 11 = bank 3
// Bit 0, ROM BIOS Location (refer to -DACK0)
// 0 = AT memory bus (MD Bus) *
// 1 = AT extended bus (XD Bus)
//
//
#define ChipRomTypeShadowRamEnable 0xfc83
#define ChipRomTypeShadowRamEnableDefault 0x00
// FC83 - ROM Chip type and Shadow RAM enable - Default 00h
// Bit 7-6, ROM Chip type
// 00 = 16K (27128) *
// 01 = 32K (27256)
// 11 = 64K (27512)
// Bit 5, 0F0000-0FFFFF 0 = Disable *, 1 = Enable
// Bit 4, 0E0000-0EFFFF 0 = Disable *, 1 = Enable
// Bit 3, 0D0000-0DFFFF 0 = Disable *, 1 = Enable
// Bit 2, 0C0000-0CFFFF 0 = Disable *, 1 = Enable
// Bit 1, 0B0000-0BFFFF 0 = Disable *, 1 = Enable
// Bit 0, 0A0000-0AFFFF 0 = Disable *, 1 = Enable
//
//DefaultValue 0FC83H,0
//
#define ChipRomAreaEnableShadowRamMode 0xfc84
#define ChipRomAreaEnableShadowRamModeDefault 0x00
// FC84 - ROM area Enable Shadow RAM mode (8-bit R/W)
// Default = 00h
// Follow the steps below to enable the shadow RAM function
// a. Set Shadow RAM to write-only mode.
// b. Read BIOS and Write BIOS data in to the Shadow RAM.
// c. Set Shadow RAM to read-only mode to prevnet memory writes.
//
// Bit 7-6, Video Shadow ROM function (C0000-DFFFF)
// 00 = Disable *
// 01 = Readable
// 10 = Writable
// 11 = Readable/Writable
// Bit 5-4, Video Shadow ROM function (A0000-BFFFF)
// 00 = Disable *
// 01 = Readable
// 10 = Writable
// 11 = Readable/Writable
// Bit 3-2, Shadow ROM function (E0000-FFFFF)
// 00 = Disable *
// 01 = Readable
// 10 = Writable
// 11 = Readable/Writable
// Bit 1, E0000-EFFFF 0 = Enable * / 1 = Disable
// Bit 0, F0000-FFFFF 0 = Enable * / 1 = Disable
//
//DefaultValue 0fc84h,0
//
#define ChipMiscFunctions 0xfc85
#define ChipMiscFunctionsDefault 0x00
// FC85 - Misc. functions - Default 00h
//

129
The C Programs

// Bit 7, DMA Clock source select


// 0 = DMACLK = SYSCLK/2 *
// 1 = DMACLK = SYSCLK
// Bit 6, DMAMEMR command delay
// 0 = One DMA clock cycle delay *
// 1 = No DMA clock cycle delay
// Bit 5-4, DMA wait states
// 00 = 1 wait state *
// 01 = 2 wait states
// 10 = 3 wait states
// 11 = 4 wait states
// Bit 3, Gate A20 Bit
// 0 = Propagate CPU A20 to A20 line *
// 1 = Set A20 to 0
// Bit 2, Reserved
// Bit 1-0, Sleep mode enable/disable. The M1207 will enter sleep mode
// (stop CPU and system clock) when the CPU issues a HLT
// instruction, followed by HLDACK. An INTR or NMI will wake
// up the M1207 from sleep mode.
// 00 = Disable sleep mode *
// 01 = Disable sleep mode
// 10 = Disable sleep mode
// 11 = Enable sleep mode
//
//DefaultValue 0fc85h, 0
//
#define ChipPlanarControl 0xfc86
#define ChipPlanarControlDefault 0xF0
// FC86 - Planar control register 1 (8-bit R/W)
// Default = 11110000
// Bit 7, RAM B0000-BFFFF 0 = Enable / 1 = Disable *
// Bit 6, RAM A0000-AFFFF 0 = Enable / 1 = Disable *
// Bit 5, RAM 90000-9FFFF 0 = Enable / 1 = Disable *
// Bit 4, RAM 80000-8FFFF 0 = Enable / 1 = Disable *
// Bit 3, RAM 70000-7FFFF 0 = Enable * / 1 = Disable
// Bit 2, RAM 60000-6FFFF 0 = Enable * / 1 = Disable
// Bit 1, RAM 50000-5FFFF 0 = Enable * / 1 = Disable
// Bit 0, RAM 40000-4FFFF 0 = Enable * / 1 = Disable
//
//DefaultValue 0fc86h,0f0h
//
#define ChipEnableCfgRegAccess 0xfc87
#define ChipEnableCfgRegAccessDefault 0x00
// FC87 - Enable configuration register access
// Read this register immediately before reading or writing other
// registers. Reading this register prepares (opens) the next
// register being accessed for read or write operations.
// The value read from this register is meaningless.
// The read operation itself is significant.
// The register access routine below will perform this operation
// for each initialization write.
//
//
#define ChipRefreshCycleOption 0xfc89
#define ChipRefreshCycleOptionDefault 0x30
// FC89 - Refresh cycle option select. Default is 0011000

130
Introduction to AutoBios

// Bit 7-6, Reserved (low)


// Bit 5, Reserved (high)
// Bit 4, Fast Gate A20 enable/disable
// 0 = Disable (use external GATEA20 from keyboard controller)
// 1 = Enable *
// Bit 3-2, Number of refreshes in one cycle
// 00 = 1 *
// 01 = 2
// 10 = 3
// 11 = 4
// Bit 1-0 Refresh mode cycle select
// 00 = 0 ( 4 ms) *
// 01 = 1 ( 8 ms)
// 10 = 2 (16 ms)
// 11 = 3 (32 ms)
//
//DefaultValue 0fc89h,030h

[Break]

---------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct ItemList DumpList[] =


{
{ "ChipClockWaitStateRegister","", ChipClockWaitStateRegister,
SizeIsByte,ChipClockWaitStateRegisterDefault, },
{ "ChipRomWaitRamTypeReg","", ChipRomWaitRamTypeReg,
SizeIsByte,ChipRomWaitRamTypeRegDefault, },
{ "ChipConfigurationStatus","", ChipConfigurationStatus,
SizeIsByte,ChipConfigurationStatusDefault, },
{ "ChipRomTypeShadowRamEnable","", ChipRomTypeShadowRamEnable,
SizeIsByte,ChipRomTypeShadowRamEnableDefault, },
{ "ChipRomAreaEnableShadowRamMode","",ChipRomAreaEnableShadowRamMode,
SizeIsByte,ChipRomAreaEnableShadowRamModeDefault,},
{ "ChipMiscFunctions","", ChipMiscFunctions,
SizeIsByte,ChipMiscFunctionsDefault, },
{ "ChipPlanarControl","", ChipPlanarControl,
SizeIsByte,ChipPlanarControlDefault, },
{ "ChipEnableCfgRegAccess","", ChipEnableCfgRegAccess,
SizeIsByte,ChipEnableCfgRegAccessDefault, },
{ "ChipRefreshCycleOption","", ChipRefreshCycleOption,
SizeIsByte,ChipRefreshCycleOptionDefault, },
{ "","",0,SizeIsByte,0,}, /* Nul String or Zero Value is End of Table */
};

/*--- Read the Acer Chip Register ------*/

unsigned ReadChipRegister(unsigned Reg, unsigned size)


{

131
The C Programs

inp(0xfc87);
//FlushCpuQueue
//FlushCpuQueue;
return(inp(Reg));
}

[Break]

------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

ChipTable LABEL WORD


;
; * denotes default value
; To insure that the chip is returned to a known state when executing
; a software reset (CTRL-ALT-DEL, for example), the registers are
; explicitly loaded with the power-on values that would exist
; from a cold power-up start.
DefaultValue 0fc80h,032h
DefaultValue 0fc81h,000h
DefaultValue 0FC83H,000h
DefaultValue 0fc84h,000h
DefaultValue 0fc85h,000h
DefaultValue 0fc86h,0f0h
DefaultValue 0fc89h,030h

; Then the desired chip values may be loaded

;
; FC80 - Clock and Wait State Register - Default 32h
; Bit 7, Reserved
; Bit 6-5, 8-bit AT cycle wait state generator
; 00 = 5 wait states
; 01 = 4 wait states*
; 10 = 3 wait states
; 11 = 2 wait states
; Bit 4-3, 16-bit AT cylce wait state generator
; 00 = 3 wait states
; 01 = 2 wait states
; 10 = 1 wait state *
; 11 = 0 wait state
;
; Bit 2-0, Processor/System Clock source select
; ProClk SysClk
; 0XX = Note A CLK2IN/4
; 101 = CLK2IN CLK2IN/2
; 110 = CLK2IN CLK2IN/4
; 111 = CLK2IN ATCLK/2

132
Introduction to AutoBios

; Bit 2 selects the CPU clock. Bit2 = 0 = low (normal) speed,


; Bit2 = 1 = high speed. If low speed is selected, page-
; interleave is disabled.
; Note A: PROCLK is CLK2IN/2 if -DACK7 is pulled up.
; PROCLK is ATCLK/2 if -DACK7 is not pulled up.
;
;DefaultValue 0fc80h,0
;
; FC81 - ROM Wait state and DRAM type - Default 00h
; Bit 7, Page/interleave mode interleave
; 0 = Disable *
; 1 = Enable
; Bit 6, 640K to 1M RAM relocation bit
; 0 = DRAM Types 1 & 8 should not remap RAM area *
; 1 = DRAM Types 2-7 should relocate RAM area 0A0000h-0FFFFh
; Bit 5-3, DRAM Type
; 1 000 = 1-bank 512K *
; 2 001 = 1-bank 2M
; 3 010 = 2-bank 1M
; 4 011 = 2-bank 4M
; 5 100 = 4-bank 2M
; 6 101 = 4-bank 5M
; 7 110 = 4-bank 8M
; 8 111 = 2-bank 640K
; Bit 2, Conventional mode RAM wait states
; 0 = 1 wait state *
; 1 = 0 wait state
; Bit 1-0, ROM wait states
; 00 = 3 waits states *
; 01 = 2 wait states
; 10 = 1 wait state
; 11 = 0 wait state
;
;DefaultValue 0fc81h,0
;
; FC82 - Configuration Status (Read Only)
; Bit 7, Reserved (low, refer to -DACK6)
; Bit 6, 8/16 Bit ROM BIOS Select (refer to -DACK5)
; 0 = 16-bit *
; 1 = 8 bit
; Bit 5, Page mode timeout enable (refer to -DACK3)
; 0 = enable *
; 1 = disable
; Bit 4, Extend 1/2 CLK2 for RAS during conventional memory access
; (refer to -DACK2)
; 0 = OFF *
; 1 = ON
; Bit 3, reserved (high, refer to -DACK1)
; Bit 2-1, Bank Parity zCheck Error. Read this register during a
; parity error to determine the error source.
; 00 = bank 0
; 01 = bank 1
; 10 = bank 2
; 11 = bank 3
; Bit 0, ROM BIOS Location (refer to -DACK0)
; 0 = AT memory bus (MD Bus) *

133
The C Programs

; 1 = AT extended bus (XD Bus)


;
;
; FC83 - ROM Chip type and Shadow RAM enable - Default 00h
; Bit 7-6, ROM Chip type
; 00 = 16K (27128) *
; 01 = 32K (27256)
; 11 = 64K (27512)
; Bit 5, 0F0000-0FFFFF 0 = Disable *, 1 = Enable
; Bit 4, 0E0000-0EFFFF 0 = Disable *, 1 = Enable
; Bit 3, 0D0000-0DFFFF 0 = Disable *, 1 = Enable
; Bit 2, 0C0000-0CFFFF 0 = Disable *, 1 = Enable
; Bit 1, 0B0000-0BFFFF 0 = Disable *, 1 = Enable
; Bit 0, 0A0000-0AFFFF 0 = Disable *, 1 = Enable
;
;DefaultValue 0FC83H,0
;
; FC84 - ROM area Enable Shadow RAM mode (8-bit R/W)
; Default = 00h
; Follow the steps below to enable the shadow RAM function
; a. Set Shadow RAM to write-only mode.
; b. Read BIOS and Write BIOS data in to the Shadow RAM.
; c. Set Shadow RAM to read-only mode to prevnet memory writes.
;
; Bit 7-6, Video Shadow ROM function (C0000-DFFFF)
; 00 = Disable *
; 01 = Readable
; 10 = Writable
; 11 = Readable/Writable
; Bit 5-4, Video Shadow ROM function (A0000-BFFFF)
; 00 = Disable *
; 01 = Readable
; 10 = Writable
; 11 = Readable/Writable
; Bit 3-2, Shadow ROM function (E0000-FFFFF)
; 00 = Disable *
; 01 = Readable
; 10 = Writable
; 11 = Readable/Writable
; Bit 1, E0000-EFFFF 0 = Enable * / 1 = Disable
; Bit 0, F0000-FFFFF 0 = Enable * / 1 = Disable
;
;DefaultValue 0fc84h,0
;
; FC85 - Misc. functions - Default 00h
;
; Bit 7, DMA Clock source select
; 0 = DMACLK = SYSCLK/2 *
; 1 = DMACLK = SYSCLK
; Bit 6, DMAMEMR command delay
; 0 = One DMA clock cycle delay *
; 1 = No DMA clock cycle delay
; Bit 5-4, DMA wait states
; 00 = 1 wait state *
; 01 = 2 wait states
; 10 = 3 wait states

134
Introduction to AutoBios

; 11 = 4 wait states
; Bit 3, Gate A20 Bit
; 0 = Propagate CPU A20 to A20 line *
; 1 = Set A20 to 0
; Bit 2, Reserved
; Bit 1-0, Sleep mode enable/disable. The M1207 will enter sleep mode
; (stop CPU and system clock) when the CPU issues a HLT
; instruction, followed by HLDACK. An INTR or NMI will wake
; up the M1207 from sleep mode.
; 00 = Disable sleep mode *
; 01 = Disable sleep mode
; 10 = Disable sleep mode
; 11 = Enable sleep mode
;
;DefaultValue 0fc85h, 0
;
; FC86 - Planar control register 1 (8-bit R/W)
; Default = 11110000
; Bit 7, RAM B0000-BFFFF 0 = Enable / 1 = Disable *
; Bit 6, RAM A0000-AFFFF 0 = Enable / 1 = Disable *
; Bit 5, RAM 90000-9FFFF 0 = Enable / 1 = Disable *
; Bit 4, RAM 80000-8FFFF 0 = Enable / 1 = Disable *
; Bit 3, RAM 70000-7FFFF 0 = Enable * / 1 = Disable
; Bit 2, RAM 60000-6FFFF 0 = Enable * / 1 = Disable
; Bit 1, RAM 50000-5FFFF 0 = Enable * / 1 = Disable
; Bit 0, RAM 40000-4FFFF 0 = Enable * / 1 = Disable
;
;DefaultValue 0fc86h,0f0h
;
; FC87 - Enable configuration register access
; Read this register immediately before reading or writing other
; registers. Reading this register prepares (opens) the next
; register being accessed for read or write operations.
; The value read from this register is meaningless.
; The read operation itself is significant.
; The register access routine below will perform this operation
; for each initialization write.
;
;
; FC89 - Refresh cycle option select. Default is 0011000
; Bit 7-6, Reserved (low)
; Bit 5, Reserved (high)
; Bit 4, Fast Gate A20 enable/disable
; 0 = Disable (use external GATEA20 from keyboard controller)
; 1 = Enable *
; Bit 3-2, Number of refreshes in one cycle
; 00 = 1 *
; 01 = 2
; 10 = 3
; 11 = 4
; Bit 1-0 Refresh mode cycle select
; 00 = 0 ( 4 ms) *
; 01 = 1 ( 8 ms)
; 10 = 2 (16 ms)
; 11 = 3 (32 ms)
;

135
The C Programs

;DefaultValue 0fc89h,030h

; include any data specified in the .Job file

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

DefaultValue -1,-1 ; -1 Arguments indicate End of Table

;--------- This is the register load loop --------------------

PreparePort = 0fc87h

ChipHook1 LABEL NEAR


mov si,offset ChipTable
.WHILE 1
mov dx,PreparePort ; prepare the port for writing
in al,dx
jmp $+2
jmp $+2
lods WORD PTR cs:[si] ; get the port #
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ax
lods WORD PTR cs:[si] ; get the value
out dx,al ; load the value
.ENDW
jmp NEAR PTR ResumeChipHook1

; ---------- no action needed ------------------

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem

136
Introduction to AutoBios

jmp NEAR PTR ResumeChipHook3

[Break]

-------------------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

137
Introduction to AutoBios

4.3.3.2 Acer1217
[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] ACER M1217 Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 10/12/93

[File Name] ACER1217.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to support the Acer AM1217 chip.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "Acer1217"

#define ChipRegPort 0x22


#define ChipDataPort 0x23

#define FastGateA20Port ChipCacheControl


#define FastGateA20Bit 0x01

#define FastResetPort ChipCacheControl


#define FastResetBit 0x20

#define ChipRomSize 0x10


#define ChipRomSizeDefault 0x00
// Bit Description
// 7-3 Dram Type
// Bank 0 Bank 1 Total
// 00000xxx = 256K*2 512K
// 00010xxx = 256K*4 1M
// 00100xxx = 512K*2 1M
// 00110xxx = 256K*4 256K*4 2M
// 01000xxx = 512K*4 2M
// 01010xxx = 1M*2 2M
// 01100xxx = 256K*4 1M*2 3M

139
The C Programs

// 01110xxx = 512K*2 1M*2 3M


// 10000xxx = 512K*4 512K*4 4M
// 10010xxx = 512K*4 1M*2 4M
// 10100xxx = 1M*4 4M
// 10110xxx = 512K*2 1M*4 5M
// 11000xxx = 256K*4 1M*4 5M
// 11010xxx = 512K*4 1M*4 6M
// 11100xxx = 1M*4 1M*2 6M
// 11110xxx = 1M*4 1M*4 8M
// 00001xxx = 4M*2 8M
// 00011xxx = 1M*4 4M*2 12M
// 00101xxx = 4M*4 16M
// 2 Onboard Memory 15M -> 15M -1 enable/disable
// 1 Refresh Type
// xxxxxx0x = RAS only refresh
// xxxxxx1x = CAS before RAS refresh
// 0 Rom Size
// xxxxxxx0 = 64K Bios
// xxxxxxx1 = 128K Bios

#define ChipDramController 0x11


#define ChipDramControllerDefault 0xF8
// Bit Description
// 7 Burst mode memory access insert wait
// 6 Memory access time insert wait
// 5 RAS timeout disable/enable (0/1)
// 4 CAS precharge time insert wait
// 3 RASactvie time insert wait
// 2 Memory remap disable/enable (0/1)
// 1 Select remap mode split/move-out (0/1)
// 0 Fast RAS precharge time

#define ChipSplitAddress 0x12


#define ChipSplitAddressDefault 0x10
// Bit Description
// 7-4 Split Address SP(23-20)
// 3-0 reserved - must be zero for normal operation

#define ChipLockRegister 0x13


#define ChipLockRegisterLock 0x00
#define ChipLockRegisterUnlock 0xC5

#define ChipPageCDShadow 0x14


#define ChipPageCDShadowDefault 0x00
// Bit Description
// 7 Shadow Ram D800-DFFF write disable/enable (0/1)
// 6 Shadow Ram D800-DFFF read disable/enable (0/1)
// 5 Shadow Ram D000-D7FF write disable/enable (0/1)
// 4 Shadow Ram D000-D7FF read disable/enable (0/1)
// 3 Shadow Ram C800-CFFF write disable/enable (0/1)
// 2 Shadow Ram C800-CFFF read disable/enable (0/1)
// 1 Shadow Ram C000-C7FF write disable/enable (0/1)
// 0 Shadow Ram C000-C7FF read disable/enable (0/1)

140
Introduction to AutoBios

#define ChipPageEFShadow 0x15


#define ChipPageEFShadowDefault 0x00
// Bit Description
// 7 Shadow Ram F800-FFFF write disable/enable (0/1)
// 6 Shadow Ram F800-FFFF read disable/enable (0/1)
// 5 Shadow Ram F000-F7FF write disable/enable (0/1)
// 4 Shadow Ram F000-F7FF read disable/enable (0/1)
// 3 Shadow Ram E800-EFFF write disable/enable (0/1)
// 2 Shadow Ram E800-EFFF read disable/enable (0/1)
// 1 Shadow Ram E000-E7FF write disable/enable (0/1)
// 0 Shadow Ram E000-E7FF read disable/enable (0/1)

#define ChipMemRange1A 0x16


#define ChipMemRange1ADefault 0x00
// Bit Description
// 7-0 ISA high speed memory address A[23-16]

#define ChipMemRange1B 0x17


#define ChipMemRange1BDefault 0xFF
// Bit Description
// 7-0 ISA high speed memory address mask A[23-16]

#define ChipMemRange1C 0x18


#define ChipMemRange1CDefault 0xF0
// Bit Description
// 7-4 ISA high speed memory address mask A[15-12]
// 3-0 ISA high speed memory address A[15-12]

#define ChipMemRange2A 0x19


#define ChipMemRange2ADefault 0x00
// Bit Description
// 7-0 ISA high speed memory address A[23-16]

#define ChipMemRange2B 0x1A


#define ChipMemRange2BDefault 0xFF
// Bit Description
// 7-0 ISA high speed memory address mask A[23-16]

#define ChipMemRange2C 0x1B


#define ChipMemRange2CDefault 0xF0
// Bit Description
// 7-4 ISA high speed memory address mask A[15-12]
// 3-0 ISA high speed memory address A[15-12]

#define ChipIORange1A 0x1C


#define ChipIORange1ADefault 0x00
// Bit Description
// 7-0 ISA high speed I/O address A[9-2]

#define ChipIORange1B 0x1D


#define ChipIORange1BDefault 0xFF
// Bit Description
// 7-0 ISA high speed I/O address mask A[9-2]

#define ChipIORange2A 0x1E

141
The C Programs

#define ChipIORange2ADefault 0x00


// Bit Description
// 7-0 ISA high speed I/O address A[9-2]

#define ChipIORange2B 0x1F


#define ChipIORange2BDefault 0xFF
// Bit Description
// 7-0 ISA high speed I/O address mask A[9-2]

#define ChipSpeedPassword 0x30


#define ChipSpeedPasswordDefault 0x08
// Bit Description
// 7-4 Speed hold time counter unit (units l/BLCK1)
// 3 CPU speed high/low (0/1)
// 2 Power down mode disable/enable (0/1)
// 1 Hardware turbo disable/enable (0/1)
// 0 Password unlock/lock (0/1)

#define ChipCacheControl 0x31


#define ChipCacheControlDefault 0x11
// Bit Description
// 7 Reserved
// 6 Power down 16MHz disable/enable (0/1)
// 5 Fast RC enable/disable (0/1) (default = 0)
// 4 Tirbo pin logic value (read only)
// 3 CPU speed cross-setting mode disable/enable (0/1)
// 2 Cache off/on (0/1)
// 1 Power down 4Mhz disable/enable (0/1) (default = 1)
// 0 Fast Gate A20 disable/enable (0/1) (default = 1)

#define ChipHighSpeedControl 0x32


#define ChipHighSpeedControlDefault 0x00
// Bit Description
// 7 ISA IO high speed disable/enable (0/1)
// 6 ISA memory high speed disable/enable (0/1)
// 5-4 CPU low speed level
// 3-1 reserved - must be set to zero for normal operation
// 0 Port F1 reset NP disable/enable (0/1)

#define ChipRecoveryPort 0x33


#define ChipRecoveryPortDefault 0x00
// Bit Description
// 7-4 IO recover period define (unit 250ns)
// 3 IO recovery period disable/enable (0/1)
// 2 On-chip IO recovery disable/enable (0/1)
// 1 reserved - must be zero for normal operation
// 0 Flush Off/On (0/1)

#define ChipPowerOnReport1 0x34


#define ChipPowerOnReport1Default 0x00
// Bit Function Pin# Pin Description (Read Only)
// 7 reserved 75 TC Tie LOW
// 6 PASSWD 133 DACK7 Password disable/enable (0/1)
// 5 reserved 134 DACK6 Tie LOW
// 4 reserved 135 DACK5 Tie LOW
// 3 KBDIRQ 142 DACK3 PS2 KB IRQ1 timing

142
Introduction to AutoBios

// disable/enable (0/1)
// 2 DADS 143 DACK2 Delay ADS disable/enable (0/1)
// 1 reserved 144 DACK1 Tie LOW
// 0 ROMBIOS 145 DACK0 8/16 bit Rom Bios select (0/1)

#define ChipPowerOnReport2 0x35


#define ChipPowerOnReport2Default 0xea
// Bit Function Pin# Pin Description (Read Only)
// 7 reserved 50 OE0J Tie HIGH
// 6-5,2 reserved
// 4-3 ATCLOCK[1-0] 64 KBSJ Define AT CLOCK mode
// 9 SSTBJ CPU CLK ATCLOCK [1-0]
// 66MHz 00
// 50MHz 01
// 40MHz 10
// 32MHz 11
// 1 PCHK 66 ROMCSJ Mem. parity chk dis/en (0/1)
// 0 GA20IO 65 XDIR FastGateA20 pin input/output

#define ChipVersion 0x36


#define ChipVersionDefault 0x00
// Bit Description
// 7 16 bit ISA cycle insert 1 wait disable/enable (0/1)
// 6 PS2 mouse IRQ12 timing disable/enable (0/1)
// 5 reserved - must be zero for normal operation
// 4 Slow refresh disable/enable (0/1)
// 3 CPU clock immediately power down disable/enable (0/1)
// 2-0 Chip Version (read only)
[Break]

---------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct ItemList DumpList[] =


{
{ "ChipRomSize","",ChipRomSize,SizeIsByte, ChipRomSizeDefault, },
{ "ChipDramController","",ChipDramController,SizeIsByte,
ChipDramControllerDefault },

{ "ChipSplitAddress","",ChipSplitAddress,SizeIsByte,ChipSplitAddressDefault, }
,

{ "ChipPageCDShadow","",ChipPageCDShadow,SizeIsByte,ChipPageCDShadowDefault, }
,

{ "ChipPageEFShadow","",ChipPageEFShadow,SizeIsByte,ChipPageEFShadowDefault, }
,
{ "ChipMemRange1A","",ChipMemRange1A,SizeIsByte,ChipMemRange1ADefault, },
{ "ChipMemRange1B","",ChipMemRange1B,SizeIsByte,ChipMemRange1BDefault, },
{ "ChipMemRange1C","",ChipMemRange1C,SizeIsByte,ChipMemRange1CDefault, },
{ "ChipMemRange2A","",ChipMemRange2A,SizeIsByte,ChipMemRange2ADefault,},

143
The C Programs

{ "ChipMemRange2B","",ChipMemRange2B,SizeIsByte,ChipMemRange2BDefault, },
{ "ChipMemRange2C","",ChipMemRange2C,SizeIsByte,ChipMemRange2CDefault, },
{ "ChipIORange1A","",ChipIORange1A,SizeIsByte,ChipIORange1ADefault, },
{ "ChipIORange1B","",ChipIORange1B,SizeIsByte,ChipIORange1BDefault, },
{ "ChipIORange2A","",ChipIORange2A,SizeIsByte,ChipIORange2ADefault, },
{ "ChipIORange2B","",ChipIORange2B,SizeIsByte,ChipIORange2BDefault, },

{ "ChipSpeedPassword","",ChipSpeedPassword,SizeIsByte,ChipSpeedPasswordDefault
, },

{ "ChipCacheControl","",ChipCacheControl,SizeIsByte,ChipCacheControlDefault, }
,

{ "ChipHighSpeedControl","",ChipHighSpeedControl,SizeIsByte,ChipHighSpeedContr
olDefault, },

{ "ChipRecoveryPort","",ChipRecoveryPort,SizeIsByte,ChipRecoveryPortDefault,},
{ "ChipVersion","",ChipVersion,SizeIsByte,ChipVersionDefault, },
{ "","",0,SizeIsByte,0}, /* Nul String or Zero Value is End of Table */
};

//---- Chip Specific routine to read a selected register ---


//-------- This routine will vary from chip to chip -----

unsigned ReadChipRegister(unsigned Reg, unsigned size)


{
unsigned Result;
outp(ChipRegPort,ChipLockRegister);
outp(ChipDataPort,ChipLockRegisterUnlock);
outp(ChipRegPort,Reg);
Result = inp(ChipDataPort);
outp(ChipRegPort,ChipLockRegister);
outp(ChipDataPort,ChipLockRegisterLock);
return(Result);
}

[Break]

----------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;--- This macro is used to simplify typing in the desired values ---

DefaultValue macro chipreg,chipval


WORD chipreg
WORD chipval
endm

144
Introduction to AutoBios

;--------- This is the register load loop --------------------

ChipTable LABEL WORD


; This sets all registers back to a power-on default state.

DefaultValue ChipLockRegister,ChipLockRegisterUnlock
DefaultValue ChipRomSizeDefault,ChipRomSizeDefault
DefaultValue ChipDramController,ChipDramControllerDefault
DefaultValue ChipSplitAddress,ChipSplitAddressDefault
DefaultValue ChipPageCDShadow,ChipPageCDShadowDefault
DefaultValue ChipPageEFShadow,ChipPageEFShadowDefault
DefaultValue ChipMemRange1A,ChipMemRange1ADefault
DefaultValue ChipMemRange1B,ChipMemRange1BDefault
DefaultValue ChipMemRange1C,ChipMemRange1CDefault
DefaultValue ChipMemRange2A,ChipMemRange2ADefault
DefaultValue ChipMemRange2B,ChipMemRange2BDefault
DefaultValue ChipMemRange2C,ChipMemRange2CDefault
DefaultValue ChipIORange1A,ChipIORange1ADefault
DefaultValue ChipIORange1B,ChipIORange1BDefault
DefaultValue ChipIORange2A,ChipIORange2ADefault
DefaultValue ChipIORange2B,ChipIORange2BDefault
DefaultValue ChipSpeedPassword,ChipSpeedPasswordDefault
DefaultValue ChipCacheControl,ChipCacheControlDefault
DefaultValue ChipHighSpeedControl,ChipHighSpeedControlDefault
DefaultValue ChipRecoveryPort,ChipRecoveryPortDefault
DefaultValue ChipVersion,ChipVersionDefault

; Now setup for particular board

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5

145
The C Programs

WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

; End of Table

DefaultValue ChipLockRegister,ChipLockRegisterLock ; Lock - Must be here !


DefaultValue -1,-1 ; -1 Arguments indicate End of Table

ChipHook1 LABEL NEAR

mov si,offset ChipTable


.WHILE 1
lods WORD PTR cs:[si]
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
lods WORD PTR cs:[si]
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al
.ENDW
jmp NEAR PTR ResumeChipHook1

; ---------- no action needed ------------------

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

-----------------------------------------------------------------

146
Introduction to AutoBios

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned Temp;
unsigned results = False;
/*
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{
case ChipEnable:
outp(ChipRegPort,ChipLockRegister);
outp(ChipDataPort,ChipLockRegisterUnlock);
outp(ChipRegPort,FastGateA20Port);
Temp = inp(ChipDataPort);
outp(ChipRegPort,FastGateA20Port);
outp(ChipDataPort,Temp | FastGateA20Bit);
outp(ChipRegPort,ChipLockRegister);
outp(ChipDataPort,ChipLockRegisterLock);
results = True;
break;

case ChipDisable:
outp(ChipRegPort,ChipLockRegister);
outp(ChipDataPort,ChipLockRegisterUnlock);
outp(ChipRegPort,FastGateA20Port);
Temp = inp(ChipDataPort);
outp(ChipRegPort,FastGateA20Port);
outp(ChipDataPort,Temp & ~FastGateA20Bit);
outp(ChipRegPort,ChipLockRegister);
outp(ChipDataPort,ChipLockRegisterLock);
results = True;
break;
};
break;

case ChipFastResetCPU:
switch (Opcode)
{
case ChipEnable:
outp(ChipRegPort,ChipLockRegister);
outp(ChipDataPort,ChipLockRegisterUnlock);
outp(ChipRegPort,FastResetPort);
Temp = inp(ChipDataPort);
outp(ChipRegPort,FastResetPort);
outp(ChipDataPort,Temp | FastResetBit);
outp(ChipRegPort,ChipLockRegister);
outp(ChipDataPort,ChipLockRegisterLock);
results = True;
break;
};
break;
};
*/

147
The C Programs

return(results);
};

[Break]

148
Introduction to AutoBios

4.3.3.3 AMD286LX
[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] AMD286LX Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] AMD286LX.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize an AMD286LX.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [C]

//--- This is a SysVue command to dump the chip registers (if any) ------

void DumpChip(VueRegSet)
{
printf("\nThis system has no chip registers to dump");
}

[Break]
[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;----------- AMD 286LX Chipset Setup -------------------

;---TABLE OF CONFIG REGISTERS---


; INDEX,DATA

LRR1 equ 00h


CCR1 equ 01h
CCR2 equ 02h

149
The C Programs

PSR equ 03h


CDR equ 04h
WSR equ 05h
IPSW1 equ 06h
IPSW2 equ 07h
IPCD equ 08h
BCR equ 09h
BMCR equ 0Ah
BMPR equ 0Bh
SER1 equ 0Ch
SER2 equ 0Dh
SER3 equ 0Eh
SPR1 equ 0Fh
SPR2 equ 10h
SPR3 equ 11h
MWS equ 12h
ROBR1 equ 13h
ROBR2 equ 14h
RABR equ 15h
DCR equ 16h
ARL equ 18h
XBE1 equ 19h
XBE2 equ 1Ah
XBE3 equ 1Bh
XBE4 equ 1Ch
XBE5 equ 1Dh
XBE6 equ 1Eh
XBE7 equ 1Fh
XBE8 equ 20h
XBD equ 21h
XBSZ equ 22h
PSFR equ 23h
MSC equ 25h

RegisterValueTable:
; return all registers to their default values
DB LRR1 ,0aah
DB CCR1 , 00h
DB CCR2 ,0c0h
DB PSR , 00h
DB CDR ,0ffh
DB WSR ,0ffh
DB IPSW1, 44h
DB IPSW2, 44h
DB IPCD , 00h
DB BCR , 00h
DB BMCR , 00h
DB BMPR , 00h
DB SER1 , 00h
DB SER2 , 00h
DB SER3 , 00h
DB SPR1 , 00h
DB SPR2 , 00h

150
Introduction to AutoBios

DB SPR3 , 00h
DB MWS , 01h
DB ROBR1, 00h
DB ROBR2,0c0h
DB RABR , 00h
DB DCR , 00h
DB ARL , 00h
DB XBE1 , 00h
DB XBE2 , 00h
DB XBE3 , 00h
DB XBE4 , 00h
DB XBE5 , 00h
DB XBE6 , 00h
DB XBE7 , 00h
DB XBE8 , 00h
DB XBD , 00h
DB XBSZ , 00h
DB PSFR , 00h
DB MSC , 00h

; ROM Bank Configuration Register 2


; Bit 7, ROM enable 15, access @ 0FC000 - 0FFFFF
; Bit 6, ROM enable 14, access @ 0F8000 - 0FBFFF
; Bit 5, ROM enable 13, access @ 0F4000 - 0F7FFF
; Bit 4, ROM enable 12, access @ 0F0000 - 0F3FFF
DB ROBR2,0f0h ;ROBR2 - top 64K enable

; Memory Wait States Register


; Bit 7, X-bus recovery time enable =ON (0)
; Bit 6, ROM recovery time enable =ON (0)
; Bit 5:4, DRAM wait states =0 (0,0)
; Bit 3:0, ROM Wait states of 4
DB MWS , 04h ;MWS - RAM 4 w/s

; Internal Peripheral Wait State Register 1


; Bits 7:4, internal interrupt wait states =4
; Bits 3:0, internal DMA wait states =4
DB IPSW1,44h ;IPWS1 - int & DMA 4 w/s

; Internal Peripheral Wait State Register 2


; Bits 7:4, internal CTC wait states =4
; Bits 3:0, internal misc/RTC wait states =4
; DB IPSW2,44h ;IPWS2 - counter & RTC
DB IPSW2,48h ;IPWS2 - counter & RTC

; Internal Peripheral Command Delay Register


; Bit 7:6, Internal misc/RTC command delays =1
; Bit 5:4, Internal CTC command delays =1
; Bit 3:2, Internal Interrupt command delays =1
; Bit 1:0, Internal DMA command delays =1
; DB IPCD,55h ;IPCD - 1 CD for all
DB IPCD,0d5h ;IPCD - 1 CD for all

; Command Delay Register


; Bit 7:6, AT bus 16 memory command delay =3
; Bit 5:4, AT bus 8 memory command delay =3

151
The C Programs

; Bit 3:2, AT bus 16 I/O command delay =3


; Bit 1:0, AT bus 8 I/O command delay =3
DB CDR,0FFh ;CDR - 0 CD M16, 1 CD M8,I16,I8 (MK=15)
(old=ff)

; Wait State Register


; Bit 7:6, AT bus 16 memory wait states =3
; Bit 5:4, AT bus 8 memory wait states =3
; Bit 3:2, AT bus 16 I/O wait states =3
; Bit 1:0, AT bus 8 I/O wait states =3
DB WSR,0FFh ;WSR - 1 w/s 16 bit M/IO, 4 w/s * bit M/IO
(MK=66)(old=ff)

; Clock Configuration Register 1


; Bit 7, Fast bus enable =Yes (1)
; Bit 6:5, AT state machine divisor =2 (1,0) = 16Mhz Merc
; Bit 4, AT state machine clock source =PROCLK 32Mhz Merc =(0)
; Bit 3, not used (0)
; Bit 2:1, Processor clock divisor =2 (1,0) =16Mhz
; Bit 0, Processor clock source =ProClk (0)
; This makes the LX just like the IBM - AT
DB CCR1,0C4h ;CCR1 - CPUCLK = IOCLK = 1x of PROCLK
(MK=22)

; Clock Configuration Register 2


; Bit 7:6, Keyboard clock cource =IOCLK (24Mhz) (0,1)
; Bit 5:4, Keyboard clock divisor =2 (12Mhz) (1,0)
; Bit 3, not used (0)
; Bit 2:1, Coprocessor clock divisor =2 (20Mhz) (1,0)
; Bit 0, Coprocessor clock source =PROCLK (40Mhz) (0)
DB CCR2,064h ;CCR2 - KBDCLK = PROCLK/2 ;C287 CLK =
PROCLK (MK=E4)(old=64)

; Peripheral Selection Register


; Bit 7:6, DMA 16 wait states =4 (1,1)
; Bit 5:4, DMA 8 wait states =4 (1,1)
; Bit 3, not used (0)
; Bit 2, Keyboard type =AT (0)
; Bit 1:0, DMA clock selection =SYSCLK (0,1)
DB PSR,0F5h ;PSR - 1 w/s DMA (8 & 16), DMACLK=SYSCLK
(MK=01)(old=f1)

; RAM Bank Configuration Register


; Bit 7:6, DRAM bank 3 type = not used (0,0)
; Bit 5:4, DRAM bank 2 type = not used (0,0)
; Bit 3:2, DRAM bank 1 type = not used (0,0)
; Bit 1:0, DRAM bank 0 type = 256Kb (01)
DB RABR,01h ;RABR - Bank 0 = 256K DRAMS

; DRAM Configuration Register


; Bit 7, Staggered refresh =OFF normal refresh (0)
; Bit 6, Slow refresh enable =OFF (0)
; Bit 5, Parity enable =OFF (0)
; Bit 4, RAS time out enable =OFF (0)
; Bit 3, not used (0)
; Bit 2, Page Mode enable =OFF (0)

152
Introduction to AutoBios

; Bit 1, Interleave mode =OFF (0)


; Bit 0, Relocate 384Kb memory above 1Mb =OFF (0)
DB DCR,01h ;DCR - no parity,no paging,no interleave

; End of list
DB 00h,00h ;Indicates end of list

;INITIALIZE CONFIGURATION REGISTERS

ChipAddressPort = 22h
ChipDataPort = 23h

ChipHook1 LABEL NEAR


mov si,OFFSET RegisterValueTable ;set start of pointer
.WHILE 1
lods BYTE PTR cs:[si] ; move contents to accum.
.BREAK .IF (al == 0)
out ChipAddressPort,al ; INDEX port
lods BYTE PTR cs:[si]
out ChipDataPort,al ; DATA associated with this port
.ENDW

mov al,09h ;configuration register select


out ChipAddressPort,al ;select BCR, enable S-Bus and RESETDRV
mov al,05h ;reset S-Bus
delay
out ChipDataPort,al

mov cx,3600 ; delay for 5ms @20Mhz


@@: dec cx
jnz @B ;loop to dec cx

mov al,09h ;select BCR


out ChipAddressPort,al
delay
mov al,01h ;bring RESETDRV false
out ChipDataPort,al

jmp NEAR PTR ResumeChipHook1

;----------- End of init table ---------------

;START REFRESH AND PRECHARGE RAM BEFORE THIS CODE

;SIZE AND CONFIGURE LOCAL MEMORY


;This code will detect what size DRAM (if any) each local memory bank
;contains. This information will then be loaded into RABR to configure
;the system's local memory size.

ChipHook2 LABEL NEAR

;mov al,15h ; force rams to 256K and exit


;out ChipAddressPort,al
;delay

153
The C Programs

;mov al,00000001b
;out ChipDataPort,al
;jmp ResumeChipHook2

mov al,015H ; point configuration index to RABR


out ChipAddressPort,al
xor ax,ax
mov ds,ax ; all memory operations to lower 64k
mov ax,0C0C0H ; initial RABR mask, bank 3 for 4Mb
DRAMs
mov cx,4 ; initialize loop counter for 1
pass/bank
xor dl,dl ; initial RABR value
ramsz: out ChipDataPort,al ; configure current bank to 4Mb DRAMs
mov si,00200H
mov WORD PTR [si],0H ; clear 000200H
mov si,00600H
mov WORD PTR [si],0H ; clear 000200H
mov si,00E00H
mov WORD PTR [si],0AA55H ; if 256kb DRAMs then written to 00200H
; if 1Mb DRAMs then written to 00600H
; if 4Mb DRAMs then written to 00E00H
mov si,0000H
mov WORD PTR [si],0 ; clear mdbus of phantom data
mov si,00200H
cmp WORD PTR [si],0AA55H ; Does the bank have 256kb DRAMs
jne chk_1M
and al,001010101B ; 256kb mask
or dl,al ; update value to program RABR with
jmp lp_end
chk_1M: mov si,00600H
cmp WORD PTR [si],0AA55H ; Does the bank have 1Mb DRAMs
jne chk_4M
and al,010101010B ; 1Mb mask
or dl,al ; update value to program RABR with
jmp lp_end
chk_4M: mov si,00E00H
cmp WORD PTR [si],0AA55H ; Does the bank have 1Mb DRAMs
jne lp_end
or dl,al ; update value to program RABR with
lp_end: mov al,ah ; update current bank to 4 Mb DRAMs
ror ax,1
ror ax,1
loop ramsz ; loop for four banks
mov al,dl
out ChipDataPort,al ; configure RABR with final value

;CONTINUE WITH BIOS INITIALIZATION

jmp NEAR PTR ResumePerChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

154
Introduction to AutoBios

;----------- End of Memory Configuration -----------

[Break]

----------------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

155
Introduction to AutoBios

4.3.3.4 Chips & Technology F8680


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] C&T F8680 PC/Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] C&TF8680.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize an LSI chip set


[Desciption] with a default personality, if desired.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "C & T F8680 PC/Chip"

// Chips & Technologies F8680 Chip Information

// F8680 Control Register Ports

#define ChipRegPort 0x22


#define ChipDataPort 0x23

// 82C836 Registers

#define ChipDmaWaitStateControl 0x01


#define ChipDmaWaitStateControlDefault 0x00
// Bit Description (default = 0x00)
// 7-6 Reserved
// 5-4 16-bit DMA wait states
// xx00xxxx = One wait state (default)
// xx01xxxx = Two wait states
// xx10xxxx = Three wait states
// xx11xxxx = Four wait states
// 3-2 8-bit DMA wait states
// xxxx00xx = One wait state (default)
// xxxx01xx = Two wait states
// xxxx10xx = Three wait states

157
The C Programs

// xxxx11xx = Four wait states


// 1 DMA XMEMR Extension
// xxxxxx0x = Enables delayed XMEMR (default)
// xxxxxx1x = Starts XMEMR at same time as XIOR
// 0 DMA Clock Select
// xxxxxxx0 = BUSCLK/2 (default)
// xxxxxxx1 = BUSCLK

#define Chip82C3836Version 0x40


#define Chip82C3836VersionDefault 0x00
// Bit Description (Read Only)
// 7-4 Family Type
// 0001xxxx = SCATsx
// 3-0 Revision Code
// xxxxyyy where yyyy = revision number

#define ChipChannelEnvironment 0x41


#define ChipChannelEnvironmentDefault 0x06
// Bit Description (default = 0x06)
// 7 Reserved
// 6 Early READY Enable
// x1xxxxxx = enable
// x0xxxxxx = disable (default)
// 5 LBA Enable
// xx1xxxxx = enable
// xx0xxxxx = disable (default)
// 4 Bus Convert Enable
// xxx1xxxx = enable
// xxx0xxxx = disable (default)
// 3-2 BUSCLK Select
// xxxx00xx = selects BUSCLK as CXIN/4
// xxxx01xx = selects BUSCLK as CXIN/5 (default)
// xxxx10xx = selects BUSCLK as CXIN/6
// xxxx11xx = reserved
// 1-0 Refresh Width
// xxxxxx00 = 140 ns
// xxxxxx01 = 210 ns
// xxxxxx10 = 280 ns (default)
// xxxxxx11 = 350 ns

#define ChipPeripheralControl 0x44


#define ChipPeripheralControlDefault 0x00
// Bit Description (default = 0x00)
// 7 Reserved
// 6 Video on the XD-Bus
// x0xxxxxx = Video on the SD-Bus
// x1xxxxxx = Video on the XD-Bus
// The default of this bit is determined by DACK2 on Reset.
// 5 Game Port on the XD-Bus
// xx0xxxxx = Game Port on the SD-Bus (default)
// xx1xxxxx = Game Port on the XD-Bus
// 4 Serial Port 2 on the XD-Bus
// xxx0xxxx = Serial Port 2 on the SD-Bus (default)
// xxx1xxxx = Serial Port 2 on the XD-Bus
// 3 Serial Port 1 on the XD-Bus
// xxxx0xxx = Serial Port 1 on the SD-Bus (default)

158
Introduction to AutoBios

// xxxx1xxx = Serial Port 1 on the XD-Bus


// 2 Parallel port on the XD-Bus
// xxxxx0xx = Parallel Port on the SD-Bus (default)
// xxxxx1xx = Parallel Port on the XD-Bus
// 1 HDC/FDC on the XD-Bus
// xxxxxx0x = HDC/FDC on the SD-Bus (default)
// xxxxxx1x = HDC/FDC on the XD-Bus
// 0 Coprocessor Ready
// xxxxxxx0 = 80387sx generates ready (default)
// xxxxxxx1 = 82C836 generates ready

#define ChipMiscStatus 0x45


#define ChipMiscStatusDefault 0x00
// Bit Description (Read Only)
// 7 NMI Inhibit Status (I/O Port 70, bit 7)
// 0xxxxxxx = NMI enabled
// 1xxxxxxx = NMI disabled
// 6 GATEA20 from the 8042
// x0xxxxxx = GATEA20 is low (A20 disabled)
// x1xxxxxx = GATEA20 is high (A20 enabled)
// 5 BUSY to CPU
// xx0xxxxx = BUSY low
// xx1xxxxx = BUSY high
// 4 Internal RTC enabled
// xxx0xxxx = external RTC used (XD-Bus)
// xxx1xxxx = internal RTC used
// 3 NA-/STCYC Select
// xxxx0xxx = STCYC-/ADRL function
// xxxx1xxx = NA-/ADRL function
// 2-0 Sense Lines 2-0 - Power up state of DACK 2-0
// 0 = corresponding DACK line pulled low
// 1 = corresponding DACK line pulled high

#define ChipPowerManagement 0x46


#define ChipPowerManagementDefault 0x00
// Bit Description (default = 0x00)
// 7 Sleep enable
// 0xxxxxxx = sleep mode disabled (default)
// 1xxxxxxx = sleep mode enabled
// 6 Aux Parity disable
// x0xxxxxx = Enable parity checking via Port 61 (default)
// x1xxxxxx = DIsable Parity checking
// 5-4 reserved
// 3-2 Run frequency
// xxxx00xx = CXIN (default)
// xxxx01xx = CXIN/2
// xxxx10xx = CXIN/4
// xxxx11xx = CXIN/8
// 1-0 Sleep frequency
// xxxxxx00 = stopped, solid high (default)
// xxxxxx01 = CXIN/2
// xxxxxx10 = CXIN/4
// xxxxxx11 = CXIN/8

#define ChipRomEnable 0x48


#define ChipRomEnableDefault 0xc0

159
The C Programs

// Bit Description (default = 0xc0)


// 7 0F8000H-0FFFFFh Rom Enable. Default = 1
// 6 0F0000H-0F7FFFh Rom Enable. Default = 1
// 5 0E8000H-0EFFFFh Rom Enable. Default = 0
// 4 0E0000H-0E7FFFh Rom Enable. Default = 0
// 3 0D8000H-0DFFFFh Rom Enable. Default = 0
// 2 0D0000H-0D7FFFh Rom Enable. Default = 0
// 1 0C8000H-0CFFFFh Rom Enable. Default = 0
// 0 0C0000H-0C7FFFh Rom Enable. Default = 0

#define ChipRamWriteProtect 0x49


#define ChipRamWriteProtectDefault 0x00
// Bit Description - 0 = read/write (default), 1 = read only
// 7 0F8000H-0FFFFFh Ram Read Only.
// 6 0F0000H-0F7FFFh Ram Read Only.
// 5 0E8000H-0EFFFFh Ram Read Only.
// 4 0E0000H-0E7FFFh Ram Read Only.
// 3 0D8000H-0DFFFFh Ram Read Only.
// 2 0D0000H-0D7FFFh Ram Read Only.
// 1 0C8000H-0CFFFFh Ram Read Only.
// 0 0C0000H-0C7FFFh Ram Read Only.

#define ChipShadowRamEnable1 0x4a


#define ChipShadowRamEnable1Default 0x00
// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0BC000H-0BFFFFh Ram Enable.
// 6 0B8000H-0BBFFFh Ram Enable.
// 5 0B4000H-0B7FFFh Ram Enable.
// 4 0B0000H-0B3FFFh Ram Enable.
// 3 0AC000H-0AFFFFh Ram Enable.
// 2 0A8000H-0ABFFFh Ram Enable.
// 1 0A4000H-0A7FFFh Ram Enable.
// 0 0A0000H-0A3FFFh Ram Enable.

#define ChipShadowRamEnable2 0x4b


#define ChipShadowRamEnable2Default 0x00
// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0DC000H-0DFFFFh Ram Enable.
// 6 0D8000H-0DBFFFh Ram Enable.
// 5 0D4000H-0D7FFFh Ram Enable.
// 4 0D0000H-0D3FFFh Ram Enable.
// 3 0CC000H-0CFFFFh Ram Enable.
// 2 0C8000H-0CBFFFh Ram Enable.
// 1 0C4000H-0C7FFFh Ram Enable.
// 0 0C0000H-0C3FFFh Ram Enable.

#define ChipShadowRamEnable3 0x4c


#define ChipShadowRamEnable3Default 0x00
// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0FC000H-0FFFFFh Ram Enable.
// 6 0F8000H-0FBFFFh Ram Enable.
// 5 0F4000H-0F7FFFh Ram Enable.
// 4 0F0000H-0F3FFFh Ram Enable.
// 3 0EC000H-0EFFFFh Ram Enable.
// 2 0E8000H-0EBFFFh Ram Enable.

160
Introduction to AutoBios

// 1 0E4000H-0E7FFFh Ram Enable.


// 0 0E0000H-0E3FFFh Ram Enable.

#define ChipDramConfiguration 0x4d


#define ChipDramConfigurationDefault 0x01
// Bit Description (default = 0x01)
// 7 CAS Wait State
// 0xxxxxxx = no added wait state (default)
// 1xxxxxxx = wait state enabled
// 6 RAS timeout
// x0xxxxxx = RAS timeout enabled (default)
// x1xxxxxx = RAS timeout disabled
// 5 reserved
// 4-0 CFG 4-0 These bits describe the DRAM configuration
// Default value is xxx00001 (512K total DRAM)

#define ChipExtendedBoundary 0x4e


#define ChipExtendedBoundaryDefault 0x00
// Bit Description (default = 0x00)
// 7 RAS encode enable
// 0xxxxxxx = RAS encode disabled (default)
// 1xxxxxxx = RAS encode enabled
// 6 reserved
// 5 RAM disable 040000h-09FFFFh
// xx0xxxxx = enables DRAM on system board (default)
// xx1xxxxx = enables DRAM on I/O channel
// 4 reserved
// 3-0 Extended boundary
// xxxx0000 No Limit (default)
// xxxx0001 1 MB (no extended memory)
// xxxx0010 1.25 MB
// xxxx0011 1.5 MB
// xxxx0100 2 MB
// xxxx0101 3 MB
// xxxx0110 4 MB
// xxxx0111 5 MB
// xxxx1000 7 MB
// xxxx1001 8 MB
// xxxx1010 9 MB
// xxxx1011 10 MB
// xxxx1100 11 MB
// xxxx1101 12 MB
// xxxx1110 13 MB
// xxxx1111 15 MB

#define ChipEmsControl 0x4f


#define ChipEmsControlDefault 0x00
// Bit Description (default = 0x00)
// 7 EMS Address Translation Enable
// 0xxxxxxx = EMS is disabled (default)
// 1xxxxxxx = EMS is enabled
// 6 EMS I/O Enable
// x0xxxxxx = EMS I/O Port is disabled (default)
// x1xxxxxx = EMS I/O Port is enabled
// 5-1 reserved
// 0 I/O Base

161
The C Programs

// xxxxxxx0 = I/O Ports 0208h, 0209h, 020Ah (default)


// xxxxxxx1 = I/O Ports 0218h, 0219h, 021Ah

[Break]

--------------------------------------------------------------------

[Extract] [HELP]

The chip is normally forced to the default states on a reset to insure


a known condition. Define the desired register values in your .Job file.
The Register names may be used, as in the following example:

CfgChipData0 = ChipDmaWaitStateControl, 0AAh


CfgChipData1 = ChipPowerManagement, 055h

[Break]

--------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct NameValueDittoList DumpList[] =


{
{ "ChipDmaWaitStateControl",ChipDmaWaitStateControl,
"",ChipDmaWaitStateControlDefault, },
{ "Chip82C3836Version", Chip82C3836Version,
"",Chip82C3836VersionDEfault, },
{ "ChipChannelEnvironment", ChipChannelEnvironment,
"",ChipChannelEnvironmentDefault, },
{ "ChipPeripheralControl", ChipPeripheralControl,
"",ChipPeripheralControlDefault, },
{ "ChipMiscStatus", ChipMiscStatus,
"",ChipMiscStatusDefault, },
{ "ChipPowerManagement", ChipPowerManagement,
"",ChipPowerManagementDefault, },
{ "ChipRomEnable", ChipRomEnable,
"",ChipRomEnableDefault, },
{ "ChipRamWriteProtect", ChipRamWriteProtect,
"",ChipRamWriteProtectDefault, },
{ "ChipShadowRamEnable1", ChipShadowRamEnable1,
"",ChipShadowRamEnable1Default, },
{ "ChipShadowRamEnable2", ChipShadowRamEnable2,
"",ChipShadowRamEnable2Default, },
{ "ChipShadowRamEnable3", ChipShadowRamEnable3,
"",ChipShadowRamEnable3Default, },
{ "ChipDramConfiguration", ChipDramConfiguration,
"",ChipDramConfigurationDefault, },
{ "ChipExtendedBoundary", ChipExtendedBoundary,
"",ChipExtendedBoundaryDefault, },
{ "ChipEmsControl", ChipEmsControl,
"",ChipEmsControlDefault, },

162
Introduction to AutoBios

{ "",0,"",0,}, /* Nul String or Zero Value is End of Table */


};

//---- Chip Specific routine to read a selected register ---


//-------- This routine will vary from chip to chip -----

unsigned ReadChipRegister(unsigned i)
{
outp(ChipRegPort,i);
return(inp(ChipDataPort));
};

[Break]

--------------------------------------------------------------------

[Extract] [MASM]

; This is code for the superstate

ResetHook:

;SuperStateCheck label near


;------------- for fujitsu network chip meltdown ------
mov al,76h
mov dx,306h
out dx,al

;super state hooks


mov ax,0
mov ds,ax
.IF (word ptr ds:[0472h] == 1234h)
mov si,OFFSET DoneSuperInit
mov al,5bh
out 6fh,al
.ENDIF

mov ax,0f000h
mov ds,ax
mov es,ax
xor si,si
mov ax,si
SearchSuperCode:
add ax,10h
mov di,OFFSET SuperSign
mov cx,LenSuperSign
repz cmpsb
mov si,ax
jz FoundSuperCode
cmp si,(OFFSET SuperSign)-10h
jae DoneSuperInit
jmp SHORT SearchSuperCode
FoundSuperCode:

mov si,ax
CheckPoint(0aah) ; got to f8680 superstate code

163
The C Programs

mov ax,si

sub ax,10h
add ax,LenSuperSign
mov si,OFFSET DoneSuperInit
jmp ax

SuperSign DB "CHIPS F8680 PC/CHIP"


LenSuperSign EQU $-SuperSign
DoneSuperInit:
; f8680 super state hooks

jmp ResumeResetHook

;--- This macro is used to simplify typing in the desired values ---

DefaultValue macro chipreg,chipval


WORD chipreg
WORD chipval
endm

;================== CHIPS & TECHNOLOGY ====================

ChipDefaultTable LABEL WORD

; Reset chip to known default state

DefaultValue ChipDmaWaitStateControl, 000h


DefaultValue ChipChannelEnvironment, 006h
DefaultValue ChipPeripheralControl, 000h
DefaultValue ChipPowerManagement, 000h
DefaultValue ChipRomEnable, 0c0h
DefaultValue ChipRamWriteProtect, 000h
DefaultValue ChipShadowRamEnable1, 000h
DefaultValue ChipShadowRamEnable2, 000h
DefaultValue ChipShadowRamEnable3, 000h
DefaultValue ChipDramConfiguration, 001h
DefaultValue ChipExtendedBoundary, 000h
DefaultValue ChipEmsControl, 000h

; Now offer the opportunity to set-up the chip

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

164
Introduction to AutoBios

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

DefaultValue 0ffh,0ffh ; -1 Arguments indicate End of Table

ChipHook1 LABEL NEAR


mov si,offset ChipDefaultTable
.WHILE 1
lods WORD PTR cs:[si]
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
lods WORD PTR cs:[si]
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al
.ENDW
jmp NEAR PTR ResumeChipHook1

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

165
The C Programs

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

----------------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

166
Introduction to AutoBios

4.3.3.5 Chips & Technology Neat


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights reserved.

[Product Name] AutoBios

[Module Name] C&T 386 NEAT Chip Set (82C836) Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] C_TNEAT.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize an LSI chip set


[Description] with a default personality, if desired.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "C & T 82C212 NEAT Chip"

// Chips & Technologies 82C212 NEAT Chip Information

// 82C212 Control Register Ports

#define ChipRegPort 0x22


#define ChipDataPort 0x23

// 82C211 Registers

#define RA0 0x60


#define RA0Default 0x00

#define RA1 0x61


#define RA1Default 0x00

#define RA2 0x62


#define RA2Default 0x00

// 82C212 Registers

#define RB0 0x64

167
The C Programs

#define RB0Default 0x00


// Bit Description
// 7 Neat mem controller ID 0 = 82C212

// 6 16-bit DMA wait states


// xx00xxxx = One wait state (default)
// xx01xxxx = Two wait states
// xx10xxxx = Three wait states
// xx11xxxx = Four wait states
// 3-2 8-bit DMA wait states
// xxxx00xx = One wait state (default)
// xxxx01xx = Two wait states
// xxxx10xx = Three wait states
// xxxx11xx = Four wait states
// 1 DMA XMEMR Extension
// xxxxxx0x = Enables delayed XMEMR (default)
// xxxxxx1x = Starts XMEMR at same time as XIOR
// 0 DMA Clock Select
// xxxxxxx0 = BUSCLK/2 (default)
// xxxxxxx1 = BUSCLK

#define RB1 0x65


#define RB1Default 0x00

#define RB2 0x66


#define RB2Default 0x00

#define RB3 0x67


#define RB3Default 0x00

#define RB4 0x68


#define RB4Default 0x00

#define RB5 0x69


#define RB5Default 0x00

#define RB6 0x6A


#define RB6Default 0x00

#define RB7 0x6B


#define RB7Default 0x00

#define RB8 0x6C


#define RB8Default 0x00

#define RB9 0x6D


#define RB9Default 0x00

#define RB10 0x6E


#define RB10Default 0x00

#define RB11 0x6F


#define RB11Default 0x00

168
Introduction to AutoBios

// Bit Description
// 7 Reserved
// 6 Early READY Enable
// x1xxxxxx = enable
// x0xxxxxx = disable (default)
// 5 LBA Enable
// xx1xxxxx = enable
// xx0xxxxx = disable (default)
// 4 Bus Convert Enable
// xxx1xxxx = enable
// xxx0xxxx = disable (default)
// 3-2 BUSCLK Select
// xxxx00xx = selects BUSCLK as CXIN/4
// xxxx01xx = selects BUSCLK as CXIN/5 (default)
// xxxx10xx = selects BUSCLK as CXIN/6
// xxxx11xx = reserved
// 1-0 Refresh Width
// xxxxxx00 = 140 ns
// xxxxxx01 = 210 ns
// xxxxxx10 = 280 ns (default)
// xxxxxx11 = 350 ns

#define ChipPeripheralControl 0x44


#define ChipPeripheralControlDefault 0x00
// Bit Description
// 7 Reserved
// 6 Video on the XD-Bus
// x0xxxxxx = Video on the SD-Bus
// x1xxxxxx = Video on the XD-Bus
// The default of this bit is determined by DACK2 on Reset.
// 5 Game Port on the XD-Bus
// xx0xxxxx = Game Port on the SD-Bus (default)
// xx1xxxxx = Game Port on the XD-Bus
// 4 Serial Port 2 on the XD-Bus
// xxx0xxxx = Serial Port 2 on the SD-Bus (default)
// xxx1xxxx = Serial Port 2 on the XD-Bus
// 3 Serial Port 1 on the XD-Bus
// xxxx0xxx = Serial Port 1 on the SD-Bus (default)
// xxxx1xxx = Serial Port 1 on the XD-Bus
// 2 Parallel port on the XD-Bus
// xxxxx0xx = Parallel Port on the SD-Bus (default)
// xxxxx1xx = Parallel Port on the XD-Bus
// 1 HDC/FDC on the XD-Bus
// xxxxxx0x = HDC/FDC on the SD-Bus (default)
// xxxxxx1x = HDC/FDC on the XD-Bus
// 0 Coprocessor Ready
// xxxxxxx0 = 80387sx generates ready (default)
// xxxxxxx1 = 82C836 generates ready

#define ChipMiscStatus 0x45


// Bit Description (Read Only)
// 7 NMI Inhibit Status (I/O Port 70, bit 7)
// 0xxxxxxx = NMI enabled
// 1xxxxxxx = NMI disabled
// 6 GATEA20 from the 8042

169
The C Programs

// x0xxxxxx = GATEA20 is low (A20 disabled)


// x1xxxxxx = GATEA20 is high (A20 enabled)
// 5 BUSY to CPU
// xx0xxxxx = BUSY low
// xx1xxxxx = BUSY high
// 4 Internal RTC enabled
// xxx0xxxx = external RTC used (XD-Bus)
// xxx1xxxx = internal RTC used
// 3 NA-/STCYC Select
// xxxx0xxx = STCYC-/ADRL function
// xxxx1xxx = NA-/ADRL function
// 2-0 Sense Lines 2-0 - Power up state of DACK 2-0
// 0 = corresponding DACK line pulled low
// 1 = corresponding DACK line pulled high

#define ChipPowerManagement 0x46


#define ChipPowerManagementDefault 0x00
// Bit Description
// 7 Sleep enable
// 0xxxxxxx = sleep mode disabled (default)
// 1xxxxxxx = sleep mode enabled
// 6 Aux Parity disable
// x0xxxxxx = Enable parity checking via Port 61 (default)
// x1xxxxxx = DIsable Parity checking
// 5-4 reserved
// 3-2 Run frequency
// xxxx00xx = CXIN (default)
// xxxx01xx = CXIN/2
// xxxx10xx = CXIN/4
// xxxx11xx = CXIN/8
// 1-0 Sleep frequency
// xxxxxx00 = stopped, solid high (default)
// xxxxxx01 = CXIN/2
// xxxxxx10 = CXIN/4
// xxxxxx11 = CXIN/8

#define ChipRomEnable 0x48


#define ChipRomEnableDefault 0xc0
// Bit Description
// 7 0F8000H-0FFFFFh Rom Enable. Default = 1
// 6 0F0000H-0F7FFFh Rom Enable. Default = 1
// 5 0E8000H-0EFFFFh Rom Enable. Default = 0
// 4 0E0000H-0E7FFFh Rom Enable. Default = 0
// 3 0D8000H-0DFFFFh Rom Enable. Default = 0
// 2 0D0000H-0D7FFFh Rom Enable. Default = 0
// 1 0C8000H-0CFFFFh Rom Enable. Default = 0
// 0 0C0000H-0C7FFFh Rom Enable. Default = 0

#define ChipRamWriteProtect 0x49


#define ChipRamWriteProtectDefault 0x00
// Bit Description - 0 = read/write (default), 1 = read only
// 7 0F8000H-0FFFFFh Ram Read Only.
// 6 0F0000H-0F7FFFh Ram Read Only.
// 5 0E8000H-0EFFFFh Ram Read Only.
// 4 0E0000H-0E7FFFh Ram Read Only.
// 3 0D8000H-0DFFFFh Ram Read Only.

170
Introduction to AutoBios

// 2 0D0000H-0D7FFFh Ram Read Only.


// 1 0C8000H-0CFFFFh Ram Read Only.
// 0 0C0000H-0C7FFFh Ram Read Only.

#define ChipShadowRamEnable1 0x4a


#define ChipShadowRamEnable1Default 0x00
// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0BC000H-0BFFFFh Ram Enable.
// 6 0B8000H-0BBFFFh Ram Enable.
// 5 0B4000H-0B7FFFh Ram Enable.
// 4 0B0000H-0B3FFFh Ram Enable.
// 3 0AC000H-0AFFFFh Ram Enable.
// 2 0A8000H-0ABFFFh Ram Enable.
// 1 0A4000H-0A7FFFh Ram Enable.
// 0 0A0000H-0A3FFFh Ram Enable.

#define ChipShadowRamEnable2 0x4b


#define ChipShadowRamEnable2Default 0x00
// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0DC000H-0DFFFFh Ram Enable.
// 6 0D8000H-0DBFFFh Ram Enable.
// 5 0D4000H-0D7FFFh Ram Enable.
// 4 0D0000H-0D3FFFh Ram Enable.
// 3 0CC000H-0CFFFFh Ram Enable.
// 2 0C8000H-0CBFFFh Ram Enable.
// 1 0C4000H-0C7FFFh Ram Enable.
// 0 0C0000H-0C3FFFh Ram Enable.

#define ChipShadowRamEnable3 0x4c


#define ChipShadowRamEnable3Default 0x00
// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0FC000H-0FFFFFh Ram Enable.
// 6 0F8000H-0FBFFFh Ram Enable.
// 5 0F4000H-0F7FFFh Ram Enable.
// 4 0F0000H-0F3FFFh Ram Enable.
// 3 0EC000H-0EFFFFh Ram Enable.
// 2 0E8000H-0EBFFFh Ram Enable.
// 1 0E4000H-0E7FFFh Ram Enable.
// 0 0E0000H-0E3FFFh Ram Enable.

#define ChipDramConfiguration 0x4d


#define ChipDramConfigurationDefault 0x01
// Bit Description
// 7 CAS Wait State
// 0xxxxxxx = no added wait state (default)
// 1xxxxxxx = wait state enabled
// 6 RAS timeout
// x0xxxxxx = RAS timeout enabled (default)
// x1xxxxxx = RAS timeout disabled
// 5 reserved
// 4-0 CFG 4-0 These bits describe the DRAM configuration
// Default value is xxx00001 (512K total DRAM)

#define ChipExtendedBoundary 0x4e


#define ChipExtendedBoundaryDefault 0x00

171
The C Programs

// Bit Description
// 7 RAS encode enable
// 0xxxxxxx = RAS encode disabled (default)
// 1xxxxxxx = RAS encode enabled
// 6 reserved
// 5 RAM disable 040000h-09FFFFh
// xx0xxxxx = enables DRAM on system board (default)
// xx1xxxxx = enables DRAM on I/O channel
// 4 reserved
// 3-0 Extended boundary
// xxxx0000 No Limit (default)
// xxxx0001 1 MB (no extended memory)
// xxxx0010 1.25 MB
// xxxx0011 1.5 MB
// xxxx0100 2 MB
// xxxx0101 3 MB
// xxxx0110 4 MB
// xxxx0111 5 MB
// xxxx1000 7 MB
// xxxx1001 8 MB
// xxxx1010 9 MB
// xxxx1011 10 MB
// xxxx1100 11 MB
// xxxx1101 12 MB
// xxxx1110 13 MB
// xxxx1111 15 MB

#define ChipEmsControl 0x4f


#define ChipEmsControlDefault 0x00
// Bit Description
// 7 EMS Address Translation Enable
// 0xxxxxxx = EMS is disabled (default)
// 1xxxxxxx = EMS is enabled
// 6 EMS I/O Enable
// x0xxxxxx = EMS I/O Port is disabled (default)
// x1xxxxxx = EMS I/O Port is enabled
// 5-1 reserved
// 0 I/O Base
// xxxxxxx0 = I/O Ports 0208h, 0209h, 020Ah (default)
// xxxxxxx1 = I/O Ports 0218h, 0219h, 021Ah

[Break]

--------------------------------------------------------------------

[Extract] [HELP]

The chip is normally forced to the default states on a reset to insure


a known condition. Define the desired register values in your .Job file.
The Register names may be used, as in the following example:

CfgChipData0 = ChipDmaWaitStateControl, 0AAh


CfgChipData1 = ChipPowerManagement, 055h

[Break]

172
Introduction to AutoBios

--------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct ItemList DumpList[] =


{
{ "RA0"," - PROCCLK Selector", RA0,SizeIsByte,RA0Default, },
{ "RA1"," - Command Delay", RA1,SizeIsByte,RA1Default, },
{ "RA2"," - Wait State Selector", RA2,SizeIsByte,RA2Default, },
{ "RB0"," - Version Register", RB0,SizeIsByte,RB0Default, },
{ "RB1"," - ROM Configuration", RB1,SizeIsByte,RB1Default, },
{ "RB2"," - Memory Enable 1", RB2,SizeIsByte,RB2Default, },
{ "RB3"," - Memory Enable 2", RB3,SizeIsByte,RB3Default, },
{ "RB4"," - Memory Enable 3", RB4,SizeIsByte,RB4Default, },
{ "RB5"," - Memory Enable 4", RB5,SizeIsByte,RB5Default, },
{ "RB6"," - Bank 0/1 Enable", RB6,SizeIsByte,RB6Default, },
{ "RB7"," - Dram Configuration", RB7,SizeIsByte,RB7Default, },
{ "RB8"," - Bank 2/3 Enable", RB8,SizeIsByte,RB8Default, },
{ "RB9"," - EMS Base Address", RB9,SizeIsByte,RB9Default, },
{ "RB10"," - EMS Address Extension", RB10,SizeIsByte,RB10Default,},
{ "RB11"," - Misc. Register", RB11,SizeIsByte,RB11Default,},
{ "","",0,0,0,}, /* Nul String is End of Table */
};

//---- Chip Specific routine to read a selected register ---


//-------- This routine will vary from chip to chip -----

unsigned ReadChipRegister(unsigned i,unsigned size)


{
outp(ChipRegPort,i);
_asm jmp $ + 2 ;
return(inp(ChipDataPort));
};

[Break]

--------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;--- This macro is used to simplify typing in the desired values ---

;================== CHIPS & TECHNOLOGY ====================

173
The C Programs

ChipDefaultTable LABEL WORD

; Reset chip to known default state

;DefaultValue RB0,RB0Default
;DefaultValue RB1,RB1Default

; Now offer the opportunity to set-up the chip

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

174
Introduction to AutoBios

CfgDefaultValue -1,-1,-1 ; -1 Arguments indicate End of Table

ChipHook1 LABEL NEAR


mov si,offset ChipDefaultTable
.WHILE 1
lods WORD PTR cs:[si]
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
lods WORD PTR cs:[si]
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al
.ENDW
jmp NEAR PTR ResumeChipHook1

; This is the place where memory chip type determination would


; normally be done.

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

----------------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned Results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{
case ChipEnable:
break;

case ChipDisable:
break;
};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{
case ChipEnable:

175
The C Programs

break;
};
break;
break;
};
return(Results);
};

[Break]

176
Introduction to AutoBios

4.3.3.6 Chips & Technology Scat 82C836


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] C&T 386 SCAT Chip Set (82C836) Support

[Version] 2.00

[Author] John O. Foster

[Date] 07/22/93

[File Name] C&TSCAT.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize an LSI chip set


[Description] with a default personality, if desired.

[History] 1.00 07/19/93 Original

**********************************************************************

[Extract] [H]

#define ChipID "C & T 82C836 SCAT Chip"

// Chips & Technologies 82C836 SCAT Chip Information

// 82C836 Control Register Ports

#define ChipRegPort 0x22


#define ChipDataPort 0x23

// 82C836 Registers

#define ChipDmaWaitStateControl 0x01


// Bit Description (default = 0x00)
// 7-6 Reserved
// 5-4 16-bit DMA wait states
// xx00xxxx = One wait state (default)
// xx01xxxx = Two wait states
// xx10xxxx = Three wait states
// xx11xxxx = Four wait states
// 3-2 8-bit DMA wait states
// xxxx00xx = One wait state (default)
// xxxx01xx = Two wait states
// xxxx10xx = Three wait states
// xxxx11xx = Four wait states

177
The C Programs

// 1 DMA XMEMR Extension


// xxxxxx0x = Enables delayed XMEMR (default)
// xxxxxx1x = Starts XMEMR at same time as XIOR
// 0 DMA Clock Select
// xxxxxxx0 = BUSCLK/2 (default)
// xxxxxxx1 = BUSCLK

#define Chip82C3836Version 0x40


// Bit Description (Read Only)
// 7-4 Family Type
// 0001xxxx = SCATsx
// 3-0 Revision Code
// xxxxyyy where yyyy = revision number

#define ChipChannelEnvironment 0x41


// Bit Description (default = 0x06)
// 7 Reserved
// 6 Early READY Enable
// x1xxxxxx = enable
// x0xxxxxx = disable (default)
// 5 LBA Enable
// xx1xxxxx = enable
// xx0xxxxx = disable (default)
// 4 Bus Convert Enable
// xxx1xxxx = enable
// xxx0xxxx = disable (default)
// 3-2 BUSCLK Select
// xxxx00xx = selects BUSCLK as CXIN/4
// xxxx01xx = selects BUSCLK as CXIN/5 (default)
// xxxx10xx = selects BUSCLK as CXIN/6
// xxxx11xx = reserved
// 1-0 Refresh Width
// xxxxxx00 = 140 ns
// xxxxxx01 = 210 ns
// xxxxxx10 = 280 ns (default)
// xxxxxx11 = 350 ns

#define ChipPeripheralControl 0x44


// Bit Description (default = 0x00)
// 7 Reserved
// 6 Video on the XD-Bus
// x0xxxxxx = Video on the SD-Bus
// x1xxxxxx = Video on the XD-Bus
// The default of this bit is determined by DACK2 on Reset.
// 5 Game Port on the XD-Bus
// xx0xxxxx = Game Port on the SD-Bus (default)
// xx1xxxxx = Game Port on the XD-Bus
// 4 Serial Port 2 on the XD-Bus
// xxx0xxxx = Serial Port 2 on the SD-Bus (default)
// xxx1xxxx = Serial Port 2 on the XD-Bus
// 3 Serial Port 1 on the XD-Bus
// xxxx0xxx = Serial Port 1 on the SD-Bus (default)
// xxxx1xxx = Serial Port 1 on the XD-Bus
// 2 Parallel port on the XD-Bus
// xxxxx0xx = Parallel Port on the SD-Bus (default)
// xxxxx1xx = Parallel Port on the XD-Bus

178
Introduction to AutoBios

// 1 HDC/FDC on the XD-Bus


// xxxxxx0x = HDC/FDC on the SD-Bus (default)
// xxxxxx1x = HDC/FDC on the XD-Bus
// 0 Coprocessor Ready
// xxxxxxx0 = 80387sx generates ready (default)
// xxxxxxx1 = 82C836 generates ready

#define ChipMiscStatus 0x45


// Bit Description (Read Only)
// 7 NMI Inhibit Status (I/O Port 70, bit 7)
// 0xxxxxxx = NMI enabled
// 1xxxxxxx = NMI disabled
// 6 GATEA20 from the 8042
// x0xxxxxx = GATEA20 is low (A20 disabled)
// x1xxxxxx = GATEA20 is high (A20 enabled)
// 5 BUSY to CPU
// xx0xxxxx = BUSY low
// xx1xxxxx = BUSY high
// 4 Internal RTC enabled
// xxx0xxxx = external RTC used (XD-Bus)
// xxx1xxxx = internal RTC used
// 3 NA-/STCYC Select
// xxxx0xxx = STCYC-/ADRL function
// xxxx1xxx = NA-/ADRL function
// 2-0 Sense Lines 2-0 - Power up state of DACK 2-0
// 0 = corresponding DACK line pulled low
// 1 = corresponding DACK line pulled high

#define ChipPowerManagement 0x46


// Bit Description (default = 0x00)
// 7 Sleep enable
// 0xxxxxxx = sleep mode disabled (default)
// 1xxxxxxx = sleep mode enabled
// 6 Aux Parity disable
// x0xxxxxx = Enable parity checking via Port 61 (default)
// x1xxxxxx = DIsable Parity checking
// 5-4 reserved
// 3-2 Run frequency
// xxxx00xx = CXIN (default)
// xxxx01xx = CXIN/2
// xxxx10xx = CXIN/4
// xxxx11xx = CXIN/8
// 1-0 Sleep frequency
// xxxxxx00 = stopped, solid high (default)
// xxxxxx01 = CXIN/2
// xxxxxx10 = CXIN/4
// xxxxxx11 = CXIN/8

#define ChipRomEnable 0x48


// Bit Description (default = 0xc0)
// 7 0F8000H-0FFFFFh Rom Enable. Default = 1
// 6 0F0000H-0F7FFFh Rom Enable. Default = 1
// 5 0E8000H-0EFFFFh Rom Enable. Default = 0
// 4 0E0000H-0E7FFFh Rom Enable. Default = 0
// 3 0D8000H-0DFFFFh Rom Enable. Default = 0
// 2 0D0000H-0D7FFFh Rom Enable. Default = 0

179
The C Programs

// 1 0C8000H-0CFFFFh Rom Enable. Default = 0


// 0 0C0000H-0C7FFFh Rom Enable. Default = 0

#define ChipRamWriteProtect 0x49


// Bit Description - 0 = read/write (default), 1 = read only
// 7 0F8000H-0FFFFFh Ram Read Only.
// 6 0F0000H-0F7FFFh Ram Read Only.
// 5 0E8000H-0EFFFFh Ram Read Only.
// 4 0E0000H-0E7FFFh Ram Read Only.
// 3 0D8000H-0DFFFFh Ram Read Only.
// 2 0D0000H-0D7FFFh Ram Read Only.
// 1 0C8000H-0CFFFFh Ram Read Only.
// 0 0C0000H-0C7FFFh Ram Read Only.

#define ChipShadowRamEnable1 0x4a


// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0BC000H-0BFFFFh Ram Enable.
// 6 0B8000H-0BBFFFh Ram Enable.
// 5 0B4000H-0B7FFFh Ram Enable.
// 4 0B0000H-0B3FFFh Ram Enable.
// 3 0AC000H-0AFFFFh Ram Enable.
// 2 0A8000H-0ABFFFh Ram Enable.
// 1 0A4000H-0A7FFFh Ram Enable.
// 0 0A0000H-0A3FFFh Ram Enable.

#define ChipShadowRamEnable2 0x4b


// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0DC000H-0DFFFFh Ram Enable.
// 6 0D8000H-0DBFFFh Ram Enable.
// 5 0D4000H-0D7FFFh Ram Enable.
// 4 0D0000H-0D3FFFh Ram Enable.
// 3 0CC000H-0CFFFFh Ram Enable.
// 2 0C8000H-0CBFFFh Ram Enable.
// 1 0C4000H-0C7FFFh Ram Enable.
// 0 0C0000H-0C3FFFh Ram Enable.

#define ChipShadowRamEnable3 0x4c


// Bit Description - 0 = disable Ram (default), 1 = enable Ram
// 7 0FC000H-0FFFFFh Ram Enable.
// 6 0F8000H-0FBFFFh Ram Enable.
// 5 0F4000H-0F7FFFh Ram Enable.
// 4 0F0000H-0F3FFFh Ram Enable.
// 3 0EC000H-0EFFFFh Ram Enable.
// 2 0E8000H-0EBFFFh Ram Enable.
// 1 0E4000H-0E7FFFh Ram Enable.
// 0 0E0000H-0E3FFFh Ram Enable.

#define ChipDramConfiguration 0x4d


// Bit Description (default = 0x01)
// 7 CAS Wait State
// 0xxxxxxx = no added wait state (default)
// 1xxxxxxx = wait state enabled
// 6 RAS timeout
// x0xxxxxx = RAS timeout enabled (default)
// x1xxxxxx = RAS timeout disabled

180
Introduction to AutoBios

// 5 reserved
// 4-0 CFG 4-0 These bits describe the DRAM configuration
// Default value is xxx00001 (512K total DRAM)
// Bank 0 1 2 3
Total
// (Valid for Non-encoded or Encoded RAS)
// xxx00000 = - - - - 0
// xxx00001 = 256K - - -
512K
// xxx00010 = 256K 256K - - 1 MB
// xxx00011 = 256K 256K - -
640K+384K
// xxx00100 = 256K 256K 256K - 1.5 MB
// xxx00101 = 256K 256K 256K 256K 2 MB
// xxx00110 = 256K 256K 1M - 3 MB
// xxx00111 = 256K 256K 1M 1M 5 MB
// xxx01000 = 256K 1M - - 2.5 MB
// xxx01001 = 256K 1M 1M -
4.5 MB
// xxx01010 = 256K 1M 1M 1M 6.5 MB
// xxx01011 = 1M - - -
2 MB
// xxx01100 = 1M 1M - -
4 MB
// xxx01101 = 1M 1M 1M -
6 MB
// xxx01110 = 1M 1M 1M 1M
8 MB
// (Valid for Encoded RAS only)
// Banks 0-1 2-3 4 5 6 7
Total
// xxx01111 = 256K 1M 1M - - -
7 MB
// xxx10000 = 256K 1M 1M 1M - - 9 MB
// xxx10001 = 256K 1M 1M 1M 1M - 11 MB
// xxx10010 = 256K 1M 1M 1M 1M 1M 13 MB
// xxx10011 = 1M 1M 1M - - - 10 MB
// xxx10100 = 1M 1M 1M 1M - - 12 MB
// xxx10101 = 1M 1M 1M 1M 1M - 14 MB
// xxx10110 = 1M 1M 1M 1M 1M 1M 16 MB

#define ChipExtendedBoundary 0x4e


// Bit Description (default = 0x00)
// 7 RAS encode enable
// 0xxxxxxx = RAS encode disabled (default)
// 1xxxxxxx = RAS encode enabled
// 6 reserved
// 5 RAM disable 040000h-09FFFFh
// xx0xxxxx = enables DRAM on system board (default)
// xx1xxxxx = enables DRAM on I/O channel
// 4 reserved
// 3-0 Extended boundary
// xxxx0000 No Limit (default)
// xxxx0001 1 MB (no extended memory)
// xxxx0010 1.25 MB
// xxxx0011 1.5 MB

181
The C Programs

// xxxx0100 2 MB
// xxxx0101 3 MB
// xxxx0110 4 MB
// xxxx0111 5 MB
// xxxx1000 7 MB
// xxxx1001 8 MB
// xxxx1010 9 MB
// xxxx1011 10 MB
// xxxx1100 11 MB
// xxxx1101 12 MB
// xxxx1110 13 MB
// xxxx1111 15 MB

#define ChipEmsControl 0x4f


// Bit Description (default = 0x00)
// 7 EMS Address Translation Enable
// 0xxxxxxx = EMS is disabled (default)
// 1xxxxxxx = EMS is enabled
// 6 EMS I/O Enable
// x0xxxxxx = EMS I/O Port is disabled (default)
// x1xxxxxx = EMS I/O Port is enabled
// 5-1 reserved
// 0 I/O Base
// xxxxxxx0 = I/O Ports 0208h, 0209h, 020Ah (default)
// xxxxxxx1 = I/O Ports 0218h, 0219h, 021Ah

[Break]

--------------------------------------------------------------------

[Extract] [HELP]

The chip is normally forced to the default states on a reset to insure


a known condition. Define the desired register values in your .Job file.
The Register names may be used, as in the following example:

CfgChipData0 = ChipDmaWaitStateControl, 0AAh


CfgChipData1 = ChipPowerManagement, 055h

[Break]

--------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct NameValueList DumpList[] =


{
{ "ChipDmaWaitStateControl",ChipDmaWaitStateControl,},
{ "Chip82C3836Version", Chip82C3836Version, },
{ "ChipChannelEnvironment", ChipChannelEnvironment, },
{ "ChipPeripheralControl", ChipPeripheralControl, },
{ "ChipMiscStatus", ChipMiscStatus, },

182
Introduction to AutoBios

{ "ChipPowerManagement", ChipPowerManagement, },
{ "ChipRomEnable", ChipRomEnable, },
{ "ChipRamWriteProtect", ChipRamWriteProtect, },
{ "ChipShadowRamEnable1", ChipShadowRamEnable1, },
{ "ChipShadowRamEnable2", ChipShadowRamEnable2, },
{ "ChipShadowRamEnable3", ChipShadowRamEnable3, },
{ "ChipDramConfiguration", ChipDramConfiguration, },
{ "ChipExtendedBoundary", ChipExtendedBoundary, },
{ "ChipEmsControl", ChipEmsControl, },
{ "",0,}, /* Nul String is End of Table */
};

//---- Chip Specific routine to read a selected register ---


//-------- This routine will vary from chip to chip -----

unsigned ReadChipRegister(unsigned i)
{
outp(ChipRegPort,i);
_asm jmp $ + 2 ;
return(inp(ChipDataPort));
};

[Break]

--------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;--- This macro is used to simplify typing in the desired values ---

DefaultValue macro chipreg,chipval


WORD chipreg
WORD chipval
endm

;================== CHIPS & TECHNOLOGY ====================

ChipDefaultTable LABEL WORD

; Reset chip to known default state

DefaultValue ChipDmaWaitStateControl, 000h


DefaultValue ChipChannelEnvironment, 006h
DefaultValue ChipPeripheralControl, 000h
DefaultValue ChipPowerManagement, 000h
DefaultValue ChipRomEnable, 0c0h
DefaultValue ChipRamWriteProtect, 000h
DefaultValue ChipShadowRamEnable1, 000h
DefaultValue ChipShadowRamEnable2, 000h

183
The C Programs

DefaultValue ChipShadowRamEnable3, 000h


DefaultValue ChipDramConfiguration, 001h
DefaultValue ChipExtendedBoundary, 000h
DefaultValue ChipEmsControl, 000h

; Now offer the opportunity to set-up the chip

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

DefaultValue -1,-1 ; -1 Arguments indicate End of Table

ChipHook1 LABEL NEAR


mov si,offset ChipDefaultTable

184
Introduction to AutoBios

.WHILE 1
lods WORD PTR cs:[si]
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
lods WORD PTR cs:[si]
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al
.ENDW
jmp NEAR PTR ResumeChipHook1

; This is the place where memory chip type determination would


; normally be done.

ChipHook2 LABEL NEAR


; check for memory chip type
; c2 = 256K part, cc = 1M part
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
mov al,0cch ; try the 1M part setup
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al

; test for 1M part

mov ax,2000h
mov es,ax ; set es = 2000h
mov ax,6000h
mov ds,ax ; set ds = 6000h
mov al,0aah
mov ds:[0],al ; set AA into 6000:0000
mov al,055h
mov es:[0],al ; now set 55 pattern in 2000:0000
cmp ds:[0],al ; see if 55 appears at 6000:0000
jnz NoMirror ; jump done if 1M part

mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
mov al,0c2h ; init the 256K part setup
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al
NoMirror:
jmp NEAR PTR ResumeChipHook2

[Break]

----------------------------------------------------------------------

[Extract] [C]

185
The C Programs

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned Results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{
case ChipEnable:
outp(0x92,inp(0x92) | 2);
Results = True;
break;

case ChipDisable:
outp(0x92,inp(0x92) & ~2);
Results = True;
break;
};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{
case ChipEnable:
// needs a 0-1 transition
outp(0x92,inp(0x92) & ~1); outp(0x92,inp(0x92) | 1);
Results = True;
break;
};
break;
break;
};
return(Results);
};

[Break]

186
Introduction to AutoBios

4.3.3.7 Headland HT12


-[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] Headland HT12 Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] HLAND12.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize an LSI chip set


[Description] with a default personality, if desired.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipRegPort 0x1ED


#define ChipDataPort 0x1EF

#define ChipID "Headland HT12P"

#define ChipSysCfg 0x10


#define ChipSysCfgDefault 0x00
// Bit Description
// 7, 2-0 Ram Configuration
// Bank3 Bank2 Bank1 Bank0 Total
// 0xxxx000 = - - - - 0K
// 0xxxx001 = 256K - - - 512K
// 0xxxx010 = 256K 64K - - 640K
// 0xxxx011 = 256K 256K - - 1M
// 0xxxx100 = 256K 1M - - 2.5M
// 0xxxx101 = 1M - - - 2M
// 0xxxx110 = 1M 1M - - 4M
// 0xxxx111 = - - - - Reserved
// 1xxxx000 = - - - - 0M
// 1xxxx001 = 256K 256K 256K - 1.5M
// 1xxxx010 = 256K 64K 1M - 3M
// 1xxxx011 = 256K 256K 256K 256K 2M
// 1xxxx100 = 256K 256K 1M 1M 5M
// 1xxxx101 = 1M 1M 1M - 6M

187
The C Programs

// 1xxxx110 = 1M 1M 1M 1M 8M
// 1xxxx111 = - - - - Reserved
// 6,5 Wait State Control
// x00xxxxx = 1 extra wait for EMS + relocation cycles
// x01xxxxx = 1 extra wait for EMS cycles only
// x10xxxxx = 1 extra wait for relocation cycles only
// x11xxxxx = No extra wait states
// 4 Memory Wait States
// xxx0xxxx = 1 wait state
// xxx1xxxx = 0 wait states
// 3 AT Bus Speed
// xxxx0xxx = 0 Full Speed
// xxxx1xxx = Low speed on I/O

#define ChipShadow1 0x12


#define ChipShadow1Default 0x00
// 7 0xxxxxxx = Disable shadow DC000-DFFFF
// 6 x0xxxxxx = Disable shadow D8000-DBFFF
// 5 xx0xxxxx = Disable shadow D4000-D7FFF
// 4 xxx0xxxx = Disable shadow D0000-D3FFF
// 3 xxxx0xxx = Disable shadow CC000-CFFFF
// 2 xxxxx0xx = Disable shadow C8000-CBFFF
// 1 xxxxxx0x = Disable shadow C4000-C7FFF
// 0 xxxxxxx0 = Disable shadow C0000-C3FFF

#define ChipShadow2 0x13


#define ChipShadow2Default 0x00
// 7 0xxxxxxx = Disable shadow FC000-FFFFF
// 6 x0xxxxxx = Disable shadow F8000-FBFFF
// 5 xx0xxxxx = Disable shadow F4000-F7FFF
// 4 xxx0xxxx = Disable shadow F0000-F3FFF
// 3 xxxx0xxx = Disable shadow EC000-EFFFF
// 2 xxxxx0xx = Disable shadow E8000-EBFFF
// 1 xxxxxx0x = Disable shadow E4000-E7FFF
// 0 xxxxxxx0 = Disable shadow E0000-E3FFF

#define ChipMiscFeature 0x14


#define ChipMiscFeatureDefault 0x09
// 7-6 00xxxxxx = Reserved - Must be set by Bios on power up.
// 5 Memory Parity
// xx0xxxxx = Enable Parity (default)
// xx1xxxxx = Disable Parity
// 4 Enable 64K/128K Bios
// xxx0xxxx = 128K Bios space decoded
// xxx1xxxx = 64K Bios space decoded
// 3 Enable Memory 40000H-9FFFFH
// xxxx0xxx = Disable
// xxxx1xxx = Enable (default)
// 2 Enable Relocation Function
// xxxxx0xx = Disable (default)
// xxxxx1xx = Enable
// 1 Enable Shadowing
// xxxxxx0x = Disable (default)
// xxxxxx1x = Enable
// 0 Quiet BUS Enable

188
Introduction to AutoBios

// xxxxxxx0 = Disable
// xxxxxxx1 = Enable (default)

#define ChipMiscStatus 0x15


#define ChipMiscStatusDefault 0x00
// 7-2 Reserved
// 1 NMI Enable Status (1 = NMI Enable)
// 0 8042 A20 Gate (1 = A20 Enabled)

#define ChipExtInfo 0x16


#define ChipExtInfoDefault 0x00
// 7-0 Reserved

#define ChipRevInfo 0x17


#define ChipRevInfoDefault 0x00
// 7-4 HT12P Identification Number (0001 = HT12P)
// 3-0 Revision Number (0001 = Rev. A)

#define ChipTopMem 0x18


#define ChipTopMemDefault 0x00
// 7 Reserved
// 6-0 Top of Extended Memory (Address Bits 22-16)

#define ChipEmsCfg 0x19


#define ChipEmsCfgDefault 0x00
// 7 Global EMS enable
// 0xxxxxxx = Disable (default)
// 1xxxxxxx = Enable
// 6-4 EMS Pages Starting Address
// x000xxxx = C000:0000
// x001xxxx = C400:0000
// x010xxxx = C800:0000
// x011xxxx = CC00:0000
// x100xxxx = D000:0000
// x101xxxx
// ... = Not Specified in Spec sheet
// x111xxxx
// 3 EMS Page Enable 3
// 0 = Disable (default), 1 = Enable
// 2 EMS Page Enable 2
// 0 = Disable (default), 1 = Enable
// 1 EMS Page ENable 1
// 0 = Disable (default), 1 = Enable
// 0 EMS Page Enable 0
// 0 = Disable (default), 1 = Enable

#define ChipEmsPage0 0x20


#define ChipEmsPage0Default 0x00
// 7-0 Address Lines 21-14

#define ChipEmsPage1 0x21


#define ChipEmsPage1Default 0x00
// 7-0 Address Lines 21-14

#define ChipEmsPage2 0x22


#define ChipEmsPage2Default 0x00

189
The C Programs

// 7-0 Address Lines 21-14

#define ChipEmsPage3 0x23


#define ChipEmsPage3Default 0x00
// 7-0 Address Lines 21-14

#define ChipEmsBit22 0x24


#define ChipEmsBit22Default 0x00
// 7-4 Reserved
// 3-0 EMS Page Register 3-0 Bit 22

[Break]

[Extract] [HELP]

These definitions are from the Headland spec sheet. We havn't installed
on a Headland board yet, so will appreciate feedback. Thanks...

[Break]

-----------------------------------------------------------------

[Extract] [C] [DUMP]

// Danny:
// This list consists of a name, then the vale defined for that name:

struct ItemList DumpList[]=


{
{ "ChipSysCfg","", ChipSysCfg,SizeIsByte,ChipSysCfgDefault, },
{ "ChipShadow1","", ChipShadow1,SizeIsByte,ChipShadow1Default, },
{ "ChipShadow2","", ChipShadow2,SizeIsByte,ChipShadow2Default, },
{ "ChipMiscFeature","",
ChipMiscFeature,SizeIsByte,ChipMiscFeatureDefault, },
{ "ChipMiscStatus","",
ChipMiscStatus,SizeIsByte,ChipMiscStatusDefault, },
{ "ChipExtInfo","", ChipExtInfo,SizeIsByte,ChipExtInfoDefault, },
{ "ChipRevInfo","", ChipRevInfo,SizeIsByte,ChipRevInfoDefault, },
{ "ChipTopMem","", ChipTopMem,SizeIsByte,ChipTopMemDefault, },
{ "ChipEmsCfg","", ChipEmsCfg,SizeIsByte,ChipEmsCfgDefault, },
{ "ChipEmsPage0","", ChipEmsPage0,SizeIsByte,ChipEmsPage0Default, },
{ "ChipEmsPage1","", ChipEmsPage1,SizeIsByte,ChipEmsPage1Default, },
{ "ChipEmsPage2","", ChipEmsPage2,SizeIsByte,ChipEmsPage2Default, },
{ "ChipEmsPage3","", ChipEmsPage3,SizeIsByte,ChipEmsPage3Default, },
{ "ChipEmsBit22","", ChipEmsBit22,SizeIsByte,ChipEmsBit22Default, },
/* at the end of the table, use a null string */
{ "","", 0,SizeIsByte,0, },
};

unsigned ReadChipRegister(unsigned Index, unsigned size)


{
outp(ChipRegPort,Index); return(inp(ChipDataPort));
};

190
Introduction to AutoBios

[Break]

-----------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;--- This macro is used to simplify typing in the desired values ---

DefaultValue macro chipreg,chipval


WORD chipreg
WORD chipval
endm

;================== HEADLAND HT12 ====================

ChipDefaultTable LABEL BYTE


; These entries force the chip to a power-on default state.

DefaultValue ChipSysCfg, 00h


DefaultValue ChipShadow1, 00h
DefaultValue ChipShadow2, 00h
DefaultValue ChipMiscFeature, 08h
DefaultValue ChipTopMem, 3fh
DefaultValue ChipEmsCfg, 00h
DefaultValue ChipEmsPage0, 00h
DefaultValue ChipEmsPage1, 00h
DefaultValue ChipEmsPage2, 00h
DefaultValue ChipEmsPage3, 00h
DefaultValue ChipEmsBit22, 00h

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

191
The C Programs

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

; End of Table Marker

DefaultValue -1,-1 ; -1 Arguments indicate End of Table

; This is the chip specific chip loading routine. This example is


; for a chip (like the HT12), which loads an "index" port to
; select a register, then writing the data out through a "data" port.

ChipHook1 LABEL NEAR


mov si,offset ChipDefaultTable
.WHILE True
lods WORD PTR cs:[si]
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
lods WORD PTR cs:[si]
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al
.ENDW
jmp NEAR PTR ResumeChipHook1

; This hook is for implementing future options, such as


; auto-determining the type of memory chip.

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

192
Introduction to AutoBios

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

---------------------------------------------------------------------

[Extract] [C]

// Expanding these routines may be done if the chipset supports these


// features. If left as-is, the normal 286 AT platform code will
// be used.

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

193
Introduction to AutoBios

4.3.3.8 Headland HT18


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] Headland HT18 Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] HLAND18.CHP

[File Status] Being Updated

[Language] Mixed MSVC 1.0/1.5 MASM 6.1/6.11

[Description] This module is used to Initialize an LSI chip set


[Description] with a default personality, if desired.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "Headland HT18"

#define ChipRegPort 0x1ED


#define ChipDataPort 0x1EF

#define FastGateA20Port 0x01 // to be defined


#define FastGateA20Bit 0x01 // to be defined

#define FastResetPort 0x01 // to be defined


#define FastResetBit 0x20 // to be defined

#define ControlReg0 0x00


#define ControlReg0Default 0x00
// Bit Description
// 7 DRAM Type
// 0xxxxxxx = 256K or 4M
// 1xxxxxxx = 1M
// 6-5 DRAM Bank Count
// x00xxxxx = 1 bank
// x01xxxxx = 2 banks
// x10xxxxx = 3 banks
// x11xxxxx = 4 banks
// 4 Shadow Ram Enable F0000
// xxx0xxxx = Enable

195
The C Programs

// xxx1xxxx = Disable
// 3 Shadow Ram Enable E0000
// xxxx0xxx = Enable
// xxxx1xxx = Disable
// 2 384K Disable
// xxxxx0xx = Enable
// xxxxx1xx = Disable
// 1 Global EMS
// xxxxxx0x = EMS Disabled
// xxxxxx1x = EMS Enabled
// 0 Context Selection Enable
// xxxxxxx0 = Standard Context
// xxxxxxx1 = Alternate Context

#define ControlReg1 0x00


#define ControlReg1Default 0x00
// Bit Description
// 7 Page Mode Enable
// 0xxxxxxx = Page Mode Disabled
// 1xxxxxxx = Page Mode Enabled
// 6 Mix Dram Type Mode Register
// x0xxxxxx = Same Type for all banks
// x1xxxxxx = Selected Type for first two banks,
// other type for last two banks
// 5-3 RAS Precharge Timing
// xx000xxx = 16 cycles
// xx001xxx = 14 cycles
// xx010xxx = 12 cycles
// xx011xxx = 10 cycles
// xx100xxx = 8 cycles
// xx101xxx = 6 cycles
// xx110xxx = 4 cycles
// xx111xxx = 2 cycles
// 2-0 RAS Active timeout (in usecs.)
// xxxxx000 = 200
// xxxxx001 = 150
// xxxxx010 = 120
// xxxxx011 = 100
// xxxxx100 = 80
// xxxxx101 = 60
// xxxxx110 = 30
// xxxxx111 = 10

#define ControlReg2 0x00


#define ControlReg2Default 0xc0
// Bit Description
// 7-6 Reserved - Must be ones
// 11xxxxxx = Reserved - Must Set
// 5-4 0 Wait State Enable
// xx00xxxx = For Page Mode 1 Wait State
// xx01xxxx = For Page Mode 0 Wait State
// xx10xxxx = For Non-Page Mode 1 Wait State
// xx11xxxx = For Non-Page Mode 0 Wait State
// 3-2 CAS Precharge Time
// xxxx00xx = undefined
// xxxx01xx = undefined

196
Introduction to AutoBios

// xxxx10xx = 2 PROCCLK cycles


// xxxx11xx = 1 PROCCLK cycle
// 1-0 CAS Active Time
// xxxxxx00 = 4 PROCCLK cycles
// xxxxxx01 = 3 PROCCLK cycles
// xxxxxx10 = undefined
// xxxxxx11 = undefined

#define ControlReg3 0x00


#define ControlReg3Default 0x00
// Bit Description
// 7-0 Top of System board memory starting
// Address of External Expansion RAM

#define ControlReg4 0x00


#define ControlReg4Default 0x00
// Bit Description
// 7-4 Chip ID
// 0001xxxx Rev. A
// 0010xxxx Rev. B
// 1000xxxx Rev. C
// 3 I/O Speed
// xxxx0xxx = PROCCLK is CLKASN/2
// xxxx1xxx = PROCCLK is CLKX2 (full speed)
// 2 NPX Select
// xxxxx0xx = Not Present
// xxxxx1xx = Present
// 1 Interleave Mode (for Rev A & B)
// xxxxxx0x = Word Interleave
// xxxxxx1x = Page Interleave
// 1 Time Out Enable (for Rev C)
// xxxxxx0x = Defeat RAS Timeout
// xxxxxx1x = Enable RAS Timeout
// 0 ROM Chip Select Disable
// xxxxxxx0 = ROMCS enables E0000-FFFFF
// xxxxxxx1 = ROMCS enables F0000-FFFFF

#define ControlReg5 0x00


#define ControlReg5Default 0x00
// Bit Description
// 7-4 Reserved - must be zero
// 3 Hispeed Switch
// xxxx0xxx = Disable Hispeed on idle (Rev. B/C)
// xxxx1xxx = Enable Hispeed on idle (Rev. B/C)
// 2 Parity Check
// xxxxx0xx = Enabled
// xxxxx1xx = Disabled
// 1 Page Interleave CAS sharing
// xxxxxx0x = Disabled
// xxxxxx1x = Enabled
// 0 Reserved

#define ControlReg6 0x00


#define ControlReg6Default 0x00
// Bit Description
// 7-2 Reserved

197
The C Programs

// 1 Master Speed Select


// xxxxxx0x = PROCCLK runs at low speed in master mode
// xxxxxx1x = PROCCLK runs at high speed in master mode
// 0 4M RAM Select
// xxxxxxx0 = No 4M DRAMS
// xxxxxxx1 = 4M Drams in any bank

[Break]

------------------------------------------------------------------

[Extract] [C] [DUMP]

struct ItemList DumpList[] =


{
{ "Control Reg 0","",ControlReg0,SizeIsByte,ControlReg0Default, },
{ "Control Reg 1","",ControlReg1,SizeIsByte,ControlReg1Default, },
{ "Control Reg 2","",ControlReg2,SizeIsByte,ControlReg2Default, },
{ "Control Reg 3","",ControlReg3,SizeIsByte,ControlReg3Default, },
{ "Control Reg 4","",ControlReg4,SizeIsByte,ControlReg4Default, },
{ "Control Reg 5","",ControlReg5,SizeIsByte,ControlReg5Default, },
{ "Control Reg 6","",ControlReg6,SizeIsByte,ControlReg6Default, },
{ "","",0,SizeIsByte,0,}, /* Nul String or Zero Value is End of Table */
};

unsigned ReadChipRegister(unsigned Index, unsigned size)


{
outp(ChipRegPort,Index); return(inp(ChipDataPort));
};

[Break]

------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;================== HEADLAND HT18 ====================

ChipDefaultTable LABEL BYTE

; DefaultValue RegisterName,RegisterDefaultValue

; Now setup for particular board

DefaultValue ControlReg0,ControlReg0Default
DefaultValue ControlReg1,ControlReg1Default
DefaultValue ControlReg2,ControlReg2Default
DefaultValue ControlReg3,ControlReg3Default
DefaultValue ControlReg4,ControlReg4Default

198
Introduction to AutoBios

DefaultValue ControlReg5,ControlReg5Default
DefaultValue ControlReg6,ControlReg6Default

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

; End of Table
DefaultValue -1,-1 ; -1 Arguments indicate End of Table

ChipHook1 LABEL NEAR


mov si,offset ChipDefaultTable
.WHILE 1
lods WORD PTR cs:[si]

199
The C Programs

.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
lods WORD PTR cs:[si]
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al
.ENDW
jmp NEAR PTR ResumeChipHook1

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

---------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

200
Introduction to AutoBios

201
Introduction to AutoBios

4.3.3.9 Intel 386 EX


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] Intel 386EX Chip Support

[Version] 2.00

[Author] John O. Foster

[Date] 08/01/94

[File Name] i386EX.CHP

[File Status] Being Updated

[Language] Mixed MSVC 1.0/1.5, MASM6.11

[Description] This module is used to support the Intel 386EX chip.

[History] 2.00 08/01/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "Intel 386EX"

// Dma Controller/Bus Arbiter Registers

#define Dma0Tar 0xf000


#define Dma0TarDOS 0x0000
#define Dma0TarName ""
#define Dma0TarDescription ""
#define Dma0TarSize SizeIsByte
#define Dma0TarDefault 0x0000

#define Dma0Byc 0xf001


#define Dma0BycDOS 0x0001
#define Dma0BycSize SizeIsByte
#define Dma0BycDefault 0x0000

#define Dma1Tar 0xf002


#define Dma1TarDOS 0x0002
#define Dma1TarSize SizeIsByte
#define Dma1TarDefault 0x0000

#define Dma1Byc 0xf003


#define Dma1BycDOS 0x0003
#define Dma1BycSize SizeIsByte
#define Dma1BycDefault 0x0000

203
The C Programs

#define DmaCmd1 0xf008


#define DmaCmd1DOS 0x0008
#define DmaCmd1Size SizeIsByte
#define DmaCmd1Default 0x0000

#define DmaSrr 0xf009


#define DmaSrrDOS 0x0009
#define DmaSrrSize SizeIsByte
#define DmaSrrDefault 0x0000

#define DmaMsk 0xf00a


#define DmaMskDOS 0x000a
#define DmaMskSize SizeIsByte
#define DmaMskDefault 0x0004

#define DmaMod1 0xf00b


#define DmaMod1DOS 0x000b
#define DmaMod1Size SizeIsByte
#define DmaMod1Default 0x0000

#define DmaClrBP 0xf00c


#define DmaClrBPDOS 0x000c
#define DmaClrBPSize SizeIsByte
#define DmaClrBPDefault 0x0000

#define DmaClr 0xf00d


#define DmaClrDOS 0x000d
#define DmaClrSize SizeIsByte
#define DmaClrDefault 0x0000

#define DmaClrMsk 0xf00e


#define DmaClrMskDOS 0x000e
#define DmaClrMskSize SizeIsByte
#define DmaClrMskDefault 0x0000

#define DmaGrpMsk 0xf00f


#define DmaGrpMskDOS 0x000f
#define DmaGrpMskSize SizeIsByte
#define DmaGrpMskDefault 0x0003

#define Dma0ReqL 0xf010


#define Dma0ReqLSize SizeIsByte
#define Dma0ReqLDefault 0x0000

#define Dma0ReqH 0xf011


#define Dma0ReqHSize SizeIsByte
#define Dma0ReqHDefault 0x0000

#define Dma1ReqL 0xf012


#define Dma1ReqLSize SizeIsByte
#define Dma1ReqLDefault 0x0000

#define Dma1ReqH 0xf013


#define Dma1ReqHSize SizeIsByte
#define Dma1ReqHDefault 0x0000

204
Introduction to AutoBios

#define DmaBsr 0xf018


#define DmaBsrSize SizeIsByte
#define DmaBsrDefault 0x00f0

#define DmaChr 0xf019


#define DmaChrSize SizeIsByte
#define DmaChrDefault 0x0000

#define DmaCmd2 0xf01a


#define DmaCmd2Size SizeIsByte
#define DmaCmd2Default 0x0008

#define DmaMod2 0xf01b


#define DmaMod2Size SizeIsByte
#define DmaMod2Default 0x0000

#define DmaIen 0xf01c


#define DmaIenSize SizeIsByte
#define DmaIenDefault 0x0000

#define DmaOVFE 0xf01d


#define DmaOVFESize SizeIsByte
#define DmaOVFEDefault 0x000a

#define DmaClrTC 0xf01e


#define DmaClrTCSize SizeIsByte
#define DmaClrTCDefault 0x0000

// Master Interrupt Controller

#define MpicP0 0xf020


#define MpicP0DOS 0x0020
#define MpicP0Size SizeIsByte
#define MpicP0Name "Master PIC Port 0"
#define MpicP0Default 0x0000

#define MpicP1 0xf021


#define MpicP1DOS 0x0021
#define MpicP1Size SizeIsByte
#define MpicP1Name "Master PIC Port 1"
#define MpicP1Default 0x0000

// Address Configuration Register

#define RemapCfg 0x0022


#define RemapCfgSize SizeIsWord
#define RemapCfgName "E3D Address Configuration Register"
#define RemapCfgLow 0x0022
#define RemapCfgLowSize SizeIsByte
#define RemapCfgHigh 0x0023
#define RemapCfgHighSize SizeIsByte
#define RemapCfgDefault 0x0000
#define RemapCfgESE 0x8000 // 1 = Expanded I/O space enabled
#define RemapCfgS1R 0x0040 // Serial Channel 1 (COM2) Address Remap
#define RemapCfgS0R 0x0020 // Serial Channel 0 (COM0) Address Remap

205
The C Programs

#define RemapCfgISR 0x0010 // Interrupt Slave 8259A Address Remap


#define RemapCfgIMR 0x0008 // Interrupt Master 8259A Address Remap
#define RemapCfgDR 0x0004 // Dma Address Remap
#define remapCfgTR 0x0001 // Timer Address Remap

// Programmable Interval Timer

#define Tmr0 0xf040


#define Tmr0DOS 0x0040
#define Tmr0Size SizeIsByte
#define Tmr0Name "Timer 0 Register"
#define Tmr0Default 0x0000

#define Tmr1 0xf041


#define Tmr1DOS 0x0041
#define Tmr1Size SizeIsByte
#define Tmr1Name "Timer 1 Register"
#define Tmr1Default 0x0000

#define Tmr2 0xf042


#define Tmr2DOS 0x0042
#define Tmr2Size SizeIsByte
#define Tmr2Name "Timer 2 Register"
#define Tmr2Default 0x0000

#define TmrCon 0xf043


#define TmrConDOS 0x0043
#define TmrConSize SizeIsByte
#define TmrConName "Timer Control Register"
#define TmrConDefault 0x0000

// DMA Page Registers

#define Dma1TarpL 0xf083


#define Dma1TarpLDOS 0x0083
#define Dma1TarpLSize SizeIsByte
#define Dma1TarpLDefault 0x0000

#define Dma1TarpH 0xf085


#define Dma1TarpHSize SizeIsByte
#define Dma1TarpHDefault 0x0000

#define Dma0TarpH 0xf086


#define Dma0TarpHSize SizeIsByte
#define Dma0TarpHDefault 0x0000

#define Dma0TarpL 0xf087


#define Dma0TarpLDOS 0x0087
#define Dma0TarpLSize SizeIsByte
#define Dma0TarpLDefault 0x0000

#define Dma0BycH 0xf098


#define Dma0BycHSize SizeIsByte
#define Dma0BycHDefault 0x0000

#define Dma1BycH 0xf099

206
Introduction to AutoBios

#define Dma1BycHSize SizeIsByte


#define Dma1BycHDefault 0x0000

// A20 Gate & Fast CPU reset

#define Port92 0xf092


#define Port92DOS 0x0092
#define Port92Size SizeIsByte
#define Port92Name "Port 92"
#define Port92Default 0x0000
// Bit Name Description
// 1 A20G
// xxxxxx0x = Address line A20 follows normal addressing mode
// xxxxxx1x = A20 forced to 0
// 0 CPURST
// xxxxxxx0 = No effect on E3C core
// xxxxxxx1 = Resets E#C core only

// Slave Interrupt Controller

#define SpicP0 0xf0a0


#define SpicP0DOS 0x00a0
#define SpicP0Size SizeIsByte
#define SpicP0Name "Slave PIC Port 0"
#define SpicP0Default 0x0000

#define SpicP1 0xf0a1


#define SpicP1DOS 0x00a1
#define SpicP1Size SizeIsByte
#define SpicP1Name "Slave PIC Port 1"
#define SpicP1Default 0x0000

// Chip Select Unit

#define Gcs0SadL 0xf400


#define Gcs0SadLSize SizeIsWord
#define Gcs0SadLDefault 0x0000

#define Gcs0SadH 0xf402


#define Gcs0SadHSize SizeIsWord
#define Gcs0SadHDefault 0x0000

#define Gcs0MskL 0xf404


#define Gcs0MskLSize SizeIsWord
#define Gcs0MskLDefault 0x0000

#define Gcs0MskH 0xf406


#define Gcs0MskHSize SizeIsWord
#define Gcs0MskHDefault 0x0000

#define Gcs1SadL 0xf408


#define Gcs1SadLSize SizeIsWord
#define Gcs1SadLDefault 0x0000

#define Gcs1SadH 0xf40a


#define Gcs1SadHSize SizeIsWord

207
The C Programs

#define Gcs1SadHDefault 0x0000

#define Gcs1MskL 0xf40c


#define Gcs1MskLSize SizeIsWord
#define Gcs1MskLDefault 0x0000

#define Gcs1MskH 0xf40e


#define Gcs1MskHSize SizeIsWord
#define Gcs1MskHDefault 0x0000

#define Gcs2SadL 0xf410


#define Gcs2SadLSize SizeIsWord
#define Gcs2SadLDefault 0x0000

#define Gcs2SadH 0xf412


#define Gcs2SadHSize SizeIsWord
#define Gcs2SadHDefault 0x0000

#define Gcs2MskL 0xf414


#define Gcs2MskLSize SizeIsWord
#define Gcs2MskLDefault 0x0000

#define Gcs2MskH 0xf416


#define Gcs2MskHSize SizeIsWord
#define Gcs2MskHDefault 0x0000

#define Gcs3SadL 0xf418


#define Gcs3SadLSize SizeIsWord
#define Gcs3SadLDefault 0x0000

#define Gcs3SadH 0xf41a


#define Gcs3SadHSize SizeIsWord
#define Gcs3SadHDefault 0x0000

#define Gcs3MskL 0xf41c


#define Gcs3MskLSize SizeIsWord
#define Gcs3MskLDefault 0x0000

#define Gcs3MskH 0xf41e


#define Gcs3MskHSize SizeIsWord
#define Gcs3MskHDefault 0x0000

#define Gcs4SadL 0xf420


#define Gcs4SadLSize SizeIsWord
#define Gcs4SadLDefault 0x0000

#define Gcs4SadH 0xf422


#define Gcs4SadHSize SizeIsWord
#define Gcs4SadHDefault 0x0000

#define Gcs4MskL 0xf424


#define Gcs4MskLSize SizeIsWord
#define Gcs4MskLDefault 0x0000

#define Gcs4MskH 0xf426


#define Gcs4MskHSize SizeIsWord

208
Introduction to AutoBios

#define Gcs4MskHDefault 0x0000

#define Gcs5SadL 0xf428


#define Gcs5SadLSize SizeIsWord
#define Gcs5SadLDefault 0x0000

#define Gcs5SadH 0xf42a


#define Gcs5SadHSize SizeIsWord
#define Gcs5SadHDefault 0x0000

#define Gcs5MskL 0xf42c


#define Gcs5MskLSize SizeIsWord
#define Gcs5MskLDefault 0x0000

#define Gcs5MskH 0xf42e


#define Gcs5MskHSize SizeIsWord
#define Gcs5MskHDefault 0x0000

#define LcsSadL 0xf430


#define LcsSadLSize SizeIsWord
#define LcsSadLDefault 0x0000

#define LcsSadH 0xf432


#define LcsSadHSize SizeIsWord
#define LcsSadHDefault 0x0000

#define LcsMskL 0xf434


#define LcsMskLSize SizeIsWord
#define LcsMskLDefault 0x0000

#define LcsMskH 0xf436


#define LcsMskHSize SizeIsWord
#define LcsMskHDefault 0x0000

#define UcsSadL 0xf438


#define UcsSadLSize SizeIsWord
#define UcsSadLDefault 0xFF6F

#define UcsSadH 0xf43A


#define UcsSadHSize SizeIsWord
#define UcsSadHDefault 0x03FF

#define UcsMskL 0xf43C


#define UcsMskLSize SizeIsWord
#define UcsMskLDefault 0xFFFF

#define UcsMskH 0xf43E


#define UcsMskHSize SizeIsWord
#define UcsMskHDefault 0x03FF

// Synchronous Serial I/O Unit

#define SsioTBuf 0xf480


#define SsioTBufSize SizeIsByte
#define SsioTBufDefault 0x0000

209
The C Programs

#define SsioRBuf 0xf482


#define SsioRBufSize SizeIsByte
#define SsioRBufDefault 0x0000

#define SsioBaud 0xf484


#define SsioBaudSize SizeIsByte
#define SsioBaudDefault 0x0000

#define SsioCon1 0xf486


#define SsioCon1Size SizeIsByte
#define SsioCon1Default 0x00c0

#define SsioCon2 0xf488


#define SsioCon2Size SizeIsByte
#define SsioCon2Default 0x0000

#define SsioCtr 0xf48a


#define SsioCtrSize SizeIsByte
#define SsioCtrDefault 0x0000

// Refresh Control Unit

#define RfsBad 0xf4a0


#define RfsBadSize SizeIsByte
#define RfsBadDefault 0x0000

#define RfsCir 0xf4a2


#define RfsCirSize SizeIsByte
#define RfsCirDefault 0x0000

#define RfsCon 0xf4a4


#define RfsConSize SizeIsByte
#define RfsConDefault 0x0000

#define RfsAdd 0xf4a6


#define RfsAddSize SizeIsByte
#define RfsAddDefault 0x0000

// Watch Dog Timer Unit

#define WdtRldH 0xf4c0


#define WdtRldHSize SizeIsByte
#define WdtRldHDefault 0x0000

#define WdtRldL 0xf4c2


#define WdtRldLSize SizeIsByte
#define WdtRldLDefault 0xffff

#define WdtCntH 0xf4c4


#define WdtCntHSize SizeIsByte
#define WdtCntHDefault 0x0000

#define WdtCntL 0xf4c6


#define WdtCntLSize SizeIsByte
#define WdtCntLDefault 0xffff

210
Introduction to AutoBios

#define WdtClr 0xf4c8


#define WdtClrSize SizeIsByte
#define WdtClrDefault 0x0000

#define WdtStatus 0xf4ca


#define WdtStatusSize SizeIsByte
#define WdtStatusDefault 0x0000

// Asynchronous Serial I/O Channel 0 (COM1)

#define RbrThrDll0 0xf4f8


#define RbrThrDll0DOS 0x03f8
#define RbrThrDll0Size SizeIsByte
#define RbrThrDll0Default 0x0000

#define IerDlh0 0xf4f9


#define IerDlh0DOS 0x03f9
#define IerDlh0Size SizeIsByte
#define IerDlh0Default 0x0000

#define Iir0 0xf4fa


#define Iir0DOS 0x03fa
#define Iir0Size SizeIsByte
#define Iir0Default 0x0000

#define Lcr0 0xf4fb


#define Lcr0DOS 0x03fb
#define Lcr0Size SizeIsByte
#define Lcr0Default 0x0000

#define Mcr0 0xf4fc


#define Mcr0DOS 0x03fc
#define Mcr0Size SizeIsByte
#define Mcr0Default 0x0000

#define Lsr0 0xf4fd


#define Lsr0DOS 0x03fd
#define Lsr0Size SizeIsByte
#define Lsr0Default 0x0000

#define Msr0 0xf4fe


#define Msr0DOS 0x03fe
#define Msr0Size SizeIsByte
#define Msr0Default 0x0000

#define Scr0 0xf4ff


#define Scr0DOS 0x03ff
#define Scr0Size SizeIsByte
#define Scr0Default 0x0000

// Clock Generation and Power Management

#define PwrCon 0xf800


#define PwrConSize SizeIsByte
#define PwrConName "Power Control Register"
#define PwrConDefault 0x0000

211
The C Programs

// Bit Name Description


// 1-0 Mode
// xxxxxx00 = Normal Halt Instruction
// xxxxxx01 = Enter Power Down Mode
// xxxxxx10 = Enter Idle Mode
// xxxxxx11 = Normal Halt Instruction

#define ClkPrs 0xf804


#define ClkPrsSize SizeIsWord
#define ClkPrsName "Clock Prescale Register"
#define ClkPrsDefault 0x0000
// Bit Name Description
// 8-0
// xxxxxxxyyyyyyyyy - where y = divide down value for PSCLK

// Chip Configuarion Registers

#define PinCfg0 0xf820


#define PinCfg0Size SizeIsByte
#define PinCfg0Name "Port1/Peripheral Pin Selection"
#define PinCfg0Default 0x0000
// Bit Name Description
// 7 BIT7
// 0xxxxxxx = PORT 1.7 is connected to package pin
// 1xxxxxxx = HLDA is connected to package pin
// 6 BIT6
// x0xxxxxx = PORT 1.6 is connected to package pin
// x1xxxxxx = HOLD is connected to package pin
// 5 BIT5
// xx0xxxxx = PORT 1.5 is connected to package pin
// xx1xxxxx = LOCK# is connected to package pin
// 4 BIT4
// xxx0xxxx = PORT 1.4 is connected to package pin
// xxx1xxxx = RI0# is connected to package pin
// 3 BIT3
// xxxx0xxx = PORT 1.3 is connected to package pin
// xxxx1xxx = DSR0# is connected to package pin
// 2 BIT2
// xxxxx0xx = PORT 1.2 is connected to package pin
// xxxxx1xx = DTR0# is connected to package pin
// 1 BIT1
// xxxxxx0x = PORT 1.1 is connected to package pin
// xxxxxx1x = RTS0# is connected to package pin
// 0 BIT0
// xxxxxxx0 = PORT 1.0 is connected to package pin
// xxxxxxx1 = DCD0# is connected to package pin

#define PinCfg1 0xf822


#define PinCfg1Size SizeIsByte
#define PinCfg1Name "Port2/Peripheral Pin Selection"
#define PinCfg1Default 0x0000
// Bit Name Description
// 7 BIT7
// 0xxxxxxx = PORT 2.7 is connected to package pin
// 1xxxxxxx = CTS0# is connected to package pin
// 6 BIT6

212
Introduction to AutoBios

// x0xxxxxx = PORT 2.6 is connected to package pin


// x1xxxxxx = TXD0 is connected to package pin
// 5 BIT5
// xx0xxxxx = PORT 2.5 is connected to package pin
// xx1xxxxx = RXD0 is connected to package pin
// 4 BIT4
// xxx0xxxx = PORT 2.4 is connected to package pin
// xxx1xxxx = GCS4# is connected to package pin
// 3 BIT3
// xxxx0xxx = PORT 2.3 is connected to package pin
// xxxx1xxx = GCS3# is connected to package pin
// 2 BIT2
// xxxxx0xx = PORT 2.2 is connected to package pin
// xxxxx1xx = GCS2# is connected to package pin
// 1 BIT1
// xxxxxx0x = PORT 2.1 is connected to package pin
// xxxxxx1x = GCS1# is connected to package pin
// 0 BIT0
// xxxxxxx0 = PORT 2.0 is connected to package pin
// xxxxxxx1 = GCS0# is connected to package pin

#define PinCfg2 0xf824


#define PinCfg2Size SizeIsByte
#define PinCfg2Name "Port3/Peripheral Pin Selection"
#define PinCfg2Default 0x0000
// Bit Name Description
// 7 BIT7
// 0xxxxxxx = PORT 3.7 is connected to package pin
// 1xxxxxxx = COMCLK is connected to package pin
// 6 BIT6
// x0xxxxxx = PORT 3.6 is connected to package pin
// x1xxxxxx = PWRDOWN is connected to package pin
// 5 BIT5
// xx0xxxxx = PORT 3.5 is connected to package pin
// xx1xxxxx = INT3 is connected to package pin
// 4 BIT4
// xxx0xxxx = PORT 3.4 is connected to package pin
// xxx1xxxx = INT2 is connected to package pin
// 3 BIT3
// xxxx0xxx = PORT 3.3 is connected to package pin
// xxxx1xxx = INT1 is connected to package pin
// 2 BIT2
// xxxxx0xx = PORT 3.2 is connected to package pin
// xxxxx1xx = INT0 is connected to package pin
// 1 BIT1
// xxxxxx0x = PORT 3.1 is connected to package pin
// xxxxxx1x = TMROUT1 is connected to package pin
// 0 BIT0
// xxxxxxx0 = PORT 3.0 is connected to package pin
// xxxxxxx1 = TMROUT0 is connected to package pin

#define PinCfg3 0xf826


#define PinCfg3Size SizeIsByte
#define PinCfg3Name "Peripheral Pin Selection"
#define PinCfg3Default 0x0000

213
The C Programs

// Bit Name Description


// 6 BIT6
// x0xxxxxx = LCS# is connected to package pin
// x1xxxxxx = REFRESH# is connected to package pin
// 5 BIT5
// xx0xxxxx = Co-Processor signals PEREQ, BUSY#, ERROR#
// are connected to package pins
// xx1xxxxx = TIMER2 signals TMROUT2, TMRCLK2, TMRGATE2
// are connected to package pins
// 4 BIT4
// xxx0xxxx = DACK0# is connected to package pin
// xxx1xxxx = GCS5# is connected to package pin
// 3 BIT3
// xxxx0xxx = EOP# is connected to package pin
// xxxx1xxx = CTS1#is connected to package pin
// 2 BIT2
// xxxxx0xx = DACK1# is connected to package pin
// xxxxx1xx = TXD1 is connected to package pin
// 1 BIT1
// xxxxxx0x = SRXCLK is connected to package pin
// xxxxxx1x = DTR1# is connected to package pin
// 0 BIT0
// xxxxxxx0 = SSIOTX is connected to package pin
// xxxxxxx1 = RTS1# is connected to package pin

#define DmaCfg 0xf830


#define DmaCfgSize SizeIsByte
#define DmaCfgName "DMA Interconnect Selections"
#define DmaCfgDefault 0x0000
// Bit Name Description
// 7 D1DIS 0/1 = Enable/Disable DMAACK1# at chip pin
// 0xxxxxxx = Enable
// 1xxxxxxx = Disable
// 6-4 D1REQ2:0
// x000xxxx = DRQ1 (pin) is connected to DREQ1
// x001xxxx = RBFINT1 is connected to DREQ1
// x010xxxx = TXEINT0 is connected to DREQ1
// x011xxxx = SSRBF is connected to DREQ1
// x100xxxx = TMROUT2 is connected to DREQ1
// x101xxxx = reserved
// x110xxxx = reserved
// x111xxxx = reserved

// 3 D0DIS 0/1 = Enable/Disable DMAACK1# at chip pin


// xxxx0xxx = Enable
// xxxx1xxx = Disable
// 2-0 D0REQ2:0
// xxxxx000 = DRQ0 (pin) is connected to DREQ0
// xxxxx001 = RBFINT0 is connected to DREQ0
// xxxxx010 = TXEINT1 is connected to DREQ0
// xxxxx011 = SSTBE is connected to DREQ0
// xxxxx100 = TMROUT1 is connected to DREQ0
// xxxxx101 = reserved
// xxxxx110 = reserved
// xxxxx111 = reserved

214
Introduction to AutoBios

#define IntCfg 0xf832


#define IntCfgSize SizeIsByte
#define IntCfgName "Interrupt Interconnect Selections"
#define IntCfgDefault 0x0000
// Bit Name Description
// 7 BIT7
// 0xxxxxxx = CAS2:0 lines are disabled from pins
// 1xxxxxxx = CAS2:0 lines are enabled to pins
// 6-4 unused
// 3 BIT3
// xxxx0xxx = VSS is connected to Slave Interrupt IR6
// xxxx1xxx = INT7 (pin) is connected to Slave Interrupt IR6
// 2 BIT2
// xxxxx0xx = VSS is connected to Slave Interrupt IR5
// xxxxx1xx = INT6 (pin) is connected to Slave Interrupt IR5
// 1 BIT1
// xxxxxx0x = VSS is connected to Slave Interrupt IR1
// xxxxxx1x = INT5 (pin) is connected to Slave Interrupt IR1
// 0 BIT0
// xxxxxxx0 = VSS is connected to Slave Interrupt IR0
// xxxxxxx1 = INT4 (pin) is connected to Slave Interrupt IR0

#define TmrCfg 0xf834


#define TmrCfgSize SizeIsByte
#define TmrCfgName "Timer Interconnect Selections"
#define TmrCfgDefault 0x0000
// Bit Name Description
// 7 TMRDIS
// 0xxxxxxx = All clock inputs are enabled
// 1xxxxxxx = CLK2, CLK1, CLK0 inputs are forced to 0
// 5 GT2EXT
// xx0xxxxx = VCC is connected to GATE2
// xx1xxxxx = TMRGATE2 is connected to GATE2
// 4 CK2EXT
// xxx0xxxx = PSCLK is connected to CLK2
// xxx1xxxx = TMRCLK2 is connected to CLK2
// 3 GT1EXT
// xxxx0xxx = VCC is connected to CLK1
// xxxx1xxx = TMRGATE1 is connected to CLK1
// 2 CK1EXT
// xxxxx0xx = PSCLK is connected to CLK1
// xxxxx1xx = TMRCLK1 is connected to CLK1
// 1 GT0EXT
// xxxxxx0x = VCC is connected to GATE0
// xxxxxx1x = TMRGATE0 is connected to GATE0
// 0 CK0EXT
// xxxxxxx0 = PSCLK is connected to CLK0
// xxxxxxx1 = TMECLK0 is connected to CLK0

#define SioCfg 0xf836


#define SioCfgSize SizeIsByte
#define SioCfgName "Serial I/O Interconnect Selections"
#define SioCfgDefault 0x0000
// Bit Name Description
// 7 BIT7
// 0xxxxxxx = SIO1 modem signals are connected to pin muxes

215
The C Programs

// 1xxxxxxx = SIO1 modem signals are connected internally


// 6 BIT6
// x0xxxxxx = SIO0 modem signals are connected to pin muxes
// x1xxxxxx = SIO0 modem signals are connected internally
// 2 BIT2
// xxxxx0xx = Internal PSCLK is connected to SSIO BCLKIN
// xxxxx1xx = Internal SERCLK is connected to SSIO BCLKIN
// 1 BIT1
// xxxxxx0x = COMCLK (pin) is connected to SIO1 BCLKIN
// xxxxxx1x = Internal SERCLK is connected to SIO1 BCLKIN
// 0 BIT0
// xxxxxxx0 = COMCLK (pin) is connected to SIO0 BCLKIN
// xxxxxxx1 = Internal SERCLK is connected to SIO0 BCLKIN

// Parallel I/O Ports

#define P1Pin 0xf860


#define P1PinSize SizeIsByte
#define P1PinDefault 0x0000

#define P1Ltc 0xf862


#define P1LtcSize SizeIsByte
#define P1LtcDefault 0x00ff

#define P1Dir 0xf864


#define P1DirSize SizeIsByte
#define P1DirDefault 0x00ff

#define P2Pin 0xf868


#define P2PinSize SizeIsByte
#define P2PinDefault 0x0000

#define P2Ltc 0xf86a


#define P2LtcSize SizeIsByte
#define P2LtcDefault 0x00ff

#define P2Dir 0xf86c


#define P2DirSize SizeIsByte
#define P2DirDefault 0x00ff

#define P3Pin 0xf870


#define P3PinSize SizeIsByte
#define P3PinDefault 0x0000

#define P3Ltc 0xf872


#define P3LtcSize SizeIsByte
#define P3LtcDefault 0x00ff

#define P3Dir 0xf874


#define P3DirSize SizeIsByte
#define P3DirDefault 0x00ff

// Asynchronous Serial I/O Channel 1 (COM2)

#define RbrThrDll1 0xf8f8


#define RbrThrDll1DOS 0x02f8

216
Introduction to AutoBios

#define RbrThrDll1Size SizeIsByte


#define RbrThrDll1Default 0x0000

#define IerDlh1 0xf8f9


#define IerDlh1DOS 0x02f9
#define IerDlh1Size SizeIsByte
#define IerDlh1Default 0x0000

#define Iir1 0xf8fa


#define Iir1DOS 0x02fa
#define Iir1Size SizeIsByte
#define Iir1Default 0x0000

#define Lcr1 0xf8fb


#define Lcr1DOS 0x02fb
#define Lcr1Size SizeIsByte
#define Lcr1Default 0x0000

#define Mcr1 0xf8fc


#define Mcr1DOS 0x02fc
#define Mcr1Size SizeIsByte
#define Mcr1Default 0x0000

#define Lsr1 0xf8fd


#define Lsr1DOS 0x02fd
#define Lsr1Size SizeIsByte
#define Lsr1Default 0x0000

#define Msr1 0xf8fe


#define Msr1DOS 0x02fe
#define Msr1Size SizeIsByte
#define Msr1Default 0x0000

#define Scr1 0xf8ff


#define Scr1DOS 0x02ff
#define Scr1Size SizeIsByte
#define Scr1Default 0x0000

[Break]

---------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct ItemList DumpList[] =


{
{ "Dma0Tar","",Dma0Tar, Dma0TarSize, Dma0TarDefault,},
{ "Dma0Tar","",Dma0Tar, Dma0TarSize, Dma0TarDefault, },
{ "Dma0Byc","",Dma0Byc, Dma0BycSize, Dma0BycDefault, },
{ "Dma1Tar","",Dma1Tar, Dma1TarSize, Dma1TarDefault, },
{ "Dma1Byc","",Dma1Byc, Dma1BycSize, Dma1BycDefault, },
{ "DmaCmd1","",DmaCmd1, DmaCmd1Size, DmaCmd1Default, },

217
The C Programs

{ "DmaSrr","",DmaSrr, DmaSrrSize, DmaSrrDefault, },


{ "DmaMsk","",DmaMsk, DmaMskSize, DmaMskDefault, },
{ "DmaMod1","",DmaMod1, DmaMod1Size, DmaMod1Default, },
{ "DmaClrBP","",DmaClrBP, DmaClrBPSize, DmaClrBPDefault, },
{ "DmaClr","",DmaClr, DmaClrSize, DmaClrDefault, },
{ "DmaClrMsk","",DmaClrMsk, DmaClrMskSize, DmaClrMskDefault, },
{ "DmaGrpMsk","",DmaGrpMsk, DmaGrpMskSize, DmaGrpMskDefault, },
{ "Dma0ReqL","",Dma0ReqL, Dma0ReqLSize, Dma0ReqLDefault, },
{ "Dma0ReqH","",Dma0ReqH, Dma0ReqHSize, Dma0ReqHDefault, },
{ "Dma1ReqL","",Dma1ReqL, Dma1ReqLSize, Dma1ReqLDefault, },
{ "Dma1ReqH","",Dma1ReqH, Dma1ReqHSize, Dma1ReqHDefault, },
{ "DmaBsr","",DmaBsr, DmaBsrSize, DmaBsrDefault, },
{ "DmaChr","",DmaChr, DmaChrSize, DmaChrDefault, },
{ "DmaCmd2","",DmaCmd2, DmaCmd2Size, DmaCmd2Default, },
{ "DmaMod2","",DmaMod2, DmaMod2Size, DmaMod2Default, },
{ "DmaIen","",DmaIen, DmaIenSize, DmaIenDefault, },
{ "DmaOVFE","",DmaOVFE, DmaOVFESize, DmaOVFEDefault, },
{ "DmaClrTC","",DmaClrTC, DmaClrTCSize, DmaClrTCDefault, },
{ "MpicP0","",MpicP0, MpicP0Size, MpicP0Default, },
{ "MpicP1","",MpicP1, MpicP1Size, MpicP1Default, },
{ "RemapCfg","",RemapCfg, RemapCfgSize, RemapCfgDefault, },
{ "Tmr0","",Tmr0, Tmr0Size, Tmr0Default, },
{ "Tmr1","",Tmr1, Tmr1Size, Tmr1Default, },
{ "Tmr2","",Tmr2, Tmr2Size, Tmr2Default, },
{ "TmrCon","",TmrCon, TmrConSize, TmrConDefault, },
{ "Dma1TarpL","",Dma1TarpL, Dma1TarpLSize, Dma1TarpLDefault, },
{ "Dma1TarpH","",Dma1TarpH, Dma1TarpHSize, Dma1TarpHDefault, },
{ "Dma0TarpH","",Dma0TarpH, Dma0TarpHSize, Dma0TarpHDefault, },
{ "Dma0TarpL","",Dma0TarpL, Dma0TarpLSize, Dma0TarpLDefault, },
{ "Dma0BycH","",Dma0BycH, Dma0BycHSize, Dma0BycHDefault, },
{ "Dma1BycH","",Dma1BycH, Dma1BycHSize, Dma1BycHDefault, },
{ "Port92","",Port92, Port92Size, Port92Default, },
{ "SpicP0","",SpicP0, SpicP0Size, SpicP0Default, },
{ "SpicP1","",SpicP1, SpicP1Size, SpicP1Default, },
{ "Gcs0SadL","",Gcs0SadL, Gcs0SadLSize, Gcs0SadLDefault, },
{ "Gcs0SadH","",Gcs0SadH, Gcs0SadHSize, Gcs0SadHDefault, },
{ "Gcs0MskL","",Gcs0MskL, Gcs0MskLSize, Gcs0MskLDefault, },
{ "Gcs0MskH","",Gcs0MskH, Gcs0MskHSize, Gcs0MskHDefault, },
{ "Gcs1SadL","",Gcs1SadL, Gcs1SadLSize, Gcs1SadLDefault, },
{ "Gcs1SadH","",Gcs1SadH, Gcs1SadHSize, Gcs1SadHDefault, },
{ "Gcs1MskL","",Gcs1MskL, Gcs1MskLSize, Gcs1MskLDefault, },
{ "Gcs1MskH","",Gcs1MskH, Gcs1MskHSize, Gcs1MskHDefault, },
{ "Gcs2SadL","",Gcs2SadL, Gcs2SadLSize, Gcs2SadLDefault, },
{ "Gcs2SadH","",Gcs2SadH, Gcs2SadHSize, Gcs2SadHDefault, },
{ "Gcs2MskL","",Gcs2MskL, Gcs2MskLSize, Gcs2MskLDefault, },
{ "Gcs2MskH","",Gcs2MskH, Gcs2MskHSize, Gcs2MskHDefault, },
{ "Gcs3SadL","",Gcs3SadL, Gcs3SadLSize,Gcs3SadLDefault, },
{ "Gcs3SadH","",Gcs3SadH, Gcs3SadHSize, Gcs3SadHDefault, },
{ "Gcs3MskL","",Gcs3MskL, Gcs3MskLSize, Gcs3MskLDefault, },
{ "Gcs3MskH","",Gcs3MskH, Gcs3MskHSize, Gcs3MskHDefault, },
{ "Gcs4SadL","",Gcs4SadL, Gcs4SadLSize, Gcs4SadLDefault, },
{ "Gcs4SadH","",Gcs4SadH, Gcs4SadHSize, Gcs4SadHDefault, },
{ "Gcs4MskL","",Gcs4MskL, Gcs4MskLSize, Gcs4MskLDefault, },
{ "Gcs4MskH","",Gcs4MskH, Gcs4MskHSize, Gcs4MskHDefault, },
{ "Gcs5SadL","",Gcs5SadL, Gcs5SadLSize, Gcs5SadLDefault, },
{ "Gcs5SadH","",Gcs5SadH, Gcs5SadHSize, Gcs5SadHDefault, },

218
Introduction to AutoBios

{ "Gcs5MskL","",Gcs5MskL, Gcs5MskLSize, Gcs5MskLDefault, },


{ "Gcs5MskH","",Gcs5MskH, Gcs5MskHSize, Gcs5MskHDefault, },
{ "LcsSadL","",LcsSadL, LcsSadLSize, LcsSadLDefault, },
{ "LcsSadH","",LcsSadH, LcsSadHSize, LcsSadHDefault, },
{ "LcsMskL","",LcsMskL, LcsMskLSize,LcsMskLDefault, },
{ "LcsMskH","",LcsMskH, LcsMskHSize, LcsMskHDefault, },
{ "UcsSadL","",UcsSadL, UcsSadLSize, UcsSadLDefault, },
{ "UcsSadH","",UcsSadH, UcsSadHSize, UcsSadHDefault, },
{ "UcsMskL","",UcsMskL, UcsMskLSize, UcsMskLDefault, },
{ "UcsMskH","",UcsMskH, Gcs1SadHSize, UcsMskHDefault, },
{ "SsioTBuf","",SsioTBuf, SsioTBufSize, SsioTBufDefault, },
{ "SsioRBuf","",SsioRBuf, SsioRBufSize, SsioRBufDefault, },
{ "SsioBaud","",SsioBaud, SsioBaudSize, SsioBaudDefault, },
{ "SsioCon1","",SsioCon1, SsioCon1Size, SsioCon1Default, },
{ "SsioCon2","",SsioCon2, SsioCon2Size, SsioCon2Default, },
{ "SsioCtr","",SsioCtr, SsioCtrSize, SsioCtrDefault, },
{ "RfsBad","",RfsBad, RfsBadSize, RfsBadDefault, },
{ "RfsCir","",RfsCir, RfsCirSize, RfsCirDefault, },
{ "RfsCon","",RfsCon, RfsConSize, RfsConDefault, },
{ "RfsAdd","",RfsAdd, RfsAddSize, RfsAddDefault, },
{ "WdtRldH","",WdtRldH, WdtRldHSize, WdtRldHDefault, },
{ "WdtRldL","",WdtRldL, WdtRldLSize, WdtRldLDefault, },
{ "WdtCntH","",WdtCntH, WdtCntHSize, WdtCntHDefault, },
{ "WdtCntL","",WdtCntL, WdtCntLSize, WdtCntLDefault, },
{ "WdtClr","",WdtClr, WdtClrSize, WdtClrDefault, },
{ "WdtStatus","",WdtStatus, WdtStatusSize, WdtStatusDefault, },
{ "RbrThrDll0","",RbrThrDll0, RbrThrDll0Size, RbrThrDll0Default, },
{ "IerDlh0","",IerDlh0, IerDlh0Size, IerDlh0Default, },
{ "Iir0","",Iir0, Iir0Size, Iir0Default, },
{ "Lcr0","",Lcr0, Lcr0Size, Lcr0Default, },
{ "Mcr0","",Mcr0, Mcr0Size, Mcr0Default, },
{ "Lsr0","",Lsr0, Lsr0Size, Lsr0Default, },
{ "Msr0","",Msr0, Msr0Size, Msr0Default, },
{ "Scr0","",Scr0, Scr0Size, Scr0Default, },
{ "PwrCon","",PwrCon, PwrConSize, PwrConDefault, },
{ "ClkPrs","",ClkPrs, ClkPrsSize, ClkPrsDefault, },
{ "PinCfg0","",PinCfg0, PinCfg0Size, PinCfg0Default, },
{ "PinCfg1","",PinCfg1,PinCfg1Size,PinCfg1Default, },
{ "PinCfg2","",PinCfg2, PinCfg2Size,PinCfg2Default, },
{ "PinCfg3","",PinCfg3, PinCfg3Size, PinCfg3Default, },
{ "DmaCfg","",DmaCfg, DmaCfgSize, DmaCfgDefault, },
{ "IntCfg","",IntCfg, IntCfgSize, IntCfgDefault, },
{ "TmrCfg","",TmrCfg, TmrCfgSize, TmrCfgDefault, },
{ "SioCfg","",SioCfg, SioCfgSize, SioCfgDefault, },
{ "P1Pin","",P1Pin, P1PinSize, P1PinDefault, },
{ "P1Ltc","",P1Ltc, P1LtcSize, P1LtcDefault, },
{ "P1Dir","",P1Dir, P1DirSize, P1DirDefault, },
{ "P2Pin","",P2Pin, P2PinSize, P2PinDefault, },
{ "P2Ltc","",P2Ltc, P2LtcSize, P2LtcDefault, },
{ "P2Dir","",P2Dir, P2DirSize, P2DirDefault, },
{ "P3Pin","",P3Pin, P3PinSize, P3PinDefault, },
{ "P3Ltc","",P3Ltc, P3LtcSize, P3LtcDefault, },
{ "P3Dir","",P3Dir, P3DirSize, P3DirDefault, },
{ "RbrThrDll1","",RbrThrDll1,RbrThrDll1Size, RbrThrDll1Default, },
{ "IerDlh1","",IerDlh1, IerDlh1Size, IerDlh1Default, },
{ "Iir1","",Iir1, Iir1Size, Iir1Default, },

219
The C Programs

{ "Lcr1","",Lcr1, Lcr1Size, Lcr1Default, },


{ "Mcr1","",Mcr1, Mcr1Size, Mcr1Default, },
{ "Lsr1","",Lsr1, Lsr1Size, Lsr1Default, },
{ "Msr1","",Msr1, Msr1Size, Msr1Default, },
{ "Scr1","",Scr1, Scr1Size, Scr1Default, },
{ "","",0,0,0,}, /* Nul String or Zero Value is End of Table */
};

//---- Chip Specific routine to read a selected register ---


//-------- This routine will vary from chip to chip -----

unsigned ReadChipRegister(unsigned Reg,unsigned size)


{
if(size == SizeIsByte) return(inp(Reg)); else return(inpw(Reg));
}

[Break]

----------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;--------- This is the register load loop --------------------

ChipTable LABEL WORD


; This sets all registers back to a power-on default state.

CfgDefaultValue Dma0Tar,Dma0TarSize,Dma0TarDefault
CfgDefaultValue RemapCfg,RemapCfgSize,RemapCfgDefault

; Now setup for particular board

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2

220
Introduction to AutoBios

ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

; End of Table

CfgDefaultValue -1,-1,-1 ; -1 Arguments indicate End of Table

ChipHook1 LABEL NEAR

include e3d.inc
;---- from intel -------
in al,92h ;Clear Port 92 Reset
and al,0feh
or al,02h
out 92H,al

MOV AX, 0080H ; open expanded I/O space


XCHG AL, AH
OUT REMAPCFGH, AL
XCHG AL, AH
OUT REMAPCFGL, AL
OUT REMAPCFGL, AX

;Initialize the Watch Dog Timer for:


; Watch Dog Timer Status = Disabled

_SetE3DRegByte WDTSTATUS, 01H ;Disable the WDT.

221
The C Programs

;Initialize the Refresh Control Unit for:


; Refresh address of 0000H.
; Refresh gate between rows is 15.6uSec
; Using a CLK2 frequency of 50 MHz (25Mhz CPU operation)
; The refresh control unit is Enabled.
; The refresh pin is not used.

_SetE3DRegWord RFSCIR, 390 ;Program refresh interval.


_SetE3DRegWord RFSBAD, 00H ;Program base address.
_SetE3DRegWord RFSADD, 00H ;Program address register.
_SetE3DRegWord RFSCON, 8000H ;Program the enable bit.

;Initialize I/O Port 1 for:


; PIN 0 = 1, DCD0
; PIN 1 = 1, RTS0
; PIN 2 = 1, DTR0
; PIN 3 = 1, DSR0
; PIN 4 = 1, RI0
; PIN 5 = 0, OutPort (FLASH Vpp Enable, 0=Enable 1=Disable)
; PIN 6 = 0, OutPort
; PIN 7 = 0, OutPort

_SetE3DRegByte P1LTC, 0FFH


_SetE3DRegByte P1DIR, 00H
_SetE3DRegByte P1CFG, 01FH

;Initialize I/O Port 2 for:


; PIN 0 = 1, OutPort
; PIN 1 = 1, OutPort
; PIN 2 = 1, CS2# (SMRAM)
; PIN 3 = 0, OutPort
; PIN 4 = 1, CS4# (DRAM)
; PIN 5 = 1, RXD0
; PIN 6 = 1, TXD0
; PIN 7 = 1, CTS0

_SetE3DRegByte P2LTC, 0FFH


_SetE3DRegByte P2DIR, 00H
_SetE3DRegByte P2CFG, 0F4H

;Initialize I/O Port 3 for:


; PIN 0 = 0, InPort (Downloader, 0=Bypass 1=Execute)
; PIN 1 = 0, OutPort
; PIN 2 = 1, OutPort
; PIN 3 = 1, INT1
; PIN 4 = 1, INT2
; PIN 5 = 1, INT3
; PIN 6 = 0, InPort (Debugger Break)
; PIN 7 = 1, COMCLK

_SetE3DRegByte P3LTC, 0FFH


_SetE3DRegByte P3DIR, 41H
_SetE3DRegByte P3CFG, 0B8H

; Initialize Peripheral Pin Configurations

222
Introduction to AutoBios

; PIN 0 = 0, SSIOTX
; PIN 1 = 0, SRXCLK
; PIN 2 = 1, TXD1
; PIN 3 = 0, EOP#/TC
; PIN 4 = 0, DACK0#
; PIN 5 = 1, Timer2
; PIN 6 = 0, GCS6#
; PIN 7 = 0, Don't Care

_SetE3DRegByte PINCFG, 024H

;Initialize Chip Select Unit for:


; UCS: Start address is 03F80000H.
; Region size is 512 KBytes.
; 2 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Disabled.
; Accessable in SMM

_SetE3DRegWord UCSADL, 0302H ;Set the upper chip select


_SetE3DRegWord UCSADH, 03F8H
_SetE3DRegWord UCSMSKL, 0FC01H
_SetE3DRegWord UCSMSKH, 0007H

; CS0: Not Used

; CS1: Not Used

; CS2: Start address is 38000H.


; Region size is 32 Kbytes.
; 2 wait states.
; Chip select is Enabled.
; 8 bit data bus size in memory space.
; External bus ready is Disabled.
; Not accessable outside SMM.

_SetE3DRegWord CS2ADL, 8502H ;Set chip select 2


_SetE3DRegWord CS2ADH, 03H
_SetE3DRegWord CS2MSKL, 7801H
_SetE3DRegWord CS2MSKH, 0H

; CS3: Start address is 0A0000H.


; Region size is 128 Kbytes.
; 0 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Enabled.
; Accessable in SMM.

_SetE3DRegWord CS3ADL, 0380H


_SetE3DRegWord CS3ADH, 0AH
_SetE3DRegWord CS3MSKL, 0FC01H
_SetE3DRegWord CS3MSKH, 1H

; CS4: Start address is 0H.

223
The C Programs

; Region size is 16 MBytes.


; 2 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Disabled.
; Accessable in SMM.

_SetE3DRegWord CS4ADL, 0302H ;Set chip select 4


_SetE3DRegWord CS4ADH, 00H
_SetE3DRegWord CS4MSKL, 0FC01H
_SetE3DRegWord CS4MSKH, 0FFH

; CS5: Start address is 0C0000H.


; Region size is 128 Kbytes.
; 0 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Enabled.
; Accessable in SMM.

_SetE3DRegWord CS5ADL, 0380H


_SetE3DRegWord CS5ADH, 0CH
_SetE3DRegWord CS5MSKL, 0FC01H
_SetE3DRegWord CS5MSKH, 1H

; CS6: Start address is 0E0000H.

; Region size is 128 Kbytes.


; 2 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Disabled.
; Accessable in SMM

_SetE3DRegWord CS6ADL, 0302H ;Set chip select 6


_SetE3DRegWord CS6ADH, 0EH
_SetE3DRegWord CS6MSKL, 0FC01H
_SetE3DRegWord CS6MSKH, 1H

;Initialize the Clock and Power Management Unit for:


; Clock frequency of 50 MHz
; Prescaled clock output of 1.19318 MHz
; Normal Halt Instructions

_SetE3DRegByte PWRCON, 00H


_SetE3DRegWord CLKPRS, 15H

;Initialize the Asynchronous Serial Ports


;
; Bit 7 = 1, Internal SIO1 modem signals
; Bit 6 = 0, External SIO0 modem signals
; Bit 2 = 0, PSCLK for SSIO clock
; Bit 1 = 0, COMCLK for SIO1 clock
; Bit 0 = 0, COMCLK for SIO0 clock

224
Introduction to AutoBios

_SetE3DRegByte SIOCFG, 080H ;Set clocking and modem control sources.

;Initialize Timer 0 for:


;
; Bit 7 = 0, Timer clocks enabled
; Bit 5 = 0, Vcc to Gate2
; Bit 4 = 0, PSCLK to CLK2
; Bit 3 = 0, Vcc to Gate1
; Bit 2 = 0, PSCLK to CLK1
; Bit 1 = 0, Vcc to Gate0
; Bit 0 = 0, PSCLK to CLK0

_SetE3DRegByte TMRCFG, 00H ;Set input sources.

;Initialize the DMACFG register for:


;
; Bit 7 = 1, Disable DACK1#
; Bits 6:4 = 100, TMROUT2 connected to DRQ1
; Bit 3 = 0, Enable DACK0#
; Bits 2:0 = 000, Pin is conneced to DRQ0

_SetE3DRegByte DMACFG, 0C0H

;Initialize the INTCFG register for:


;
; Bit 7 = 0, Disable CAS lines
; Bit 3 = 1, Pin is connected to IRQ7
; Bit 2 = 1, Pin is connected to IRQ6
; Bit 1 = 1, Pin is connected to IRQ5
; Bit 0 = 1, Pin is connected to IRQ4

_SetE3DRegByte INTCFG, 0FH

;------- end from intel -------

; to be enabled when reg names are reconciled and init values are
; loaded into the default table section.
; this will replace the linear section above taken from the Intel
; tech notes
; mov si,offset ChipTable
; .WHILE 1
; lods WORD PTR cs:[si]
; .BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
; mov dx,ax ; move port address to DX
; jmp $+2 ; added delay
; lods WORD PTR cs:[si] ; get size for port
; mov bx,ax
; jmp $+2 ; added delay
; lods WORD PTR cs:[si] ; get value for port
; jmp $+2 ; added delay
; .IF (bx == SizeIsByte)
; out dx,al
; .ELSE
; out dx,ax
; .ENDIF

225
The C Programs

; .ENDW

;----------- from intel ---------


; disable the expanded I/O space

MOV AL, 00H


OUT REMAPCFGH,AL

;------ end from intel -----------------

jmp NEAR PTR ResumeChipHook1

; ---------- no action needed ------------------

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

-----------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned Temp;
unsigned results = False;
/*
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{
case ChipEnable:
// results = True;
break;

case ChipDisable:
// results = True;
break;
};
break;

case ChipFastResetCPU:
switch (Opcode)
{
case ChipEnable:
// results = True;

226
Introduction to AutoBios

break;
};
break;
};
*/
return(results);
};

[Break]

//---------------------------------------------

INIT_EX PROC FAR

in al,92h ;Clear Port 92 Reset


and al,0feh
or al,02h
out 92H,al

MOV AX, 0080H ; open expanded I/O space


XCHG AL, AH
OUT REMAPCFGH, AL
XCHG AL, AH
OUT REMAPCFGL, AL
OUT REMAPCFGL, AX

;Initialize the Watch Dog Timer for:


; Watch Dog Timer Status = Disabled

_SetE3DRegByte WDTSTATUS, 01H ;Disable the WDT.

;Initialize the Refresh Control Unit for:


; Refresh address of 0000H.
; Refresh gate between rows is 15.6uSec
; Using a CLK2 frequency of 50 MHz (25Mhz CPU operation)
; The refresh control unit is Enabled.
; The refresh pin is not used.

_SetE3DRegWord RFSCIR, 390 ;Program refresh interval.


_SetE3DRegWord RFSBAD, 00H ;Program base address.
_SetE3DRegWord RFSADD, 00H ;Program address register.
_SetE3DRegWord RFSCON, 8000H ;Program the enable bit.

;Initialize I/O Port 1 for:


; PIN 0 = 1, DCD0
; PIN 1 = 1, RTS0
; PIN 2 = 1, DTR0
; PIN 3 = 1, DSR0
; PIN 4 = 1, RI0
; PIN 5 = 0, OutPort (FLASH Vpp Enable, 0=Enable 1=Disable)
; PIN 6 = 0, OutPort
; PIN 7 = 0, OutPort

227
The C Programs

_SetE3DRegByte P1LTC, 0FFH


_SetE3DRegByte P1DIR, 00H
_SetE3DRegByte P1CFG, 01FH

;Initialize I/O Port 2 for:


; PIN 0 = 1, OutPort
; PIN 1 = 1, OutPort
; PIN 2 = 1, CS2# (SMRAM)
; PIN 3 = 0, OutPort
; PIN 4 = 1, CS4# (DRAM)
; PIN 5 = 1, RXD0
; PIN 6 = 1, TXD0
; PIN 7 = 1, CTS0

_SetE3DRegByte P2LTC, 0FFH


_SetE3DRegByte P2DIR, 00H
_SetE3DRegByte P2CFG, 0F4H

;Initialize I/O Port 3 for:


; PIN 0 = 0, InPort (Downloader, 0=Bypass 1=Execute)
; PIN 1 = 0, OutPort
; PIN 2 = 1, OutPort
; PIN 3 = 1, INT1
; PIN 4 = 1, INT2
; PIN 5 = 1, INT3
; PIN 6 = 0, InPort (Debugger Break)
; PIN 7 = 1, COMCLK

_SetE3DRegByte P3LTC, 0FFH


_SetE3DRegByte P3DIR, 41H
_SetE3DRegByte P3CFG, 0B8H

; Initialize Peripheral Pin Configurations


; PIN 0 = 0, SSIOTX
; PIN 1 = 0, SRXCLK
; PIN 2 = 1, TXD1
; PIN 3 = 0, EOP#/TC
; PIN 4 = 0, DACK0#
; PIN 5 = 1, Timer2
; PIN 6 = 0, GCS6#
; PIN 7 = 0, Don't Care

_SetE3DRegByte PINCFG, 024H

;Initialize Chip Select Unit for:


; UCS: Start address is 03F80000H.
; Region size is 512 KBytes.
; 2 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Disabled.
; Accessable in SMM

_SetE3DRegWord UCSADL, 0302H ;Set the upper chip select


_SetE3DRegWord UCSADH, 03F8H

228
Introduction to AutoBios

_SetE3DRegWord UCSMSKL, 0FC01H


_SetE3DRegWord UCSMSKH, 0007H

; CS0: Not Used

; CS1: Not Used

; CS2: Start address is 38000H.


; Region size is 32 Kbytes.
; 2 wait states.
; Chip select is Enabled.
; 8 bit data bus size in memory space.
; External bus ready is Disabled.
; Not accessable outside SMM.

_SetE3DRegWord CS2ADL, 8502H ;Set chip select 2


_SetE3DRegWord CS2ADH, 03H
_SetE3DRegWord CS2MSKL, 7801H
_SetE3DRegWord CS2MSKH, 0H

; CS3: Start address is 0A0000H.


; Region size is 128 Kbytes.
; 0 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Enabled.
; Accessable in SMM.

_SetE3DRegWord CS3ADL, 0380H


_SetE3DRegWord CS3ADH, 0AH
_SetE3DRegWord CS3MSKL, 0FC01H
_SetE3DRegWord CS3MSKH, 1H

; CS4: Start address is 0H.


; Region size is 16 MBytes.
; 2 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Disabled.
; Accessable in SMM.

_SetE3DRegWord CS4ADL, 0302H ;Set chip select 4


_SetE3DRegWord CS4ADH, 00H
_SetE3DRegWord CS4MSKL, 0FC01H
_SetE3DRegWord CS4MSKH, 0FFH

; CS5: Start address is 0C0000H.


; Region size is 128 Kbytes.
; 0 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Enabled.
; Accessable in SMM.

_SetE3DRegWord CS5ADL, 0380H


_SetE3DRegWord CS5ADH, 0CH

229
The C Programs

_SetE3DRegWord CS5MSKL, 0FC01H


_SetE3DRegWord CS5MSKH, 1H

; CS6: Start address is 0E0000H.

; Region size is 128 Kbytes.


; 2 wait states.
; Chip select is Enabled.
; 16 bit data bus size in memory space.
; External bus ready is Disabled.
; Accessable in SMM

_SetE3DRegWord CS6ADL, 0302H ;Set chip select 6


_SetE3DRegWord CS6ADH, 0EH
_SetE3DRegWord CS6MSKL, 0FC01H
_SetE3DRegWord CS6MSKH, 1H

;Initialize the Clock and Power Management Unit for:


; Clock frequency of 50 MHz
; Prescaled clock output of 1.19318 MHz
; Normal Halt Instructions

_SetE3DRegByte PWRCON, 00H


_SetE3DRegWord CLKPRS, 15H

;Initialize the Asynchronous Serial Ports


;
; Bit 7 = 1, Internal SIO1 modem signals
; Bit 6 = 0, External SIO0 modem signals
; Bit 2 = 0, PSCLK for SSIO clock
; Bit 1 = 0, COMCLK for SIO1 clock
; Bit 0 = 0, COMCLK for SIO0 clock

_SetE3DRegByte SIOCFG, 080H ;Set clocking and modem control sources.

;Initialize Timer 0 for:


;
; Bit 7 = 0, Timer clocks enabled
; Bit 5 = 0, Vcc to Gate2
; Bit 4 = 0, PSCLK to CLK2
; Bit 3 = 0, Vcc to Gate1
; Bit 2 = 0, PSCLK to CLK1
; Bit 1 = 0, Vcc to Gate0
; Bit 0 = 0, PSCLK to CLK0

_SetE3DRegByte TMRCFG, 00H ;Set input sources.

;Initialize the DMACFG register for:


;
; Bit 7 = 1, Disable DACK1#
; Bits 6:4 = 100, TMROUT2 connected to DRQ1
; Bit 3 = 0, Enable DACK0#
; Bits 2:0 = 000, Pin is conneced to DRQ0

_SetE3DRegByte DMACFG, 0C0H

230
Introduction to AutoBios

;Initialize the INTCFG register for:


;
; Bit 7 = 0, Disable CAS lines
; Bit 3 = 1, Pin is connected to IRQ7
; Bit 2 = 1, Pin is connected to IRQ6
; Bit 1 = 1, Pin is connected to IRQ5
; Bit 0 = 1, Pin is connected to IRQ4

_SetE3DRegByte INTCFG, 0FH

; disable the expanded I/O space

MOV AL, 00H


OUT REMAPCFGH,AL

; far jump to start of user routine


db 0eah
dw 0xxxxh ; Place IP location here
dw 0xxxxh ; Place CS location here

231
Introduction to AutoBios

4.3.3.10 Opti 82C499


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] OPTi Single Chip DXSC Chip (82C499) Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] OPTI499.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize an LSI chip set


[Desciption] with a default personality, if desired.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "OPTi 82C499 Chip"

// OPTi 82C499 Chip Information

// 82C499 Control Register Ports

#define ChipRegPort 0x22


#define ChipDataPort 0x24

// 82C836 Registers

#define ChipControlRegister1 0x20 // default = 00


#define ChipControlRegister1Default 0x00
// Bit Description (default = 0x00)
// 7-6 Revision # of 82C499
// 5 Burst Wait State Control
// xx0xxxxx = sec. cache read hit 3-1-1-1 or 2-1-1-1 (default)
// xx1xxxxx = sec. cache read hit 3-2-2-2 or 2-2-2-2
// 4 AT Clock Selections
// xxx0xxxx = source from CLK2 (default)
// xxx1xxxx = source form CLK1
// 3 Single ALE Enable
// xxxx0xxx = disable (default)
// xxxx1xxx = enable

233
The C Programs

// 2 Extra AT Cycle Wair State Enable


// xxxxx0xx = disable (default)
// xxxxx1xx = enable
// 1 Emulation keyboard Reset Control
// xxxxxx0x = disable (default)
// xxxxxx1x = enable
// 0 Fast Reset Enable
// xxxxxxx0 = disable (default)
// xxxxxxx1 = enable

#define ChipControlRegister2 0x21 // default = 00


#define ChipControlRegister2Default 0x00
// Bit Description
// 7 Master Mode Byte Swap Enable
// 0xxxxxxx = disable (default)
// 1xxxxxxx = enable
// 6 Cache Write 2 Wait States
// x0xxxxxx = 0/1 wait states - see also Bit 1 (default)
// x1xxxxxx = 2 wait states
// 5 Parity check
// xx0xxxxx = enable (default)
// xx1xxxxx = disable
// 4 Cache enable
// xxx0xxxx = disabled (default)
// xxx1xxxx = enabled
// 3-2 Cache size
// xxxx00xx = 64KB (default)
// xxxx01xx = 128KB
// xxxx10xx = 256KB
// xxxx11xx = 512Kb
// 1 Cache Write 0/1 Wait State Control
// xxxxxx0x = 1 wait state (default)
// xxxxxx1x = 0 wait state
// 0 Cache Read Wait State Control
// xxxxxxx0 = 3-1-1-1 cycle
// xxxxxxx1 = 2-1-1-1 cycle

#define ChipShadowRamControlRegister1 0x22 // default = 84


#define ChipShadowRamControlRegister1Default 0x84
// Bit Description (default = 0x06)
// 7 ROM (F0000-FFFFF) enable
// 0xxxxxxx = R/W on write-protected DRAM
// 1xxxxxxx = Read from ROM, Write to DRAM (default)
// 6 Shadow Ram at D0000-DFFFF
// x0xxxxxx = disable (default)
// x1xxxxxx = enable
// 5 Shadow Ram at E0000-EFFFF
// xx0xxxxx = disable (default)
// xx1xxxxx = enable
// 4 Shadow D0000-DFFFF Write Protect
// xxx0xxxx = disable (default)
// xxx1xxxx = enable
// 3 Shadow E0000-EFFFF Write Protect
// xxxx0xxx = disable (default)
// xxxx1xxx = enable
// 2 Hidden Refresh

234
Introduction to AutoBios

// xxxxx0xx = enable
// xxxxx1xx = disable (default)
// 1 Fast Gate A20
// 386 Mode
// xxxxxx0x = GA20 always zero (default)
// xxxxxx1x = GA20 generated
// 486 Mode
// xxxxxx0x = A20M# always active (default)
// xxxxxx1x = Enable A20
// 0 Slow Refresh
// xxxxxxx0 = disable (default)
// xxxxxxx1 = enable

#define ChipShadowRamControlRegister2 0x23 // default = 00


#define ChipShadowRamControlRegister2Default 0x00
// Bit Description (default = 0x00)
// 7 Shadow Ram at EC000-EFFFF
// 0xxxxxxx = disable (default)
// 1xxxxxxx = enable
// 6 Shadow Ram at E8000-EBFFF
// x0xxxxxx = disable (default)
// x1xxxxxx = enable
// 5 Shadow Ram at E4000-E7FFF
// xx0xxxxx = disable (default)
// xx1xxxxx = enable
// 4 Shadow Ram at E0000-E3FFF
// xxx0xxxx = disable (default)
// xxx1xxxx = enable
// 3 Shadow Ram at DC000-DFFFF
// xxxx0xxx = disable (default)
// xxxx1xxx = enable
// 2 Shadow Ram at D8000-DBFFF
// xxxxx0xx = disable (default)
// xxxxx1xx = enable
// 1 Shadow Ram at D4000-D7FFF
// xxxxxx0x = disable (default)
// xxxxxx1x = enable
// 0 Shadow Ram at D0000-D3FFF
// xxxxxxx0 = disable (default)
// xxxxxxx1 = enable

#define ChipDramControlRegister1 0x24 // default = 87


#define ChipDramControlRegister1Default 0x87
// Bit Description (Read Only)
// 7-4 DRAM types for Bank0 Bank1
// 0000xxxx = 256K X
// 0001xxxx = 256K 256K
// 0010xxxx = 256K 1M
// 0011xxxx = X X
// 01XXxxxx = X X
// 1000xxxx = 1M X (default)
// 1001xxxx = 1M 1M
// 1010xxxx = 1M 4M
// 1011xxxx = 4M 1M
// 1100xxxx = 4M X
// 1101xxxx = 4M 4M

235
The C Programs

// 111Xxxxx = X X
// 3 UNUSED (default = 0)
// 2-0 DRAM types for Bank2 Bank3
// xxxxx000 = 1M X
// xxxxx001 = 1M 1M
// xxxxx010 = X X
// xxxxx011 = 4M 1M
// xxxxx100 = 4M X
// xxxxx101 = 4M 4M
// xxxxx11X = X X (default)

#define ChipDramControlRegister2 0x25 // default = F0


#define ChipDramControlRegister2Default 0xf0
// Bit Description (default = 0xF0)
// 7-6 Read Cycle Wait States
// 00xxxxxx = Not used
// 01xxxxxx = 0 wait states
// 10xxxxxx = 1 wait state
// 11xxxxxx = 2 wait states (default)
// 5-4 Write Cycle Wait States
// xx00xxxx = 0 Wait states
// xx01xxxx = 1 wait state
// xx10xxxx = 2 wait states
// xx11xxxx = 3 wait states (default)
// 3 Fast decode enable
// xxxx0xxx = disable (default)
// xxxx1xxx = enable
// 2 CAS# delay for DMA/Master cycles
// xxxxx0xx = CAS# asserted 1 clock after RAS# (default)
// xxxxx1xx = CAS# asserted 2 clocks after RAS#
// 1-0 ATCLK Selection (see bit 4 of register 0x20)
// xxxxxx00 = CLKI/6 (default)
// xxxxxx01 = CLKI/5
// xxxxxx10 = CLKI/4
// xxxxxx11 = CLKI/3

#define ChipShadowRamControlRegister3 0x26 // default = 00


#define ChipShadowRamControlRegister3Default 0x00
// Bit Description
// 7 Enable ROMCS# for write cycles (to support Flash Eproms)
// 0xxxxxxx = disable (default)
// 1xxxxxxx = enable
// 6 Shadow Ram Copy enable for C0000-CFFFF
// x0xxxxxx = read/write AT Bus (default)
// x1xxxxxx = read AT Bus/write to Ram
// 5 Shadow write protect C0000-CFFFF
// xx0xxxxx = not protected (default)
// xx1xxxxx = protected
// 4 Shadow Ram Enable C0000-CFFFF
// xxx0xxxx = disabled (default)
// xxx1xxxx = enabled
// 3 Enable shadow ram at CC000-CFFFF
// xxxx0xxx = disabled (default)
// xxxx1xxx = enabled
// 2 Enable shadow ram at C8000-CBFFF
// xxxxx0xx = disabled (default)

236
Introduction to AutoBios

// xxxxx1xx = enabled
// 1 Enable shadow ram at C4000-C7FFF
// xxxxxx0x = disabled (default)
// xxxxxx1x = enabled
// 0 Enable shadow ram at C0000-C3FFF
// xxxxxxx0 = disabled (default)
// xxxxxxx1 = enabled

#define ChipControlRegister3 0x27 // default = D1


#define ChipControlRegister3Default 0xd1
// 7 Enable NCA# pin to low state
// 0xxxxxxx = disable
// 1xxxxxxx = enable (default)
// 6 Fast AT Cycle
// x0xxxxxx = disable
// x1xxxxxx = enable (default)
// 5 Back to back I/O delay control
// xx0xxxxx = 3 BLK back to back I/O delay (default)
// xx1xxxxx = no back to back I/O delay
// 4 Video Bios at C0000-C8000 area non-cacheable
// xxx0xxxx = Cacheable
// xxx1xxxx = Non-cacheable (default)
// 3-0 Cacheable address range for local memory
// xxxx0000 = 0 - 64 Mb
// xxxx0001 = 0 - 4 Mb (default)
// xxxx0010 = 0 - 8 Mb
// xxxx0011 = 0 - 12 Mb
// xxxx0100 = 0 - 16 Mb
// xxxx0101 = 0 - 20 Mb
// xxxx0110 = 0 - 24 Mb
// xxxx0111 = 0 - 28 Mb
// xxxx1000 = 0 - 32 Mb
// xxxx1001 = 0 - 36 Mb
// xxxx1010 = 0 - 40 Mb
// xxxx1011 = 0 - 44 Mb
// xxxx1100 = 0 - 48 Mb
// xxxx1101 = 0 - 52 Mb
// xxxx1110 = 0 - 56 Mb
// xxxx1111 = 0 - 60 Mb

#define ChipNonCacheBlock1Register1 0x28 // default = 80


#define ChipNonCacheBlock1Register1Default 0x80
// 7-5 Size of non-cacheable memory block 1
// 000xxxxx = 64K
// 001xxxxx = 128K
// 010xxxxx = 256K
// 011xxxxx = 512K
// 1XXxxxxx = disabled (default)
// 4-2 unused
// 1-0 Address bits of A25 and A24 of non-cache mem block 1

#define ChipNonCacheBlock1Register2 0x29 // default = 10


#define ChipNonCacheBlock1Register2Default 0x10
// 7-0 Address bits A23-A16 of non-cache mem block 1

#define ChipNonCacheBlock2Register1 0x2A // default = 80

237
The C Programs

#define ChipNonCacheBlock2Register1Default 0x80


// 7-5 Size of non-cacheable memory block 1
// 000xxxxx = 64K
// 001xxxxx = 128K
// 010xxxxx = 256K
// 011xxxxx = 512K
// 1XXxxxxx = disabled (default)
// 4-3 CAWE# pulse width for DMA/Master write hit cycles
// xxx00xxx = 3 CLKs (default)
// xxx01xxx = 1 CLK
// xxx10xxx = unused
// xxx11xxx = Same as the pulse witdh of MEMWR#
// 2 unused, must be set to 1 by BIOS
// 1-0 Address bits of A25 and A24 of non-cache mem block 2

#define ChipNonCacheBlock2Register2 0x2B // default = 10


#define ChipNonCacheBlock2Register2Default 0x10
// 7-0 Address bits A23-A16 of non-cache mem block 2

#define ChipRomChipSelectRegister3 0x2D // default = 00


#define ChipRomChipSelectRegister3Default 0x00
// 7-6 unused
// 5 Enable ROMCS# at E8000 to EFFFF
// xx0xxxxx = disable
// xx1xxxxx = enable
// 4 Enable ROMCS# at E0000 to E7FFF
// xx0xxxxx = disable
// xx1xxxxx = enable
// 3 Enable ROMCS# at D8000 to DFFFF
// xx0xxxxx = disable
// xx1xxxxx = enable
// 2 Enable ROMCS# at D0000 to D7FFF
// xx0xxxxx = disable
// xx1xxxxx = enable
// 1 Enable ROMCS# at C8000 to CFFFF
// xx0xxxxx = disable
// xx1xxxxx = enable
// 0 Enable ROMCS# at C0000 to C7FFF
// xx0xxxxx = disable
// xx1xxxxx = enable

[Break]

--------------------------------------------------------------------

[Extract] [HELP]

The chip is normally forced to the default states on a reset to insure


a known condition. Define the desired register values in your .Job file.
The Register names may be used, as in the following example:

CfgChipData0 = ChipDmaWaitStateControl, 0AAh


CfgChipData1 = ChipPowerManagement, 055h

[Break]

238
Introduction to AutoBios

--------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct ItemList DumpList[] =


{
{ "ChipControlRegister1","", ChipControlRegister1,
SizeIsByte,ChipControlRegister1Default, },
{ "ChipControlRegister2","", ChipControlRegister2,
SizeIsByte,ChipControlRegister2Default, },
{ "ChipShadowRamControlRegister1","", ChipShadowRamControlRegister1,
SizeIsByte,ChipShadowRamControlRegister1Default, },
{ "ChipShadowRamControlRegister2","", ChipShadowRamControlRegister2,
SizeIsByte,ChipShadowRamControlRegister2Default, },
{ "ChipDramControlRegister1","", ChipDramControlRegister1,
SizeIsByte,ChipDramControlRegister1Default, },
{ "ChipDramControlRegister2","", ChipDramControlRegister2,
SizeIsByte,ChipDramControlRegister2Default, },
{ "ChipShadowRamControlRegister3","", ChipShadowRamControlRegister3,
SizeIsByte,ChipShadowRamControlRegister3Default, },
{ "ChipControlRegister3","", ChipControlRegister3,
SizeIsByte,ChipControlRegister3Default, },
{ "ChipNonCacheBlock1Register1","", ChipNonCacheBlock1Register1,
SizeIsByte,ChipNonCacheBlock1Register1Default, },
{ "ChipNonCacheBlock1Register2","", ChipNonCacheBlock1Register2,
SizeIsByte,ChipNonCacheBlock1Register2Default, },
{ "ChipNonCacheBlock2Register1","", ChipNonCacheBlock2Register1,
SizeIsByte,ChipNonCacheBlock2Register1Default, },
{ "ChipNonCacheBlock2Register2","", ChipNonCacheBlock2Register2,
SizeIsByte,ChipNonCacheBlock2Register2Default, },
{ "ChipRomChipSelectRegister3","", ChipRomChipSelectRegister3,
SizeIsByte,ChipRomChipSelectRegister3Default, },
{ "","",0,SizeIsByte,0,}, /* Nul String or Zero Value is End of Table */
};

//---- Chip Specific routine to read a selected register ---


//-------- This routine will vary from chip to chip -----

unsigned ReadChipRegister(unsigned i,unsigned size)


{
outp(ChipRegPort,i);
return(inp(ChipDataPort));
};

[Break]

--------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed

239
The C Programs

; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;========================== OpTi ============================

ChipDefaultTable LABEL WORD

; Reset chip to known default state

DefaultValue ChipControlRegister1,00
DefaultValue ChipControlRegister2,00
DefaultValue ChipShadowRamControlRegister1,84h
DefaultValue ChipShadowRamControlRegister2,00
DefaultValue ChipDramControlRegister1,87h
DefaultValue ChipDramControlRegister2,0f0h
DefaultValue ChipShadowRamControlRegister3,00
DefaultValue ChipControlRegister3,0d1h
DefaultValue ChipNonCacheBlock1Register1,80h
DefaultValue ChipNonCacheBlock1Register2,10h
DefaultValue ChipNonCacheBlock2Register1,80h
DefaultValue ChipNonCacheBlock2Register2,10h
DefaultValue ChipRomChipSelectRegister3,00

; Now offer the opportunity to set-up the chip

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

240
Introduction to AutoBios

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

DefaultValue -1,-1 ; -1 Arguments indicate End of Table

ChipHook1 LABEL NEAR


mov si,offset ChipDefaultTable
.WHILE 1
lods WORD PTR cs:[si]
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
lods WORD PTR cs:[si]
mov dx,ChipDataPort
jmp $+2 ; added delay
out dx,al
.ENDW
jmp NEAR PTR ResumeChipHook1

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

----------------------------------------------------------------------

[Extract] [C]

// The 82C499 automatically intercepts these internally

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned Results = False;
return(Results);
};

241
The C Programs

[Break]

242
Introduction to AutoBios

4.3.3.11 SunTac
[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] SunTac Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] SUNTAC.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize an LSI chip set


[Description] with a default personality, if desired.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipRegPort 0xec


#define ChipDataPort 0xed

[Break]

--------------------------------------------------------------------

[Extract] [C]

unsigned ReadChipRegister(unsigned q)
{
return(q);
};

[Break]

------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR

243
The C Programs

jmp NEAR PTR ResumeResetHook

;--- This macro is used to simplify typing in the desired values ---

DefaultValue macro chipreg,chipval


WORD chipreg
WORD chipval
endm

;================== SUNTAC ====================

ChipDefaultTable LABEL BYTE

; DefaultValue 00h,20h ; Meaning depends on chip being loaded


; DefaultValue 02h,0f1h
; DefaultValue 04h,11h
; DefaultValue 06h,08h
; DefaultValue 07h,40h
DefaultValue 0ffh,0ffh ; -1 Arguments indicate End of Table

ChipHook1 LABEL NEAR


mov si,offset ChipDefaultTable
.WHILE 1
lods WORD PTR cs:[si]
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ChipRegPort
xchg ah,al
jmp $+2 ; added delay
out dx,al ; set register address
mov dx,ChipDataPort
xchg ah,al
jmp $+2 ; added delay
out dx,al
.ENDW
jmp NEAR PTR ResumeChipHook1

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

-------------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{

244
Introduction to AutoBios

case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

245
Introduction to AutoBios

4.3.3.12 UMC 481 - 482


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] UMC 481/482 Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] UMC481_2.CHP

[File Status]

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize UMC 481/482 Chips.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

//--- Definition of Registers ----------

#define ChipRegPort 0x22


#define ChipDataPort 0x24

#define FastA20Port 0x92


#define FastA20Bit 0x02

#define FastResetPort 0x92


#define FastResetBit 0x01

// 82C482A Registers
#define RevisionReg 0x80
#define RevisionRegDefault 0x80
// Read Only

#define ControlRegA 0x81


#define ControlRegADefault 0x00
// Bit Description
// 7-6 CPU Clock Selection
// ; 0 0 = CKOUT = CKIN
// ; 0 1 = CKOUT = CKIN/2
// ; 1 0 = CKOUT = CKIN/3
// ; 1 1 = CKOUT = CKIN/4
// ; 5 = Keyboard Clock Selection

247
The C Programs

// ; 0 = KBCLK = OSC14/2
// ; 1 = KBCLK is defined by Bits 7-6 of ControlRegB
// ; 4 = DMA address/data hold time
// ; 0 1-2 T-state
// ; 1 2-3 T-state
// ; 3 = Turbo Pin - Read Only
// ; 1 = high speed
// ; 0 = low speed
// ; 2-0 = AT bus clock selection
// ; For 386 mode
// ; 0 0 0 ATCLK = CLK2/12
// ; 0 0 1 ATCLK = CLK2/10
// ; 0 1 0 ATCLK = CLK2/8
// ; 0 1 1 ATCLK = CLK2/6
// ; 1 X 0 ATCLK = CLK2/4
// ; 1 0 X ATCLK = CLK2/4
// ; 1 1 1 ATCLK = CLK2/16
// ;
// ; For 486 mode
// ; 0 0 0 ATCLK = CLK2/6
// ; 0 0 1 ATCLK = CLK2/5
// ; 0 1 0 ATCLK = CLK2/4
// ; 0 1 1 ATCLK = CLK2/3
// ; 1 X 0 ATCLK = CLK2/2
// ; 1 0 X ATCLK = CLK2/2
// ; 1 1 1 ATCLK = CLK2/8
//
#define ControlRegB 0x82
#define ControlRegBDefault 0x00
// ; Default = 00h
// ; 7-6 = Keyboard Clock Selection
// ; For 386 mode
// ; 0 0 KBCLK = CLK2/12
// ; 0 1 KBCLK = CLK2/8
// ; 1 0 KBCLK = CLK2/6
// ; 1 1 KBCLK = CLK2/4
// ; For 486 mode
// ; 0 0 KBCLK = CLK2/6
// ; 0 1 KBCLK = CLK2/4
// ; 1 0 KBCLK = CLK2/3
// ; 1 1 KBCLK = CLK2/2
// ; 5 = Flush 486 internal cache
// ; 1 = PFLUSH# is active to flush 486 internal cache
// ; 4-3 = Turbo function slection
// ; 0 0 Same as 82C482 (CLKOUT = CKIN)
// ; 0 1 CKOUT = CKIN/2
// ; 1 X controlled by 8742
// ; 2 = LOWA20# selection
// ; 0 LOWA20# control from 8742
// ; 1 LOWA20# from chipset
// ; 1-0 = I/O Command recovery time
// ; 0 0 - 2 BCLK
// ; 0 1 - 4 BCLK
// ; 1 0 - 8 BCLK
// ; 1 1 - 12 BCLK
//

248
Introduction to AutoBios

//
// ; 82C481A Registers
#define IdReg 0x90
#define IdRegDefault 0x00
// ; Read Only

#define WaitStateReg 0x91


#define WaitStateRegDefault 0x00
// ; Default = 00h
// ; 7 = Reserved
// ; 6 = Cache Hit Burst Option (valid only for 486)
// ; 0 - fast cache read hit
// ; 1 - normal cache read hit
// ; 5 = reserved
// ; 4 = Cache write hit option (valid only for 486)
// ; 0 - fast cache write hit
// ; 1 - normal cache write hit
// ; 3 = reserved
// ; 2 = DRAM type
// ; 0 - page mode
// ; 1 - fast page mode
// ; 1-0 = DRAM wait states
// ; 0 0 - 2 wait states
// ; 0 1 - reserved
// ; 1 0 - 1 wait state
// ; 1 1 - 0 wait states

#define CacheReg 0x92


#define CacheRegDefault 0x00
// ; Default = 00h
// ; 7 = Non-cacheable Block 2 enable
// ; 0 - disable (cacheable)
// ; 1 - enable (non-cacheable)
// ; 6 = Non-cacheable Block 1 enable
// ; 0 - disable (cacheable)
// ; 1 - enable (non-cacheable)
// ; 5 = Write back enable
// ; 0 - disable write back on any cache read miss
// ; 1 - enable write back on any cache read miss
// ; 4 = reserved
// ; 3 = Cache ram size
// ; 0 - two banks of cache ram (8 pieces)
// ; 1 - one bank of cache ram (4 pieces)
// ; 2-1 = Cache line size (should be 00 if CPU is 486)
// ; 0 0 - 16 bytes
// ; 0 1 - reserved
// ; 1 0 - 8 bytes
// ; 1 1 - 4 bytes
// ; 0 = Cache enable
// ; 0 - disable
// ; 1 - enable

#define TagReg 0x93


#define TagRegDefault 0x00
// ; Default = 00h
// ; 7 = main memory above 16MB cacheability

249
The C Programs

// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 6 = math coprocessor ready delayed by 1 T-state
// ; 0 - delay by 1 T-state
// ; 1 - no delay
// ; 5 = Check ELBA# pin in T1 or T2 state (only for 486)
// ; 0 - check ELBA# signal in T1
// ; 1 - check ELBA# signal in T2
// ; 4-0 = Cache RAM size
// ; 00000 - 1MB
// ; 10000 - 512KB
// ; 11000 - 256KB
// ; 11100 - 128KB
// ; 11110 - 64KB
// ; 11111 - 32KB

#define Block1HighReg 0x94


#define Block1HighRegDefault 0x00
// ; Default = 00h
// ; 7-6 = reserved
// ; 5-0 = NC1A25-NC1A20

#define Block1LowReg 0x95


#define Block1LowRegDefault 0x00
// ; Default = 00h
// ; 7-0 = NC1A19-NC1A12

#define Block1SizeReg 0x96


#define Block1SizeRegDefault 0x00
// ; Default = 00h
// ; 7-0 = MK1A19-MK1A12 - determines size of non-cacheable Block 1
// ; 11111111 - 4KB
// ; 11111110 - 8KB
// ; 11111100 - 16KB
// ; 11111000 - 32KB
// ; 11110000 - 64KB
// ; 11100000 - 128KB
// ; 11000000 - 256KB
// ; 10000000 - 512KB
// ; 00000000 -1024KB

#define Block2HighReg 0x97


#define Block2HighRegDefault 0x00
// ; Default = 00h
// ; 7 = DMA wait state
// ; 0 - no CAS delayed
// ; 1 - CAS delayed by i T-state
// ; 6 = E Segment ROM location
// ; 0 - E segment is on system board
// ; 1 - E segment is on I/O bus
// ; 5-4 = reserved
// ; 3 = SWTRBO# (for 386 only)
// ; 0 - normal
// ; 1 - Softwae non-trubo mode
// ; 2 = FALTH (386 only)
// ; 0 - normal

250
Introduction to AutoBios

// ; 1 - in non-turbo mode force write-back on


// ; every cache read miss
// ; 1-0 = NC2A25-NC2A24
// ; See Block2LowReg

#define Block2LowReg 0x98


#define Block2LowRegDefault 0x00
// ; Default = 00h
// ; 7-0 = NC2A23-NC2A16

#define Block2SizeReg 0x99


#define Block2SizeRegDefault 0x00
// ; Default = 00h
// ; 7-0 = MK2A23-MK2A16 - determines size of non-cacheable Block 2
// ; 11111111 - 64KB
// ; 11111110 - 128KB
// ; 11111100 - 256KB
// ; 11111000 - 512KB
// ; 11110000 - 1MB
// ; 11100000 - 2MB
// ; 11000000 - 4MB
// ; 10000000 - 8MB
// ; 00000000 - 16MB

#define DramReg 0x9a


#define DramRegDefault 0x01
// ; Default = 01h
// ; 7-6 = Bank 4
// ; 0 0 - no DRAM installed
// ; 0 1 - 256K
// ; 1 0 - 1M
// ; 1 1 - 4M
// ; 5-4 = Bank 3
// ; 0 0 - no DRAM installed
// ; 0 1 - 256K
// ; 1 0 - 1M
// ; 1 1 - 4M
// ; 3-2 = Bank 2
// ; 0 0 - no DRAM installed
// ; 0 1 - 256K
// ; 1 0 - 1M
// ; 1 1 - 4M
// ; 1-0 = Bank 1
// ; 0 0 - no DRAM installed
// ; 0 1 - 256K
// ; 1 0 - 1M
// ; 1 1 - 4M

#define SegmentReg 0x9b


#define SegmentRegDefault 0x00
// ; Default = 00h
// ; 7-6 = Hidden memory remapping
// ; 0 0 - no remapping
// ; 0 1 - 256K (A-E segments) remapped to top of system memory
// ; 1 0 - 384K (A-F segments) remapped to top of system memory
// ; 1 1 - reserved

251
The C Programs

// ; 5 = E segment cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 4 = Shadow ram for E segment
// ; 0 - ROM
// ; 1 - shadow RAM
// ; 3 = write protect E segment
// ; 0 - not write protected
// ; 1 - write protected
// ; 2 = F segment cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 1 = Shadow ram for F segment
// ; 0 - ROM
// ; 1 - shadow RAM
// ; 0 = write protect F segment
// ; 0 - not write protected
// ; 1 - write protected

#define SegmentCacheReg 0x9c


#define SegmentCacheRegDefault 0x00
// ; Default = 00h
// ; 7 = 000DC000-000DFFFF region cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 6 = 000D8000-000DBFFF region cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 5 = 000D4000-000D7FFF region cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 4 = 000D0000-000DFFFF region cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 3 = 000CC000-000CFFFF region cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 2 = 000C8000-000CBFFF region cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 1 = 000C4000-000C7FFF region cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable
// ; 0 = 000C0000-000C3FFF region cacheability
// ; 0 - non-cacheable
// ; 1 - cacheable

#define SegmentShadowReg 0x9d


#define SegmentShadowRegDefault 0x00
// ; Default = 00h
// ; 7 = Shadow RAM for 000DC000-000DFFFF region
// ; 0 - ROM
// ; 1 - Shadow RAM
// ; 6 = Shadow RAM for 000D8000-000DBFFF region
// ; 0 - ROM
// ; 1 - Shadow RAM

252
Introduction to AutoBios

// ; 5 = Shadow RAM for 000D4000-000D7FFF region


// ; 0 - ROM
// ; 1 - Shadow RAM
// ; 4 = Shadow RAM for 000D0000-000D3FFF region
// ; 0 - ROM
// ; 1 - Shadow RAM
// ; 3 = Shadow RAM for 000CC000-000CFFFF region
// ; 0 - ROM
// ; 1 - Shadow RAM
// ; 2 = Shadow RAM for 000C8000-000CBFFF region
// ; 0 - ROM
// ; 1 - Shadow RAM
// ; 1 = Shadow RAM for 000C4000-000C7FFF region
// ; 0 - ROM
// ; 1 - Shadow RAM
// ; 0 = Shadow RAM for 000C0000-000C3FFF region
// ; 0 - ROM
// ; 1 - Shadow RAM

#define SegmentWriteReg 0x9e


#define SegmentWriteRegDefault 0x00

// ; Default = 00h
// ; 7 = Write Protect for 000DC000-000DFFFF region
// ; 0 - not write protected
// ; 1 - write protected
// ; 6 = Write Protect for 000D8000-000DBFFF region
// ; 0 - not write protected
// ; 1 - write protected
// ; 5 = Write Protect for 000D4000-000D7FFF region
// ; 0 - not write protected
// ; 1 - write protected
// ; 4 = Write Protect for 000D0000-000D3FFF region
// ; 0 - not write protected
// ; 1 - write protected
// ; 3 = Write Protect for 000CC000-000CFFFF region
// ; 0 - not write protected
// ; 1 - write protected
// ; 2 = Write Protect for 000C8000-000CBFFF region
// ; 0 - not write protected
// ; 1 - write protected
// ; 1 = Write Protect for 000C4000-000C7FFF region
// ; 0 - not write protected
// ; 1 - write protected
// ; 0 = Write Protect for 000C0000-000C3FFF region
// ; 0 - not write protected
// ; 1 - write protected

#define DramDetectingReg 0x9f


#define DramDetectingRegDefault 0x01
// ; Default = 01h
// ; 7 = Test - always program to 0 for normal operation
// ; 6 = reserved
// ; 5 = force DRAM column address MA10 high
// ; 0 - normal column address MA10
// ; 1 - column address MA10 = 1

253
The C Programs

// ; 4 = force DRAM column address MA9 high


// ; 0 - normal column address MA9
// ; 1 - column address MA9 = 1
// ; 3 = Map address space of bank 4 to bank 1
// ; 0 - no mapping
// ; 1 - mapping
// ; 2 = Map address space of bank 3 to bank 1
// ; 0 - no mapping
// ; 1 - mapping
// ; 1 = Map address space of bank 2 to bank 1
// ; 0 - no mapping
// ; 1 - mapping
// ; 0 = Map address space of bank 1 to bank 1
// ; 0 - no mapping
// ; 1 - mapping

[Break]

------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct ItemList DumpList[] =


{
{ "RevisionReg","", RevisionReg, SizeIsByte, RevisionRegDefault,
},
{ "ControlRegA","", ControlRegA, SizeIsByte, ControlRegADefault,
},
{ "ControlRegB","", ControlRegB, SizeIsByte, ControlRegBDefault,
},
{ "IdReg","", IdReg, SizeIsByte, IdRegDefault,
},
{ "WaitStateReg","", WaitStateReg, SizeIsByte, WaitStateRegDefault,
},
{ "CacheReg","", CacheReg, SizeIsByte, CacheRegDefault,
},
{ "TagReg","", TagReg, SizeIsByte, TagRegDefault,
},
{ "Block1HighReg","", Block1HighReg, SizeIsByte, Block1HighRegDefault,
},
{ "Block1LowReg","", Block1LowReg, SizeIsByte, Block1LowRegDefault,
},
{ "Block1SizeReg","", Block1SizeReg, SizeIsByte, Block1SizeRegDefault,
},
{ "Block2HighReg","", Block2HighReg, SizeIsByte, Block2HighRegDefault,
},
{ "Block2LowReg","", Block2LowReg, SizeIsByte, Block2LowRegDefault,
},
{ "Block2SizeReg","", Block2SizeReg, SizeIsByte, Block2SizeRegDefault,
},

254
Introduction to AutoBios

{ "DramReg","", DramReg, SizeIsByte, DramRegDefault,


},
{ "SegmentReg","", SegmentReg, SizeIsByte, SegmentRegDefault,
},
{ "SegmentCacheReg","", SegmentCacheReg, SizeIsByte,
SegmentCacheRegDefault, },
{ "SegmentShadowReg","", SegmentShadowReg, SizeIsByte,
SegmentShadowRegDefault, },
{ "SegmentWriteReg","", SegmentWriteReg, SizeIsByte,
SegmentWriteRegDefault, },
{ "DramDetectingReg","", DramDetectingReg, SizeIsByte,
DramDetectingRegDefault, },
{ "","",0,SizeIsByte,0,}, /* Nul String or Zero Value is End of Table */
};

#define ChipID "UMC 481/482"

/*--- Dump The UMC Chip Registers ------*/

unsigned ReadChipRegister(unsigned Reg, unsigned size)


{
outp(ChipRegPort,Reg);
return(inp(ChipDataPort));
}

[Break]

--------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

RegisterValueTable:
; Return all registers to their default values
; This insures a warm boot sees a known state.

DefaultValue ControlRegA,ControlRegADefault
DefaultValue ControlRegB,ControlRegBDefault

; Now load the configuration from the .Job

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

255
The C Programs

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

; End of list
DW -1,-1 ;Indicates end of list

;INITIALIZE CONFIGURATION REGISTERS

ChipHook1 LABEL NEAR


mov si,OFFSET RegisterValueTable ;set start of pointer
.WHILE 1
lods WORD PTR cs:[si] ; move contents to accum.
.BREAK .IF (ax == WORD PTR -1)
out ChipRegPort,al ; INDEX port
lods WORD PTR cs:[si]
out ChipDataPort,al ; DATA associated with this port
.ENDW
jmp NEAR PTR ResumeChipHook1

256
Introduction to AutoBios

;----------- End of init table ---------------

;>>>>>> Note: this is bypassed for now

;SIZE AND CONFIGURE LOCAL MEMORY


;This code will detect what size DRAM (if any) each local memory bank
;contains. This information will then be loaded into RAMCFGx
; to configure the system's local memory size.

; Set all banks to no DRAM, then check bank 3,2,1,0


; Start addresses will set according to sizes found

Simm256 equ 0ah


Simm1024 equ 0ch
Simm4096 equ 0eh

TestPattern label word


WORD 0000eh,000e0h,00e00h,0e000h ; 4 MB patterns
RamPattern label word
WORD 0000eh,0000ch,0000ah,00008h ; bank 0 - table of finds
WORD 000e0h,000c0h,000a0h,00080h ; bank 1 - table of finds
WORD 00e00h,00c00h,00a00h,00800h ; bank 2 - table of finds
WORD 0e000h,0c000h,0a000h,08000h ; bank 3 - table of finds

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2
COMMENT ~
xor dx,dx ; clear accumulator
mov ds,dx ; all memory operations to lower 64k
mov bx,8 ; initialize loop counter for 1 pass/bank
.WHILE (bx != 0)
sub bx,2 ; use bx for a word table Index
mov cx,cs:TestPattern[bx]
mov al,RAMCFG1 ; load ram cfg registers
out ChipRegPort,al
mov al,ch
out ChipDataPort,al
mov al,RAMCFG0
out ChipRegPort,al
mov al,cl
out ChipDataPort,al ; configure current bank to 4Mb DRAMs
mov WORD PTR ds:[00400h],0H ; clear 000200H
mov WORD PTR ds:[00c00h],0H ; clear 000600H
mov WORD PTR ds:[01c00h],0AA55H
; if 256kb DRAMs then written to 00200H
; if 1Mb DRAMs then written to 00600H
; if 4Mb DRAMs then written to 00E00H

mov WORD PTR ds:[0],0 ; clear mdbus of phantom data


shl bx,2 ; rebase Index bx to RamPattern Table
mov ax,cs:RamPattern[bx+6] ; clear result accumulator of any
pattern
.IF (WORD PTR ds:[00400h] == 0AA55h) ; Does the bank have 256kb DRAMs
mov ax,cs:RamPattern[bx+4] ; 256kb pattern

257
The C Programs

.ELSE
.IF (WORD PTR ds:[00c00h] == 0AA55h) ; Does the bank have 1Mb DRAMs
mov ax,cs:RamPattern[bx+2] ; 1Mb pattern
.ELSE
.IF (WORD PTR ds:[01c00h] == 0AA55h) ; Does the bank have 1Mb DRAMs
mov ax,cs:RamPattern[bx] ; 4 Mb pattern
.ENDIF
.ENDIF
.ENDIF
shr bx,2 ; rebase Index bx
or dx,ax ; update current bank
.ENDW ; loop for four banks
mov al,RAMCFG1 ; load ram cfg registers
out ChipRegPort,al
mov al,dh
out ChipDataPort,al
mov al,RAMCFG0
out ChipRegPort,al
mov al,dl
out ChipDataPort,al
~
jmp NEAR PTR ResumeChipHook2

;----------- End of Memory Configuration -----------

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

-----------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};

258
Introduction to AutoBios

break;
break;
};
return(results);
};

[Break]

259
Introduction to AutoBios

4.3.3.13 VLSI 310


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] VLSI 82C310 Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] VLSI310.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize a VLSI 82C310 Chip.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipRegPort = 0ech


#define ChipDataPort = 0edh
[Break]

--------------------------------------------------------------------

[Extract] [C]

unsigned ReadChipRegister(unsigned q)
{
return(q);
};

[Break]

--------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

261
The C Programs

;--- Definition of Registers ----------

RAMMAP equ 03h

;----- old defs -----

FastA20Port equ 092h


FastA20Bit equ 002h

FastResetPort equ 092h


FastResetBit equ 001h

RAMTMG equ 01h


;
RAMCFG0 equ 02h
RAMCFG1 equ 03h
RAMSET equ 04h
NTBREF equ 05h
CLKCTL equ 06h
MISCSET equ 07h
; Bit 3 CEN Cache Enable
; 0 = Primary cache disabled
; 1 = Primary cache selectively enable by PMR's,
; Segment Registers, and Address Decoder.
; Default = 0
DMACTL equ 08h
BUSCTL equ 0fh
; Bit 6 10/16 IO Address Decode
; 0 = 16 bit address decode (default)
; 1 = 10 bit address decode

FBCR equ 0bh


ROMSET equ 0ch

; Shadow Ram Segment Control Registers


; 7-6 5-4 3-2 1-0
; 00 = read/write slot bus (default)
; 01 = setup mode: read slot bus, write system board
; 10 = shadow mode mode: read system board, write slot bus
; 11 = read/write system board
AAXS equ 0dh
; AC000 A8000 A4000 A0000
BAXS equ 0eh
; BC000 B8000 B4000 B0000
CAXS equ 0fh
; CC000 C8000 C4000 C0000
DAXS equ 10h
; DC000 D8000 D4000 D0000
EAXS equ 11h
; EC000 E8000 E4000 E0000
FAXS equ 12h
; FC000 F8000 F4000 F0000

; Segment Cacheability Registers


; 7-6 5-4 3-2 1-0
; 00 = not write protected, cacheable

262
Introduction to AutoBios

; 01 = not write protected, not cacheable


; 10 = write protected, cacheable
; 11 = write protected, not cacheable
ACBL equ 13h
; AC000 A8000 A4000 A0000
BCBL equ 14h
; BC000 B8000 B4000 B0000
CCBL equ 15h
; CC000 C8000 C4000 C0000
DCBL equ 16h
; DC000 D8000 D4000 D0000
ECBL equ 17h
; EC000 E8000 E4000 E0000
FCBL equ 18h
; FC000 F8000 F4000 F0000

; Prgrammed memory region register format


PMRA1 equ 20h
; 7 6 5 - 0
; LBA_ISA NCBL AX5-AX0
PMRE1 equ 21h
; 7 - 0
; RE7- RE0
PMRA2 equ 22h
; 7 6 5 - 0
; LBA_ISA NCBL AX5-AX0
PMRE2 equ 23h
; 7 - 0
; RE7- RE0

RegisterValueTable:
; Return all registers to their default values
; This insures a warm boot sees a known state.

; Add Desired values in a continuing table here


; See the VLSI documentation for a register description
;
DB RAMTMG, 056h
; DB RAMCFG0,08ch ; 1 meg simms
; DB RAMCFG0,08ah ; 256 K simms
DB RAMCFG0,088h ; no ram
DB RAMCFG1,088h ; no ram
DB RAMSET, 006h
DB NTBREF, 000h ; changed 11-10-92
DB CLKCTL, 018h
DB MISCSET,069h
DB DMACTL, 038h
DB BUSCTL, 020h
DB FBCR, 000h
DB ROMSET, 009h
DB AAXS, 000h
DB BAXS, 000h
DB CAXS, 000h
DB DAXS, 000h
DB EAXS, 000h

263
The C Programs

DB FAXS, 000h
DB ACBL, 055h
DB BCBL, 055h
DB CCBL, 055h
DB DCBL, 055h
DB ECBL, 055h
DB FCBL, 055h
DB PMRA1, 000h
DB PMRE1, 000h
DB PMRA2, 000h
DB PMRE2, 000h

; End of list
DB 00h,00h ;Indicates end of list

;INITIALIZE CONFIGURATION REGISTERS

ChipHook1 LABEL NEAR


mov si,OFFSET RegisterValueTable ;set start of pointer
.WHILE 1
lods BYTE PTR cs:[si] ; move contents to accum.
.BREAK .IF (al == 0)
out ChipRegPort,al ; INDEX port
lods BYTE PTR cs:[si]
out ChipDataPort,al ; DATA associated with this port
.ENDW
jmp NEAR PTR ResumeChipHook1

;----------- End of init table ---------------

; Prototype memory typing routine for 82C310


; uses MASM 6 .IF-.ELSE-.ENDIF directives, which should be converted
; into conditional jumps with labels for MASM 5.1
; Interleave is done automatically by the chip (so says the spec sheet)
; Actual # of banks loaded will be determined by memory sizing routines.

RAMMAP equ 03h

; Always set to 3 banks, and Simm Type


Simm256 equ 03h
Simm1024 equ 07h
Simm4096 equ 0bh
SimmMixed equ 0fh

ChipHook2 LABEL NEAR


xor ax,ax
mov ds,ax ; all memory operations to lower 64k

mov al,RAMMAP ; load ram cfg register


out ChipRegPort,al
mov al,Simm4096
out ChipDataPort,al

264
Introduction to AutoBios

mov WORD PTR ds:[00200h],0H ; clear 000200H


mov WORD PTR ds:[00600h],0H ; clear 000600H
mov WORD PTR ds:[00e00h],0AA55H
; if 256kb DRAMs then written to 00200H
; if 1Mb DRAMs then written to 00600H
; if 4Mb DRAMs then written to 00E00H
mov WORD PTR ds:[0],0 ; clear mdbus of phantom data
mov ah,3 ; default to mixed type which we will consider invalid.

.IF (WORD PTR ds:[00200h] == 0AA55h) ; Does the bank have 256kb DRAMs
mov ah,Simm256 ; 256kb pattern
.ELSE
.IF (WORD PTR ds:[00600h] == 0AA55h) ; Does the bank have 1Mb DRAMs
mov ah,Simm1024 ; 1Mb pattern
.ELSE
.IF (WORD PTR ds:[00e00h] == 0AA55h) ; Does the bank have 4Mb DRAMs
mov ah,Simm4096 ; 4 Mb pattern
.ENDIF
.ENDIF
.ENDIF

.IF(ah == 3) ; consider this invalid, and default to 256K


mov ah,Simm256
.ENDIF
mov al,RAMMap ; load ram cfg registers
out ChipRegPort,al
mov al,ah
out ChipDataPort,al
jmp NEAR PTR ResumeChipHook2

;----------- End of Memory Configuration -----------

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

---------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};

265
The C Programs

break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

266
Introduction to AutoBios

4.3.3.14 VLSI 315


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] VLSI 82C315 Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 10/05/93

[File Name] VLSI315.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize a VLSI 82C315 Chip.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "VLSI 315 Chip"

#define ChipRegPort 0xec


#define ChipDataPort 0xed

#define FastA20Port 0xee // read = enable A20, write = disable A20


#define FastA20Bit 0x00

#define FastResetPort 0xef // read = reset


#define FastResetBit 0x00

#define CpuSpeedFastPort 0xf4 // write = select fast


#define CpuSpeedSlowPort 0xf5 // write = select slow

//--- Definition of Registers ---

#define VER 0x00


#define VERDefault 0x00
#define SLTPTR 0x02
#define SLTPTRDefault 0xff
#define RAMMAP 0x03
#define RAMMAPDefault 0x00
#define RAMSET 0x05
#define RAMSETDefault 0x00
#define REFCTL 0x06

267
The C Programs

#define REFCTLDefault 0x00


#define CLKCTL 0x07
#define CLKCTLDefault 0x10
#define PMRA2 0x08
#define PMRA2Default 0x00
#define PMRR2 0x09
#define PMRR2Default 0x00
#define MCDCTL 0x0A
#define MCDCTLDefault 0x80
#define ABAXS 0x0E
#define ABAXSDefault 0x00
#define CAXS 0x0F
#define CAXSDefault 0x00
#define DAXS 0x10
#define DAXSDefault 0x00
#define FEAXS 0x11
#define FEAXSDefault 0x00
#define SLPCTL 0x13
#define SLPCTLDefault 0x01
#define MISCSET 0x14
#define MISCSETDefault 0x19
#define ROMDMA 0x15
#define ROMDMADefault 0x28
#define BUSCTL1 0x16
#define BUSCTL1Default 0x00
#define BUSCTL2 0x17
#define BUSCTL2Default 0x00
#define SMICTL 0x18
#define SMICTLDefault 0x20
#define PMRA1 0x19
#define PMRA1Default 0x00
#define PMRR1 0x1A
#define PMRR1Default 0x00
#define RTCLSB 0x1B
#define RTCLSBDefault 0x70
#define RTCMSB 0x1C
#define RTCMSBDefault 0x00
#define KBDCTRL 0x1d
#define KBDCTRLDefault 0xdb
#define SMIMSKA 0x80
#define SMIMSKADefault 0x00
#define SMIMSKB 0x81
#define SMIMSKBDefault 0x00
#define SMISTSA 0x82
#define SMISTSADefault 0x00
#define SMISTSB 0x83
#define SMISTSBDefault 0x00
#define PIO2HI 0x84
#define PIO2HIDefault 0x00
#define PIO2LO 0x85
#define PIO2LODefault 0x00
#define PIO1HI 0x86
#define PIO1HIDefault 0x00
#define PIO1LO 0x87
#define PIO1LODefault 0x00
#define IOTMR 0x8A

268
Introduction to AutoBios

#define IOTMRDefault 0x0f


#define HDTMR 0x8B
#define HDTMRDefault 0x0f
#define FDTMR 0x8C
#define FDTMRDefault 0x0f
#define PIO1TMR 0x8D
#define PIO1TMRDefault 0x0f
#define PIO2TMR 0x8E
#define PIO2TMRDefault 0x0f

[Break]

--------------------------------------------------------------------

[Extract] [C] [DUMP]

struct ItemList DumpList[]=


{
{ "VER"," - Version Register", VER,
SizeIsByte,VERDefault, },
{ "SLTPTR"," - Slot Pointer", SLTPTR,
SizeIsByte,SLTPTRDefault, },
{ "RAMMAP"," - Dram Map Register", RAMMAP,
SizeIsByte,RAMMAPDefault, },
{ "RAMSET"," - Dram Control Register", RAMSET,
SizeIsByte,RAMSETDefault, },
{ "REFCTL"," - Refresh Control Register", REFCTL,
SizeIsByte,REFCTLDefault, },
{ "CLKCTL"," - Clock Control Register", CLKCTL,
SizeIsByte,CLKCTLDefault, },
{ "PMRA1"," - Programmable Local Bus Region 1 Address", PMRA1,
SizeIsByte,PMRA1Default, },
{ "PMRR1"," - Programmable Local Bus Region 1 Range", PMRR1,
SizeIsByte,PMRR1Default, },
{ "MCDCTL"," - Memory Card Control", MCDCTL,
SizeIsByte,MCDCTLDefault, },
{ "ABAXS"," - Segments A,B Shadow Configuration", ABAXS,
SizeIsByte,ABAXSDefault, },
{ "CAXS"," - Segment C Shadow Configuration", CAXS,
SizeIsByte,CAXSDefault, },
{ "DAXS"," - Segment D Shadow Configuration", DAXS,
SizeIsByte,DAXSDefault, },
{ "FEAXS"," - Segments F,E Shadow COnfiguration", FEAXS,
SizeIsByte,FEAXSDefault, },
{ "SLPCTL"," - Sleep Mode Register", SLPCTL,
SizeIsByte,SLPCTLDefault, },
{ "MISCSET"," - Misc. Configuration", MISCSET,
SizeIsByte,MISCSETDefault, },
{ "ROMDMA"," - Extended DMA Configuration", ROMDMA,
SizeIsByte,ROMDMADefault, },
{ "BUSCTL1"," - Bus Control Register 1", BUSCTL1,
SizeIsByte,BUSCTL1Default, },
{ "BUSCTL2"," - Bus Control Register 2", BUSCTL2,
SizeIsByte,BUSCTL2Default, },
{ "SMICTL"," - System Management Interrupt", SMICTL,
SizeIsByte,SMICTLDefault, },

269
The C Programs

{ "PMRA2"," - Programmable Local Bus Region 2 Address", PMRA2,


SizeIsByte,PMRA2Default, },
{ "PMRR2"," - Programmable Local Bus Region 2 Range", PMRR2,
SizeIsByte,PMRR2Default, },
{ "RTCLSB"," - RTC Address LSB", RTCLSB,
SizeIsByte,RTCLSBDefault, },
{ "RTCMSB"," - RTC Address MSB", RTCMSB,
SizeIsByte,RTCMSBDefault, },
{ "KBDCTRL"," - Keyboard Control ", KBDCTRL,
SizeIsByte,KBDCTRLDefault, },
{ "SMIMSKA"," - SMI IO Trap Register A", SMIMSKA,
SizeIsByte,SMIMSKADefault, },
{ "SMIMSKB"," - SMI IO Trap Register B", SMIMSKB,
SizeIsByte,SMIMSKBDefault, },
{ "SMISTSA"," - SMI IO Trap Status Register A", SMISTSA,
SizeIsByte,SMISTSADefault, },
{ "SMISTSB"," - SMI IO Trap Status Register B", SMISTSB,
SizeIsByte,SMISTSBDefault, },
{ "PIO2HI"," - Programmable IO Trap Register 2 High", PIO2HI,
SizeIsByte,PIO2HIDefault, },
{ "PIO2LO"," - Programmable Io Trap Register 2 Low", PIO2LO,
SizeIsByte,PIO2LODefault, },
{ "PIO1HI"," - Programmable IO Trap Register 1 High", PIO1HI,
SizeIsByte,PIO1HIDefault, },
{ "PIO1LO"," - Programmable IO Trap Register 1 Low", PIO1LO,
SizeIsByte,PIO1LODefault, },
{ "IOTMR"," - Timer Register", IOTMR,
SizeIsByte,IOTMRDefault, },
{ "HDTMR"," - Hard Disk Timer", HDTMR,
SizeIsByte,HDTMRDefault, },
{ "FDTMR"," - Floppy Disk Timer", FDTMR,
SizeIsByte,FDTMRDefault, },
{ "PIO1TMR"," - Programmed IO Timer 1", PIO1TMR,
SizeIsByte,PIO1TMRDefault, },
{ "PIO2TMR"," - Programmed IO Timer 1", PIO2TMR,
SizeIsByte,PIO2TMRDefault, },
{ "","",0,SizeIsByte,0,0,},
};

unsigned ReadChipRegister(unsigned i,unsigned size)


{
outp(ChipRegPort,i);
_asm jmp $+2
return(inp(ChipDataPort));
};

[Break]

-------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

270
Introduction to AutoBios

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

ChipDefaultTable LABEL WORD


; Return all registers to their default values
; This insures a warm boot sees a known state.
DefaultValue SLTPTR ,SLTPTRDefault
DefaultValue RAMMAP ,RAMMAPDefault
DefaultValue RAMSET ,RAMSETDefault
DefaultValue REFCTL ,REFCTLDefault
DefaultValue CLKCTL ,CLKCTLDefault
DefaultValue PMRA1 ,PMRA1Default
DefaultValue PMRR1 ,PMRR1Default
DefaultValue MCDCTL ,MCDCTLDefault
DefaultValue ABAXS ,ABAXSDefault
DefaultValue CAXS ,CAXSDefault
DefaultValue DAXS ,DAXSDefault
DefaultValue FEAXS ,FEAXSDefault
DefaultValue SLPCTL ,SLPCTLDefault
DefaultValue MISCSET,MISCSETDefault
DefaultValue ROMDMA ,ROMDMADefault
DefaultValue BUSCTL1,BUSCTL1Default
DefaultValue BUSCTL2,BUSCTL2Default
DefaultValue SMICTL ,SMICTLDefault
DefaultValue PMRA2 ,PMRA2Default
DefaultValue PMRR2 ,PMRR2Default
DefaultValue RTCLSB ,RTCLSBDefault
DefaultValue RTCMSB ,RTCMSBDefault
DefaultValue KBDCTRL,KBDCTRLDefault
DefaultValue IOTMR ,IOTMRDefault
DefaultValue HDTMR ,HDTMRDefault
DefaultValue FDTMR ,FDTMRDefault
DefaultValue PIO1TMR,PIO1TMRDefault
DefaultValue PIO2TMR,PIO2TMRDefault

; Add Desired values in a continuing table here


; See the VLSI documentation for a register description
;
IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2
ENDIF

IFDEF CfgChipData3

271
The C Programs

WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

IFDEF CfgChipData5
WORD CfgChipData5
ENDIF

IFDEF CfgChipData6
WORD CfgChipData6
ENDIF

IFDEF CfgChipData7
WORD CfgChipData7
ENDIF

IFDEF CfgChipData8
WORD CfgChipData8
ENDIF

IFDEF CfgChipData9
WORD CfgChipData9
ENDIF

; End of list
DefaultValue -1,-1 ;Indicates end of list

;INITIALIZE CONFIGURATION REGISTERS

ChipHook1 LABEL NEAR


mov si,OFFSET ChipDefaultTable ;set start of pointer
.WHILE 1
lods WORD PTR cs:[si] ; move contents to accum.
.BREAK .IF (ax == WORD PTR -1)
mov dx,ChipRegPort
jmp $+2 ; added delay
out dx,al ; set register address
lods WORD PTR cs:[si]
mov dx,ChipDataPort
jmp $+2
out dx,al ; write data to register
.ENDW
jmp NEAR PTR ResumeChipHook1

;----------- End of init table ---------------

ChipHook2 LABEL NEAR


; DRAM Sizing would go here.................
jmp NEAR PTR ResumeChipHook2

272
Introduction to AutoBios

;----------- End of Memory Configuration -----------

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

--------------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

273
Introduction to AutoBios

4.3.3.15 VLSI 486


[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] VLSI 82C486 Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] VLSI486.CHP

[File Status] Being Updated

[Language] Mixed MSC8 MASM6.1

[Description] This module is used to Initialize a VLSI 82C486 Chip.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "VLSI 82C486"

#define ChipRegPort 0xec


#define ChipDataPort 0xed

[Break]

-------------------------------------------------------------------

[Extract] [C]

/*--- Dump The VLSI 82C486 Registers ------*/

unsigned ReadChipRegister(unsigned Reg, unsigned size)


{
outp(0xec,Reg);
return(inp(0xed));
};

[Break]

-------------------------------------------------------------------

[Extract] [MASM]

275
The C Programs

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

;--- Definition of Registers ----------

FastA20Port equ 092h


FastA20Bit equ 002h

FastResetPort equ 092h


FastResetBit equ 001h

RAMTMG equ 01h


;
RAMCFG0 equ 02h
RAMCFG1 equ 03h
RAMSET equ 04h
NTBREF equ 05h
CLKCTL equ 06h
MISCSET equ 07h
; Bit 3 CEN Cache Enable
; 0 = Primary cache disabled
; 1 = Primary cache selectively enable by PMR's,
; Segment Registers, and Address Decoder.
; Default = 0
DMACTL equ 08h
BUSCTL equ 0fh
; Bit 6 10/16 IO Address Decode
; 0 = 16 bit address decode (default)
; 1 = 10 bit address decode

FBCR equ 0bh


ROMSET equ 0ch

; Shadow Ram Segment Control Registers


; 7-6 5-4 3-2 1-0
; 00 = read/write slot bus (default)
; 01 = setup mode: read slot bus, write system board
; 10 = shadow mode mode: read system board, write slot bus
; 11 = read/write system board
AAXS equ 0dh
; AC000 A8000 A4000 A0000
BAXS equ 0eh
; BC000 B8000 B4000 B0000
CAXS equ 0fh
; CC000 C8000 C4000 C0000
DAXS equ 10h
; DC000 D8000 D4000 D0000
EAXS equ 11h
; EC000 E8000 E4000 E0000
FAXS equ 12h
; FC000 F8000 F4000 F0000

276
Introduction to AutoBios

; Segment Cacheability Registers


; 7-6 5-4 3-2 1-0
; 00 = not write protected, cacheable
; 01 = not write protected, not cacheable
; 10 = write protected, cacheable
; 11 = write protected, not cacheable
ACBL equ 13h
; AC000 A8000 A4000 A0000
BCBL equ 14h
; BC000 B8000 B4000 B0000
CCBL equ 15h
; CC000 C8000 C4000 C0000
DCBL equ 16h
; DC000 D8000 D4000 D0000
ECBL equ 17h
; EC000 E8000 E4000 E0000
FCBL equ 18h
; FC000 F8000 F4000 F0000

; Prgrammed memory region register format


PMRA1 equ 20h
; 7 6 5 - 0
; LBA_ISA NCBL AX5-AX0
PMRE1 equ 21h
; 7 - 0
; RE7- RE0
PMRA2 equ 22h
; 7 6 5 - 0
; LBA_ISA NCBL AX5-AX0
PMRE2 equ 23h
; 7 - 0
; RE7- RE0

RegisterValueTable:
; Return all registers to their default values
; This insures a warm boot sees a known state.

; Add Desired values in a continuing table here


; See the VLSI documentation for a register description
;
DB RAMTMG, 056h
; DB RAMCFG0,08ch ; 1 meg simms
; DB RAMCFG0,08ah ; 256 K simms
DB RAMCFG0,088h ; no ram
DB RAMCFG1,088h ; no ram
DB RAMSET, 006h
DB NTBREF, 000h ; changed 11-10-92
DB CLKCTL, 018h
DB MISCSET,069h
DB DMACTL, 038h
DB BUSCTL, 020h
DB FBCR, 000h
DB ROMSET, 009h
DB AAXS, 000h
DB BAXS, 000h

277
The C Programs

DB CAXS, 000h
DB DAXS, 000h
DB EAXS, 000h
DB FAXS, 000h
DB ACBL, 055h
DB BCBL, 055h
DB CCBL, 055h
DB DCBL, 055h
DB ECBL, 055h
DB FCBL, 055h
DB PMRA1, 000h
DB PMRE1, 000h
DB PMRA2, 000h
DB PMRE2, 000h

; End of list
DB 00h,00h ;Indicates end of list

;INITIALIZE CONFIGURATION REGISTERS

ChipHook1 LABEL NEAR


mov si,OFFSET RegisterValueTable ;set start of pointer
.WHILE 1
lods BYTE PTR cs:[si] ; move contents to accum.
.BREAK .IF (al == 0)
out ChipRegPort,al ; INDEX port
lods BYTE PTR cs:[si]
out ChipDataPort,al ; DATA associated with this port
.ENDW
jmp NEAR PTR ResumeChipHook1

;----------- End of init table ---------------

;SIZE AND CONFIGURE LOCAL MEMORY


;This code will detect what size DRAM (if any) each local memory bank
;contains. This information will then be loaded into RAMCFGx
; to configure the system's local memory size.

; Set all banks to no DRAM, then check bank 3,2,1,0


; Start addresses will set according to sizes found

Simm256 equ 0ah


Simm1024 equ 0ch
Simm4096 equ 0eh

TestPattern label word


WORD 0000eh,000e0h,00e00h,0e000h ; 4 MB patterns
RamPattern label word
WORD 0000eh,0000ch,0000ah,00008h ; bank 0 - table of finds
WORD 000e0h,000c0h,000a0h,00080h ; bank 1 - table of finds
WORD 00e00h,00c00h,00a00h,00800h ; bank 2 - table of finds

278
Introduction to AutoBios

WORD 0e000h,0c000h,0a000h,08000h ; bank 3 - table of finds

ChipHook2 LABEL NEAR


xor dx,dx ; clear accumulator
mov ds,dx ; all memory operations to lower 64k
mov bx,8 ; initialize loop counter for 1 pass/bank
.WHILE (bx != 0)
sub bx,2 ; use bx for a word table Index
mov cx,cs:TestPattern[bx]
mov al,RAMCFG1 ; load ram cfg registers
out ChipRegPort,al
mov al,ch
out ChipDataPort,al
mov al,RAMCFG0
out ChipRegPort,al
mov al,cl
out ChipDataPort,al ; configure current bank to 4Mb DRAMs
mov WORD PTR ds:[00400h],0H ; clear 000200H
mov WORD PTR ds:[00c00h],0H ; clear 000600H
mov WORD PTR ds:[01c00h],0AA55H
; if 256kb DRAMs then written to 00200H
; if 1Mb DRAMs then written to 00600H
; if 4Mb DRAMs then written to 00E00H

mov WORD PTR ds:[0],0 ; clear mdbus of phantom data


shl bx,2 ; rebase Index bx to RamPattern Table
mov ax,cs:RamPattern[bx+6] ; clear result accumulator of any
pattern
.IF (WORD PTR ds:[00400h] == 0AA55h) ; Does the bank have 256kb DRAMs
mov ax,cs:RamPattern[bx+4] ; 256kb pattern
.ELSE
.IF (WORD PTR ds:[00c00h] == 0AA55h) ; Does the bank have 1Mb DRAMs
mov ax,cs:RamPattern[bx+2] ; 1Mb pattern
.ELSE
.IF (WORD PTR ds:[01c00h] == 0AA55h) ; Does the bank have 1Mb DRAMs
mov ax,cs:RamPattern[bx] ; 4 Mb pattern
.ENDIF
.ENDIF
.ENDIF
shr bx,2 ; rebase Index bx
or dx,ax ; update current bank
.ENDW ; loop for four banks
mov al,RAMCFG1 ; load ram cfg registers
out ChipRegPort,al
mov al,dh
out ChipDataPort,al
mov al,RAMCFG0
out ChipRegPort,al
mov al,dl
out ChipDataPort,al

jmp NEAR PTR ResumeChipHook2

;----------- End of Memory Configuration -----------

279
The C Programs

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

--------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;
break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};
return(results);
};

[Break]

280
Introduction to AutoBios

4.3.3.16 Wildcard
[Extract] [HELP]
***********************************************************************

[Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.

[Product Name] AutoBios

[Module Name] Megatel Wildcard Chip Set Support

[Version] 2.00

[Author] John O. Foster

[Date] 04/11/94

[File Name] Wildcard.CHP

[File Status] Being Updated

[Language] Mixed MSVC 1.0/1.5 MASM6.1x

[Description] This module is used to Initialize the Wildcard chip.

[History] 2.00 04/11/94 Original

**********************************************************************

[Extract] [H]

#define ChipID "Megatel Wildcard"

#define ChipCtrlReg0 0x61


#define ChipCtrlReg0Default 0x30
// Bit Description
// 7 Clear Keyboard Data Register
// 6 Enable Keyboard Clock
// 5 Disable I/O Check
// 4 Disable Parity Check
// 3 Not Used
// 2 Switch Select
// 1 Enable Speaker
// 0 Gate Speaker

#define ChipCtrlReg1 0x62


#define ChipCtrlReg1Default 0x00
//
// WRITE
//
// Bit Description
// 7-6 # of floppies
// 5-4 Not Used
// 3-2 Onboard Memory Size
// 1 8087 installed
// 0 Not Used

281
The C Programs

//
// READ (when Switch Select = 0)
//
// Bit Description
// 7 Parity Check
// 6 I/O Check
// 5-4 Timer 2 Out
// 3 CtrlReg2 bit 7
// 2 CtrlReg2 bit 6
// 1 Video switch 1
// 0 Video switch 0
//
// READ (when Switch Select = 1)
//
// Bit Description
// 7 Parity Check
// 6 I/O Check
// 5-4 Timer 2 Out
// 3 CtrlReg1 bit 3
// 2 CtrlReg1 bit 2
// 1 CtrlReg1 bit 1
// 0 CtrlReg1 bit 0
//
//
//
#define ChipCtrlReg2 0x63
#define ChipCtrlReg2Default 0x01
// Bit Description
// 7 9.54 Mhz
// 6 7.15 Mhz
// 5 Fast Mode
// 4 512K Ram Size (2 banks of 256K Rams)
// 3 Lock Register (bits 0-4)
// 2 256K Ram (1 bank of 256K Rams)
// 1 8087 present (enable 8087 NMI)
// 0 Disable Parity

#define NMIMaskRegister 0xa0


#define NMIMaskRegisterDefault 0x00

[Break]

---------------------------------------------------------------------

[Extract] [C] [DUMP]

//--- This is the code for the standalone ChipDump Utility, and for
//--- the SysVue command to dump the chip registers (if any)
//--- The .EXE for the utility will be the XXXX.Chp filename.

struct ItemList DumpList[] =


{
{ "ChipCtrlReg0","", ChipCtrlReg0,
SizeIsByte,ChipCtrlReg0Default, },

282
Introduction to AutoBios

{ "ChipCtrlReg1","", ChipCtrlReg1,
SizeIsByte,ChipCtrlReg1Default, },
{ "ChipCtrlReg2","", ChipCtrlReg2,
SizeIsByte,ChipCtrlReg2Default, },
{ "","",0,SizeIsByte,0,}, /* Nul String or Zero Value is End of Table */
};

/*--- Read the Acer Chip Register ------*/

unsigned ReadChipRegister(unsigned Reg, unsigned size)


{
return(inp(Reg));
}

[Break]

------------------------------------------------------------------

[Extract] [MASM]

; This is the option point for code that needs to be executed


; immediately after the reset. An example is the C&T F8680.

ResetHook LABEL NEAR


jmp NEAR PTR ResumeResetHook

ChipTable LABEL WORD


;
; * denotes default value
; To insure that the chip is returned to a known state when executing
; a software reset (CTRL-ALT-DEL, for example), the registers are
; explicitly loaded with the power-on values that would exist
; from a cold power-up start.
DefaultValue ChipCtrlReg0,ChipCtrlReg0Default
DefaultValue ChipCtrlReg1,ChipCtrlReg1Default
DefaultValue ChipCtrlReg2,ChipCtrlReg2Default
DefaultValue NMIMaskRegister,NMIMaskRegisterDefault

; Then the desired chip values may be loaded

IFDEF CfgChipData
WORD CfgChipData
ENDIF

IFDEF CfgChipData0
WORD CfgChipData0
ENDIF

IFDEF CfgChipData1
WORD CfgChipData1
ENDIF

IFDEF CfgChipData2
WORD CfgChipData2

283
The C Programs

ENDIF

IFDEF CfgChipData3
WORD CfgChipData3
ENDIF

IFDEF CfgChipData4
WORD CfgChipData4
ENDIF

DefaultValue -1,-1 ; -1 Arguments indicate End of Table

;--------- This is the register load loop --------------------

ChipHook1 LABEL NEAR


mov si,offset ChipTable
.WHILE True
lods WORD PTR cs:[si] ; get the port #
.BREAK .IF (ax == WORD PTR -1) ; Check for teminating code
mov dx,ax
lods WORD PTR cs:[si] ; get the value
out dx,al ; load the value
.ENDW
jmp NEAR PTR ResumeChipHook1

; ---------- no action needed ------------------

ChipHook2 LABEL NEAR


jmp NEAR PTR ResumeChipHook2

ChipHook3 LABEL NEAR


; reserved for activating shadow mem
jmp NEAR PTR ResumeChipHook3

[Break]

-------------------------------------------------------------------------

[Extract] [C]

unsigned ChipFunction(unsigned Function, unsigned Opcode)


{
unsigned results = False;
/* switch(Function)
{
case ChipFastGateA20:
switch (Opcode)
{

};
break;

284
Introduction to AutoBios

break;

case ChipFastResetCPU:
switch (Opcode)
{

};
break;
break;
};*/

return(results);
};

[Break]

285
Introduction to AutoBios

4.4 Platform Definitions


Platform Definition files may be created for each class or type of platform being used. For instance, if
some projects use XT system boards, and others use 386AT system boards, then platform definitions
could be used to specify the majority of options to be selected for each type of board. In these two
families, .Job files can be used to specify minor changes that might be required if system boards varied
from vendor-to-vendor, or when vendor production changes caused boards to be slightly different.
Rather than having to specify many options in each .job file, only the minimum .job file will be required.
4.4.1 The Default Platform
4.4.1.1 The Common Platform Definition
This file is used to provide default definitions for all the Cfg options possible, so should an option be
undefined in a higher-level .Plt or .Job file, options will not be left in an ambiguous state. Notice that
options are enclosed in "If Defined" conditionals, so that higher-level definitions take precedence.
#*************************************************************************
#
# [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Module Name] Common Platform Configuration File
#
# [Version] 3.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] COMMON.PLT
#
# [Description]
#
# This file holds the lowest level of Cfg option definitions.
# The Platform files (XT.plt, AT.plt, AT286.plt, AT386.plt,
# AT486.plt) are used to describe the standard options for
# each platform, and are the middle level cfg definitions.
#
# The highest level of options is the "xxx.job" file, which the
# user can specify the items for a particular Job or Project.
#
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
# [Display] ---------- Primitive Definitions ----------------
# [Display] True = 1
# [Display] False = 0
#
!ifndef True
True = 1

287
The C Programs

!endif

!ifndef False
False = 0
!endif

#----------------------------------------------------------------------
# Default Conditional Configuration Options
#
# The following variables will normally be specifically defined
# in the xxxx.Job file for the particular project. If variables are
# not specified in xxxx.Job, then this file will supply the default
# definitions.

# The philosophy of these flags is that they be defined as either


# True/False, or as a value. The source code modules will then
# report on undefined or mis-spelled variable names.
# This philosophy has not been implemented, but will reduce the
# possibility of un-detected errors in the Bios.
#----------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Project Configuration and Identification Information
# [CfgHelp] You may include a project version number or use the default
# [CfWord] CfgProjectVersion =
# [CfgWordOptions] "Text String"
# [CfgWordDefault] "0.99"
# [CfgWordAsk] "CfgProjectVersion = "
# [CfgWordAnswer]
# [CfgWordOutput] CfgProjectVersion =
#
!ifndef CfgProjectVersion
CfgProjectVersion = "0.99"
!endif
#
# [Cfg#]
# [CfgHelp] You may include a customer identification
# [CfWord] CfgProjectCustomer =
# [CfgWordOptions] "Text String"
# [CfgWordDefault] "Generic"
# [CfgWordAsk] "CfgProjectCustomer = "
# [CfgWordAnswer]
# [CfgWordOutput] CfgProjectCustomer =
# [Cfg#]
#
!ifndef CfgProjectCustomer
CfgProjectCustomer= "Generic"
!endif
#
# [Cfg#]
# [CfgHelp] You may include a project part number
# [CfWord] CfgProjectPartNr =
# [CfgWordOptions] "Text String"
# [CfgWordDefault] "92093000000-00001"
# [CfgWordAsk] "CfgProjectPartNr = "
# [CfgWordAnswer]
# [CfgWordOutput] CfgProjectPartNr =

288
Introduction to AutoBios

# [Cfg#]
#
!ifndef CfgProjectPartNr
CfgProjectPartNr = "92093000000-00001"
!endif
#
# [Cfg#]
# [CfgHelp] You may include a project option string
# [CfWord] CfgProjectOption =
# [CfgWordOptions] "Text String"
# [CfgWordDefault] "None"
# [CfgWordAsk] "CfgProjectOption = "
# [CfgWordAnswer]
# [CfgWordOutput] CfgProjectOption =
# [Cfg#]
#
!ifndef CfgProjectOption
CfgProjectOption = "None"
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Platform Support
# [CfgHelp] Only One of these flags should be defined.
# [CfgHelp] This is the general directive. Specific overrides are
# [CfgHelp] possible (see Keyboard) for some drivers and devices.
# [CfgWord] CfgPlatformAT =
# [CfgWordOptions] True/False
# [CfgWordDefault] False
# [CfgWordAsk] "CfgPlatformAT = "
# [CfgWordAnswer]
# [CfgWordOutput] CfgPlatformAT =
# [Cfg#]
#
!ifndef CfgPlatformAT
CfgPlatformAT = False
!endif

!ifndef CfgPlatformWildcard
CfgPlatformWildcard = False
!endif

# [CfgHelp] This flag is for kb or no-KB. it supports the Intel 386EX


!ifndef CfgKeyboard
CfgKeyboard = True
!endif

#
# [Cfg#]
# [CfgHelp] You may specify a Bios type identification byte
# [CfgWord] CfgTypeByte =
# [CfgWordOptions] 0ffh = PC, 0feh = XT, 0fch = AT
# [CfgWordDefault] 0fch

289
The C Programs

# [Cfg#]
#
!ifndef CfgTypeByte
CfgTypeByte = 0fch
!endif
#
# [Cfg#]
# [CfgHelp] These flags designate the level of code to be generated
# [CfgHelp] by the compiler and assembler
# [CfgHelp] 0 (= 8086/8088), 1 (= 80186/80188),
# [CfgHelp] 2 (= 80286), 3 (= 80386), 4 (= 80486)
# [CfgWord] CfgCompiler =
# [CfgWordOptions] 0, 1, 2, 3
# [CfgWordDefault] 2
# [Cfg#]
#
!ifndef CfgCompiler
CfgCompiler = 2
!endif
#
# [Cfg#]
# [CfgWord] CfgMasm =
# [CfgWordOptions] .86, .186, 286p, .386p
# [CfgWordDefault] .386p
# [Cfg#]
#
!ifndef CfgMasm
CfgMasm = .386p
!endif
#
# [Cfg#]
#----------------------------------------------------------------------------
#
# [Cfg#]
# [CfgHelp] Prom Checksum Selection
# [CfgHelp] Determines whether a Bios checksum test is performed.
# [CfgWord] CfgRomChecksum =
# [CfgWordOptions] True, False
# [CfgWordDefault] True
# [Cfg#]
#
!ifndef CfgRomChecksum
CfgRomChecksum = True
!endif
#
# [Cfg#]
#----------------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Language and Locale Options
# [CfgHelp] These flags may be used to specify default langauge and
# [CfgHelp] locale options.
# [CfgWord] CfgLanguage =
# [CfgWord] CfgLocale =
# [CfgWordOptions]
# [CfgWordDefault] English, US

290
Introduction to AutoBios

!ifndef CfgLanguage
CfgLanguage = "English"
!endif

!ifndef CfgLocale
CfgSubLanguage = "US"
!endif

#----------------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Scratch Ram (Objects) location
# [CfgHelp] System Object (Scratch Ram) absolute location definition.
# [CfgHelp] Caution: The System Object is normally allocated at the top of
# [CfgHelp] the System RAM area (typically 640k). If it is desired to
# [CfgHelp] use a discontiguous area, this flag may be used to specify its
# [CfgHelp] location. For normal use, this flag should be left undefined.
# [CfgHelp] See the following flag definition also.
# [Cfg#]
# [CfgWord] CfgSystemObjectAbsolute =
# [CfgWordOptions] 0xyyyy
# [CfgWordDefault] 0xe000
# [Cfg#]
# Alert: This option not presently available
#CfgSystemObjectAbsolute = 0xe000
#
# [Cfg#]
# [CfgSection] Scratch Ram (Objects) Pointer Location
# [CfgHelp] System Object (Scratch Ram) pointer is normally stored at the
# [CfgHelp] primary location defined below. If the Bios (or a StandAlone)
# [CfgHelp] finds the Primary location is unavailable, then an attempt will
# [CfgHelp] be made to use the alternate location.
# [Cfg#]
# [CfgWord] CfgSysObjectPtrPrimary =
# [CfgWord] CfgSysObjectPtrAlternate =
# [Cfg#]
#
!ifndef CfgSysObjectPtrPrimary
CfgSysObjectPtrPrimary = 0x0000040e
!endif

!ifndef CfgSysObjectPtrAlternate
CfgSysObjectPtrAlternate = 0x000004f0
!endif

# [Cfg#]
#----------------------------------------------------------------------------
# [Cfg#]
# [CfgSection] System Object (Scratch Ram) size definition.
# [CfgHelp] Caution: The System Object Size defaults to 4096 bytes, if this
# [CfgHelp] flag is left undefined. It may be used to specify a the size
# [CfgHelp] of memory assigned to be used for the System Object.
# [CfgHelp] This flag should normally be left undefined.
# [Cfg#]
# [CfgWord] CfgSystemObjectSize =
# [CfgWordOptions] size (multiple of 1024)

291
The C Programs

# [CfgWordDefault] 8192
# [Cfg#]
#
#CfgSystemObjectSize = 8192
#
!ifndef CfgSystemObjectSize
CfgSystemObjectSize = 4096
!endif
#
# [Cfg#]
#-------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Hardware Diagnostics Support
# [CfgHelp] This enables/disables checkpoints.
# [CfgWord] CfgCheckPoint True/False Enables/disables checkpoint support
# [Cfg#]
#
!ifndef CfgCheckPoint
CfgCheckPoint = True
!endif
#
# [Cfg#]
# [CfgHelp] This defines the I/O port address to be used for writing
checkpoint
# [CfgHelp] codes. It is normally 128 (0x80 - 80h).
# [CfgWord] CfgCheckPointPort = I/O port number (expressed in decimal!)
# [Cfg#]
#
!ifndef CfgCheckPointPort
CfgCheckPointPort = 128
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Codeview/Debug Information
# [CfgHelp] This flag may be defined to enable the Codeview Debug
# [CfgHelp] facilities. It includes generating code listings and
# [CfgHelp] CodeView information. To build the release version,
# [CfgHelp] it may be defined False.
# [CfgWord] CfgCodeView = $(True/False)
# [Cfg#]
#
!ifndef CfgCodeView
CfgCodeView = $(False)
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgHelp] This flag may be defined to enable generating Listing files.
# [CfgHelp] To build the release version, it may be defined False.
# [CfgWord] CfgListings = $(True/False)
# [Cfg#]
#
!ifndef CfgListings

292
Introduction to AutoBios

CfgListings = $(True)
!endif
#
#--------------------------------------------------------------------
# [Cfg#]
# [CfgHelp] This flag may be defined True to suppress the normal cold-boot
# [CfgHelp] sign on messages.

!ifndef CfgQuietPost
CfgQuietPost = False
!endif

#--------------------------------------------------------
#
# [Cfg#]
# [CfgHelp] These are the Unexpected Interrupt Handling Options.
# [CfgHelp]
# [CfgWord]
# [Cfg#]
#
!ifndef CfgUnexpecIntHandler
CfgUnexpecIntHandler = True
!endif
#

#
!ifndef CfgUnexpecIntDisplay
CfgUnexpecIntDisplay = True
!endif
#

#
!ifndef CfgUnexpecIntTrap
CfgUnexpecIntTrap = True
!endif
#

#--------------------------------------------------------------------
#--------------------------------------------------------------------
# [Cfg#]
# [CfgHelp] These flags are defined to spcify the console I/O.
# [CfgHelp] The default is defined for KB/Video
# [Cfg#]
#

!ifndef CfgConsoleInKeyboard
CfgConsoleInKeyboard = True
!endif
#

!ifndef CfgConsoleInSerial
CfgConsoleInSerial = False
!endif
#

293
The C Programs

!ifndef CfgConsoleOutVideo
CfgConsoleOutVideo = True
!endif
#

!ifndef CfgConsoleOutSerial
CfgConsoleOutSerial = False
!endif
#

# [Cfg#]
# [CfgHelp] These flags should be defined to redirect SysVue I/O.
# [CfgHelp] The default if not defined is KB/CRT
# [CfgHelp] If defined, the device will be COM1
# [CfgWord] CfgSysVueConsole = False/True
# [Cfg#]
#

!ifndef CfgSysVueConsole
CfgSysVueConsole = False
!endif
#

!ifndef CfgSysVueConsolePort
CfgSysVueConsolePort = 0x3f8
!endif
#

# [CfgHelp] This is the init byte for a comm port setup as in Int 14h
!ifndef CfgSysVueConsoleInit
CfgSysVueConsoleInit = 0xe3
!endif
#
!ifndef CfgSysVueConsoleBaud
CfgSysVueConsoleBaud = 9600
!endif
#

!ifndef CfgSysVueConsoleIRQ
CfgSysVueConsoleIRQ = 3
!endif
#

# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] ANSI Support
# [CfgHelp] This flag may be defined to enable future ANSI support.
# [CfgWord] CfgANSI = False/True
# [Cfg#]
#
!ifndef CfgANSI
CfgANSI = False
!endif
#
# [Cfg#]

294
Introduction to AutoBios

#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Serial Channel Support
# [CfgHelp] This flag should be defined to enable support for COM Ports.
# [Cfg#]
#
!ifndef CfgComm
CfgComm = True
!endif
#
# [Cfg#]
# [CfgHelp] These flags may be used to select/deselect specific opcode
services
# [Cfg#]
#
!ifndef CfgCommOpcodeInit
CfgCommOpcodeInit = True
!endif
#
!ifndef CfgCommOpcodeSend
CfgCommOpcodeSend = True
!endif
#
!ifndef CfgCommOpcodeRx
CfgCommOpcodeRx = True
!endif
#
!ifndef CfgCommOpcodeStatus
CfgCommOpcodeStatus = True
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgHelp] This argument may be used to Initialize the COM ports.
# [CfgHelp] Valid argument are baud rate, # data bits, parity, stop bits.
# [Cfg#]
#
!ifndef CfgComm1Init
CfgComm1Init = 9600,8,N,1
!endif
#
!ifndef CfgComm2Init
CfgComm2Init = 9600,8,N,1
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [CfgHelp] This flag may be specify COM channel device (if not 8250 family)
# [Cfg#]
#
!ifndef CfgComm1Device
CfgComm1Device = 8250
!endif
#
!ifndef CfgComm2Device

295
The C Programs

CfgComm2Device = 8250
!endif
#
#--------------------------------------------------------------------
#
# [CfgHelp] This definition specifies which port to use for virtual
# [CfgHelp] support error reporting port. Normally 0x8e (128+14).
# [CfgHelp] This should NOT be the same as the Checkpoint Port!!!
# [CfgWord] CfgVirtualErrorPort = I/O port number (expressed in decimal!)
# [Cfg#]
#
!ifndef CfgVirtualErrorPort
CfgVirtualErrorPort = 142
!endif
#
# [Cfg#]
# [CfgHelp] This flag specifies whether the full extended memory test
# [CfgHelp] should be performed. A short extended memory sizing routine
# [CfgHelp] only can be run, which will check the last location in each
# [CfgHelp] 64K memory block.
# [CfgWord] CfgVirtualErrorPort = I/O port number (expressed in decimal!)
# [Cfg#]
#
!ifndef CfgVirtualFullTest
CfgVirtualFullTest = False
!endif
#

#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] CMOS Memory Support
# [CfgHelp] Summary of AT CMOS Memory definitions
# [CfgHelp] Real time clock is BCD values in locations 00-0D.
# [CfgHelp] 00 Seconds
# [CfgHelp] 01 Seconds Alarm
# [CfgHelp] 02 Minutes
# [CfgHelp] 03 Minutes Alarm
# [CfgHelp] 04 Hours
# [CfgHelp] 05 Hours Alarm
# [CfgHelp] 06 Day of Week
# [CfgHelp] 07 Day of Month
# [CfgHelp] 08 Month
# [CfgHelp] 09 Year
# [CfgHelp]
# [CfgHelp] 0A Bit 7 - Update in Progress
# [CfgHelp]
# [CfgHelp] 0E is the Diagnostic Status Byte:
# [CfgHelp] Bit 7 - Chip lost power
# [CfgHelp] Bit 6 - Bad checksum
# [CfgHelp] Bit 5 - Bad configuration byte
# [CfgHelp] Bit 4 - Bad memory size
# [CfgHelp] Bit 3 - Bad hard disk byte
# [CfgHelp] Bit 2 - Bad time of day
# [CfgHelp]
# [CfgHelp] 0F is the restart status byte. It is loaded before
# [CfgHelp] doing a re-start of the 80286, such as when

296
Introduction to AutoBios

# [CfgHelp] returning from protected mode.


# [CfgHelp]
# [CfgHelp] 10 designates the floppy disk drive type:
# [CfgHelp] Bits 7-4 Drive A:
# [CfgHelp] Bits 3-0 Drive B:
# [CfgHelp] 0 No drive
# [CfgHelp] 1 360K drive
# [CfgHelp] 2 1.2 MB drive
# [CfgHelp] 3 720K drive
# [CfgHelp] 4 1.44 MB drive
# [CfgHelp]
# [CfgHelp] 12 is the hard disk drive type:
# [CfgHelp] Bits 7-4 1st Hard Drive
# [CfgHelp] Bits 3-0 2nd Hard Drive
# [CfgHelp] 0 No drive
# [CfgHelp] 1-E Type 1-15
# [CfgHelp] F Use contents of byte 19 or 1A.
# [CfgHelp]
# [CfgHelp]
# [CfgHelp] 14 is the equipment byte:
# [CfgHelp] Bits 7-6: 00 = 1 Floppy
# [CfgHelp] 01 2 Floppies
# [CfgHelp] 10 3 Floppies (AT BiosKit)
# [CfgHelp] 11 4 Floppies (AT BiosKit)
# [CfgHelp] Bits 5-4: 00 = EGA/VGA
# [CfgHelp] 01 CGA 40 x 25
# [CfgHelp] 10 CGA 80 x 25
# [CfgHelp] 11 MDA
# [CfgHelp]
# [CfgHelp] Bit 1: 80287 installed
# [CfgHelp] Bit 0: Floppy drive(s) present
# [CfgHelp]
# [CfgHelp] 15-16 are the memory size below 1MB
# [CfgHelp] (preset by setup program)
# [CfgHelp] 17-18 are the memory size above 1MB
# [CfgHelp] (preset by setup program)
# [CfgHelp]
# [CfgHelp] 19 1st Hard Disk type when 12(Bits 7-4) = type F
# [CfgHelp]
# [CfgHelp] 1A 2nd Hard Disk type when 12(Bits 3-0) = type F
# [CfgHelp]
# [CfgHelp] 2E-2F are the checksum for bytes 10-2D.
# [CfgHelp]
# [CfgHelp] 30-31 indicate the memory size above 1MB as
# [CfgHelp] determined by power-up routines.
# [CfgHelp]
# [CfgHelp] 32 is the BCD century byte
# [CfgHelp]
# [CfgHelp] 33 indicates the power-on information flags:
# [CfgHelp] Bit 7 Top 128K of RAM is installed (shadow
# [CfgHelp] RAM is available).
# [CfgHelp] Bit 6 First bootup after running setup
# [CfgHelp] routine.
# [CfgHelp]
# [CfgHelp] To read or write to the AT's CMOS memory:
# [CfgHelp] Output cell address to I/O port 70.

297
The C Programs

# [CfgHelp] Read/Write data from/to I/O port 71.


# [Cfg#]
# [Cfg#]
# [CfgHelp] This flag may be defined to enable support for AT CMOS memory.
# [Cfg#]
#
!ifndef CfgCmos
CfgCmos = True
!endif

# [Cfg#] True if a CMos Clock/Calendar is in System


!ifndef CfgCmosClock
CfgCmosClock = True
!endif

#
# [Cfg#]
# [CfgHelp] This flag may be defined to force loading AT CMOS values at power-
on.
# [Cfg#]
#
!ifndef CfgCmosInit
CfgCmosInit = False
!endif
#
!ifndef CfgCmosInitIfBadChecksum
CfgCmosInitIfBadChecksum = True
!endif
#
!ifndef CfgCmosInitIfBadBattery
CfgCmosInitIfBadBattery = True
!endif
#
# [Cfg#]
# [CfgHelp] This flag causes (if CfgCmosInit is defined) the Cmos to be
# [CfgHelp] reloaded on every power-up. Otherwise Cmos will be reloaded
# [CfgHelp] only when the power is lost.
# [Cfg#]
#
!ifndef CfgCmosInitAlways
CfgCmosInitAlways = False
!endif
#
# [Cfg#]
# [CfgHelp] These equates are used to specify the Cmos address and data ports
# [CfgHelp] if they are not located at the default 70,71 hex. Specify Values
# [CfgHelp] in decimal !!
# [Cfg#]
#
#!ifndef CfgCmosRegPort
#CfgCmosRegPort = 112
#!endif
#
#!ifndef CfgCmosDataPort
#CfgCmosDataPort = 113
#!endif

298
Introduction to AutoBios

#
# [Cfg#]
# [CfgHelp] This string may be used to define the initialization Index,Data
# [CfgHelp] if CfgCmosInit is defined.
# [CfgHelp] The 1st value is the cmos register, the 2nd is the value to
load......
# [Cfg#]
#
!ifndef CfgCmosData
#CfgCmosData = 10h,40h,14h,31h
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Video Support
# [CfgHelp] This flag may be defined to configure support for a Video DIsplay.
# [CfgHelp] Video sub-functions and modes may be enabled selectively.
# [CfgHelp] Not all of these flags are implemented
# [Cfg#]
#
!ifndef CfgVideo
CfgVideo = True
!endif
#
!ifndef CfgVideoAll
CfgVideoAll = True
!endif
#
#CfgVideoMono =
#CfgVideoCGA =
#CfgVideoText =
#CfgVideoGraf =
#
# [Cfg#]
# [CfgHelp] If Video is enabled, and All modes are specified, all flags are
enabled.
# [Cfg#]
#
!ifndef CfgVideo
!ifndef CfgVideoAll
CfgVideoMono = True
CfgVideoCGA = True
CfgVideoText = True
CfgVideoGraf = True
!endif
!endif
#

!ifndef CfgVideoGraf
CfgVideoGraf = True
!endif

!ifndef CfgVideoMono
CfgVideoMono = True
!endif

299
The C Programs

!ifndef CfgVideoText
CfgVideoText = True
!endif

!ifndef CfgVideoCGA
CfgVideoCGA = True
!endif

# [Cfg#]
# [CfgHelp] These flags define 2 possible romscan areas for VGA adapters.
# [CfgHelp] If undefined C000-C800 will be used for default.
# [Cfg#]
#
!ifndef CfgVideoPrimaryVGAStart
CfgVideoPrimaryVGAStart = 0xc000
!endif
#
!ifndef CfgVideoPrimaryVGAEnd
CfgVideoPrimaryVGAEnd = 0xc7ff
!endif
#
!ifndef CfgVideoSecondaryVGAStart
CfgVideoSecondaryVGAStart = 0
!endif
#
!ifndef CfgVideoSecondaryVGAEnd
CfgVideoSecondaryVGAEnd = 0
!endif

# If you want to clear the screen on setup, set this flag to true
# this allows you to clear a VGA bios ID string on power-up
!ifndef CfgVideoClearScreen
CfgVideoClearScreen = False
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Memory Configuration
# [CfgHelp] This flag may be defined to define the Maximum Ram in the system.
# [CfgHelp] If not defined, 640K will be used as the default.
# [CfgHelp] Use this only if your Max DRAM is less than 640K.
# [Cfg#]
#
!ifndef CfgMaxMem
CfgMaxMem = 640
!endif
#
# [Cfg#]
#------------------------------------------------------------------
# [CfgHelp] These variables deal with the granularity and the range of
# [CfgHelp] the memory test used for the system ram area
# [CfgHelp] Some platforms may not have stable patterns available in
# [CfgHelp] the bios area for the mem test. Some examples: The V25
# [CfgHelp] reads a byte ptr to the register area at f000:ffff.

300
Introduction to AutoBios

# [CfgHelp] The F8680 updates locations in the shadowed superstate area.


# [Cfg#]
#
!ifndef CfgExtMem
CfgExtMem = 15360
!endif

!ifndef CfgMemTestGranularity
CfgMemTestGranularity = 64
!endif
#
!ifndef CfgMemTestPatternBias
CfgMemTestPatternBias = 0
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Print Screen Support
# [CfgHelp] This flag may be defined to enable the PrintScreen Function.
# [Cfg#]
#
!ifndef CfgPrintScreen
CfgPrintScreen = True
!endif
#
# [Cfg#]
# This flag will enable the print screen key to generate an Int 5
# if set true (normal condition).
!ifndef CfgEnableKeyPrintScreen
CfgEnableKeyPrintScreen = True
!endif
#
# This flag will enable/disable the CtrlAltDel key to generate a reboot
#
!ifndef CfgEnableKeyCtrlAltDel
CfgEnableKeyCtrlAltDel = True
!endif

# This flag will enable/disable the VtrlBreak key from generating


# an Int 1B
!ifndef CfgEnableKeyCtrlBreak
CfgEnableKeyCtrlBreak = True
!endif

!ifndef CfgEnableKeySysReq
CfgEnableKeySysReq = True
!endif

# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Keyboard Support
# [CfgHelp] These are override flags for the Keyboard Driver.
# [CfgHelp] If they are left undefined (the normal case), the keyboard

301
The C Programs

# [CfgHelp] will follow the paltform definition.


# [CfgHelp] If one (and ONLY one) is defined, then that will force
# [CfgHelp] the keyboard definition.
# [Cfg#]
#
!ifndef CfgKeyboard
CfgKeyboard = True
!endif
#
!ifndef CfgKeyboardStyleAT
CfgKeyboardStyleAT = False
!endif
#
# [Cfg#]
# [CfgHelp] Some platforms may use a generic or dissimilar keyboard.
# [CfgHelp] The AMD286LX is one which offers a choice.
# [Cfg#]

# [Cfg#]
# [CfgHelp] This flag can specify whether to include the Keyboard
# [CfgHelp] Intercpet Function (Int 15, Fun 4F) or not. This is a
# [CfgHelp] normal AT class function.
# [Cfg#]

!ifndef CfgKeyboardIntercept
CfgKeyboardIntercept = True
!endif

# [Cfg#]
# [CfgHelp] This flag specifies whether to wait for a response code to
# [CfgHelp] the keyboard reset. This may take up to 400 milliseconds
# [CfgHelp] if a keyboard is not present.
# [Cfg#]

#ifndef CfgKeyboardResetTest
CfgKeyboardResetTest = False
#endif

#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Printer Support
# This flag should be defined to enable support for LPT 1,2,3.
# [Cfg#]
#
!ifndef CfgLPT
CfgLPT = True
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] System Services Support
# [CfgHelp] This flag should be defined to enable support for Cassette
functions.
# [Cfg#]

302
Introduction to AutoBios

#
!ifndef CfgSysSrv
CfgSysSrv = True
!endif
#
!ifndef CfgSysSrvCassetteMotorOn
CfgSysSrvCassetteMotorOn = False
!endif
#
!ifndef CfgSysSrvCassetteMotorOff
CfgSysSrvCassetteMotorOff = False
!endif
#
!ifndef CfgSysSrvCassetteRead
CfgSysSrvCassetteRead = False
!endif
#
!ifndef CfgSysSrvCassetteWrite
CfgSysSrvCassetteWrite = False
!endif
#
!ifndef CfgSysSrvKeyboardIntercept
CfgSysSrvKeyboardIntercept = True
!endif
#
!ifndef CfgSysSrvDeviceOpen
CfgSysSrvDeviceOpen = True
!endif
#
!ifndef CfgSysSrvDeviceClose
CfgSysSrvDeviceClose = True
!endif
#
!ifndef CfgSysSrvProgramTerminate
CfgSysSrvProgramTerminate = True
!endif
#
!ifndef CfgSysSrvEventWait
CfgSysSrvEventWait = True
!endif
#
!ifndef CfgSysSrvJoystick
CfgSysSrvJoystick = True
!endif
#
!ifndef CfgSysSrvSysReqKey
CfgSysSrvSysReqKey = True
!endif
#
!ifndef CfgSysSrvWait
CfgSysSrvWait = True
!endif
#
!ifndef CfgSysSrvMoveBlock
CfgSysSrvMoveBlock = True
!endif

303
The C Programs

#
!ifndef CfgSysSrvGetExtendedMemorySize
CfgSysSrvGetExtendedMemorySize = True
!endif
#
!ifndef CfgSysSrvSwitchToProtectedMode
CfgSysSrvSwitchToProtectedMode = True
!endif
#
!ifndef CfgSysSrvDeviceBusy
CfgSysSrvDeviceBusy = True
!endif
#
!ifndef CfgSysSrvInterruptComplete
CfgSysSrvInterruptComplete = True
!endif
#
!ifndef CfgSysSrvGetSystemConfigParms
CfgSysSrvGetSystemConfigParms = True
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Floppy Disk Support
# [CfgHelp] These flags may be used to define the diskette support desired.
# [CfgWord] CfgDisk True/False Enables/disables floppy disk support
# [Cfg#]
#
!ifndef CfgDisk
CfgDisk = True
!endif
#
# [Cfg#]
# [CfgHelp] These flags may be used to specify the default drive types.
# [CfgWord] CfgDisk1Type 360/720/1200/1440 Specifies type of drive A:
# [Cfg#]
#
!ifndef CfgDisk1Type
CfgDisk1Type = 0
!endif
#
# [Cfg#]
# [CfgWord] CfgDisk1Type 360/720/1200/1440 Specifies type of drive B:
# [Cfg#]
#
!ifndef CfgDisk2Type
CfgDisk2Type = 0
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [CfgHelp] This flag may be used to specify a non-twisted cable
# [CfgHelp] for the floppy drives
# [CfgWord] CfgDiskCableSwap True/False Specifies normal/straight cable
# [Cfg#]

304
Introduction to AutoBios

#
!ifndef CfgDiskCableSwap
CfgDiskCableSwap = False
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Hard Disk Support
# [CfgHelp] This flag may be defined to enable hard disk support for AT's.
# [CfgWord] CfgHard True/False Enables/disables hard disk support
# [Cfg#]
#
!ifndef CfgHard
CfgHard = False
!endif
#
# [Cfg#]
# [CfgHelp] These may be defined to specify the default hard drive types.
# [CfgHelp] CfgInitCMOS must be defined to process these drive types.
# [CfgWord] CfgHard1Type = drive type #
# [CfgWord] CfgHard2Type = drive type #
# [Cfg#]
#
#CfgHard1Type = 47
#
# [Cfg#]
#
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Rom Scan Support
# [CfgHelp] This Flag should be defined if you wish to perform the RomScan.
# [Cfg#]
#
!ifndef CfgRomScanEnable
CfgRomScanEnable = True
!endif
#
# [Cfg#]
# [CfgHelp] If the RomScan is enabled, you may specify whether the scan
# [CfgHelp] will occur on the normal IBM compatible 2K boundaries, or
# [CfgHelp] on 512 byte boundaries.
# [CfgHelp] If the value is undefined, the default is 2048 byte multiples.
# [Cfg#]
#
!ifndef CfgRomScanBoundaries
CfgRomScanBoundaries = 2048
!endif
#
# [Cfg#]
# [CfgHelp] These flags may be used to define non-standard romscan areas.
# [CfgHelp] If undefined, the default is C800 - Start-of-Bios.
# [CfgHelp] See CfgVideo options for complementary functions.
# [Cfg#]
#
!ifndef CfgRomScanPrimaryStart

305
The C Programs

CfgRomScanPrimaryStart = 0xc800
!endif
#
!ifndef CfgRomScanPrimaryEnd
CfgRomScanPrimaryEnd = 0xe000
!endif
#
!ifndef CfgRomScanSecondaryStart
CfgRomScanSecondaryStart = 0x0000
!endif
#
!ifndef CfgRomScanSecondaryEnd
CfgRomScanSecondaryEnd = 0x0000
!endif
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Boot Options Support
# [CfgHelp] This Value may be defined if you wish to boot to SysVue BEFORE
# [CfgHelp] booting to disk. Normally SysVue will boot after the Disk boot
# [CfgHelp] fails. In either case, the "EXIT" command of SysVue will try
# [CfgHelp] another boot sequence again.
# [Cfg#]
#
!ifndef CfgBootSysVue
CfgBootSysVue = False
!endif
#
# [CfgHelp] This flag may be used if you want to include your own
# [CfgHelp] boot routine. This may transfer control to a hard-coded
# [CfgHelp] routine at a specific location.
#
CfgBootUser = False
CfgBootUserLocation = 0e0001234
#
# [CfgHelp] If you are using a disk-based boot, this flag may be used to
# [CfgHelp] specify the order of devices; i.e.; A: then C:, C: then A:. etc.
# [CfgHelp] This Value may be defined if you wish select one of four possible
# [CfgHelp] orders of booting.
# [Boot]
# The default CfgBootOrder = 0 is A:, C: if left undefined.
# CfgBootOrder = 1 is C:, A:
# CfgBootOrder = 2 is A:
# CfgBootOrder = 3 id C:
#
#
!ifndef CfgBootOrder
CfgBootOrder = 0
!endif
#
#
# [CfgHelp] This flag may be used if you want to include your own
# [CfgHelp] special signature in the boot record. This prevents an
# [CfgHelp] unauthorized boot diskette from loading.

306
Introduction to AutoBios

!ifndef CfgBootSignatureCheck
CfgBootSignatureCheck = False
!endif

!ifndef CfgBootSignatureLoc
CfgBootSignatureLoc = 3
!endif

!ifndef CfgBootSignature
CfgBootSignature = ""
!endif

# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]
# [CfgSection] Bios Size Configuration Support
# [CfgHelp] This Value may be defined if you wish to pad the front of the
# [CfgHelp] Bios to free up the begining of the segment
# [CfgHelp] This Value is usually 0000 for AT's and 8000h for XT's.
# [CfgHelp] If the Value is not defined, 0000 is assumed.
# [Cfg#]
#
!ifndef CfgPad
CfgPad = 0000h
!endif
#
# [Cfg#]
#
#--------------------------------------------------------------------
# [CfgHelp] These flags may be defined to specify the target system.
# [CfgHelp] They provide a preset description for popular combinations.
# [CfgHelp] They are intended to provide the first-highest-level choice.
# [CfgHelp] They may then set up standard conditions for that target
# [CfgHelp] Note: These Project Flags should be placed at the beginning
# [CfgHelp] so that the default expansions come last.
# [Cfg#]
#
#CfgTargetGenericXT
#CfgTargetGenericAT
#CfgTargetAMD286LX
#
# [Cfg#]
# [CfgHelp] these flags may be expanded to replace the chip flags below,
# [CfgHelp] since they allow more comprehensive configuration definitions.
# [CfgHelp] These sets may then be enabled/disabled with one major flag,
# [CfgHelp] making it easier to define multiple configurations.
# [CfgHelp] Example of project specific targets is shown below
# [Cfg#]
#
#CfgTargetMyProject1
#CfgTargetMyProject2
#
# [Cfg#]
#--------------------------------------------------------------------
# [Cfg#]

307
The C Programs

# [CfgSection] ChipSet Support


# [CfgHelp] This flag may be defined to specify an LSI ChipSet on the
# [CfgHelp] motherboard. If it is not defined, the dummy NoChip routine is
used.
# [Cfg#]
#
!ifndef CfgChip
CfgChip = NoChip
!endif
#
#CfgChipPorts =
#CfgChipData = 0fc80h,036h,0fc81h,050h,0fc82h,00fh
#CfgChipData1 = 0fc83h,040h,0fc84h,002h,0fc85h,000h
#CfgChipData2 = 0fc86h,0c0h,0fc88h,004h,0fc89h,03eh
#CfgChipData3 =
#CfgChipData4 =
#
#------------------------------------------------------------------
#
!ifndef CfgPostMake
CfgPostMake =
!endif

#
# END OF CONDITIONAL CONFIGURATION OPTIONS
#--------------------------------------------------------------------------

308
Introduction to AutoBios

4.4.2 The Specific Platforms


The specific platform files are loaded ahead of the common.plt file, and definitions declared will take
precedence over the defaults provided in the common.plt file. Definitions left undeclared will revert to
the default stated in the common.plt file, so onnly those definitions required for a type of platfrom which
differ from the defaults need be declared. This example file shows the typical composition of a platform-
specific definition. Items such as Compiler and Assembler code-generation directives, CMOS features,
hard disk support, etc. may be defined in this file. This level of platform file collects "standard"
definitions, eliminating the need to include copious detail in the .Job file, allowing it to be kept to a
minimum of complexity.

309
Introduction to AutoBios

4.4.2.1 The AT386 Platform


#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Title] Configuration Builder Version 1.00
#
# [Module Name] AT-386 Platform Configuration Options FIle
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 04/11/94
#
# [File Name] AT386.PLT
#
# [Description]
#
# This file is used to specify the standard options for an
# AT type platform. If no user "xxxx.Job" file is specified
# for a project, this will configure a generic AT.
#
# [History] 2.00 04/11/94 Original
#
#**************************************************************************
#
# [Display] ---------- Primitive Definitions ----------------
# [Display] True = 1
# [Display] False = 0
#
!ifndef True
True = 1
!endif

!ifndef False
False = 0
!endif

#----------------------------------------------------------------------
# Default Conditional Configuration Options
#
# The following variables will normally be specifically defined
# in the xxxx.Job file for the particular project. If variables are
# not specified in xxxx.Job, then this file will supply the default
# definitions.

# The philosophy of these flags is that they be defined as either


# True/False, or as a value. The source code modules will then
# report on undefined or mis-spelled variable names.
# This philosophy has not been implemented, but will reduce the
# possibility of un-detected errors in the Bios.

311
The C Programs

#----------------------------------------------------------------------
# Default Project Configuration and Identification Information
# [SubTitle]
# [Section] User Text Strings
# [SubSection]
# [Item]
# [Keyword.Search for this string]
# [Default] CfgProjectVersion = "0.99"
# [Help] You may include a project version number or use the default
# [Help]
# [Ask] "CfgProjectVersion = "
# [Answer]
# [Output] CfgProjectVersion =
# [Wait]
#
!ifndef CfgProjectVersion
CfgProjectVersion = "0.99"
!endif

!ifndef CfgProjectCustomer
CfgProjectCustomer= "Generic"
!endif

!ifndef CfgProjectPartNr
CfgProjectPartNr = "92093000000-00001"
!endif

!ifndef CfgProjectOption
CfgProjectOption = "None"
!endif

#--------------------------------------------------------------------
# [Section] Platform Support
# [Help] Only One of these flags should be defined.
# [Help] This is the general directive. Specific overrides are
# [Help] possible (see Keyboard) for some drivers and devices.

!ifndef CfgPlatformAT
CfgPlatformAT = True
!endif

!ifndef CfgTypeByte
CfgTypeByte = 0fch
!endif

!ifndef CfgTypeParms
CfgTypeParms = 08h,00h,0fch,01,070h,0,0,0,0,0
!endif

# [Help] These flags designate the level of code to be generated


# [Help] by the compiler and assembler/

!ifndef CfgCompiler
CfgCompiler = 3
!endif

312
Introduction to AutoBios

!ifndef CfgMasm
CfgMasm = .386p
!endif

#--------------------------------------------------------------------
#[Section] CMOS Memory Support
# [Help] This flag may be defined to enable support for AT CMOS memory.

!ifndef CfgCmos
CfgCmos = True
!endif

# [Help] This flag may be defined to force loading AT CMOS values at power-on.
#

!ifndef CfgCmosInit
CfgCmosInit = False
!endif

!ifndef CfgCmosInitIfBadChecksum
CfgCmosInitIfBadChecksum = True
!endif

!ifndef CfgCmosInitIfBadBattery
CfgCmosInitIfBadBattery = True
!endif

# [Help] This flag causes (if CfgCmosInit is defined) the Cmos to be


# [Help] reloaded on every power-up. Otherwise Cmos will be reloaded
# [Help] only when the power is lost.

!ifndef CfgCmosInitAlways
CfgCmosInitAlways = False
!endif

#--------------------------------------------------------------------
# [Section] Keyboard Support
# [Help] These are override flags for the Keyboard Driver.
# [Help] If they are left undefined (the normal case), the keyboard
# [Help] will follow the paltform definition.
# [Help] If one (and ONLY one) is defined, then that will force
# [Help] the keyboard definition.

!ifndef CfgKeyboardStyleAT
CfgKeyboardStyleAT = True
!endif

#--------------------------------------------------------------------
#--------------------------------------------------------------------
# [Section] Hard Disk Support
# [Help] This flag may be defined to enable hard disk support for AT's.

!ifndef CfgHard
CfgHard = True

313
The C Programs

!endif

# [Help]These may be defined to specify the default hard drive types.


# CfgInitCMOS must be defined to process these drive types.
#CfgHard1Type = 47
#CfgHard2Type = 0

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

314
Introduction to AutoBios

4.4.2.2 The i386EX Platform


#*************************************************************************
#
# [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
#
# [Product Name] AutoBios
#
# [Title] Bios Configuration Builder Version 1.00
#
# [Module Name] Intel 386EX Platform Configuration Options File
#
# [Version] 2.00
#
# [Author] John O. Foster
#
# [Date] 08/30/94
#
# [File Name] i386EX.PLT
#
# [Description]
#
# This file is used to specify the standard options for an
# EX type platform. If no user "xxxx.Job" file is specified
# for a project, this will configure a i386EX.
#
# [History] 2.00 08/30/94 Original
#
#**************************************************************************
#
# [Display] ---------- Primitive Definitions ----------------
# [Display] True = 1
# [Display] False = 0
#
!ifndef True
True = 1
!endif

!ifndef False
False = 0
!endif

#----------------------------------------------------------------------
# Default Conditional Configuration Options
#
# The following variables will normally be specifically defined
# in the xxxxJob file for the particular project. If variables are
# not specified in xxxx.Job, then this file will supply the default
# definitions.

# The philosophy of these flags is that they be defined as either


# True/False, or as a value. The source code modules will then
# report on undefined or mis-spelled variable names.
# This philosophy has not been implemented, but will reduce the
# possibility of un-detected errors in the Bios.

315
The C Programs

#----------------------------------------------------------------------
# Default Project Configuration and Identification Information
# [SubTitle]
# [Section] User Text Strings
# [SubSection]
# [Item]
# [Keyword.Search for this string]
# [Default] CfgProjectVersion = "0.99"
# [Help] You may include a project version number or use the default
# [Help]
# [Ask] "CfgProjectVersion = "
# [Answer]
# [Output] CfgProjectVersion =
# [Wait]
#
!ifndef CfgProjectVersion
CfgProjectVersion = "0.99"
!endif

!ifndef CfgProjectCustomer
CfgProjectCustomer= "Generic"
!endif

!ifndef CfgProjectPartNr
CfgProjectPartNr = "92093000000-00001"
!endif

!ifndef CfgProjectOption
CfgProjectOption = "None"
!endif

#--------------------------------------------------------------------
# [Section] Platform Support
# [Help] Only One of these flags should be defined.
# [Help] This is the general directive. Specific overrides are
# [Help] possible (see Keyboard) for some drivers and devices.

!ifndef CfgPlatformAT
CfgPlatformAT = True
!endif

!ifndef CfgTypeByte
CfgTypeByte = 0fch
!endif

!ifndef CfgTypeParms
CfgTypeParms = 08h,00h,0fch,01,070h,0,0,0,0,0
!endif

# [Help] These flags designate the level of code to be generated


# [Help] by the compiler and assembler/

!ifndef CfgCompiler
CfgCompiler = 3
!endif

316
Introduction to AutoBios

!ifndef CfgMasm
CfgMasm = .386p
!endif

#----------------------------------------------------------------------------
# [Section] Prom Configuration
# Prom Configuration Information
# [Help] If a single prom chip will be used, a split ID field will be omitted.

!ifndef CfgPromSingle
CfgPromSingle = False
!endif

#--------------------------------------------------------------------

!ifndef CfgLPT
CfgLPT = False
!endif

!ifndef CfgPrintScreen
CfgPrintScreen = False
!endif

!ifndef CfgCmosClock
CfgCmosClock = False
!endif

!ifndef CfgANSI
CfgANSI = True
!endif

#--------------------------------------------------------------------
#[Section] CMOS Memory Support
# [Help] This flag may be defined to enable support for AT CMOS memory.

!ifndef CfgCmos
CfgCmos = False
!endif

# [Help] This flag may be defined to force loading AT CMOS values at power-on.
#

!ifndef CfgCmosInit
CfgCmosInit = False
!endif

!ifndef CfgCmosInitIfBadChecksum
CfgCmosInitIfBadChecksum = True
!endif

!ifndef CfgCmosInitIfBadBattery
CfgCmosInitIfBadBattery = True
!endif

# [Help] This flag causes (if CfgCmosInit is defined) the Cmos to be


# [Help] reloaded on every power-up. Otherwise Cmos will be reloaded

317
The C Programs

# [Help] only when the power is lost.

!ifndef CfgCmosInitAlways
CfgCmosInitAlways = False
!endif

#--------------------------------------------------------------------
# [Section] Keyboard Support

!ifndef CfgKeyboard
CfgKeyboard = False
!endif

#--------------------------------------------------------------------

!ifndef CfgDisk
CfgDisk = False
!endif

!ifndef CfgVideo
CfgVideo = False
!endif

!ifndef CfgKeyboardIntercept
CfgKeyboardIntercept = False
!endif

#--------------------------------------------------------------------
# [Section] Hard Disk Support
# [Help] This flag may be defined to enable hard disk support for AT's.

!ifndef CfgHard
CfgHard = False
!endif

# END OF CONDITIONAL CONFIGURATION OPTIONS


#--------------------------------------------------------------------------

318
Introduction to AutoBios

5. The Definition Modules


These modules provide definitions for structures, functions, variables, and constants for AutoBios.

5.1 The Bios.h File


The Bios.h file is the 'C' header file used for all the Bios modules. The 'C' language utilities used in the
build process use normal .h files since they run from normal Ram. Because the Bios is a prom-resident
program, it has its own special requirements in the use of the CPU's segment registers. Declarations to
provide interrupt routine support are also in this file. A special simplified interrupt sequence is provided
in order to save and restore registers when either calling interrupt routines, or in defining a function to act
as an interrupt routine. Because of these features included in the Bios.h file, interrupt service routines are
written as regular functions, with the machine register state being declared as unsigned integer parameters
on the stack.
Bios.h is translated by the Masm utility H2INC into the Bios.inc file, which insures that the assembly
language modules have access to the definitions and type-checking provided by the Bios.h file. This
insures that definitions used by the assembly modules are always in synchronization with the top-level
definitions used by the C language modules.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios h file of standard definitons
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Bios.H
//
// [Language] MSVC 1.5
//
// [Description] This file is used for Bios definitions.
//
// [History] 2.00 04/11/94 Original
//
//
//-----------------------------------------------------------------------

#define SystemLocation CfgSysObjectPtrPrimary

// ----- Enumerations -----------

// enums for video types


enum { VGA, CGA40, CGA, CGA80, Mono, };

319
The C Programs

// enums for spy functions


enum { Snap, Watch, Log, SizeOfSpyList, };

// enums for SysVue origins


enum { OriginTrap = 1, OriginTrace, OriginBoot, OriginDivide,
OriginSysError, OriginKey, OriginReEnter, OriginBreakKey, };

// enums for delay functions


enum { Microseconds, Milliseconds, Seconds };

// Size Identifiers

#define SizeIsString 0
#define SizeIsByte 1
#define SizeIsWord 2
#define SizeIsLong 4

/* Get the Configuration information */

#include "product.h"
#include "job.h"
#include "platform.h"
#include "common.h"
#include "chiph.tmp"
#include "stddefs.h"
#include "intregs.h"
#include "Bios8042.h"
#include "lang.h"

struct FDiskParmItem
{
char SpecifyByte1;
char SpecifyByte2;
char MotorWait;
char BytesPerSectorCode;
char SectorsTrack;
char Gap;
char Dtl;
char Gap3;
char FillCharByte;
char HeadSettle;
char MotorStart;
char MaxTracks;
char DataRate;
char Step;
char DriveID;
char MediaID;
};

/*******************************************************

Hard Disk Table Structure Definition

This table resides in the top.asm module, and the


initializing definitions are in that module. The table

320
Introduction to AutoBios

is used by the hard.c module.

*******************************************************/

struct HDTable
{
unsigned Cyls;
char Heads;
unsigned ReducedWrite; /* XT Only - AT = 0*/
unsigned PreComp; /* default 0 */
char MaxECC; /* XT Only */
char Control; /* set to 0 */
char TimeOut; /* XT Only */
char FormatTimeOut; /* XT Only */
char CheckTimeOut; /* XT Only */
unsigned Landing;
char Sectors;
char Reserved; /* Reserved, Set to 0 */
};

#ifndef _H2INC

struct NameValueList
{
char near * Name;
unsigned Value;
};

#endif

struct ItemList
{
char near * ItemName;
char near * ItemDescription;
unsigned ItemAddress;
unsigned ItemSize;
unsigned ItemDefault;
unsigned ItemValue;
};

#define DevicePod BIT0


#define DeviceVideo BIT1
#define DeviceSysVue BIT2
#define DeviceSysSrv BIT3
#define DeviceEquipment BIT4
#define DeviceMemory BIT5
#define DeviceLpt BIT6
#define DeviceCom BIT7
#define DeviceDisk BIT8
#define DeviceHard BIT9
#define DeviceTod BIT10
#define DeviceBoot BIT11
#define DeviceTimer BIT12
#define DeviceKeyboard BIT13
#define DevicePrtScr BIT14
#define DeviceNODEVICES 0

321
The C Programs

//=====================================================================
//
// This is the inline assembly language code definition to provide
// Bios Stack swapping. A portion of the BiosObject is reserved for
// the Bios Stack. A service routine may elect to use it's own stack
// by swapping from the user stack to the Bios Stack.
// This allows Bios serovice routines to be recursive without using
// a large amount of the user's stack. To determine whether the
// Bios routine is being called from the user, or another Bios routine,
// an InBios semaphore swaps the stack only when entering from a
// users routine.
//
// The typical use is:
// InterruptEnvelope(MemCall,DeviceMem,0)
// or:
// InterruptEnvelope(SysMain,DeviceSysVue,OriginTrap)
//
// Note: a Device = 0 skips the Snapshot calls
//

#define InterruptEnvelope(Destination,DeviceMask,OriginCode) \
_asm { \
/* Save the original SS for a calling argument, the SP is held in bp */ \
_asm mov cx,ss \
_asm mov dx,bp \
/* Get the BiosObject ptr */ \
_asm xor ax,ax \
_asm mov es,ax \
_asm mov es,es:[SystemLocation] \
_asm les di,es:[0].Bios_Ptr \
/* disable interrupts */ \
_asm lahf \
_asm cli \
/* Check the InBios Semaphore */ \
_asm cmp word ptr es:[di].InBios,0 \
/* Skip swapping if already in the Bios */ \
_asm jnz skipswap \
/* First time into Bios, so do the swap, saving the old SS:SP */ \
_asm mov es:[di].StackSaveSP,bp \
_asm mov es:[di].StackSaveSS,ss \
/* The new stack will be in the BiosObject */ \
_asm mov bx,es \
_asm mov ss,bx \
_asm lea bx,es:[0].BiosStackEnd \
_asm add bx,di \
_asm mov sp,bx \
_asm skipswap: \
/* Increment the InBios semaphore */ \
_asm inc word ptr es:[di].InBios \
_asm sahf \
/* Set the Data Segment to the Code Segment */ \
_asm mov ax,cs \
_asm mov ds,ax \
/* Call the snap and service routines with a ptr to the regs */ \

322
Introduction to AutoBios

_asm mov ax,OriginCode \


_asm push ax \
_asm mov ax,DeviceMask \
_asm push ax \
_asm push cx \
_asm push dx \
_asm mov ax,DeviceMask \
_asm or ax,ax \
_asm jz NoSnapIn \
_asm call SnapIn \
_asm NoSnapIn: \
_asm call Destination \
_asm mov ax,DeviceMask \
_asm or ax,ax \
_asm jz NoSnapOut \
_asm call SnapOut \
_asm NoSnapOut: \
_asm add sp,8 \
/* Now check to see if an unswap is needed - Get the BiosObject */ \
_asm lahf \
_asm cli \
_asm xor bx,bx \
_asm mov es,bx \
_asm mov es,es:[SystemLocation] \
_asm les di,es:[0].Bios_Ptr \
/* Decrement the InBios semaphore */ \
_asm dec word ptr es:[di].InBios \
/* If it goes to zero, resume the callers stk, else still in Bios */ \
_asm cmp word ptr es:[di].InBios,0 \
_asm jnz skipunswap \
/* Do the unswap */ \
_asm mov ss,es:[di].StackSaveSS \
_asm mov bp,es:[di].StackSaveSP \
/* continue on and return to caller */ \
_asm skipunswap: \
_asm sahf \
};

//=====================================================================

#include "objects.h"

// these are arbitrary identifiers so the main routine will know how it was
entered

/*
// This definition sizes the block acquire to include the variables
// specified in the variable declaration
*/

/* Function Prototypes */

void far *acquire_system_block(char far * name,


unsigned BlockSize,unsigned object_type);

323
The C Programs

#define AcquireObject(blk_ptr,id,object_type) acquire_system_block(id, \


sizeof(blk_ptr), object_type)

unsigned GetCS(void); /* Returns Current Code Segment */


unsigned GetSS(void);
unsigned GetSavedSS(void);
unsigned GetSavedSP(void);
unsigned GetSP(void);
unsigned GetES(void);
unsigned GetDS(void);
unsigned char GetDH(void);
unsigned char GetDL(void);

void far *CreateSystemObject(unsigned BlockSize);


unsigned ReleaseObject(void far * object_pointer);
unsigned near ClearObject(void far * object_pointer);
void far *GetBiosObject(void);
void far *GetSystemObject(void);
void far *GetVirtualObject(void);
unsigned ConsoleBreak(void);

int outp(unsigned, int);


unsigned outpw(unsigned, unsigned);
int inp(unsigned);
unsigned inpw(unsigned);

void _enable(void);
void _disable(void);
#define PushInterruptStatus _asm { pushf }
#define PopInterruptStatus _asm { popf }
#define NoOpcode _asm { _asm nop };
#define FlushCpuQueue _asm { _asm jmp $+2 };
void interrupt far SysError(unsigned);

void MemCpy(void far * dest, void far * src, unsigned count);

/*--- Defining Peeks and Pokes ------*/

#define peekb(addr) (*(char _far *)addr)


#define peek(addr) (*(unsigned _far *)addr)
#define peekd(addr) (*(unsigned long _far *)addr)

#define pokeb(addr,value) (*(char _far *)addr) = value


#define poke(addr, value) (*(unsigned _far *)addr) = value
#define poked(addr,value) (*(unsigned long _far *)addr) = value

/*---- Setting up the variable arguments list declarations -----*/


/*
* define a macro to compute the size of a type, variable or expression,
* rounded up to the nearest multiple of sizeof(int). This number is its
* size as function argument (Intel architecture). Note that the macro
* depends on sizeof(int) being a power of 2!
*/

324
Introduction to AutoBios

typedef unsigned char far * va_list;

#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) -


1) )
#define va_start(ap,v) ap = (va_list)&v + _INTSIZEOF(v)
#define va_arg(ap,t) ( *(t _far *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ap = (va_list)0

unsigned printf(char far * FormatPtr, ...);


unsigned printsnapstring(char far * FormatPtr, ...);
/*-----------------------------------------------------------*/

unsigned scanf(char far * string[],unsigned long far * value);


char far * StrCpy(char far *, char far *);
unsigned StrCmp(char far *,char far *);
unsigned StrniCmp(char far *,char far *, unsigned);
char far * StrChr(char far *, char);
char far * StrStr(char far *,char far *);
unsigned StrLen(char far * s);
char far * StrMatch (char far *,char far *);
void Pause(void);
unsigned kbhit(void);
unsigned GetChar(void); // get char from console no echo
unsigned GetCharEcho(void); // get char from console with echo
void ScanCall (void far *);
unsigned long AsciiToHex(char far *);
unsigned long AsciiToHexMask(char far *);
unsigned AsciiToDec(char far *);
unsigned IsHexString(char far *);
unsigned IsDecimalString(char far *);

/*----------------------------------------------------------------------*/

/*------- Set the definitions for the character functions ---------*/

unsigned IsAlpha(char);
unsigned IsUpper(char);
unsigned IsLower(char);
unsigned IsDigit(char);
unsigned IsHexDigit(char);
unsigned IsSpace(char);
unsigned IsPunct(char);
unsigned isalnum(char);
unsigned IsPrintable(char);
unsigned IsGraph(char);
unsigned IsCntrl(char);
unsigned IsAscii(char);

char ToUpper(char);
char ToLower(char);

/*-- macros to form and to dissect far pointers --*/


#define MK_FP(seg,ofs) ((void far *) (((long) (seg) << 16 | ((ofs) &
0xffff))))
#define FP_SEG(fp) (*((unsigned *)&(fp) + 1))
#define FP_OFF(fp) (*((unsigned *)&(fp)))

325
The C Programs

/* Motherboard type byte definitions */

#define at 0xfc /* type byte definition */


#define xt 0xfe /* type byte definition */

/*--- definitions of variables in data segment segment 40h ---*/

#define BOOT_AREA (*((char far *) 0x00007c00))


#define PRSC_BUSY (*((char far *) 0x00000500))

#define TimerLongMax 0x1800b0 /* 24 hour count */

struct BootSectorBuffer { unsigned BootBufferSpace[256]; };

#include "lowram.h"

/*----------------- Function Prototypes ---------------------*/

#define MaxArgs 16

unsigned build_args(char far * g1,


char far * g2,char (far * (far * g3)[]),
unsigned maxargs);

#define LoadDS(); _asm { _asm push cs _asm pop ds };

unsigned SnapActive(void);
unsigned WatchActive(void);
unsigned LogActive(void);
void MarkDeviceActive(unsigned device);
void MarkDeviceInactive(unsigned device);

unsigned PutChar(char);

/*--- declarations for Bios Identity Markers ----*/

void BiosID(void);
void PartNrID(void);
void VersionID(void);
void OwnerID(void);
void CustomerID(void);
void DateStamp(void);
void BiosStart(void);

//--------------------------------------------------------------

void SnapIn(struct _IRegs far * Regs,unsigned device);


void SnapOut(struct _IRegs far * Regs,unsigned device);

/*------ Standard Function Prototypes -----*/

/* Standard Bios Function Prototypes */


void interrupt far Boot(InterruptRegisters);
void interrupt far SystemServicesFunctionCall(InterruptRegisters);
void interrupt far CommFunctionCall(InterruptRegisters);

326
Introduction to AutoBios

void interrupt far SysVueConsoleISR(InterruptRegisters);


void interrupt far FDiskFunctionCall(InterruptRegisters);
void interrupt far FDiskISR(void);
void interrupt far Divide(InterruptRegisters);
void interrupt far IntNMI(void);
void interrupt far ReDirect(void);
void interrupt far Int287(void);
void interrupt far HDiskFunctionCall(InterruptRegisters);
void interrupt far HDiskISR(void);
void interrupt far KeyboardFunctionCall(InterruptRegisters);
void interrupt far KeyboardInterruptServiceRoutine(void);
void interrupt far PrinterFunctionCall(InterruptRegisters);
void interrupt far PrintScreenFunctionCall(InterruptRegisters);
void interrupt far RTC_INT(void);
void interrupt far TimerISR(void);
void interrupt far TimeOfDayFunctionCall(InterruptRegisters);
void interrupt far VideoFunctionCall(InterruptRegisters);
void interrupt far MemSizeFunctionCall(InterruptRegisters);
void interrupt far EquipmentFunctionCall(InterruptRegisters);

#ifndef _H2INC
unsigned SysVueSetup(ActionArgument);
unsigned MemSizeSetup(ActionArgument);
unsigned TimeOfDaySetup(ActionArgument);
unsigned SystemServicesSetup(ActionArgument);
unsigned BootSetup(ActionArgument);
unsigned MoveSysObjectRoutine(ActionArgument);
unsigned RomCheckSunRoutine(ActionArgument);
unsigned CommSetup(ActionArgument);
unsigned ConsoleCommSetup(ActionArgument);
unsigned LptSetup(ActionArgument);
unsigned FDiskSetup(ActionArgument);
unsigned HDiskSetup(ActionArgument);
unsigned RomScanRoutine(ActionArgument);
unsigned EquipmentSetup(ActionArgument);
unsigned KeyboardSetup(ActionArgument);
unsigned TimerSetup(ActionArgument);
unsigned VideoSetup(ActionArgument);
unsigned PrintScreenSetup(ActionArgument);
unsigned SysVueConsoleSetup(ActionArgument);
unsigned CDSetup(ActionArgument);
#endif

void DummyIret(void);
void DummyISR(void);
void beep(void);
void OutCmos(unsigned,unsigned);
void ResetCmosBits(unsigned,unsigned);
void SetCmosBits(unsigned,unsigned);
void ToggleCmosBits(unsigned,unsigned);
unsigned InCmos(unsigned);
unsigned long SetTimeOutCount(unsigned);
void DelayCall(unsigned count,unsigned resolution);
void BootJump(unsigned char);
unsigned Motherboard(unsigned);

327
The C Programs

unsigned TimeOfDay(void);
unsigned RamTestOK(unsigned base,unsigned gran,unsigned bias);
unsigned ChecksumOK(unsigned,unsigned);
unsigned ChecksumBiosOK(void);
unsigned SetTimerCount(void);
unsigned read_refresh_count(void);
unsigned CalcHDiskSize(unsigned,unsigned,unsigned);
unsigned long SetTimeOutCount(unsigned count);
unsigned CmosType(char drive_nr);
unsigned CallDiskDiagnostic(void);
unsigned CallDiskReset(unsigned);
void CallDiskInitDrive(unsigned);
void CallDiskRecalibrate(unsigned);
unsigned CallDiskRead(unsigned Drive,unsigned NrSectors,
unsigned Track,unsigned Head,unsigned Sector,
unsigned char far *Buffer);
void RepeatIn(void far *buffer,unsigned portnr,unsigned count);
void RepeatOut(void far *buffer,unsigned portnr,unsigned count);
void FDiskChain(void);

unsigned long RomScan(unsigned address);


unsigned long ClockReadTime(void);
unsigned long ClockReadDate(void);
void DisplayTime(void);
void DisplayDate(void);
unsigned long LongMultiply(unsigned long,unsigned);
unsigned ConvertBcdToBinary(char);
unsigned gets(char far * buffer,unsigned buffer_size,char term);
void DisplayDrives(void);
unsigned CalcCmosChecksum(void);
void DisplayFlags(unsigned);
unsigned KeyboardIntercept(struct KBRegs far *);
void PrintHardDiskTitleBar(void);
void DisplayUserHardTypes(void);
void LoadUserDriveParms();
unsigned GetHighOfLong(unsigned long);

void DisplayRegisters(struct _IRegs far * Reg,char far *


Marker);
void DisplayRegistersAndFlags(struct _IRegs far * Reg);
void DisplayFlags(unsigned Flag);
void ColdBoot(void);
void WarmBoot(void);
void SendEOI1(void);
void SendEOI2(void);
unsigned ReadSwitches(void);
unsigned long ReadTimer(void);
unsigned GetVideoJumper(void);

unsigned VideoSetMode(unsigned);
unsigned VideoGetMode(void);
void VideoWriteTty(char);
void VideoSetCursor(unsigned);
void VideoScrollUp(unsigned,unsigned,unsigned,unsigned);
void MoveRow(unsigned,unsigned,unsigned,unsigned);
void ClearRow(unsigned,unsigned,unsigned,unsigned);

328
Introduction to AutoBios

void MoveGraphicsRow(unsigned,unsigned,unsigned,unsigned);
void ClearGraphicsRow(unsigned,unsigned,unsigned,unsigned);
void VideoWriteChar(unsigned);
void VideoWriteAC(char,unsigned);
unsigned VideoReadAC(void);
void VideoClearScreen(void);

#define CarryBit 0x0001


#define ZeroBit 0x0040

/*--------------------------------------------------------------------*/

#include "sysvue.h"

//-----------------------------------------------------------

struct SysVueCommandList
{
char near * CmdName;
char near * CmdHelpString;
void (near * Cmd)(VueRegSet);
};

// This structure is for the SysVue command line parser. The token
// is followed by the index for the save array of the value of the token.
//

unsigned BuildArguments(VueRegSet);

void PrintList (struct NameValueList *);


void PrintNames(struct NameValueList *);

// This is an interesting case !!


// The structure defintion for the list is disabled for H2INC
// because the "Name" is a MASM reserved keyword and produces
// a warning. By defining this dummy function, H2INC forces
// an external definition PROTO for the structure which allows
// it to be defined by being undefined !!
// One would think something is awry here, but it seems to work
void NoRoutine (struct NameValueDittoList *);

char far * GetName(unsigned, struct NameValueList *);


unsigned GetValue(char far *, struct NameValueList *);
unsigned NameExists( char far *, struct NameValueList *);
unsigned ValueExists(unsigned, struct NameValueList *);
unsigned ParseDigitString(char far *, unsigned);

struct NameValueList __based(__segname("_TEXT"))DeviceList[];


struct NameValueList __based(__segname("_TEXT"))FlagOnList[];
struct NameValueList __based(__segname("_TEXT"))FlagOffList[];
struct NameValueList __based(__segname("_TEXT"))OriginList[];
struct NameValueList __based(__segname("_TEXT"))RegisterList[];
struct NameValueList __based(__segname("_TEXT"))RegisterIndexList[];
struct NameValueList __based(__segname("_TEXT"))SpecialList[];
struct NameValueList __based(__segname("_TEXT"))CmosList[];

329
The C Programs

struct NameValueList __based(__segname("_TEXT"))DisplayList[];


struct NameValueList __based(__segname("_TEXT"))DiskList[];
struct NameValueList __based(__segname("_TEXT"))BootOrderList[];
struct NameValueList __based(__segname("_TEXT"))BitList[];
struct NameValueList __based(__segname("_TEXT"))ReverseBitList[];
struct NameValueList __based(__segname("_TEXT"))SpyList[];
struct NameValueList __based(__segname("_TEXT"))ExceptionList[];
struct NameValueList __based(__segname("_TEXT"))SetupMessageList[];
struct ItemList __based(__segname("_TEXT"))DumpList[];
struct SysVueCommandList __based(__segname("_TEXT"))CommandList[];

struct WordWordList
{
unsigned Word1;
unsigned Word2;
};

struct WordWordList __based(__segname("_TEXT"))CmosDefaultTable[];

struct ByteByteList
{
unsigned Byte1;
unsigned Byte2;
};

unsigned Trap(void);

//------ Standard CMOS Chip Register Definitions -------

#define CmosRegSeconds 0x80


#define CmosRegSecondAlarm 0x81
#define CmosRegMinutes 0x82
#define CmosRegMinuteAlarm 0x83
#define CmosRegHours 0x84
#define CmosRegHourAlarm 0x85
#define CmosRegDayOfWeek 0x86
#define CmosRegDayOfMonth 0x87
#define CmosRegMonth 0x88
#define CmosRegYear 0x89
#define CmosRegStatusA 0x8A
#define CmosRegStatusB 0x8B
#define CmosRegBitDaylight 0x01
#define CmosRegStatusC 0x8C
#define CmosRegStatusD 0x8D
#define CmosRegDiagnosticStatus 0x8E
#define CmosRegBitBadBat 0x80
#define CmosRegBitBadSum 0x40
#define CmosRegBitBadCfg 0x20
#define CmosRegRestartStatus 0x8F
#define CmosRegChecksumStart 0x90
#define CmosRegDiskDriveType 0x90

//---------- Non Standard Options --------


#define CmosRegOptionFlags 0x91
#define CmosRegBitBootOrder 0x03

330
Introduction to AutoBios

//----- Resuming Standard Definitions ----

#define CmosRegHardDriveType 0x92


#define CmosRegEquipment 0x94
#define CmosRegBaseMemLow 0x95
#define CmosRegBaseMemHigh 0x96
#define CmosRegExtMemLow 0x97
#define CmosRegExtMemHigh 0x98
#define CmosRegExtendedDriveC 0x99
#define CmosRegExtendedDriveD 0x9A

//---- on-standard definitions for User Defined Hard Drives ----

#define CmosRegDrive47CylLow 0x9B


#define CmosRegDrive47CylHigh 0x9C
#define CmosRegDrive47Heads 0x9D
#define CmosRegDrive47Sectors 0x9E

#define CmosRegDrive48CylLow 0x9F


#define CmosRegDrive48CylHigh 0xA0
#define CmosRegDrive48Heads 0xA1
#define CmosRegDrive48Sectors 0xA2

//------------ Resuming Standard Definitions --------------

#define CmosRegChecksumEnd 0xAD


#define CmosRegChecksumHigh 0xAE
#define CmosRegChecksumLow 0xAF
#define CmosRegExtMemFoundLow 0xB0
#define CmosRegExtMemFoundHigh 0xB1
#define CmosRegCentury 0xB2
#define CmosRegInformationFlags 0xB3

#include "virtual.h"

/*********************************************************/

331
Introduction to AutoBios

5.2 The StdDefs.h File


The StdDefs file includes the fundamental standard definitions used in AutoBios, such as Bit position
definitions, etc. This file is used by bios.h.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios Standard Definitions
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] STDDEFS.H
//
// [Language] MSVC 1.0/1.5
//
// [Description] This file is used for Bios definitions.
//
// [History] 2.00 04/11/94 Original
//
//
//-----------------------------------------------------------------------

/* Definitions of commonly used abbreviations */

#define NULL 0
#define EOS '\0'

// Definitions for SysVue Watch and Snap Flag Bits

#define BIT15 0x8000


#define BIT14 0x4000
#define BIT13 0x2000
#define BIT12 0x1000
#define BIT11 0x0800
#define BIT10 0x0400
#define BIT9 0x0200
#define BIT8 0x0100
#define BIT7 0x0080
#define BIT6 0x0040
#define BIT5 0x0020
#define BIT4 0x0010
#define BIT3 0x0008
#define BIT2 0x0004
#define BIT1 0x0002
#define BIT0 0x0001

//
// Define the watch and snap bits

333
The C Programs

// These bits are also used by the block acquire/release


// function as the owners ID codes. This is for future enhancements.
//

#define DeviceMaskPod BIT0


#define DeviceMaskVideo BIT1
#define DeviceMaskSysVue BIT2
#define DeviceMaskSysSrv BIT3
#define DeviceMaskEquipment BIT4
#define DeviceMaskMemory BIT5
#define DeviceMaskLpt BIT6
#define DeviceMaskCom BIT7
#define DeviceMaskDisk BIT8
#define DeviceMaskHard BIT9
#define DeviceMaskTod BIT10
#define DeviceMaskBoot BIT11
#define DeviceMaskTimer BIT12
#define DeviceMaskKeyboard BIT13
#define DeviceMaskPrtScr BIT14
#define DeviceMaskCDRom BIT15
#define DeviceMaskNODEVICES 0

// This is the master enable flag for snaps. Only snaps on this
// list can be enabled.
#define SnapMasterPattern DeviceMaskSysSrv | \
DeviceMaskLpt | \
DeviceMaskDisk | \
DeviceMaskHard | \
DeviceMaskBoot | \
DeviceMaskPrtScr | \
DeviceMaskEquipment | \
DeviceMaskMemory | \
DeviceMaskCDRom
// This is the master enable flag for watches. Only watches on this
// list can be enabled.
#define WatchMasterPattern DeviceMaskSysSrv | \
DeviceMaskLpt | \
DeviceMaskDisk | \
DeviceMaskHard | \
DeviceMaskBoot | \
DeviceMaskPrtScr | \
DeviceMaskEquipment | \
DeviceMaskMemory | \
DeviceMaskPod | \
DeviceMaskCDRom
// This is the master enable flag for logging. Only logs on this
// list can be enabled.
#define LogMasterPattern DeviceMaskSysSrv | \
DeviceMaskLpt | \
DeviceMaskDisk | \
DeviceMaskHard | \
DeviceMaskBoot | \
DeviceMaskPrtScr | \
DeviceMaskEquipment | \
DeviceMaskMemory

334
Introduction to AutoBios

#ifndef CfgCmosRegPort
#define CmosRegPort 112
#else
#define CmosRegPort CfgCmosRegPort
#endif

#ifndef CfgCmosDataPort
#define CmosDataPort 113
#else
#define CmosDataPort CfgCmosDataPort
#endif

typedef unsigned int size_t;


#define offsetof(s,m) (size_t)&(((s *)0)->m)

/*-- To add Port 0x80 hexadecimal outputs, use this definition --*/
#if CfgCheckPoint
#ifndef _H2INC
#define CheckPoint(xy) _asm { _asm mov al,xy _asm out CfgCheckPointPort,al }
#endif
#else
#ifndef _H2INC
#define CheckPoint(xy) _asm { }
#endif
#endif

/* These Locations are defined for use by SysVue and Bios' */

#define SystemSegmentPointer (*((unsigned far *) SystemLocation))


#define EquipmentWord (*((unsigned far *) 0x00000410))
#define MemorySizeWord (*((unsigned far *) 0x00000413))
#define ResetFlag (*((unsigned far *) 0x00000472))
#define BiosTypeByte (*((char far *) 0xf000fffe))

#define InterruptRegisters struct _IRegs Reg

struct ActionItemList {
char near * ActionMessage;
//char near * TrueMessage;
//char near * FalseMessage;
unsigned (near * DoRoutine)();
//unsigned (near * TrueRoutine)();
//unsigned (near * FalseRoutine)();
//unsigned long LongValue;
};

#define ActionArgument struct ActionItemList far * ActionItem

// Standard Setup Routine Status Replies

#define SetupStatusNul 0 // causes no report to be printed


#define SetupStatusOK 1
#define SetupStatusError 2
#define SetupStatusTimeOut 4

335
The C Programs

#define SetupStatusStub 8
#define SetupStatusInactive 16
#define SetupStatusDeleted 32
#define SetupStatusReserved 64
#define SetupStatusNotFound 128

#if CfgCompiler
#define pushI(immediate) _asm { _asm mov ax,immediate _asm push ax }
#else
#define pushI(immediate) _asm { _asm push immediate }
#endif

//--------------------------------

unsigned IsAlpha(char);
unsigned IsUpper(char);
unsigned IsLower(char);
unsigned IsDigit(char);
unsigned IsHexDigit(char);
unsigned IsSpace(char);
unsigned IsPunct(char);
unsigned isalnum(char);
unsigned IsPrint(char);
unsigned IsGraph(char);
unsigned IsCntrl(char);
unsigned IsAscii(char);

336
Introduction to AutoBios

5.3 The Objects.h File


The Objects.h file is used to define the Object structure used throughout AutoBios. These structures are
very generic, and are intended to be used in a variety of applications in addition to AutoBios. Because
the objects share a consistent design, a few primitive operators can perform a set of fundamental
functions which can provide a basis for many useful functions.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios Object Definitons
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] OBJECTS.H
//
// [Language] MSVC 1.5
//
// [Description] This file is used for Object definitions.
//
// [History] 3.00 04/11/94 Original
//
//
//-----------------------------------------------------------------------

/*===============================================================*/

/* Declarations of Object Types - may be extended */

enum /* Slots are reserved in the System Object for Thread Headers */
{
SystemObjectType,
PoolObjectType,
BiosObjectType,
SysVueObjectType,
VirtualObjectType,
ExecObjectType,
TaskObjectType,
TaskControlBlockObjectType,
StackObjectType,
EventObjectType,
MailboxObjectType,
SignalObjectType,
TextObjectType,
ProcessObjectType,
BufferObjectType,
FifoObjectType,
SpareObjectType,

337
The C Programs

CfgObjectType,
};

/* This Detailed definition of the Object Status unsigned is used to


// define bit fields
*/
#define ObjectStatusDefinition union { \
struct { \
unsigned InUse:1; \
unsigned Empty:1; \
unsigned Full:1; \
unsigned Available:1; \
unsigned Waiting:1; \
unsigned Reserved:1; \
unsigned Permanent:1; \
unsigned Native:1; \
} ObjectStatusFlags; \
unsigned ObjectStatus; \
}; \

/* This is the fundamental Object Header - It Contains sufficient


** information to Identify the Object. Additional Object-Specific
** information will be defined in the Object itself.
*/

typedef struct _ObjectHeader


{
unsigned long ObjectLength; /* length in bytes (mod 16) */
unsigned ObjectPrority; /* Priority 0-65535 (lowest) */
ObjectStatusDefinition /* Defined Previously */
unsigned long ObjectType; /* xxxObjectType Thread ID */
unsigned long ObjectHandle; /* user defined handle */
char ObjectName[16]; /* ASCII text string */
void far * ObjectFlink; /* Thread forward link */
void far * ObjectBlink; /* Thread Backward link */
void far * ObjectParent; /* Parent Option */
void far * ObjectChild; /* Child Option */
} ObjectHeader;
/* Note on General Object Structure:
// Objects which will be maintaining a set of generic "list or threads"
// should place them right after the ObjectHeader structure to allow
// a standard "top of list" fetching routine based on a standard
// use of an index.
// See the GetSystemObject and GetBiosObject MASM routines for
// an example of dedicated routines which could be made generic.
*/

/*-- Declaration to define an object --*/


/*
// The first definition will declare the header, and the second will
// provide a readable end marker.
*/
//#define DefineObject(name) typedef struct name { ObjectHeader
// Note: Because of the way H2INC vers. 1.10 processes the above line,

338
Introduction to AutoBios

// the object definitions below use the typedef itself.


// This generates the correct strucuture for the .INC file.
//#define EndDefineObject }

/*-- This is used to specify a default user Object --*/


/*
// It is used in the acquire and release routines to allow access
// to the header items without a specific object description
*/

typedef struct _Object


{
ObjectHeader;
} Object;

/*=== definition of System Object ===*/


/*
// The System Object should consist of a list of pointers to other Objects.
// This would be the header list according to the type of an Object.
// Then we could index down the pointers according to type and find
// the head Object for each type string.
// One way to do this would be to store a type-code and a far pointer
// so we could resrve some space for n types active at once.
// this would be like a "files-open" or "buffers" or a "root" directory
//================================================
// Try this idea -
// The system directory contains 16 entries, or thread-heads for 16 Object
// types which are permanently assigned. Additional types may be defined
// by flinking to another directory Object as needed.

//-- The System Object has some unique qualities -


//-- Because it is the first one created, it has a set of primary pool
//-- pointers, so that an acquire-block operation can be done to set up
//-- the rest of the system-required Object, (including the operational
//-- pools), using the normal acquire-routines. One of the blocks allocated
//-- can be the primary pool, using the normal pool structure
*/

struct paragraf { char padder[16]; };

typedef struct _SystemObject


{
ObjectHeader;
/* The first items in the System Object are the thread heads */
struct _BiosObject far * Bios_Ptr;
struct _SysVueObject far * SysVueObjectPtr;
struct _VirtualObject far * VirtualPtr;
void far *Exec_Ptr; /* etc., etc., etc. to occupy 16 slots */
void far *Task_Ptr;
void far *TCB_Ptr;
void far *Stack_Ptr;
void far *Event_Ptr;
void far *Mailbox_Ptr;
void far *Signal_Ptr;
void far *Text_Ptr;
void far *Process_Ptr;

339
The C Programs

void far *Buffer_Ptr;


void far *Fifo_Ptr;
void far *Spare_Ptr;
/* The Primary Pool descriptor items are first */
struct paragraf far * PoolStart; /* This is the default system pool */
struct paragraf far * PoolCurrentOpen;
struct paragraf far * PoolEnd;
unsigned long Null_Type; /* Pointer to ourself - NULL - */
void far * Pool_Ptr; /* ptr to user pools */
/* These are misc. flags and variables which may be included */
unsigned RedirectFlag; /* this skews the alignment, object should be adjusted
*/
unsigned Not_Used[7];
/* This marks the start of the Primary System Pool */
char far * PoolBlock;
} SystemObject;

#if(0==1)
/* Note - the thread list will need to be changed to a directory structure,
where two long slots will hold the handle and the thread-head. This
will allow using any legal handle without reserving max-space, as is
required now. The thread-heads can be found by scanning the directory
with the handle as the key.
This is the proposed structure for the directory entry
struct { unsigned long HandleEntry; char far * ThreadEntry; } DirEntry;

DefineObject(Future_SYSTEM_Object)
char far * PoolStart; /* This is the default system pool */
char far * PoolCurrentOpen;
char far * PoolEnd;
char far * PoolExtension /* a flink to the pool extenssion */ /*
Pointer to ourself - NULL - */
DirEntry;
DirEntry;
DirEntry;
DirEntry;
DirEntry;
DirEntry;
DirEntry;
DirEntry;
char far * PoolBlock;
/* this is the start of the system pool area */
EndDefineObject;
#endif

/*
// The first pool in the thread is the main (primary) one. Additional
// pools may be created by flinking.
*/

#define PoolLength 2048

typedef struct _PoolObject


{
ObjectHeader;

340
Introduction to AutoBios

/*
//-- By making these pointers 32 bit, we will be compatible with
//-- 386/486 linear mode. We may use only the lower 16 bits now,
//-- but the structure will be ready.
*/
unsigned long PoolStart;
unsigned long PoolCurrentOpen;
unsigned long PoolEnd;
unsigned long PoolExtension;
unsigned PoolBlock[PoolLength/2];
} PoolObject;

/* Definition of the Bios Type Object */

struct StructureFlagMaster
{
unsigned Flag;
unsigned Master;
unsigned Save;
unsigned Reserved;
};

#define BiosStackSize 512

typedef struct _BiosObject


{
ObjectHeader;
unsigned ActiveDevice; /* This flag is dynamically updated */
struct StructureFlagMaster FlagMaster[SizeOfSpyList];
unsigned BreakFlag; /* this is set by a console break */
struct _FDRegs far * FDiskObject;
struct _VideoRegs far * VideoObject;
struct FDiskParmItem FDiskParmTable;
struct HDTable HardDrive47;
struct HDTable HardDrive48;
unsigned InBios; /* == 0 means from user, != 0 means already in bios */
unsigned DevicesInstalled;
unsigned StackSaveSP;
unsigned StackSaveSS;
unsigned BiosStackBeg;
unsigned BiosStack[BiosStackSize];
unsigned BiosStackEnd;
} BiosObject;

/* These structures define the configuration block at the beginning of the


bios.
This block will not be checksummed, so that various bios options may be
selected
by modifying these flags and parameters.
*/

#define CfgStatusDefinition union { \


struct { \

341
The C Programs

unsigned Locked:1; \
unsigned Enabled:1; \
unsigned Full:1; \
unsigned Available:1; \
unsigned Waiting:1; \
unsigned Reserved:1; \
unsigned Permanent:1; \
unsigned Native:1; \
} CfgStatusFlags; \
unsigned CfgStatus; \
}; \

typedef struct _CfgBlockSystem


{
unsigned char paraname[8] ;
CfgStatusDefinition
unsigned CfgParm;
unsigned long LongCfgParm;
}CfgBlockSystem;

// --- The SysVue Object is defined in the SysVue.H file -----

342
Introduction to AutoBios

5.4 The LowRam.h File


The LowRam.h file is used to define the assignment of the Bios related low memory area at 0040:0000.
These definitions are important, since standard Bios usage, and some poorly-behaving applications
expect values at specific locations. Many of the variables are only of interest to the Bios itself, while
others may be used by direct access. An example would by the "number of hard disk drives" at
0040:0075, which is read directly by DOS to determine the number of hard drives in a system. Although
this is under/un-documented in DOS documentation, it is an example of common usage. Any decision to
change the placement of variables in this area should be validated by thorough testing to insure no ill side
effects emerge.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios Low Ram Definitons
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] LOWRAM.H
//
// [Language] MSVC 1.0/1.5
//
// [Description] This file is used for Bios definitions.
//
// [History] 2.00 04/11/94 Original
//
//
//-----------------------------------------------------------------------

/*--- This defines the structure of the Bios Ram area -----*/

typedef struct _BiosRam


{
void far * IntVector[128]; /* 0x0000 - 0x01FF */
char unused_vectors[0x200]; /* 0X0200 - 0X03FF */
unsigned COMM_LIST[4]; /* 0x0400 */
unsigned LPT_LIST[3]; /* 0x0408 */
unsigned xSYSTEM_SEGMENT_PTR; /* 0x040E - defined in sf.h */
union
{
struct /* 0x0410 */
{
unsigned DiskPresent:1;
unsigned NpxPresent:1;
unsigned PointingDevice:1;
unsigned Reserved:1;
unsigned VideoMode:2;
unsigned NrDrives:2;

343
The C Programs

unsigned Reserved1:1;
unsigned NrComPorts:3;
unsigned GamePort:1;
unsigned Reserved2:1;
unsigned NrLptPorts:2;
} EquipFlag;
unsigned EquipByte;
};

char TURBO_FLAG; /* 0x0412 */


unsigned MEMORY_SIZE; /* 0x0413 */
unsigned spare2; /* 0x0415 */

union
{
struct
{
char RightShift:1;
char LeftShift:1;
char CtrlShift:1;
char AltShift:1;
char ScrollState:1;
char NumState:1;
char CapsState:1;
char InsertState:1;
} KbFlag; /* 0x0417 */
char KbFlagByte;
};

union
{
struct
{
char LeftCtrl:1;
char LeftAlt:1;
char SysReq:1;
char HoldState:1;
char ScrollShift:1;
char NumShift:1;
char CapsShift:1;
char InsertShift:1;
} KbFlag1;
char KbFlagByte1; /* 0x0418 */
};

char ALT_INPUT; /* 0x0419 */


unsigned KbBufferHead; /* 0x041A Index */
unsigned KbBufferTail; /* 0X041C Index */
unsigned KbBuffer[16]; /* 0X041E */

union
{
struct
{
char RecalDrive0:1;
char RecalDrive1:1;

344
Introduction to AutoBios

char Spares:5;
char IntFlag:1;
} SeekStatus; /* 0X043E */
char SeekStatusByte;
};

union
{
struct
{
char Drive0isOn:1;
char Drive1isOn:1;
char Drive2isOn:1;
char Drive3isOn:1;
char DriveSelected:2;
char Reserved:1;
char WriteFormatOperation:1; /* 0X043F */
} MotorStatus;
char MotorStatusByte;
};

char MOTOR_COUNT; /* 0X0440 */

union
{
struct
{
char ErrorCode:5;
char ControllerFailed:1;
char SeekError:1;
char DriveNotReady:1;
} DiskStatus; /* 0X0441 */
char DiskStatusByte;
};

char FDC_STATUS[7]; /* 0X0442 */


char CRT_MODE; /* 0X0449 */
unsigned CRT_COLS; /* 0X044A */
unsigned CRT_LENGTH; /* 0X044C */
unsigned CRT_START; /* 0X044E */
union /* 0X0450 */
{
struct
{
unsigned char Col;
unsigned char Row;
} Cursor[8];
unsigned CursorWord[8];
};
union
{
unsigned CursorMode; /* 0X0460 */
struct
{
char CursorEndLine;
char CursorStartLine;

345
The C Programs

};
};
char ActivePage; /* 0X0462 */
unsigned ADDR_6845; /* 0X0463 */
char CRT_MODE_SET; /* 0X0465 */
char CRT_PALLETTE; /* 0X0466 */
unsigned VirtualOffset; /* 0X0467 */
unsigned VirtualSegment; /* 0X0469 */
unsigned char VirtualFlag; /* 0X046B */
union
{
unsigned long TimerLong; /* 0X046C */
struct
{
unsigned TimerLow;
unsigned TimerHigh;
};
};
char TimerOverflow; /* 0X0470 */
char BIOS_BREAK; /* 0X0471 */
unsigned RESET_FLAG; /* 0X0472 */
char HD_STATUS1; /* 0X0474 */
char HD_NUM; /* 0X0475 */
char HD_CONTROL; /* 0X0476 */
char spare3;
char LPT_TIMEOUT_LIST[4]; /* 0X0478 */
char COMM_TIMEOUT_LIST[4]; /* 0X047C */
unsigned KbBufferStart; /* 0X0480 Index */
unsigned KbBufferEnd; /* 0X0482 Index */
char ROWS; /* 0X0484 */
unsigned POINTS; /* 0X0485 */
char INFO; /* 0X0487 */
char INFO_3; /* 0X0488 */
char sparex[3]; /* 0X0489 */
char HD_STATUS; /* 0X048C */
char HD_ERROR; /* 0X048D */
char HD_INT_FLAG; /* 0X048E */
char HF_CNTRL; /* 0X048F */

struct
{
char DriveType:3;
char DriveEst:1;
char MediaType:3;
char MediaEst:1;
} DiskID[4]; /* 0X0490 */

char LastTrack[2]; /* 0X0492 */

union
{
struct
{
char LastCodeE1:1;
char LastCodeE0:1;

346
Introduction to AutoBios

char RightCtrl:1;
char RightAlt:1;
char Keyboard101:1;
char ForcedNumLock:1;
char LastCodeFirstID:1;
char ReadIDinProgress:1;
} KbFlag3; /* 0X0496 */
char KbFlagByte3;
};

union
{
struct
{
char LEDs:3;
} Kb;

struct
{
char ScrollLED:1;
char NumLED:1;
char CapsLED:1;
char Reserved:1;
char AckRxed:1;
char ResendRxed:1;
char UpdateInProgress:1;
} KbFlag2; /* 0X0497 */
char KbFlagByte2;
};

union
{
unsigned long UserFlagLong; /* 0X0498 */
struct
{
unsigned UserFlagOffset;
unsigned UserFlagSegment;
};
};

union
{
unsigned long RtcLong; /* 0X049C */
struct
{
unsigned RtcLow;
unsigned RtcHigh;
};
};

char RtcWaitFlag; /* 0X04A0 */


} BiosRam;

347
Introduction to AutoBios

5.5 The IntRegs.h File


The IntRegs.h file is used to define the stack structure when accessing the pushed registers resulting from
the execution of an Interrupt. This structure can vary, depending on the Compiler options selected
regarding the /G switch, specifying 286/386 code generation. In 286 (and 8086) mode, 16-bit registers
are pushed on the stack by the "interrupt" function declarator. When using the 386 level switch, 32-bit
registers are pushed, altering their relative positions on the stack.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Interrupt Register Definitons
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] INTREGS.H
//
// [Language] MSVC 1.0/1.5
//
// [Description] This file is used for Bios definitions.
//
// [History] 2.00 04/11/94 Original
//
//
//-----------------------------------------------------------------------

/*-- Define the Registers on the Stack for an Interrupt Call --*/

// Addition for 386/486 - Interrupt declarations use pushad !

#if (CfgCompiler >= 3)

#define SizeofRegArray 21

typedef struct _DWordRegs


{
unsigned dwordpadding[2];
unsigned long RegEDI;
unsigned long RegESI;
unsigned long RegEBP;
unsigned long RegESP;
unsigned long RegEBX;
unsigned long RegEDX;
unsigned long RegECX;
unsigned long RegEAX;
} DWordRegs;

349
The C Programs

typedef struct _WordRegs


{
unsigned RegES;
unsigned RegDS;
unsigned RegDI;
unsigned regDIpadding;
unsigned RegSI;
unsigned regSIpadding;
unsigned RegBP;
unsigned regBPpadding;
unsigned RegSP;
unsigned regSPpadding;
unsigned RegBX;
unsigned regBXpadding;
unsigned RegDX;
unsigned regDXpadding;
unsigned RegCX;
unsigned regCXpadding;
unsigned RegAX;
unsigned regAXpadding;
unsigned RegIP;
unsigned RegCS;
unsigned RegFlags;
} WordRegs;

/* byte registers */

typedef struct _ByteRegs


{
unsigned padding[10];
unsigned char RegBL, RegBH;
unsigned regBLBHpadding;
unsigned char RegDL, RegDH;
unsigned regDLDHpadding;
unsigned char RegCL, RegCH;
unsigned regCLCHpadding;
unsigned char RegAL, RegAH;
unsigned regALAHpadding;
} ByteRegs;

#else

#define SizeofRegArray 13

typedef struct _WordRegs


{
unsigned RegES;
unsigned RegDS;
unsigned RegDI;
unsigned RegSI;
unsigned RegBP;
unsigned RegSP;
unsigned RegBX;
unsigned RegDX;
unsigned RegCX;
unsigned RegAX;

350
Introduction to AutoBios

unsigned RegIP;
unsigned RegCS;
unsigned RegFlags;
} WordRegs;

/* byte registers */

typedef struct _ByteRegs


{
unsigned padding[6];
unsigned char RegBL, RegBH;
unsigned char RegDL, RegDH;
unsigned char RegCL, RegCH;
unsigned char RegAL, RegAH;
} ByteRegs;
#endif

typedef struct _IRegs


{
union
{
#if (CfgCompiler >= 3)
DWordRegs;
#endif
WordRegs;
ByteRegs;
unsigned Array[SizeofRegArray];
};
} Regs;

351
Introduction to AutoBios

5.6 The SysVue.h File


The SysVue.h file provides the definitions required by the SysVue module. It includes a definition of the
SysVue object structure, as well as function prototypes and miscellaneous definitions. Since SysVue has
applicability outside of the AutoBios environment, these definitions are grouped in a separate module.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios SysVue definitons
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] SYSVUE.H
//
// [Language] MSVC 1.0/1.5
//
// [Description] This file is used for Bios definitions
//
// [History] 2.00 04/11/94 Original
//
//
//-----------------------------------------------------------------------

/***********************************************************************
*
* SysVue Definitions
*
********************************************************************/

/* SysVue Function Prototypes */


void interrupt far SysBreak(InterruptRegisters);
/*void interrupt far SysError(InterruptRegisters); */
void interrupt far SysKey(InterruptRegisters);
void interrupt far SysTrace(InterruptRegisters);
void interrupt far SysTrap(InterruptRegisters);
void interrupt far SysVue(InterruptRegisters);

/*void get_line_input(char far * buffer,unsigned buffer_size,char terminator);


*/

/* variables are in system System segment of RAM */

typedef struct _SysVueObject


{
ObjectHeader;
char far * ArgV[MaxArgs];
char LineBuffer[120];

353
The C Programs

struct Tokens
{
union TokenValueStructure
{
char far * CharPtr;
unsigned far * WordPtr;
unsigned long far * LongPtr;
char CharValue[4];
unsigned WordValue[2];
unsigned long LongValue;
} Value;
union TokenMaskStructure
{
unsigned WordMask[2];
unsigned long LongMask;
} ValueMask;
} Token[MaxArgs + 1];

unsigned ArgC;
unsigned long LastDumpSave; // Used by CmdDump.c
char far * ThisTokenPtr; // These two ptrs are used by StrTok
char far * NextTokenPtr;

void far * SysVueBreakChain;


void far * SysVueTraceChain;
void far * SysVueTrapChain;
unsigned SysVueBusy; // 0/1 = not busy/busy
char ModeType,ModeSize; // used by many commands
char Sum; // used by RHex and WHex
char CharCount; // used by RHex and WHex
char ExitFlag; // used by SysVue main loop
char EnterBuffer[16]; // used by CmdEnter.c
unsigned long EnterValue; // used by CmdEnter.c
char HexRecordType;
char HexInChar;
char HexCharToken;
unsigned TraceCount;
struct _BiosObject far * BiosObjectPtr;
struct _IRegs far * RegsPtr;
void far * OldMe;
} SysVueObject;

/* L O C A L D E F I N I T I O N S */

#define TypeAscii 1
#define TypeHex 2

/* Definitions for Read/Write Intel Hex Format */

enum { IntelDataRecord, IntelEOFRecord, IntelAddressRecord,


IntelStartRecord, };

// this enumeration list is used for the register display commands.

enum order
{

354
Introduction to AutoBios

nulreg,
axsave,bxsave,cxsave,dxsave,spsave,
bpsave,sisave,disave,dssave,essave,
sssave,cssave,ipsave,pswsave,
};

enum extendedorder
{
enulreg,
eaxsave,ebxsave,ecxsave,edxsave,espsave,
ebpsave,esisave,edisave,edssave,eessave,
esssave,ecssave,eipsave,epswsave,
};

#define CYbit 0x0001 /* Carry */


#define NCbit 0x0001 /* No Carry */
#define PEbit 0x0004 /* Parity Even */
#define PObit 0x0004 /* Parity Odd */
#define ACbit 0x0010 /* Auxillary Carry */
#define NAbit 0x0010 /* No Auxillary Carry */
#define ZRbit 0x0040 /* Zero */
#define NZbit 0x0040 /* Non-Zero */
#define NGbit 0x0080 /* Negative */
#define PLbit 0x0080 /* Positive */
#define TFbit 0x0100 /* Trap */
#define NTbit 0x0100 /* No Trap */
#define EIbit 0x0200 /* Interrupt Enable */
#define DIbit 0x0200 /* Interrupt Disable */
#define UPbit 0x0400 /* Up Direction */
#define DNbit 0x0400 /* Down Direction */
#define OVbit 0x0800 /* Overflow */
#define NVbit 0x0800 /* No Overflow */

/*--------------------------------------------------------------------*/

/* Shorthand definition for SysVue Object structure pointers */


#define VueRegSet struct _SysVueObject far * Me
#define VueSet Me

char far * StrTok(VueRegSet,char far * String);

/* Command Prototypes */

/* SysVue Command Prototypes */

void CmdChip(VueRegSet);
void CmdBootDump(VueRegSet);
void CmdCompare(VueRegSet);
void CmdCompareAscii(VueRegSet);
void CmdCompareByte(VueRegSet);
void CmdCompareWord(VueRegSet);
void CmdCompareDouble(VueRegSet);
void CmdChecksum(VueRegSet);
void CmdCLS(VueRegSet);
void CmdColdBoot(VueRegSet);
void CmdCmos(VueRegSet);

355
The C Programs

void CmdDate(VueRegSet);
void CmdDevices(VueRegSet);
void CmdDump(VueRegSet);
void CmdDumpAscii(VueRegSet);
void CmdDumpByte(VueRegSet);
void CmdDumpWord(VueRegSet);
void CmdDumpDouble(VueRegSet);
void CmdDrive(VueRegSet);
void CmdEnter(VueRegSet);
void CmdEnterAscii(VueRegSet);
void CmdEnterByte(VueRegSet);
void CmdEnterWord(VueRegSet);
void CmdEnterDouble(VueRegSet);
void CmdExit(VueRegSet);
void CmdFill(VueRegSet);
void CmdFillAscii(VueRegSet);
void CmdFillByte(VueRegSet);
void CmdFillWord(VueRegSet);
void CmdFillDouble(VueRegSet);
void CmdHardBoot(VueRegSet);
void CmdHex(VueRegSet);
void CmdHelp(VueRegSet);
void CmdInPort(VueRegSet);
void CmdInPortByte(VueRegSet);
void CmdInPortWord(VueRegSet);
void CmdInPortCmos(VueRegSet);
//void InvokeInterrupt(VueRegSet);
void CmdLog(VueRegSet);
void CmdMove(VueRegSet);
void CmdMem(VueRegSet);
void CmdOutPort(VueRegSet);
void CmdOutPortByte(VueRegSet);
void CmdOutPortWord(VueRegSet);
void CmdOutPortCmos(VueRegSet);
void CmdOrder(VueRegSet);
void CmdWarmBoot(VueRegSet);
void CmdWHex(VueRegSet);
void CmdRHex(VueRegSet);
void CmdRegDisplay(VueRegSet);
void CmdRAX(VueRegSet);
void CmdRBX(VueRegSet);
void CmdRCX(VueRegSet);
void CmdRBP(VueRegSet);
void CmdRDX(VueRegSet);
void CmdRSP(VueRegSet);
void CmdRSI(VueRegSet);
void CmdRDI(VueRegSet);
void CmdRDS(VueRegSet);
void CmdRES(VueRegSet);
void CmdRSS(VueRegSet);
void CmdRCS(VueRegSet);
void CmdRIP(VueRegSet);
void CmdRF(VueRegSet);
void CmdScan(VueRegSet);
void CmdSysInfo(VueRegSet);
void CmdSearch(VueRegSet);

356
Introduction to AutoBios

void CmdSearchAscii(VueRegSet);
void CmdSearchByte(VueRegSet);
void CmdSearchWord(VueRegSet);
void CmdSearchDouble(VueRegSet);
void CmdSFRDUMPER(VueRegSet);
void CmdSnap(VueRegSet);
void CmdTypes(VueRegSet);
void CmdUser(VueRegSet);
void CmdWatch(VueRegSet);
void CmdTime(VueRegSet);
void CmdTrace(VueRegSet);
void CmdVectors(VueRegSet);
void CmdVideo(VueRegSet);
void CmdToCon(VueRegSet);
void CmdToLpt(VueRegSet);
void CmdObjectDump(VueRegSet);

357
Introduction to AutoBios

5.7 The Virtual.h File


The Virtual.h file provides definitions for the extended memory support features included on AT class
machines. It includes definitions to support testing the extended memory during the power-on, as well as
definitions for the extended memory related Interrupt 15 function calls.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios Virtual Mode Support definitons
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] VIRTUAL.H
//
// [Language] MSVC 1.0/1.5
//
// [Description] This file is used for Bios definitions.
//
// [History] 2.00 04/11/94 Original
//
//
//-----------------------------------------------------------------------

/******** Virtual Mode Support Definitions **********/

#define ErrorPort 0x80


#define EnableA20Command 0xdf
#define DisableA20Command 0xdd
#define PortB 0x61
#define inta00 0x20
#define inta01 0x21
#define intb00 0xa0
#define intb01 0xa1
//status_port equ 064h

//restart_command equ 0feh


#define DisableParity 0x0c
#define EnableParity 0xf3
#define ParityError 0xc0

unsigned NormalGateA20(unsigned value);


#define VirtualEnableBit 1

/*== Global, Local, and Interrupt Descriptor Table structures ==*/

/*------ Code/Data/Gate Descriptor definitions ------*/

359
The C Programs

typedef struct _LDT_ENTRY { /* ldte */


unsigned LimitLow;
unsigned BaseLow;
unsigned char BaseMid;
unsigned char Access;
unsigned char Reserved;
unsigned char BaseHigh;
} LDT_ENTRY, *PLDT_ENTRY;

typedef unsigned short Dummy;

typedef struct _IDT_ENTRY { /* idte */


unsigned OffsetLow;
unsigned Selector;
unsigned char Reserved;
unsigned char GateType;
unsigned OffsetHigh;
} IDT_ENTRY, *PIDT_ENTRY;

typedef unsigned short Dummy;

//--- The Global Descriptor Table for Test/Move Operations -----

// This structure order is determined by the function call format.


// Do not alter it !!!!!!!!

typedef struct StructureMoveGDT


{
LDT_ENTRY MoveNullDescriptor;
LDT_ENTRY MoveGDTDescriptor;
LDT_ENTRY MoveDS;
LDT_ENTRY MoveES;
LDT_ENTRY MoveCS;
LDT_ENTRY MoveSS;
} MoveGDT;

//--- The Global Descriptor Table for Switch Mode Operation ---
//
// This structure order is determined by the function call format.
// Do not alter it !!!!!!!!
typedef unsigned short Dummy;

typedef struct StructureModeGDT


{
LDT_ENTRY ModeNullDescriptor; /* 00 - unusable */
LDT_ENTRY ModeGDTDescriptor; /* 08 - GDT */
LDT_ENTRY ModeIDTDescriptor; /* 10 - IDT */
LDT_ENTRY ModeDS; /* 18 - data */
LDT_ENTRY ModeES; /* 20 - extra */
LDT_ENTRY ModeSS; /* 28 - stack */
LDT_ENTRY ModeCS; /* 30 - code */
LDT_ENTRY ModeBios; /* 38 - bios */
} ModeGDT;

typedef unsigned short Dummy;

360
Introduction to AutoBios

// This is the Virtual Object for AT Extended Mem Function Calls

typedef struct _VirtualObject


{
ObjectHeader;
union
{
MoveGDT VirtualTestGDT;
MoveGDT VirtualMoveGDT;
ModeGDT VirtualModeGDT;
};
} VirtualObject;

unsigned VirtualMove(unsigned,MoveGDT far *);


unsigned VirtualMode(unsigned,ModeGDT far *);
unsigned TestExtendedMemoryOK(void);
unsigned ExtMemTest(void);
unsigned VirtualTestMasm(MoveGDT far *);
unsigned VirtualMoveMasm(unsigned,MoveGDT far *);
unsigned VirtualModeMasm(ModeGDT far *);
void Shutdown(void);

//==================================================================

char __based(__segname("_TEXT"))DelimiterList[];

//---- Hooks to chipset personality module optional functions ----

// This is a chip specific routine in each xxx.Chp file

unsigned ReadChipRegister(unsigned i);

// These are "being implemented".

// Chip Functions - Additional function codes may be added by


// extending the enumeration list.

enum { ChipFastGateA20 = 1,
ChipProtect, ChipFastCPU,
ChipFastResetCPU, ChipFastResetNPX,
};

// Chip Operations on above functions - These should support a


// standard set:
// The returns for "Installed" are T/F, installed/not installed
// If function is installed, then the remaining opcodes are valid.
// If they return True - operation succesfull
// False - operation failed
// The Status call will return a status word ??

enum { ChipInstalled = 1,
ChipStatus, ChipEnable,
ChipDisable,
};

unsigned ChipFunction(unsigned Function,unsigned Operation);

361
The C Programs

362
Introduction to AutoBios

5.8 The BiosPrfx.inc File


The BiosPrfx.inc is the include file used for the assembly (.ASM) modules. It specifies the memory
model, macro definitions, segment loading order for the linker, and required absolute offset locations for
various data and code.

.NOLIST
;*************************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights reserved.
;
; [Product Name] AutoBios
;
; [Module Name] Bios assembly module prefix
;
; [Version] 3.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] BiosPrfx.INC
;
; [Description] This include file is used for the standard definitions
; [Description] for assembly language modules of the bios.
;
; It is used to define the segment names, the segment loading sequence,
; assorted macros, and location assignments.
;
; [History] 2.00 04/11/94 Original
;
;***************************************************************************

.model small,C

include bios.inc

;--- The appropriate processor level directive is set here, based


;--- on the selection in Common.Plt, a Platform.Plt or .Job file

CfgMasm

;--- Declare the segment sequence to insure that the Linker places
;--- them in the proper order !

.seq

_TEXT SEGMENT WORD PUBLIC 'CODE'


_TEXT ENDS

_DATA SEGMENT WORD PUBLIC 'DATA'


_DATA ENDS

CONST SEGMENT WORD PUBLIC 'CONST'

363
The C Programs

CONST ENDS

_BSS SEGMENT WORD PUBLIC 'BSS'


_BSS ENDS

_STACK SEGMENT WORD STACK 'STACK'


_STACK ENDS

_FILL SEGMENT WORD PUBLIC 'FILL'


_FILL ENDS

_ATEXT SEGMENT PARA PUBLIC 'ACODE'


_ATEXT ENDS

;--- All modules use the C conventions for mixed-language compatibility.

;--- This assigns all the segments to a common group for the Linker

DGROUP GROUP _TEXT,_DATA,CONST,_BSS,_FILL,_ATEXT


assume cs:DGROUP,ds:DGROUP

;--- The EXTERNDEF's declare combined public/external symbols ---

EXTERNDEF Restart2:near
EXTERNDEF Restart5:near
EXTERNDEF Restart9:near
EXTERNDEF Restart10:near

EXTERNDEF Reset:near
EXTERNDEF BiosPod:near ; pod module is a destination
EXTERNDEF ORG_FFF0:byte
EXTERNDEF VideoFont:byte

EXTERNDEF ResetHook:near
EXTERNDEF ChipHook1:near
EXTERNDEF ChipHook2:near
EXTERNDEF ChipHook3:near

EXTERNDEF ResumeResetHook:near
EXTERNDEF ResumeChipHook1:near
EXTERNDEF ResumeChipHook2:near
EXTERNDEF ResumeChipHook3:near

; macros for Bios generation

;--- This macro is used to simplify typing in the desired values ---
; for cmos initialization values

CfgDefaultValue macro RegAddr,RegSize,RegValue ; use when size required


WORD RegAddr
WORD RegSize
WORD RegValue

364
Introduction to AutoBios

endm

CmosDefaultValue macro RegAddr,RegValue


WORD RegAddr
WORD RegValue
endm

DefaultValue macro RegAddr,RegValue ; for use with most chips


WORD RegAddr
WORD RegValue
endm

IF CfgCheckPoint
CheckPoint macro arg
mov al,arg
out CfgCheckPointPort,al
endm
ELSE
CheckPoint macro arg
endm
ENDIF

FarJmp macro seg,off


db 0eah
dw off
dw seg
endm

delay macro
jmp $+2
endm

send_eoi macro
push ax
mov al,20h
out 20h,al
delay
out 0a0h,al
pop ax
endm

ReadCmosRegister macro reg


mov al,reg
delay
out CmosRegPort,al ; select the address
delay
in al,CmosDataPort ; get the cmos contents
endm

WriteCmosRegister macro reg,value ; don't use al as the value register !


mov al,reg
delay
out CmosRegPort,al ; select the address
mov al,value
delay

365
The C Programs

out CmosDataPort,al ; write the value


endm

; Bios Equates

dma equ 00 ; dma channel 0 addr reg port addr

pit_port_1 equ 041h

pit_port_cmnd equ 043h

pio_port_b equ 061h ; 8255 port b addr

.data
.LIST
.code

366
Introduction to AutoBios

6. The ASM Modules


These programs are used to include assembly language functions, tables, virtual memory support, and
initial start-up code for the Bios.
This section includes the major modules and the minor individual functions

6.1 Major Modules and Files

6.1.1 The BiosJump.asm Module


The BiosJump.asm File is an assembly language file which is linked so as to reside in the top portion of
the Bios segment. It is the module which responds to the power-on hardware reset of the system. This
module is where the execution of code starts, and is used to reset critical peripheral functions and start
Ram Refresh. A minimum block of Ram is assigned to allow the use of a stack and then control is
transferred to the POD (Power On Diagnostics) routine. This module also contains the assembly
language support functions used by the Bios. The Bios ID and Copyright ASCII text information, the
CPU type byte, the Bios date-stamp, and the Bios checksum byte are also in this module.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] Bios Power-On Jump Module
;
; [Version] 3.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] BiosJump.ASM
;
; [Language] MS MASM 6.1
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
; This module serves this purpose;
; 1. It provides the power-on jump at location FFFF0.
;
; This module is linked as the final module in order for it to respond
; to the hardware reset power-on jump.
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

367
The C Programs

include BiosPrfx.inc

_ATEXT SEGMENT
assume cs:DGROUP

;=== This is the hardware entry point after a reset ===

ORG_FFF0 LABEL BYTE


ORG 00000h
BiosJump proc
FarJmp 0f000h, BiosStart
BiosJump endp

;=== This is the standard location for the date-stamp ===


ORG 00005h

DateStamp proc
BYTE '--/--/--',0
DateStamp endp

; These locations are loaded with the current date by biosdate during
; the build process.

;======== This is the CPU type BYTE ===========


ORG 0000eh
TypeByte proc
BYTE CfgTypeByte
TypeByte endp

; This location is loaded with the type BYTE value by biostype


; during the build process.

;=== This is where the Bios checksum value is stored =====


CheckSumByte proc
BYTE 0
CheckSumByte endp

; This location is loaded with the calculated checksum by biossum


; during the build process.

_ATEXT ENDS

end

368
Introduction to AutoBios

6.1.2 The BiosPad.asm Module


The BiosPad.asm File is an assembly language file used to assign the starting offset of the Bios to a
location greater than 0000 in the segment. If it is desired to reserve space at the beginning of the Bios
segment for optional rom-scan modules, or to reduce the size of the Bios to less than 64 Kbytes in order
to use a smaller-size prom, the biospad module is used to declare the Bios starting offset. A signature is
placed at the beginning of this module to facilitate the detection of secondary and test Bios'. The
signature is a representation of the word "bios" expressed by the hexadecimal characters "b105".
;***********************************************************************
;
; [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] Pad out the front of the bios
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] BiosPad.ASM
;
; [Description] This module is used to fill out the front of the bios
; [Description] prom when a less than 64k bios is desired. The linker
; [Description] always generates a 64k binary image module. The unused
; [Description] locations are preset to all ones (FF) so that prom
; [Description] programmers may skip over these locations. This leaves
; [Description] them unused and available for merging in optional
; [Description]rom-scan modules for an extended custom Bios.
;
; [History] 2.00 04/11/94 Original
;
;**********************************************************************

include BiosPrfx.inc
.code

IFNDEF CfgPad ; This set the starting offset for the Bios
ORG 0000h
ELSE
ORG CfgPad
ENDIF

BiosStart proc
db ProductName
db " - Copyright (c) 1988-1997 John O. Foster"
db " - All Rights Reserved "
BiosStart endp

END

369
The C Programs

370
Introduction to AutoBios

6.1.3 The BiosFill.asm File


The BiosFill.asm File is an assembly language file used during the linking process to upwardly justify
the BiosJump module so that it resides at the end of the Bios segment. During the first Link, the
resulting size of the BiosFill.Obj module is determined by using a zero-length file (BiosBlank.Inc), while
on the second link, a calculated-length file created by BiosGen (BiosFill.Inc) is used. As a result, the
second link produces a Bios file with the location-critical code properly top-justified.
;*************************************************************************
;
; [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] Fill at link time
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] BiosFill.ASM
;
; [Description] Uses BiosFill.inc (generated by BIOSGEN) to fill out
; [Description] area so the BiosTop module will be positioned
; [Description]correctly at the top of the bios.
;
; [History] 2.00 04/11/94 Original
;
;*************************************************************************

include BiosPrfx.inc

_FILL SEGMENT

include Biosfill.inc

_FILL ENDS

end

371
Introduction to AutoBios

6.1.4 The Typing.asm Module


This program exercises some tests on the CPU chip itself, to determine its type. It can detect 8086,
80286, 80386, and 80486 classes. This result is displayed by the SysVue Systen Info (SI) command.
;***********************************************************************
;
; [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MotherBoard Typing Routine
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] Typing.ASM
;
; [Language] MASM 6.1
;
; [Functional Description]
;
; [Description] This routine returns a T/F indicating whether the
; [Description] MotherBoard and CPU were of the type interrogated.

; unsigned MotherBoard(unsigned ask)


; where ask is xt, at, 88, 186, 286, 386, or better.
;
; [History] 2.00 04/11/94 Original
;
;********************************************************************

include BiosPrfx.inc

;/*======= return True if (type == arg) =======*/


;// If you wish to dynamically determine the kind of machine,
;// then these functions will check the type byte.
;// To determine CPU type, expand this function with CPU testing.

;// check for motherboard type


; .model small,c
; .code

;MotherBoard proc ,arg:word


; mov al,cs:[0fffeh]
; xor ah,ah
; xor ax,arg
; jnz @F
; mov ax,True
; ret
;@@: mov ax,False
; ret
;MotherBoard endp

373
The C Programs

; Function cputype(), for real OR protected mode. Returns (in AX)


; the value 86, 186, 286 or 386; negative if protected mode.

.286P ;enable protected-mode instr.

CpuType proc ,ask:word


push bp
push sp ;86/186 will push SP-2,
pop ax ;286/386 will push SP
cmp ax,sp
jz isnot86 ;if equal, SP was pushed
mov ax,186 ;is it 86 or 186?
mov cl,32 ; 186 uses count mod 32 = 0;
shl ax,cl ; 86 shifts 32 so ax = 0
jnz exit ;non-zero: no shift, so 186
mov ax,86 ;zero: shifted out all bits
jmp exit
isnot86:
pushf ;Test 16 or 32 operand size:
mov ax,sp ; pushed 2 or 4 bytes of flags?
popf ; restore SP
inc ax ; restore AX by 2 bytes
inc ax
cmp ax,sp ; did pushf change SP by 2?
jnz is32bit ; if not, then 4 bytes of flags
is16bit:
sub sp,6 ;Is it 286 or 386 in 16-bit mode?
mov bp,sp ;allocate stack space for GDT ptr
sgdt qword ptr [bp] ;(use PWORD PTR for MASM5)
add sp,4 ;discard 2 words of GDT pointer
pop ax ;get third word
inc ah ;286 stores -1, 386 0 or 1
jnz is386
is286:
mov ax,286 ;set return value
jmp testprot
is32bit:
BYTE 66h ;16-bit override in 32-bit mode
is386:
mov ax,386
testprot:
smsw cx ;Protected? Machine status -> CX
ror cx,1 ;protection bit -> carry flag
jnc exit ;real mode if no carry
neg ax ;protected: return neg value
exit: pop bp
ret
CpuType endp

end

374
Introduction to AutoBios

375
Introduction to AutoBios

6.1.5 The Chip.asm Module


The Chip.asm module contains the Masm language chipset support code. During the build process, the
Masm portion of the .Chp module is extracted into a temporary file, "chipasm.tmp" and used as an
include file for this module.
;***********************************************************************
;
; [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] Chip Masm Function(s) Module
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] Chip.ASM
;
; [Description] This module collects the .CHP -> .TMP module to build a
; [Description] chip-specific Masm module.
;
; [History] 2.00 04/11/94 Original
;
;**********************************************************************

include BiosPrfx.inc
include chipasm.tmp

END

377
Introduction to AutoBios

6.1.6 The Virualt.asm File


The Virtual.asm File contains the Masm portion of the virtual mode routines. The higher level C
portions of virtual support are in the SysSrv.c module.
Three major items are handled by the virtual routines:
1. Sizing and testing any extended ram
2. Block move routine which supports Virtual Ram Disks.
3. Switching machine operation to virtual mode.
Default descriptor tables are built for ram test and for the block move. The user needs to build the tables
when switching to virtual mode. The test and the move routines have their own restart sequences, so that
the CPU may be restarted back in real mode, and continue operation.
A restart consists of saving a restart code in the CMOS RAM at location 0F. An error code may be
returned in DMA page register port 80. The values are used to determine what action to take. A signal is
then sent to the 8042 keyboard controller which pulses the reset line to the CPU. The CPU then restarts
in the default real-mode and the restart-code value is checked to see if it is other than a power-up or a
normal reset switch sequence. If a valid restart code value is found in port 80, the BiosJump.asm module
code diverts to the specific restart sequence. This restart sequence then restores the machine state
(registers) and returns control to the program which caused the CPU to go to virtual mode.
The 286 CPU normally starts operation in the real-mode upon power-up. It may be switched to virtual
mode by setting the protection enable (PE) bit in the machine status word (MSW). Because of a quirk in
the original design of the 286 CPU, the only way to switch back to the real-mode, (which is the normal
mode for DOS), is by actually causing a hardware reset of the CPU chip. To permit this, the 8042 output
port has an output line which connects to the 286's reset input line. A command may be sent to the 8042
to pulse this reset line.
The 386 has provision for switching to and from the virtual mode internally by modifying the machine
status register (MSW) by a 386-specific instruction (MOV to Control Register). This enhancement of the
386 negates the need for the complicated restart handling of the 286.
One item about the 286 which is of interest is that there is a Interrupt Descriptor Table Register (IDTR)
which provides the base address of the interrupt vectors. Upon a hardware reset, this register is set to a
value of 0000, so that the base address of the interrupt vector segment is at zero. When switching to
virtual mode, this register is changed to point to an Interrupt Descriptor Table (IDT). This permits the
interrupt vector segment to be re-located without changing the contents of the vector locations. This
basing register is also active in the real-mode (since it defaults to 0000, we are not aware of its existence
in real-mode) and can be used to relocate or substitute multiple sets of interrupt vectors. In standard
DOS practice, however, this option is not exercised.
Why the DMA page register is used to save parameters - During the restart sequence, there are usually
some values that need to be passed from the virtual-mode program back to the real-mode program. These
could be saved in the CMOS RAM, or somewhere in system memory. A very convenient spot that was
originally used on the AT type machines, is the DMA page register chip. In the earlier PC and XT type
of machines, the register was a write only device, which handled the four standard DMA channels. This
chip held the high four bits of the memory address during a DMA transfer, as the 8237 DMA chip only
has 16-bit internal registers. The AT type of machines have an additional 8237 DMA controller for 16-
bit wide data transfers. Now there was a need for 8 page registers (one for each of the 8 DMA channels).
Instead of using two of the XT type chips (74670), a newer chip was selected. This is the 74612 type of
chip. This contains 16 8-bit registers, 8 of which are used for the DMA channels.

379
The C Programs

These registers are both read/write, so two of these are used for passing parameters by the Bios. The
basic restart-type code is passed in location 0F of the CMOS-RAM, but an error-descriptive value is
passed in the page register port at 80, and a second argument may be passed in register port 88.
Notes for potential 386/376 users - The 386, as mentioned previously, has an enhanced mechanism for
switching between real and virtual modes, while the 376 assumes the virtual mode of operation from
reset, since it does not have the real-mode capability.
;---------------------------------------------------------------------
; [Copyright] Copyright (c) 1997 John O. Foster - All rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] Virtual memory support (MASM)
;
; [Version] 3.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] Virtual.ASM
;
; [Language] MASM 6.11
;
; [Description]
;
; [History] 2.00 04/11/94 Original
;
;----------------------------------------------------------------------

include biosprfx.inc

DefaultShutDown macro
mov al,2 ; signify exception error
out CfgVirtualErrorPort,al
mov al,0feh
out Port8042Command,al
@@: hlt
jmp @B
endm

StartLoc equ 00010h


EndLoc equ 0fffeh ; limit for 386

externdef RomIDTDescriptor:near
externdef NullRomIDTDescriptor:near

;---- these are opcodes to be used with the virtual support ------

VirtualTestMasm proc Vptr:FAR PTR MoveGDT


pusha
push ds
push es

380
Introduction to AutoBios

; save stack Description in low ram


mov ax,0
mov ds,ax
;assume ds:LowRam
mov ds:_BiosRam.VirtualSegment,ss
mov ds:_BiosRam.VirtualOffset,sp

lds si,Vptr

LGDT fword ptr ds:[si+MoveGDT.MoveGDTDescriptor]

LIDT fword ptr cs:[RomIDTDescriptor]

CheckPoint(60h)

mov ax,VirtualEnableBit
lmsw ax ; goto virtual mode

jmp $+2 ; this jump to clear queue

db 0eah ; jmp far ptr into cs: selector


; to set access rights
dw next
dw offset MoveGDT.MoveCS
next label byte

cld ; set the direction forward


; SS should select the stack segment
mov ax,offset MoveGDT.MoveSS
mov ss,ax
; DS should select the Virtual Object
mov ax,offset MoveGDT.MoveDS
mov ds,ax
mov dx,StartLoc ; start at 1 Mb - 64K
mov ds:[MoveGDT.MoveES.BaseLow],0 ; set es: segment = xx0000

.WHILE (dx < EndLoc)

mov ds:[MoveGDT.MoveES.BaseMid],dl ; set es: segment


mov ds:[MoveGDT.MoveES.BaseHigh],dh

if CfgVirtualFullTest ; size and test memory

mov ax,offset MoveGDT.MoveES


mov es,ax
sub di,di
sub si,si
mov cx,8000h ; move 64k
; this preloads the block
rep movs word ptr es:[di],word ptr cs:[si]
sub di,di
sub si,si
mov cx,8000h ; compare 64k
; this does the actual test
repe cmps word ptr cs:[si],word ptr es:[di]

381
The C Programs

.BREAK .IF (cx != 0)


sub di,di ; now clear the block
mov cx,8000h ; clear 64k
xor ax,ax
rep stosw
inc dx ; point to the next block

else ; size memory only

mov ax,offset MoveGDT.MoveES


mov es,ax

mov ax,55aah
xchg es:[0fffeh],ax
xchg es:[0fffeh],ax
.BREAK .IF (ax != 55aah)

sub di,di ; now clear the block


mov cx,8000h ; clear 64k
xor ax,ax
rep stosw

inc dx ; point to the next block

endif

.ENDW
sub dx,StartLoc ; rejustify to "0000"
shl dx,6 ; example 256K = 100h

; just return tested OK size - pod can display findings


WriteCmosRegister CmosRegExtMemFoundLow,dl
WriteCmosRegister CmosRegExtMemFoundHigh,dh

; This is the real 386/486 return from the ext mem test

;---- 386 return to real mode procedure -------


cli
LIDT fword ptr cs:[NullRomIDTDescriptor]

mov eax,0
mov CR3,eax

mov eax,CR0
and eax,07ffffffeh
mov CR0,eax

jmp $+2 ; this jump to clear queue

db 0eah ; jmp far ptr into real mode


dw next2
dw 0f000h
next2:
;----- end of 386 return procedure --------

382
Introduction to AutoBios

Restart2 label near


CheckPoint(64h)
WriteCmosRegister CmosRegRestartStatus,0
mov ax,0
mov ds,ax
;assume ds:LowRam

mov ss,ds:_BiosRam.VirtualSegment ; restore the original real stack


mov sp,ds:_BiosRam.VirtualOffset

pop es
pop ds
popa

INVOKE ChipFunction,ChipFastGateA20,ChipDisable
.IF(ax != True)
INVOKE NormalGateA20,DisableA20Command
.IF(ax != True)
mov al,3
out CfgVirtualErrorPort,al
.ENDIF
.ENDIF
CheckPoint(65h)
in al,CfgVirtualErrorPort ; get error port to return
.IF (al == 0)
mov ax,True
.ELSE
mov ax,False
.ENDIF
ret
VirtualTestMasm endp

;--------------------------------------------------------------------

VirtualMoveMasm proc Count:word,Vptr:FAR PTR MoveGDT


pusha
push ds
push es

; save stack Description in low ram


cli
mov ax,0
mov ds,ax
;assume ds:LowRam
mov ds:_BiosRam.VirtualSegment,ss
mov ds:_BiosRam.VirtualOffset, sp

mov cx,Count ; get and save the move count


mov bx,Count

lds si,Vptr

LGDT fword ptr ds:[si+MoveGDT.MoveGDTDescriptor]

LIDT fword ptr cs:[RomIDTDescriptor]

383
The C Programs

mov ax,VirtualEnableBit
lmsw ax ; go into protected mode

delay ; this jump to clear queue


db 0eah ; jmp far ptr into cs: selector
dw continue ; continue executing 2 lines below
dw offset MoveGDT.MoveCS
continue:
mov ax,offset MoveGDT.MoveSS ; set up selectors
mov ss,ax
mov ax,offset MoveGDT.MoveDS
mov ds,ax
mov ax,offset MoveGDT.MoveES
mov es,ax
sub di,di
sub si,si ; word count is already in CX
cld
rep movsw ; this does the actual move

;if CfgVirtualMoveVerify
mov cx,bx ; get copy of count
sub di,di
sub si,si
repe cmpsw
jcxz VerifyOk
mov al,55h ; use 55 for a verify error
out CfgVirtualErrorPort,al
VerifyOk:
;endif
if 0
in al,PortB ; see if a parity error on move
and al,ParityError
.IF (al != 0)
xchg ds:[di],ax ; re-write the bad word
xchg ds:[di],ax
mov al,1 ; set parity error code in bucket
out CfgVirtualErrorPort,al
in al,PortB
delay
or al,DisableParity ; reset parity
out PortB,al
delay
and al,EnableParity
out PortB,al
.ENDIF
endif

;---- 386 return to real mode procedure -------


cli
LIDT fword ptr cs:[NullRomIDTDescriptor]

mov eax,0
mov CR3,eax

mov eax,CR0
and eax,07ffffffeh

384
Introduction to AutoBios

mov CR0,eax

jmp $+2 ; this jump to clear queue

db 0eah ; jmp far ptr into real mode

dw next1
dw 0f000h
next1:

;----- end of 386 return procedure --------

;- This is where the restart from the block moves comes in -

Restart9 label near


WriteCmosRegister CmosRegRestartStatus,0
mov ax,0
mov ds,ax
cli
;assume ds:LowRam

mov ss,ds:_BiosRam.VirtualSegment ; restore the original real stack


mov sp,ds:_BiosRam.VirtualOffset

INVOKE ChipFunction, ChipFastGateA20, ChipDisable


.IF (ax != True)
INVOKE NormalGateA20, DisableA20Command
.IF (ax != True)
mov al,3 ; no - set A20 error code
out CfgVirtualErrorPort,al
.ENDIF
.ENDIF

pop es
pop ds
popa

in al,CfgVirtualErrorPort ; get returning error code


xor ah,ah
sti
ret ; return with error code in AH
VirtualMoveMasm endp

;----------------------------------------------------------------

VirtualModeMasm proc Vptr:FAR PTR StructureModeGDT

lds si,Vptr

LGDT fword ptr ds:[si+StructureModeGDT.ModeGDTDescriptor]

LIDT fword ptr ds:[si+StructureModeGDT.ModeIDTDescriptor]

mov ax,VirtualEnableBit
lmsw ax ; go to protected mode

385
The C Programs

delay ; this jump to clear queue


mov ax,offset StructureModeGDT.ModeDS
mov ds,ax
mov ax,offset StructureModeGDT.ModeES
mov es,ax
mov ax,offset StructureModeGDT.ModeSS
mov ss,ax
pop bx ; get the return address off the stack
add sp,4 ; need to adjust this !!!!
; we may have to back up through the call
; into the Int 15 function to return
; to the real caller. ????
push offset StructureModeGDT.ModeCS ; push cs selector on stack
push bx ; push return on stack
retf ; return to user
VirtualModeMasm endp

; These are the "continue" points for returning from virtual mode to
; real mode, when using the switch to virtual mode function above
; The User MUST disable both interrupts and NMI, and load V_OFFSET and
; V_SEGMENT with a valid continuation address. Then the user must
; load the restart code (5d or 10d (05h or 0ah)) in CMOS location
; xx, then cause a double fault exception to force a CPU reset. Not many
; users get involved in this.
; Programmers Opinion: If you really want to operate in virtual mode,
; get a 386 machine.

Restart5 label near


WriteCmosRegister CmosRegRestartStatus,0
in al,Port8042Data ; purge the keyboard buffer
mov al,20h ; send an EOI to the interrupt controller
out 20h,al ; to purge pending timer interrupts
Restart10 label near
WriteCmosRegister CmosRegRestartStatus,0
mov ax,0 ; voffset is in segment 0040:
mov ds,ax
jmp dword ptr ds:[_BiosRam.VirtualOffset]

ShutDown proc

DefaultShutDown
ShutDown endp

end

386
Introduction to AutoBios

6.2 Minor Modules and Functions

6.2.1 The Beep.asm Function


This function sounds a beep on the internal PC speaker.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Audible Beep Read Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] Beep.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include Biosprfx.inc

beep proc uses ax bx cx dx


mov bx,128 ; 128 cycles last about 1/12 sec.
mov dx,pio_port_b
in al,dx ; save the 8255 port BYTE
mov ah,al
.REPEAT
and al,0fch ; turn the beeper off
out dx,al
mov cx,64 ; make the duty cycle 50%
.REPEAT
.UNTILCXZ ; loop for time delay
or al,2 ; turn the beeper on
out dx,al
mov cx,64 ; leave it on = to the off time
.REPEAT
.UNTILCXZ ; loop for time delay
dec bx
.UNTIL (bx == 0) ; count the major cycles down
mov al,ah ; get the original port BYTE
out dx,al ; restore the 8255 to previous

387
The C Programs

ret
beep endp

end

388
Introduction to AutoBios

6.2.2 The CalcSize.asm Function


This function returns the calculated size of a hard drive based on cylinders, sectors, and heads.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Calculate hard Disk Size Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] CalcSize.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;----- calc the hdisk size - this uses some long unsigneds -----

; unsigned CalcHDiskSize(unsigned cyls,unsigned heads,unsigned sectors);


; returns a value in ax in megaBYTEs
; By doing this in ASM, the C Lib function is not needed.

CalcHDiskSize proc uses dx si,cyls:WORD,heads:WORD,sectors:WORD


xor dx,dx
mov ax,cyls
mov si,heads
mul si
mov si,sectors
mul si
mov si,2000
div si
ret
CalcHDiskSize endp

end

389
Introduction to AutoBios

6.2.3 The ClkMisc.asm Functions


These functions perform the Clock/Calendar Set/Read functions.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Clock Read/Set Functions
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] ClkMisc.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

ClockReadTime proc uses cx ; returns hrs/mins in dx, seconds in ah


mov ax,0200h
int 1ah
.IF(CARRY?) ; if an XT or bad status, zero the cells
xor dx,dx
xor ax,ax
.ENDIF
mov ax,dx
mov dx,cx
ret
ClockReadTime endp

ClockSetTime proc uses cx dx,hours:WORD,minutes:WORD,secs:WORD,daylight:WORD


mov ax,0300h
mov ch,BYTE PTR hours
mov cl,BYTE PTR minutes
mov dh,BYTE PTR secs
mov dl,BYTE PTR daylight
and dl,1
int 1ah
.IF(CARRY?)
mov ax,False
.ELSE

391
The C Programs

mov ax,True
.ENDIF
ret
ClockSetTime endp

ClockReadDate proc uses cx ; returns mon/day in dx, cent/yr in ax


mov ax,0400h
int 1ah
.IF(CARRY?) ; if bad status, zero result
xor cx,cx
.ENDIF
mov ax,cx
ret
ClockReadDate endp

ClockSetDate proc uses cx dx,month:WORD,day:WORD,year:WORD


mov ax,0500h
mov cx,WORD PTR year
;mov ch,BYTE PTR century
;mov cl,BYTE PTR year
mov dh,BYTE PTR month
mov dl,BYTE PTR day
int 1ah
.IF(CARRY?)
mov ax,False
.ELSE
mov ax,True
.ENDIF
ret
ClockSetDate endp

;--------long multiply for setting tod clock ------

; unsigned long LongMultiply(unsigned long,unsigned)

LongMultiply proc uses bx ds,dxax_arg:DWORD,bx_arg:WORD


lds ax,dxax_arg ; retrieve long argument
mov dx,ds ; into DX:AX
mov bx,bx_arg ; get unsigned argument
mul bx ; produce result in DX:AX
ret
LongMultiply endp

ConvertBcdToBinary proc uses cx,arg:BYTE


mov ah,arg ; get BCD argument
mov al,ah ; copy it to AL to begin unpacking BCD char
mov cl,4
shr ah,cl ; justify upper nibble to right
and al,0fh ; discard upper nibble in AL
aad ; converts unpacked BCD to binary
xor ah,ah ; return as unsigned
ret
ConvertBcdToBinary endp

end

392
Introduction to AutoBios

393
Introduction to AutoBios

6.2.4 The ClrObjct.asm Function


This function clears the data area of a released object.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Clear Object Function
;
; [Version] 3.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] ClrObjct.asm
;
; [Language] MS MASM 6.11
;
; [Purpose] This function clears the specified object (called with ptr)
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;---------- clear a de-allocated block ------------

ClearObject proc near uses ax cx es di,farjaddr:FAR PTR


les di,farjaddr
.IF (!(BYTE PTR es:[di] & 0fh)) ; if count !para, bad block !!
mov cx,es:[di] ; get count from block
.IF (cx != 0) ; skip if block count = 0
xor ax,ax
rep stos BYTE PTR es:[di]
.ENDIF
.ENDIF
ret
ClearObject endp

end

395
Introduction to AutoBios

6.2.5 The CmosTble.asm File


This file contains a table of the Cmos Default values as detemrined by the configuration definitions. It is
loaded into Cmos memory on an AT platform if CfgCmosInit is True, or as a lookup table for XT
platforms.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Cmos Default Table
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] CmosTble.asm
;
; [Language] MS MASM 6.11
;
; [Purpose] Provides Cmos Default Initialization Table
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

public CmosDefaultTable
CmosDefaultTable WordWordList {1,1}

; ---- Build the Floppy Drive defaults ------

DiskType = 0 ; use temp accumulator


EquipTemp = 0

; Force the Status Registers in case they don't default normally


CmosDefaultValue CmosRegStatusA, 26h
CmosDefaultValue CmosRegStatusB, 02h

ifdef CfgDisk1Type

if (CfgDisk1Type EQ 360)
DiskType = 10h
endif
if (CfgDisk1Type EQ 1200)
DiskType = 20h
endif

397
The C Programs

if (CfgDisk1Type EQ 720)
DiskType = 30h
endif
if (CfgDisk1Type EQ 1440)
DiskType = 40h
endif
if (CfgDisk1Type EQ 2880)
DiskType = 50h
endif

EquipTemp = 1
endif

ifdef CfgDisk2Type

if (CfgDisk2Type EQ 360)
DiskType = DiskType OR 01h
endif
if (CfgDisk2Type EQ 1200)
DiskType = DiskType OR 02h
endif
if (CfgDisk2Type EQ 720)
DiskType = DiskType OR 03h
endif
if (CfgDisk2Type EQ 1440)
DiskType = DiskType OR 04h
endif
if (CfgDisk2Type EQ 2880)
DiskType = DiskType OR 05h
endif

EquipTemp = 41h
endif

CmosDefaultValue CmosRegDiskDriveType, DiskType

ifdef CfgVideoType

if (CfgVideoType EQ VGA)
EquipTemp = EquipTemp OR 00h
endif
if (CfgVideoType EQ CGA40)
EquipTemp = EquipTemp OR 10h
endif
if (CfgVideoType EQ CGA)
EquipTemp = EquipTemp OR 20h
endif
if (CfgVideoType EQ CGA80)
EquipTemp = EquipTemp OR 20h
endif
if (CfgVideoType EQ Mono)
EquipTemp = EquipTemp OR 30h
endif

endif

398
Introduction to AutoBios

CmosDefaultValue CmosRegEquipment, EquipTemp

; ---- Build the Hard Drive defaults ------

HardType = 0 ; use temp accumulator

ifdef CfgHard1Type
if CfgHard1Type LE 15
HardType = CfgHard1Type * 16
else
HardType = 0f0h
CmosDefaultValue CmosRegExtendedDriveC,CfgHard1Type
endif
endif

ifdef CfgHard2Type
if CfgHard2Type LE 15
HardType = HardType OR CfgHard2Type
else
HardType = HardType OR 00fh
CmosDefaultValue CmosRegExtendedDriveD,CfgHard2Type
endif
endif
CmosDefaultValue CmosRegHardDriveType,HardType

; ---- Build the User defined Hard Drive defaults ------

ifdef CfgHard47Cyls
ifdef CfgHard47Heads
ifdef CfgHard47Sectors
CmosDefaultValue CmosRegDrive47CylLow, LOW CfgHard47Cyls
CmosDefaultValue CmosRegDrive47CylHigh, HIGH CfgHard47Cyls
CmosDefaultValue CmosRegDrive47Heads, CfgHard47Heads
CmosDefaultValue CmosRegDrive47Sectors, CfgHard47Sectors
endif
endif
endif

ifdef CfgHard48Cyls
ifdef CfgHard48Heads
ifdef CfgHard48Sectors
CmosDefaultValue CmosRegDrive48CylLow, LOW CfgHard48Cyls
CmosDefaultValue CmosRegDrive48CylHigh, HIGH CfgHard48Cyls
CmosDefaultValue CmosRegDrive48Heads, CfgHard48Heads
CmosDefaultValue CmosRegDrive48Sectors, CfgHard48Sectors
endif
endif
endif

;-- Build the Boot Order flag ----

ifdef CfgBootOrder
CmosDefaultValue CmosRegOptionFlags, CfgBootOrder
else
CmosDefaultValue CmosRegOptionFlags, 0
endif

399
The C Programs

ifdef CfgBaseMem
CmosDefaultValue CmosRegBaseMemHigh, HIGH CfgBaseMem
CmosDefaultValue CmosRegBaseMemLow, LOW CfgBaseMem
endif

ifdef CfgExtMem
CmosDefaultValue CmosRegExtMemHigh, HIGH CfgExtMem
CmosDefaultValue CmosRegExtMemLow, LOW CfgExtMem
endif

ifdef CfgCmosData
dw CfgCmosData
endif

CmosDefaultValue -1,-1 ; -1 Arguments indicate End of Table

end

400
Introduction to AutoBios

6.2.6 The CTypes.asm Function


These functions return information about the attributes of an ASCII character.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Character Types Functions
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] CTypes.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose]
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

; This is a definition table for using character macros


; However, the compiler may generate more code using macros
; then it would calling functions, so the functions are also
; coded, giving the option of using either.

_U equ 001H ; UPPER - upper case letter A-Z


_L equ 002H ; LOWER - lower case letter a-z
_N equ 004H ; DIGIT - digit 0-9
_S equ 008H ; SPACE - whitespace tab, cr,newline, vt, ff
_P equ 010H ; PUNCT - punctuation character
_C equ 020H ; CONTROL - control
_B equ 040H ; BLANK - space char
_X equ 080H ; HEX - hexadecimal digit 0-9, a-f, A-F

public _ctype
public _ctype_

_ctype LABEL BYTE


_ctype_ LABEL BYTE

BYTE _C ; 000
BYTE _C ; 001
BYTE _C ; 002

401
The C Programs

BYTE _C ; 003
BYTE _C ; 004
BYTE _C ; 005
BYTE _C ; 006
BYTE _C ; 007
BYTE _C ; 008
BYTE _S+_C ; 009
BYTE _S+_C ; 00A
BYTE _S+_C ; 00B
BYTE _S+_C ; 00C
BYTE _S+_C ; 00D
BYTE _C ; 00E
BYTE _C ; 00F
BYTE _C ; 010
BYTE _C ; 011
BYTE _C ; 012
BYTE _C ; 013
BYTE _C ; 014
BYTE _C ; 015
BYTE _C ; 016
BYTE _C ; 017
BYTE _C ; 018
BYTE _C ; 019
BYTE _C ; 01A
BYTE _C ; 01B
BYTE _C ; 01C
BYTE _C ; 01D
BYTE _C ; 01E
BYTE _C ; 01F
BYTE _S+_B ; 020
BYTE _P ; 021
BYTE _P ; 022
BYTE _P ; 023
BYTE _P ; 024
BYTE _P ; 025
BYTE _P ; 026
BYTE _P ; 027
BYTE _P ; 028
BYTE _P ; 029
BYTE _P ; 02A
BYTE _P ; 02B
BYTE _P ; 02C
BYTE _P ; 02D
BYTE _P ; 02E
BYTE _P ; 02F
BYTE _N+_X ; 030
BYTE _N+_X ; 031
BYTE _N+_X ; 032
BYTE _N+_X ; 033
BYTE _N+_X ; 034
BYTE _N+_X ; 035
BYTE _N+_X ; 036
BYTE _N+_X ; 037
BYTE _N+_X ; 038
BYTE _N+_X ; 039
BYTE _P ; 03A

402
Introduction to AutoBios

BYTE _P ; 03B
BYTE _P ; 03C
BYTE _P ; 03D
BYTE _P ; 03E
BYTE _P ; 03F
BYTE _P ; 040
BYTE _U+_X ; 041
BYTE _U+_X ; 042
BYTE _U+_X ; 043
BYTE _U+_X ; 044
BYTE _U+_X ; 045
BYTE _U+_X ; 046
BYTE _U ; 047
BYTE _U ; 048
BYTE _U ; 049
BYTE _U ; 04A
BYTE _U ; 04B
BYTE _U ; 04C
BYTE _U ; 04D
BYTE _U ; 04E
BYTE _U ; 04F
BYTE _U ; 050
BYTE _U ; 051
BYTE _U ; 052
BYTE _U ; 053
BYTE _U ; 054
BYTE _U ; 055
BYTE _U ; 056
BYTE _U ; 057
BYTE _U ; 058
BYTE _U ; 059
BYTE _U ; 05A
BYTE _P ; 05B
BYTE _P ; 05C
BYTE _P ; 05D
BYTE _P ; 05E
BYTE _P ; 05F
BYTE _P ; 060
BYTE _L+_X ; 061
BYTE _L+_X ; 062
BYTE _L+_X ; 063
BYTE _L+_X ; 064
BYTE _L+_X ; 065
BYTE _L+_X ; 066
BYTE _L ; 067
BYTE _L ; 068
BYTE _L ; 069
BYTE _L ; 06A
BYTE _L ; 06B
BYTE _L ; 06C
BYTE _L ; 06D
BYTE _L ; 06E
BYTE _L ; 06F
BYTE _L ; 070
BYTE _L ; 071
BYTE _L ; 072

403
The C Programs

BYTE _L ; 073
BYTE _L ; 074
BYTE _L ; 075
BYTE _L ; 076
BYTE _L ; 077
BYTE _L ; 078
BYTE _L ; 079
BYTE _L ; 07A
BYTE _P ; 07B
BYTE _P ; 07C
BYTE _P ; 07D
BYTE _P ; 07E
BYTE _C ; 07F
BYTE 128 dup (0)

ctype macro arg


mov ah,arg
push bx
mov bx,offset _ctype
mov al,char
xlatb cs:[bx] ; get the bit code for this character in al
pop bx
and al,ah ; and it with the desired pattern
xor ah,ah ; if result = 0, then False, = 1 then True
endm

IsAlpha proc uses bx,char:BYTE


ctype < _U + _L >
ret
IsAlpha endp

IsUpper proc uses bx,char:BYTE


ctype _U
ret
IsUpper endp

IsLower proc uses bx,char:BYTE


ctype _L
ret
IsLower endp

IsDigit proc uses bx,char:BYTE


ctype _N
ret
IsDigit endp

IsHexDigit proc uses bx,char:BYTE


ctype _X
ret
IsHexDigit endp

IsSpace proc uses bx,char:BYTE


ctype _S
ret
IsSpace endp

404
Introduction to AutoBios

IsPunct proc uses bx,char:BYTE


ctype _P
ret
IsPunct endp

isalnum proc uses bx,char:BYTE


ctype < _U + _L + _N >
ret
isalnum endp

IsPrint proc uses bx,char:BYTE


ctype < _B + _P + _U + _L + _N >
ret
IsPrint endp

IsGraph proc uses bx,char:BYTE


ctype < _P + _U + _L + _N >
ret
IsGraph endp

IsCntrl proc uses bx,char:BYTE


ctype _C
ret
IsCntrl endp

IsAscii proc char:BYTE


.IF (char >= ' ') && (char <= 7eh)
mov ax,True
.ELSE
mov ax,False
.ENDIF
cmp char,20h
jb no
cmp char,7eh
ja no
yes: mov ax,True
ret
no: mov ax,False
ret
IsAscii endp

ToUpper proc char:BYTE


INVOKE IsLower,char
.IF (ax != False)
and char,0dfh
.ENDIF
mov al,char
xor ah,ah
ret
ToUpper endp

ToLower proc char:BYTE


INVOKE IsUpper,char
.IF (ax != False)

405
The C Programs

or char,20h
.ENDIF
mov al,char
xor ah,ah
ret
ToLower endp

end

406
Introduction to AutoBios

6.2.7 The Delay.asm Function


This function returns to the caller after a specified delay, of micro, milli, or seconds..
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.

;
; [Product Name] AutoBios
;
; [Module Name] MASM DelayCall Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] Delay.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

; void delay_call(unsigned count,unsigned resolution);


; values for resolution descriptor

DelayCall proc uses ax cx dx ds,count:WORD,res:WORD


.IF (res == Microseconds)
mov cx,count ; load the count
shr cx,1 ; divide it by 4
shr cx,1 ; then add the count for 1.25 * count
add cx,count ; cx = count * 1.25 *.8us = about 1 us
shl cx,1 ; double the count because the counter
; decrements by 2
call read_timer_count ; do a double read
call read_timer_count

.IF (ax <= cx) ; counter lower than delay-count


.REPEAT ; stall until timer rolls over
call read_timer_count
.UNTIL (ax > cx)
.ENDIF
sub ax,cx ; subtract desired count from current count
mov cx,ax
.REPEAT

407
The C Programs

call read_timer_count
.UNTIL (ax <= cx) ; delay until current count <= calced count
.ELSE
.IF (res == Milliseconds)
mov cx,count ; this is major loop
.REPEAT
INVOKE DelayCall,1000,Microseconds
.UNTILCXZ ; repeat major loop for total counts
.ELSE
.IF (res == Seconds)
mov cx,count ; this is major loop
.REPEAT
INVOKE DelayCall,1000,Milliseconds
.UNTILCXZ ; repeat major loop for total counts
.ENDIF
.ENDIF
.ENDIF
ret
DelayCall endp

read_timer_count proc ; each count = .4 usecs


; only even counts will be read
xor al,al ; latch timer 0 count into storage register
out 43h,al
jmp @F ; delay for 8253 response
@@: jmp @F
@@: jmp @F
@@: in al,40h
mov ah,al
jmp @F ; delay for 8253 response
@@: jmp @F
@@: jmp @F
@@: in al,40h
xchg ah,al
; shl ax,1 ; return a change every .8 usecs
ret ; return count in ax
read_timer_count endp

; Note: Remember that the counters in the 8253/8254 are down counters,
; so that we have to subtract the desired count from the current count.
; The tick timer runs in Mode 3, so that counts are decremented by two (2)
; on the falling edge of each clock pulse (every .8 usecs).

end

408
Introduction to AutoBios

6.2.8 The DskChain.asm Function


This function performs the detection of a disk call to determine whether to route it to the floppy or hard
disk service.
;***********************************************************************
;
; [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Disk Vector Chaining Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DskRead.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

; this chains the hard -> floppy disk

if CfgHard
FDiskChain proc near ; sits at vector 13 if hdisk installed
.IF (dl & 80h)
jmp near ptr HDiskFunctionCall
.ELSE
int 40h
retf 2
.ENDIF
ret
FDiskChain endp

endif
;------------------------------------------------------------------
; returns the high order word of an unsigned long integer as an
; unsigned in ax
; unsigned GetHighOfLong(unsigned long)
;
if CfgHard

GetHighOfLong proc arg:DWORD

409
The C Programs

mov ax,Word PTR arg+2


ret
GetHighOfLong endp

endif

end

410
Introduction to AutoBios

6.2.9 The DskDiag.asm Function


This function is an optimized function call.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Disk Diagnostic Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DskDiag.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

CallDiskDiagnostic proc uses dx ; returns True if OK


mov ax,1400h
mov dl,80h
int 13h
.IF (!CARRY?)
mov ax,True
.ELSE
mov ax,False
.ENDIF
ret
CallDiskDiagnostic endp

end

411
Introduction to AutoBios

6.2.10 The DskInit.asm Function


This function is an optimized function call.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Disk Init Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DskInit.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose]
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

CallDiskInitDrive proc uses dx, unit:WORD ; returns True if OK


mov ax,0900h
mov dl,BYTE PTR unit
int 13h
.IF (!CARRY?)
mov ax,True
.ELSE
mov ax,False
.ENDIF
ret
CallDiskInitDrive endp

end

413
Introduction to AutoBios

6.2.11 The DskRead.asm Function


This function is an optimized function call.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Disk Read Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DskRead.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;unsigned CallDiskRead(unsigned Drive, unsigned NrSectors,unsigned Track,


; unsigned Head,unsigned Sector,char far *Buffer);

CallDiskRead proc uses bx cx dx es, unit:WORD,nr_sectors:WORD, \


track:WORD,head:WORD,sector:WORD,buffer_address:FAR PTR BYTE
mov ah,02
mov al,BYTE PTR nr_sectors
mov ch,BYTE PTR track
mov cl,BYTE PTR sector
mov dh,BYTE PTR head
mov dl,BYTE PTR unit
les bx,buffer_address
int 13h
.IF (!CARRY?)
mov ax,True
.ELSE
mov ax,False
.ENDIF
ret
CallDiskRead endp

end

415
The C Programs

416
Introduction to AutoBios

6.2.12 The DskRecal.asm Function


This function is an optimized function call.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Disk Recalibrate Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DskRecal.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose]
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

CallDiskRecalibrate proc uses dx, unit:WORD ; returns True if OK


mov ax,1100h
mov dl,BYTE PTR unit
int 13h
.IF (!CARRY?)
mov ax,True
.ELSE
mov ax,False
.ENDIF
ret
CallDiskRecalibrate endp

end

417
Introduction to AutoBios

6.2.13 The DskReset.asm Function


This function is an optimized function call.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Disk Reset Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DskReset.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

CallDiskReset proc uses dx,unit:WORD ; returns True if reset OK


xor ax,ax
mov dl,BYTE PTR unit
int 13h
.IF (!CARRY?)
mov ax,True
.ELSE
mov ax,False
.ENDIF
ret
CallDiskReset endp

end

419
Introduction to AutoBios

6.2.14 The DummyIrt.asm Function


This is a Dummy or Null Interrupt Return.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Dummy Iret Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DummyIrt.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose]
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

DummyIret proc
iret
DummyIret endp

end

421
Introduction to AutoBios

6.2.15 The GetBios.asm Function


This function returns the address of the Bios Object.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM GetBiosObject Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] GetBios.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

; void far * GetBiosObject(void);


; Returns DX:AX = BiosObject far ptr
GetBiosObject proc uses ds
xor ax,ax
mov ds,ax
mov ds,ds:[SystemLocation]
lds ax,ds:SystemObject.Bios_Ptr
mov dx,ds
ret
GetBiosObject endp

end

423
Introduction to AutoBios

6.2.16 The GetChar.asm Function


This function returns a character from the standard input device, normally the Keyboard.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Get Character Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] GetChar.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;=========== Console In Routine - GetChar(void) ===============

;unsigned GetChar(void);
GetChar proc
xor ax,ax
int 16h
ret
GetChar endp

;=========== Console In with Echo - GetCharEcho(void) ===============

;unsigned GetCharEcho(void);
GetCharEcho proc uses bx
xor ax,ax
int 16h
push ax
mov ah,0eh
mov bx,0
int 10h
pop ax
ret
GetCharEcho endp

425
The C Programs

end

426
Introduction to AutoBios

6.2.17 The GetRegs.asm Function


This function returns the value of the specified register.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Get Registers Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] GetRegs.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;-- get the current stack segment value --


; unsigned get_ss(void);

GetSS proc
mov ax,ss
ret
GetSS endp

GetSP proc
mov ax,sp
add ax,2 ; return value before the call
ret
GetSP endp

GetES proc
mov ax,es
ret
GetES endp

GetCS proc
mov ax,cs
ret
GetCS endp

427
The C Programs

GetDS proc
mov ax,ds
ret
GetDS endp

GetDH proc
mov al,dh
ret
GetDH endp

GetDL proc
mov al,dl
ret
GetDL endp

end

428
Introduction to AutoBios

6.2.18 The GetSys.asm Function


This function returns the address of the System Object.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM GetSystemObject Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] GetSys.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

; void far * GetSystemObject(void);


; Returns DX:AX = SystemSegmenPointer:0
GetSystemObject proc uses ds
xor ax,ax
mov ds,ax
mov dx,ds:[SystemLocation]
ret
GetSystemObject endp

end

429
Introduction to AutoBios

6.2.19 The GetVirt.asm Function


This function returns the address of the Virtual Object.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM GetVirtualObject Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] GetVirt.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

; void far * GetVirtualObject(void);


; Returns DX:AX = BiosObject far ptr
GetVirtualObject proc uses ds
xor ax,ax
mov ds,ax
mov ds,ds:[SystemLocation]
lds ax,ds:SystemObject.VirtualPtr
mov dx,ds
ret
GetVirtualObject endp

end

431
Introduction to AutoBios

6.2.20 The HardTble.asm File


This table contains the descriptive parameters for the hard drive types.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;

; [Product Name] AutoBios


;
; [Module Name] MASM Hard Disk Parameter Table
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DskRead.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

IF CfgHard
; This is where the hard disk table can reside. There is room for
; 60-70 entries as needed. You may modify these entries to support
; the disk types you desire.

drive_type macro a1,a2,a3,a4,a5,a6,a7


HDTable <a2,a3,0,a4,0,a5,0,0,0,a6,a7,0>
endm

;ALIGN 16

public HDiskTable

HDiskTable LABEL BYTE


; [Extract] [HELP]
; Hard Drive Type Table as defined in BiosTop.Asm
drive_type 1, 306, 4,128,0, 305,17
drive_type 2, 615, 4,300,0, 615,17
drive_type 3, 615, 6,300,0, 615,17
drive_type 4, 940, 8,512,0, 940,17
drive_type 5, 940, 6,512,0, 940,17
drive_type 6, 615, 4, -1,0, 615,17

433
The C Programs

drive_type 7, 462, 8,256,0, 511,17


drive_type 8, 733, 5, -1,0, 733,17
drive_type 9, 900,15, -1,8, 901,17
drive_type 10,820, 3, -1,0, 820,17
drive_type 11,855, 5, -1,0, 855,17
drive_type 12,855, 7, -1,0, 855,17
drive_type 13,306, 8,128,0, 319,17
drive_type 14,733, 7, -1,0, 733,17
drive_type 15, 0, 0, 0,0, 0, 0
drive_type 16,612, 4, 0,0, 663,17
drive_type 17,977, 5,300,0, 977,17
drive_type 18,977, 7, -1,0, 977,17
drive_type 19,1024,7,512,0,1023,17
drive_type 20,733, 5,300,0, 732,17
drive_type 21,733, 7,300,0, 733,17
drive_type 22,733, 5,300,0, 733,17
drive_type 23,306, 4, 0,0, 336,17
drive_type 24,612, 4,305,0, 663,17
drive_type 25,306, 4, -1,0, 340,17
drive_type 26,612, 4, -1,0, 670,17
drive_type 27,698, 7,300,0, 732,17
drive_type 28,976, 5,488,0, 977,17
drive_type 29,306, 4, 0,0, 340,17
drive_type 30,611, 4,306,0, 663,17
drive_type 31,732, 7,300,0, 732,17
drive_type 32,1023,5, -1,0,1023,17
drive_type 33,306, 2, -1,0, 305,17
drive_type 34,612, 4,305,0, 663,17
drive_type 35,306, 4, -1,0, 340,17
drive_type 36,612, 4, -1,0, 670,17
drive_type 37,698, 7,300,0, 732,17
drive_type 38,976, 5,488,0, 977,17
drive_type 39,306, 4, 0,0, 340,17
drive_type 40,611, 4,306,0, 663,17
drive_type 41,732, 7,300,0, 732,17
drive_type 42,1023,5, -1,0,1023,17
drive_type 43,306, 2, -1,0, 305,17
drive_type 44,612, 4,305,0, 663,17
drive_type 45,306, 4, -1,0, 340,17
drive_type 46,612, 4, -1,0, 670,17
; User defined types 47 & 48 are also available

; [Break]
; The SysVue "TYPES" Command looks for this following
; entry to sense the end of the hard drive parameter table.
drive_type -1,-1,-1,-1,-1,-1,-1 ; end of table
ENDIF

end

434
Introduction to AutoBios

6.2.21 The IDString.asm File


This file contains the text Identification Strings for the Bios.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Identification Strings
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] IDstrings.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

BiosID proc
ifdef CfgBiosID
BYTE CfgBiosID,0
else
BYTE ProductName,0
endif
BiosID endp

VersionID proc
ifdef CfgProjectVersion
BYTE CfgProjectVersion,0
else
BYTE "Version 1.00 ",0
endif
VersionID endp

CustomerID proc
ifdef CfgProjectCustomer
BYTE CfgProjectCustomer,0
else
BYTE "Software Farm",0
endif
CustomerID endp

435
The C Programs

name_id proc
BYTE ProductName,0
name_id endp

PartNrID proc
ifdef CfgProjectPartNr
BYTE CfgProjectPartNr,0
else
BYTE "92xxxxx-xxxxx",0
endif
PartNrID endp

OwnerID proc

BYTE "Copyright (c) John O. Foster 1988-1997 - All Rights Reserved ",0

OwnerID endp

end

436
Introduction to AutoBios

6.2.22 The KbTable.asm File


This file contains the scan code to key code translation table for the keyboard service routine.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Keyboard Translation Table
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] KbTable.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides the translation table from scan codes to key codes
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;======== This is the keyboard table ====================

;char KbTable[89][4];
; This table covers all keys.
;** Some keys are pre-checked for special handling.
;** Some special keys are padded out in this table.
;** The format is: base,upper,ctrl,alt cases.
;** The alt cases are handled as extended codes.

public KbTable
KbTable label byte

BYTE 0 ,0 ,0 ,0 ; base 0 padding for indexing


BYTE 27 ,27 ,27 ,-1 ; key 1 - Escape key
BYTE '1','!',-1 ,120 ; key 2 - '1'
BYTE '2','@',0 ,121 ; key 3 - '2' - special handling
BYTE '3','#',-1 ,122 ; key 4 - '3'
BYTE '4','$',-1 ,123 ; key 5 - '4'
BYTE '5','%',-1 ,124 ; key 6 - '5'
BYTE '6','^',30 ,125 ; key 7 - '6'
BYTE '7','&',-1 ,126 ; key 8 - '7'
BYTE '8','*',-1 ,127 ; key 9 - '8'

437
The C Programs

BYTE '9','(',-1 ,128 ; key 10 - '9'


BYTE '0',')',-1 ,129 ; key 11 - '0'
BYTE '-','_',31 ,130 ; key 12 - '-'
BYTE '=','+',-1 ,131 ; key 13 - '='
BYTE 8 ,8 ,127, -1 ; key 14 - backspace
BYTE 9 ,-1 ,-1 , -1 ; key 15 - tab
BYTE 'q','Q',17 , 16 ; key 16 - 'Q'
BYTE 'w','W',23 , 17 ; key 17 - 'W'
BYTE 'e','E',5 , 18 ; key 18 - 'E'
BYTE 'r','R',18 , 19 ; key 19 - 'R'
BYTE 't','T',20 , 20 ; key 20 - 'T'
BYTE 'y','Y',25 , 21 ; key 21 - 'Y'
BYTE 'u','U',21 , 22 ; key 22 - 'U'
BYTE 'i','I',9 , 23 ; key 23 - 'I'
BYTE 'o','O',15 , 24 ; key 24 - 'O'
BYTE 'p','P',16 , 25 ; key 25 - 'P'
BYTE '[','}',27 , -1 ; key 26 - '['
BYTE ']','}',29 , -1 ; key 27 - ']'
BYTE 13 ,13 ,10 , -1 ; key 28 - CR
BYTE -1 ,-1 ,-1 , -1 ; key 29 - control shift
BYTE 'a','A',1 , 30 ; key 30 - 'A'
BYTE 's','S',19 , 31 ; key 31 - 'S'
BYTE 'd','D',4 , 32 ; key 32 - 'D'
BYTE 'f','F',6 , 33 ; key 33 - 'F'
BYTE 'g','G',7 , 34 ; key 34 - 'G'
BYTE 'h','H',8 , 35 ; key 35 - 'H'
BYTE 'j','J',10 , 36 ; key 36 - 'J'
BYTE 'k','K',11 , 37 ; key 37 - 'K'
BYTE 'l','L',12 , 38 ; key 38 - 'L'
BYTE ';',':',-1 , -1 ; key 39 - ';'
BYTE 39,'"' ,-1 , -1 ; key 40 - '''
BYTE '`','~',-1 , -1 ; key 41 - '`'
BYTE -1 ,-1 ,-1 , -1 ; key 42 - left shift
BYTE 92,'|',28 , -1 ; key 43 - '\'
BYTE 'z','Z',26 , 44 ; key 44 - 'Z'
BYTE 'x','X',24 , 45 ; key 45 - 'X'
BYTE 'c','C',3 , 46 ; key 46 - 'C'
BYTE 'v','V',22 , 47 ; key 47 - 'V'
BYTE 'b','B',2 , 48 ; key 48 - 'B'
BYTE 'n','N',14 , 49 ; key 49 - 'N'
BYTE 'm','M',13 , 50 ; key 50 - 'M'
BYTE ',','<',-1 , -1 ; key 51 - ','
BYTE '.','>',-1 , -1 ; key 52 - '.'
BYTE '/','?',-1 , -1 ; key 53 - '/'
BYTE -1 ,-1 ,-1 , -1 ; key 54 - right shift -
BYTE '*',-1,114, -1 ; key 55 - prt-scr -
BYTE -1 ,-1 ,-1, -1 ; key 56 - Alt -
BYTE 32 ,32 ,32 , 32 ; key 57 - space bar
BYTE -1 ,-1 ,-1, -1 ; key 58 - caps-lock -
; function key cases
BYTE 59 ,84 ,94 ,104 ; key 59 - F1Key
BYTE 60 ,85 ,95 ,105 ; key 60 - F2Key
BYTE 61 ,86 ,96 ,106 ; key 61 - F3Key
BYTE 62 ,87 ,97 ,107 ; key 62 - F4Key
BYTE 63 ,88 ,98 ,108 ; key 63 - F5Key
BYTE 64 ,89 ,99 ,109 ; key 64 - F6Key

438
Introduction to AutoBios

BYTE 65 ,90 ,100,110 ; key 65 - F7Key


BYTE 66 ,91 ,101,111 ; key 66 - F8Key
BYTE 67 ,92 ,102,112 ; key 67 - F9Key
BYTE 68 ,93 ,103,113 ; key 68 - F10Key
BYTE -1 ,-1 ,-1 ,-1 ; key 69 - num-lock -
BYTE -1 ,-1 ,-1 ,-1 ; key 70 - scroll-lock -
; num key pad - cases are base,upper,ctrl,alt
BYTE 71 ,'7',119,-1 ; key 71 - home
BYTE 72 ,'8',-1 ,-1 ; key 72 - cursor up
BYTE 73 ,'9',132,-1 ; key 73 - page up
BYTE '-','-',-1 ,-1 ; key 74 - minus sign
BYTE 75 ,'4',115,-1 ; key 75 - cursor left
BYTE -1 ,'5',-1 ,-1 ; key 76 - center key
BYTE 77 ,'6',116,-1 ; key 77 - cursor right
BYTE '+','+',-1 ,-1 ; key 78 - plus sign
BYTE 79 ,'1',117,-1 ; key 79 - end
BYTE 80 ,'2',-1 ,-1 ; key 80 - cursor down
BYTE 81 ,'3',118,-1 ; key 81 - page down
BYTE 82 ,'0',-1 ,-1 ; key 82 - insert
BYTE 83 ,'.',-1 ,-1 ; key 83 - delete
BYTE -1 , -1,-1 ,-1 ; key 84 - sys key
BYTE -1 , -1,-1 ,-1 ; key 85
BYTE -1 , -1,-1 ,-1 ; key 86
BYTE 133,135,137,139 ; key 87 - F11Key
BYTE 134,136,138,140 ; key 88 - F12Key

end

439
Introduction to AutoBios

6.2.23 The PutChVid.asm Function


This function writes a character to the display device.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Put Char Video Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] PutChVid.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

; console out routine


; unsigned putcharvideo(char); // returns output character

PutCharVideo proc uses bx, char:BYTE


mov ah,0eh
mov al,char
mov bx,0
int 10h
mov al,char
xor ah,ah
ret
PutCharVideo endp

end

441
Introduction to AutoBios

6.2.24 The RepInOut.asm Functions


These functions perform the block transfers of hard disk data.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Hard Disk Repeated In/Out Functions
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] DskRead.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

RepeatIn proc uses es di cx dx,XfrAddress:FAR PTR,port:WORD,count:WORD


mov dx,port
les di,XfrAddress
mov cx,count
pushf ; save flags while disabling
cli
cld
rep insw
popf
ret
RepeatIn endp

; This is used by the hard disk driver for data-out xfers

RepeatOut proc uses ds si cx dx,XfrAddress:FAR PTR,port:WORD,count:WORD


mov dx,port
lds si,XfrAddress
mov cx,count
pushf ; save flags while disabling
cli
cld
rep outsw
popf

443
The C Programs

ret
RepeatOut endp

end

444
Introduction to AutoBios

6.2.25 The ScanCall.asm Function


These functions perform the checksum test and scan calls for rom-scan modules.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM CheckSumOk & ScanCall Functions
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] ScanCall.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose]
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;------- this is the rom scan checksum called by 'C' -----

; Returns True if checksum == 0,


; False if checksum not correct.
; unsigned checksum(unsigned segment,unsigned # 512 byte blocks)

CheckSumOK proc uses bx cx dx ds,segptr:WORD,length_arg:WORD


mov ds,segptr ; get base address
mov dx,length_arg ; get count
xor ax,ax
xor bx,bx
.REPEAT
mov cx,512
.REPEAT
add al,ds:[bx]
inc bx ; point to next BYTE
.UNTILCXZ
dec dx
.UNTIL (dx == 0)
.IF (al == 0)
mov ax,True
.ELSE
mov ax,False
.ENDIF

445
The C Programs

ret
CheckSumOK endp

;-- this is the far call routine called by 'C' rom scan ---

ScanCall proc uses si di cx ax bx dx ds es,scanmodule:FAR PTR


push bp
call [scanmodule]
pop bp
ret
ScanCall endp

end

446
Introduction to AutoBios

6.2.26 The StrCpy.asm Function


This function performs a String Copy.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM String Copy Function
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] ClrObjct.asm
;
; [Language] MS MASM 6.11
;
; [Purpose] This function copies a string
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;------ copy a string from src to dest ---------

; void StrCpy(char far * dest, char far * src);

StrCpy proc near uses ax si di ds es,qdest:FAR PTR BYTE,qsrc:FAR PTR BYTE


lds si,qsrc
les di,qdest
.REPEAT
lodsb
stosb
.UNTIL (al == 0)
ret
StrCpy endp

end

447
Introduction to AutoBios

6.2.27 The SysCfgTb.asm Table


This table contains descriptive information of the system and Bios configuration.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM System Configuration Table
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] SysCfgTb.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides System Configuration Parms
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

; This is the table referenced by the Int 15, Function C0


; get system configuration parameters call.

EXTERNDEF SystemConfigurationTable:NEAR
SystemConfigurationTable LABEL NEAR

ifdef CfgTypeParms
BYTE CfgTypeParms
else
WORD 8 ; length of table in BYTEs
BYTE 0fch ; model BYTE
BYTE 01h ; sub model BYTE
BYTE 0 ; bios level
BYTE 70h ; DMA 3,cascade 8259, rtc clock
BYTE 4 dup(0); spares
endif

end

449
Introduction to AutoBios

6.2.28 The VidFont.asm Table


This table contains the graphic video font for CGA video.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Video Font Table
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] VidFont.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose]
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

VideoFont LABEL BYTE


; These are the bit-mapped characters for the graphics mode.
; They must be here because some user software uses these for
; generating characters in graphics mode.

BYTE 000h,000h,000h,000h,000h,000h,000h,000h ; 00 - nul


BYTE 07eh,081h,0a5h,081h,0bdh,099h,081h,07eh ; 01 - ^A
BYTE 07eh,0ffh,0dbh,0ffh,0c3h,0e7h,0ffh,07eh ; 02 - ^B
BYTE 06ch,0feh,0feh,0feh,07ch,038h,010h,000h ; 03 - ^C
BYTE 010h,038h,07ch,0feh,07ch,038h,010h,000h ; 04 - ^D
BYTE 038h,07ch,038h,0feh,0feh,07ch,038h,07ch ; 05 - ^E
BYTE 010h,010h,038h,07ch,0feh,07ch,038h,07ch ; 06 - ^F
BYTE 000h,000h,018h,03ch,03ch,018h,000h,000h ; 07 - ^G
BYTE 0ffh,0ffh,0e7h,0c3h,0c3h,0e7h,0ffh,0ffh ; 08 - ^H
BYTE 000h,03ch,066h,042h,042h,066h,03ch,000h ; 09 - ^I
BYTE 0ffh,0c3h,099h,0bdh,0bdh,099h,0c3h,0ffh ; 0A - ^J
BYTE 00fh,007h,00fh,07dh,0cch,0cch,0cch,078h ; 0B - ^K
BYTE 03ch,066h,066h,066h,03ch,018h,07eh,018h ; 0C - ^L
BYTE 03fh,033h,03fh,030h,030h,070h,0f0h,0e0h ; 0D - ^M
BYTE 07fh,063h,07fh,063h,06eh,067h,0e6h,0c0h ; 0E - ^N
BYTE 099h,05ah,03ch,0e7h,0e7h,03ch,05ah,099h ; 0F - ^O
BYTE 080h,0e0h,0f8h,0feh,0f8h,0e0h,080h,000h ; 10 - ^P
BYTE 002h,00eh,03eh,0feh,03eh,00eh,002h,000h ; 11 - ^Q
BYTE 018h,03ch,07eh,018h,018h,07eh,03ch,018h ; 12 - ^R

451
The C Programs

BYTE 066h,066h,066h,066h,066h,000h,066h,000h ; 13 - ^S
BYTE 07fh,0dbh,0dbh,07bh,01bh,01bh,01bh,000h ; 14 - ^T
BYTE 03eh,063h,038h,06ch,06ch,038h,0cch,078h ; 15 - ^U
BYTE 000h,000h,000h,000h,07eh,07eh,07eh,000h ; 16 - ^V
BYTE 018h,03ch,07eh,018h,07eh,03ch,018h,0ffh ; 17 - ^W
BYTE 018h,03ch,07eh,018h,018h,018h,018h,000h ; 18 - ^X
BYTE 018h,018h,018h,018h,07eh,03ch,018h,000h ; 19 - ^Y
BYTE 000h,018h,00ch,0feh,00ch,018h,000h,000h ; 1A - ^Z
BYTE 000h,030h,060h,0feh,060h,030h,000h,000h ; 1B - ^[
BYTE 000h,000h,0c0h,0c0h,0c0h,0feh,000h,000h ; 1C - ^\
BYTE 000h,024h,066h,0ffh,066h,024h,000h,000h ; 1D - ^]
BYTE 000h,018h,03ch,07eh,0ffh,0ffh,000h,000h ; 1E - ^6
BYTE 000h,0ffh,0ffh,07eh,03ch,018h,000h,000h ; 1F - ^-
BYTE 000h,000h,000h,000h,000h,000h,000h,000h ; 20 - spc
BYTE 030h,078h,078h,030h,030h,000h,030h,000h ; 21 - !
BYTE 06ch,06ch,06ch,000h,000h,000h,000h,000h ; 22 - "
BYTE 06ch,06ch,0feh,06ch,0feh,06ch,06ch,000h ; 23 - #
BYTE 030h,07ch,0c0h,078h,00ch,0f8h,030h,000h ; 24 - $
BYTE 000h,0c6h,0cch,018h,030h,066h,0c6h,000h ; 25 - %
BYTE 038h,06ch,038h,076h,0dch,0cch,076h,000h ; 26 - &
BYTE 060h,060h,0c0h,000h,000h,000h,000h,000h ; 27 - '
BYTE 018h,030h,060h,060h,060h,030h,018h,000h ; 28 - (
BYTE 060h,030h,018h,018h,018h,030h,060h,000h ; 29 - )
BYTE 000h,066h,03ch,0ffh,03ch,066h,000h,000h ; 2A - *
BYTE 000h,030h,030h,0fch,030h,030h,000h,000h ; 2B - +
BYTE 000h,000h,000h,000h,000h,030h,030h,060h ; 2C - ,
BYTE 000h,000h,000h,0fch,000h,000h,000h,000h ; 2D - -
BYTE 000h,000h,000h,000h,000h,030h,030h,000h ; 2E - .
BYTE 006h,00ch,018h,030h,060h,0c0h,080h,000h ; 2F - /
BYTE 07ch,0c6h,0ceh,0deh,0f6h,0e6h,07ch,000h ; 30 - 0
BYTE 030h,070h,030h,030h,030h,030h,0fch,000h ; 31 - 1
BYTE 078h,0cch,00ch,038h,060h,0cch,0fch,000h ; 32 - 2
BYTE 078h,0cch,00ch,038h,00ch,0cch,078h,000h ; 33 - 3
BYTE 01ch,03ch,06ch,0cch,0feh,00ch,01eh,000h ; 34 - 4
BYTE 0fch,0c0h,0f8h,00ch,00ch,0cch,078h,000h ; 35 - 5
BYTE 038h,060h,0c0h,0f8h,0cch,0cch,078h,000h ; 36 - 6
BYTE 0fch,0cch,00ch,018h,030h,030h,030h,000h ; 37 - 7
BYTE 078h,0cch,0cch,078h,0cch,0cch,078h,000h ; 38 - 8
BYTE 078h,0cch,0cch,07ch,00ch,018h,070h,000h ; 39 - 9
BYTE 000h,030h,030h,000h,000h,030h,030h,000h ; 3A - :
BYTE 000h,030h,030h,000h,000h,030h,030h,060h ; 3B - ;
BYTE 018h,030h,060h,0c0h,060h,030h,018h,000h ; 3C - <
BYTE 000h,000h,0fch,000h,000h,0fch,000h,000h ; 3D - =
BYTE 060h,030h,018h,00ch,018h,030h,060h,000h ; 3E - >
BYTE 078h,0cch,00ch,018h,030h,000h,030h,000h ; 3F - ?
BYTE 07ch,0c6h,0deh,0deh,0deh,0c0h,078h,000h ; 40 - @
BYTE 030h,078h,0cch,0cch,0fch,0cch,0cch,000h ; 41 - A
BYTE 0fch,066h,066h,07ch,066h,066h,0fch,000h ; 42 - B
BYTE 03ch,066h,0c0h,0c0h,0c0h,066h,03ch,000h ; 43 - C
BYTE 0f8h,06ch,066h,066h,066h,06ch,0f8h,000h ; 44 - D
BYTE 0feh,062h,068h,078h,068h,062h,0feh,000h ; 45 - E
BYTE 0feh,062h,068h,078h,068h,060h,0f0h,000h ; 46 - F
BYTE 03ch,066h,0c0h,0c0h,0ceh,066h,03eh,000h ; 47 - G
BYTE 0cch,0cch,0cch,0fch,0cch,0cch,0cch,000h ; 48 - H
BYTE 078h,030h,030h,030h,030h,030h,078h,000h ; 49 - I
BYTE 01eh,00ch,00ch,00ch,0cch,0cch,078h,000h ; 4A - J

452
Introduction to AutoBios

BYTE 0e6h,066h,06ch,078h,06ch,066h,0e6h,000h ; 4B - K
BYTE 0f0h,060h,060h,060h,062h,066h,0feh,000h ; 4C - L
BYTE 0c6h,0eeh,0feh,0feh,0d6h,0c6h,0c6h,000h ; 4D - M
BYTE 0c6h,0e6h,0f6h,0deh,0ceh,0c6h,0c6h,000h ; 4E - N
BYTE 038h,06ch,0c6h,0c6h,0c6h,06ch,038h,000h ; 4F - O
BYTE 0fch,066h,066h,07ch,060h,060h,0f0h,000h ; 50 - P
BYTE 078h,0cch,0cch,0cch,0dch,078h,01ch,000h ; 51 - Q
BYTE 0fch,066h,066h,07ch,06ch,066h,0e6h,000h ; 52 - R
BYTE 078h,0cch,0e0h,070h,01ch,0cch,078h,000h ; 53 - S
BYTE 0fch,0b4h,030h,030h,030h,030h,078h,000h ; 54 - T
BYTE 0cch,0cch,0cch,0cch,0cch,0cch,0fch,000h ; 55 - U
BYTE 0cch,0cch,0cch,0cch,0cch,078h,030h,000h ; 56 - V
BYTE 0c6h,0c6h,0c6h,0d6h,0feh,0eeh,0c6h,000h ; 57 - W
BYTE 0c6h,0c6h,06ch,038h,038h,06ch,0c6h,000h ; 58 - X
BYTE 0cch,0cch,0cch,078h,030h,030h,078h,000h ; 59 - Y
BYTE 0feh,0c6h,08ch,018h,032h,066h,0feh,000h ; 5A - Z
BYTE 078h,060h,060h,060h,060h,060h,078h,000h ; 5B - [
BYTE 0c0h,060h,030h,018h,00ch,006h,002h,000h ; 5C - \
BYTE 078h,018h,018h,018h,018h,018h,078h,000h ; 5D - ]
BYTE 010h,038h,06ch,0c6h,000h,000h,000h,000h ; 5E - ^
BYTE 000h,000h,000h,000h,000h,000h,000h,0ffh ; 5F - _
BYTE 030h,030h,018h,000h,000h,000h,000h,000h ; 60 - '
BYTE 000h,000h,078h,00ch,07ch,0cch,076h,000h ; 61 - a
BYTE 0e0h,060h,060h,07ch,066h,066h,0dch,000h ; 62 - b
BYTE 000h,000h,078h,0cch,0c0h,0cch,078h,000h ; 63 - c
BYTE 01ch,00ch,00ch,07ch,0cch,0cch,076h,000h ; 64 - d
BYTE 000h,000h,078h,0cch,0fch,0c0h,078h,000h ; 65 - e
BYTE 038h,06ch,060h,0f0h,060h,060h,0f0h,000h ; 66 - f
BYTE 000h,000h,076h,0cch,0cch,07ch,00ch,0f8h ; 67 - g
BYTE 0e0h,060h,06ch,076h,066h,066h,0e6h,000h ; 68 - h
BYTE 030h,000h,070h,030h,030h,030h,078h,000h ; 69 - i
BYTE 00ch,000h,00ch,00ch,00ch,0cch,0cch,078h ; 6A - j
BYTE 0e0h,060h,066h,06ch,078h,06ch,0e6h,000h ; 6B - k
BYTE 070h,030h,030h,030h,030h,030h,078h,000h ; 6C - l
BYTE 000h,000h,0cch,0feh,0feh,0d6h,0c6h,000h ; 6D - m
BYTE 000h,000h,0f8h,0cch,0cch,0cch,0cch,000h ; 6E - n
BYTE 000h,000h,078h,0cch,0cch,0cch,078h,000h ; 6F - o
BYTE 000h,000h,0dch,066h,066h,07ch,060h,0f0h ; 70 - p
BYTE 000h,000h,076h,0cch,0cch,07ch,00ch,01eh ; 71 - q
BYTE 000h,000h,0dch,076h,066h,060h,0f0h,000h ; 72 - r
BYTE 000h,000h,07ch,0c0h,078h,00ch,0f8h,000h ; 73 - s
BYTE 010h,030h,07ch,030h,030h,034h,018h,000h ; 74 - t
BYTE 000h,000h,0cch,0cch,0cch,0cch,076h,000h ; 75 - u
BYTE 000h,000h,0cch,0cch,0cch,078h,030h,000h ; 76 - v
BYTE 000h,000h,0c6h,0d6h,0feh,0feh,06ch,000h ; 77 - w
BYTE 000h,000h,0c6h,06ch,038h,06ch,0c6h,000h ; 78 - x
BYTE 000h,000h,0cch,0cch,0cch,07ch,00ch,0f8h ; 79 - y
BYTE 000h,000h,0fch,098h,030h,064h,0fch,000h ; 7A - z
BYTE 01ch,030h,030h,0e0h,030h,030h,01ch,000h ; 7B - {
BYTE 018h,018h,018h,000h,018h,018h,018h,000h ; 7C - |
BYTE 0e0h,030h,030h,01ch,030h,030h,0e0h,000h ; 7D - }
BYTE 076h,0dch,000h,000h,000h,000h,000h,000h ; 7E - ~
BYTE 000h,010h,038h,06ch,0c6h,0c6h,0feh,000h ; 7F -

end

453
The C Programs

454
Introduction to AutoBios

6.2.29 The VidFuns.asm Functions


These functions are optimized calls to the video services.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Video Functions
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] VidFuns.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose] Provides Power-on routines
;
; [Functional Description]
;
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

VideoSetMode proc uses ax, new_mode:WORD


xor ah,ah
mov al,BYTE PTR new_mode
push bp
int 10h
pop bp
ret
VideoSetMode endp

VideoGetMode proc
mov ah,0fh
push bp
int 10h
pop bp
ret
VideoGetMode endp

VideoSetCursor proc uses ax bx dx, new_row_col:WORD


mov ah,02h
mov bh,0
mov dx,new_row_col
push bp
int 10h

455
The C Programs

pop bp
ret
VideoSetCursor endp

VideoGetCursor proc uses bx cx


mov ah,03h
xor bx,bx
push bp
int 10h
pop bp
mov ax,dx
ret
VideoGetCursor endp

VideoWriteTty proc uses ax bx, out_char:BYTE


mov ah,0eh
mov al,out_char
xor bx,bx
push bp
int 10h
pop bp
ret
VideoWriteTty endp

VideoWriteChar proc uses ax bx cx, out_char:WORD


mov ah,0ah
mov al,BYTE PTR out_char
xor bx,bx
mov cx,1
push bp
int 10h
pop bp
ret
VideoWriteChar endp

VideoWriteAC proc uses ax cx, out_char:BYTE,out_attrib:WORD


mov ah,09h
mov al,out_char
mov bx,out_attrib
xchg bh,bl
xor bh,bh
mov cx,1
push bp
int 10h
pop bp
ret
VideoWriteAC endp

VideoScrollUp proc uses ax bx cx dx,


nr_lines:WORD,attribute:WORD,upper:WORD,lower:WORD
mov ah,06h
mov al,BYTE PTR nr_lines
mov bh,BYTE PTR attribute
mov cx,upper
mov dx,lower
push bp

456
Introduction to AutoBios

int 10h
pop bp
ret
VideoScrollUp endp

VideoReadAC proc uses bx


mov ah,08h
xor bh,bh
push bp
int 10h
pop bp
ret
VideoReadAC endp

VideoGetCols proc uses bx


mov ah,0fh
xor bh,bh
push bp
int 10h
pop bp
mov al,ah
xor ah,ah
ret
VideoGetCols endp

VideoClearScreen proc uses bx


mov ah,0fh
push bp
int 10h
pop bp
mov ah,0
push bp
int 10h
pop bp
ret
VideoClearScreen endp

end

457
Introduction to AutoBios

6.2.30 The VidMoves.asm Functios


These functions are optimized Video Row Moves and Clears.
;***********************************************************************
;
; [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] MASM Video Row Move & Clear Functions
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 04/11/94
;
; [File Name] VidMoves.asm
;
; [Language] MS MASM 6.1x
;
; [Purpose]
;
; [Functional Description]
;
; [History] 2.00 04/11/94 Original
;
;*****************************************************************

include BiosPrfx.inc

;------ move string routine for alpha mode crt scrolling

; void MoveRow(unsigned segment,unsigned from_offset,


; unsigned to_offset, unsigned count)

MoveRow proc uses cx si di es ds,segptr:WORD,from:WORD,to:WORD,count:WORD


mov ds,segptr ; segment
mov es,segptr
mov si,from ; from
mov di,to ; to
mov cx,count ; count
cld
.IF (cx != 0)
rep movsw
.ENDIF
ret
MoveRow endp

;------ clear row routine for alpha mode crt scrolling

; void ClearRow(unsigned segment, unsigned address,


; unsigned count, unsigned fill)

ClearRow proc uses ax cx di es,segptr:WORD,addrptr:WORD,count:WORD,filler:WORD

459
The C Programs

mov es,segptr ; segment


mov di,addrptr ; address
mov cx,count ; count
mov ax,filler ; fill
cld
.IF (cx != 0)
rep stosw
.ENDIF
ret
ClearRow endp

;-- move string routine for graphics mode crt scrolling

; void MoveGraphicsRow(segment, from_offset,to_offset, count)

MoveGraphicsRow proc uses cx dx si di es


ds,segptr:WORD,from:WORD,to:WORD,count:WORD
mov dx,0 ; use dx to move four lines each
move_graphics_row5:
mov ds,segptr ; segment
mov es,segptr
mov si,from ; from
mov di,to ; to
mov cx,count ; count
cld
add si,dx
add di,dx
.IF (cx != 0)
rep movsw
.ENDIF
mov si,[bp+6] ; from
mov di,[bp+8] ; to
add si,2000h ; add for odd row
add di,2000h ; add for odd row
mov cx,[bp+10] ; count
cld
add si,dx
add di,dx
.IF (cx != 0)
rep movsw
.ENDIF
add dx,80
cmp dx,320
jb move_graphics_row5
ret
MoveGraphicsRow endp

;------ clear row routine for alpha mode crt scrolling

; void ClearGraphicsRow(segment, address, count, fill)

ClearGraphicsRow proc uses ax cx dx di


es,segptr:WORD,addrptr:WORD,count:WORD,filler:WORD
mov dx,0 ; use dx to clear four lines each
clear_graphics_row5:
mov es,segptr ; segment

460
Introduction to AutoBios

mov di,addrptr ; address


mov cx,count ; count
mov ax,filler ; fill
cld
add di,dx
.IF (cx != 0)
rep stosw
.ENDIF
mov di,[bp+6] ; address
add di,2000h ; add for odd row
mov cx,[bp+8] ; count
mov ax,[bp+10] ; fill
add di,dx
cld
.IF (cx != 0)
rep stosw
.ENDIF
add dx,80
cmp dx,320
jb clear_graphics_row5
ret
ClearGraphicsRow endp

end

461
Introduction to AutoBios

7. The C Programs
These are the modules of the Bios which are in C. They include the Function Calls and the Interrupt
Service Routines.

7.1 The Lists.c File


The Lists file contains the collection of List structures that are used by AutoBios. These lists are
generally of the Name-Value form, where a text string is correlated with a value. Four basic functions
provide operations on these lists in the form of:
1. NameExists - Determine if a text string exists in the list.
2. ValueExists - Determine if a value exists in the list.
3. GetName - Return the pointer to the name associated with a specified value.
4. GetValue - Return the value associated with a specified name.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] The Bios List Collection
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Lists.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This is the collection of Lists used for Bios
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

struct NameValueList FlagOnList[] =


{

463
The C Programs

{"OV",OVbit, },
{"DN",DNbit, },
{"EI",EIbit, },
{"TF",TFbit, },
{"NG",NGbit, },
{"ZR",ZRbit, },
{"AC",ACbit, },
{"PE",PEbit, },
{"CY",CYbit, },
{"" ,0, },
};

struct NameValueList FlagOffList[] =


{
{"NV",NVbit, },
{"UP",UPbit, },
{"DI",DIbit, },
{"NT",NTbit, },
{"PL",PLbit, },
{"NZ",NZbit, },
{"NA",NAbit, },
{"PO",PObit, },
{"NC",NCbit, },
{"" ,0, },
};

// This list is used for a bit position mask for various routines

struct NameValueList BitList[] =


{
{"0", 0x0001, },
{"1", 0x0002, },
{"2", 0x0004, },
{"3", 0x0008, },
{"4", 0x0010, },
{"5", 0x0020, },
{"6", 0x0040, },
{"7", 0x0080, },
{"8", 0x0100, },
{"9", 0x0200, },
{"10",0x0400, },
{"11",0x0800, },
{"12",0x1000, },
{"13",0x2000, },
{"14",0x4000, },
{"15",0x8000, },
{"", 0, },
};

struct NameValueList ReverseBitList[] =


{
{"15",0x8000, },
{"14",0x4000, },
{"13",0x2000, },
{"12",0x1000, },
{"11",0x0800, },

464
Introduction to AutoBios

{"10",0x0400, },
{"9", 0x0200, },
{"8", 0x0100, },
{"7", 0x0080, },
{"6", 0x0040, },
{"5", 0x0020, },
{"4", 0x0010, },
{"3", 0x0008, },
{"2", 0x0004, },
{"1", 0x0002, },
{"0", 0x0001, },
{"", 0, },
};

/* This list is used for Snapshot, Watch, and Log Commands */

struct NameValueList DeviceList[] =


{
{"Floppy", DeviceMaskDisk, },
{"Disk", DeviceMaskDisk, },
{"Hard", DeviceMaskHard, },
{"Video", DeviceMaskVideo, },
{"SysVue", DeviceMaskSysVue, },
{"Vue", DeviceMaskSysVue, },
{"SysSrv", DeviceMaskSysSrv, },
{"Equipment",DeviceMaskEquipment,},
{"Equip", DeviceMaskEquipment,},
{"Memory", DeviceMaskMemory, },
{"Mem", DeviceMaskMemory, },
{"LPT", DeviceMaskLpt, },
{"COM", DeviceMaskCom, },
{"TOD", DeviceMaskTod, },
{"Boot", DeviceMaskBoot, },
{"Timer", DeviceMaskTimer, },
{"Keyboard", DeviceMaskKeyboard, },
{"Kb", DeviceMaskKeyboard, },
{"Prsc", DeviceMaskPrtScr, },
{"POD", DeviceMaskPod, },
{"" , 0, },
};

//These compare strings will reference the saved register values


//These structuree should be like the command table structure !

struct NameValueList RegisterList[] =


{
{ "AX",axsave, },
{ "BX",bxsave, },
{ "CX",cxsave, },
{ "DX",dxsave, },
{ "SI",sisave, },
{ "DI",disave, },
{ "CS",cssave, },
{ "DS",dssave, },
{ "ES",essave, },

465
The C Programs

{ "SS",sssave, },
{ "SP",spsave, },
{ "IP",ipsave, },
{ "",0,},
};

//--------------------------------------------------------------

//void LengthAddition(void);
//void PointerDetection(void);

//struct NameValueList SpecialList[] =


//{
// { "L", (unsigned)LengthAddition, },
// { ":", (unsigned)PointerDetection, },
// { "", 0, },
//};

struct NameValueList DisplayList[] =


{
{ "VGA", 0, },
{ "EGA", 0, },
{ "CGA 40 x 25",1, },
{ "CGA 80 x 25",2, },
{ "CGA", 2, },
{ "Mono", 3, },
{ "", 0, },
};

//----- this is the text list for the floppy drive types --------

struct NameValueList DiskList[] =


{
{ "None", 0, },
{ "360", 1, },
{ "1200", 2, },
{ "1.2", 2, },
{ "720", 3, },
{ "1440", 4, },
{ "1.44", 4, },
{ "2880", 5, },
{ "2.88", 5, },
{ "", 0, },
};

struct NameValueList CmosList[] =


{
{ "CmosRegSeconds", CmosRegSeconds, },
{ "CmosRegSecondAlarm", CmosRegSecondAlarm, },
{ "CmosRegMinutes", CmosRegMinutes, },
{ "CmosRegMinuteAlarm", CmosRegMinuteAlarm, },
{ "CmosRegHours", CmosRegHours, },
{ "CmosRegHourAlarm", CmosRegHourAlarm, },

466
Introduction to AutoBios

{ "CmosRegDayOfWeek", CmosRegDayOfWeek, },
{ "CmosRegDayOfMonth", CmosRegDayOfMonth, },
{ "CmosRegMonth", CmosRegMonth, },
{ "CmosRegYear", CmosRegYear, },
{ "CmosRegStatusA", CmosRegStatusA, },
{ "CmosRegStatusB", CmosRegStatusB, },
{ "CmosRegStatusC", CmosRegStatusC, },
{ "CmosRegStatsuD", CmosRegStatusD, },
{ "CmosRegDiagnosticStatus", CmosRegDiagnosticStatus, },
{ "CmosRegRestartStatus", CmosRegRestartStatus, },
{ "CmosRegDiskDriveType", CmosRegDiskDriveType, },
{ "CmosRegOptionFlags", CmosRegOptionFlags, },
{ "CmosRegHardDriveType", CmosRegHardDriveType, },
{ "CmosRegEquipment", CmosRegEquipment, },
{ "CmosRegBaseMemLow", CmosRegBaseMemLow, },
{ "CmosRegBaseMemHigh", CmosRegBaseMemHigh, },
{ "CmosRegExtMemLow", CmosRegExtMemLow, },
{ "CmosRegExtMemHigh", CmosRegExtMemHigh, },
{ "CmosRegExtendedDriveC", CmosRegExtendedDriveC, },
{ "CmosRegExtendedDriveD", CmosRegExtendedDriveD, },
{ "CmosRegChecksumHigh", CmosRegChecksumHigh, },
{ "CmosRegChecksumLow", CmosRegChecksumLow, },
{ "CmosRegExtMemFoundLow", CmosRegExtMemFoundLow, },
{ "CmosRegExtMemFoundHigh", CmosRegExtMemFoundHigh, },
{ "CmosRegCentury", CmosRegCentury, },
{ "CmosRegInformationFlags", CmosRegInformationFlags, },
{ "CmosRegDrive47CylLow", CmosRegDrive47CylLow, },
{ "CmosRegDrive47CylHigh", CmosRegDrive47CylHigh, },
{ "CmosRegDrive47Heads", CmosRegDrive47Heads, },
{ "CmosRegDrive47Sectors", CmosRegDrive47Sectors, },
{ "CmosRegDrive48CylLow", CmosRegDrive48CylLow, },
{ "CmosRegDrive48CylHigh", CmosRegDrive48CylHigh, },
{ "CmosRegDrive48Heads", CmosRegDrive48Heads, },
{ "CmosRegDrive48Sectors", CmosRegDrive48Sectors, },
{ "", 0, },
};

struct NameValueList BootOrderList[] =


{
{ "A:C", 0, },
{ "C:A", 1, },
{ "A", 2, },
{ "C", 3, },
{ "", 0, },
};

//------------------------------------------------
// This is a prototype for an index list for the stored registers
struct NameValueList RegisterIndexList[] =
{
{"AX",axsave,},
{"EAX",eaxsave,},
{"BX",bxsave,},
{"EBX",ebxsave,},

467
The C Programs

{"CX",cxsave,},
{"ECX",ecxsave,},
{"DX",dxsave,},
{"EDX",edxsave,},
{"SP",spsave,},
{"ESP",espsave,},
{"BP",bpsave,},
{"EBP",ebpsave,},
{"SI",sisave,},
{"ESI",esisave,},
{"DI",disave,},
{"EDI",edisave,},
{"DS",dssave,},
{"ES",essave,},
{"SS",sssave,},
{"CS",cssave,},
{"IP",ipsave,},
{"EIP",eipsave,},
{"PSW",pswsave,},
{"EPSW",epswsave,},
{"" ,0, },
};
//----------------------------------------------------
struct NameValueList RegisterTokenList[] =
{
{"AX",axsave,},
{"BX",bxsave,},
{"CX",cxsave,},
{"DX",dxsave,},
{"SP",spsave,},
{"BP",bpsave,},
{"SI",sisave,},
{"DI",disave,},
{"DS",dssave,},
{"ES",essave,},
{"SS",sssave,},
{"CS",cssave,},
{"IP",ipsave,},
{"PSW",pswsave,},
{"" ,0, },
};

struct NameValueList ExtendedRegisterTokenList[] =


{
{"EAX",eaxsave,},
{"EBX",ebxsave,},
{"ECX",ecxsave,},
{"EDX",edxsave,},
{"ESP",espsave,},
{"EBP",ebpsave,},
{"ESI",esisave,},
{"EDI",edisave,},
{"DS",dssave,},
{"ES",essave,},
{"SS",sssave,},
{"CS",cssave,},

468
Introduction to AutoBios

{"EIP",eipsave,},
{"EPSW",epswsave,},
{"" ,0, },
};

struct NameValueList OriginList[] =


{
{"Trap", OriginTrap, },
{"Trace", OriginTrace,},
{"Boot", OriginBoot,},
{"Divide", OriginDivide,},
{"SysErr", OriginSysError,},
{"Key", OriginKey, },
{"ReEnter", OriginReEnter, },
{"Break Key", OriginBreakKey, },
{"", 0,},
};

//--------------------------------------------

struct NameValueList SpyList[] =


{
{ "Snap", Snap, },
{ "Watch", Watch, },
{ "Log", Log, },
{ "", 0, },
};

//---------------------------------------------

#define ExceptionDivideError 0
#define ExceptionDebugInterrupt 1
#define ExceptionNMI 2
#define ExceptionBreakpoint 3
#define ExceptionINTO 4
#define ExceptionBound 5
#define ExceptionInvalidOpcode 6
#define ExceptionNoNPX 7
#define ExceptionDoubleFault 8
#define ExceptionNpxSegmentOverrun 9
#define ExceptionInvalidTSS 10
#define ExceptionNoSegment 11
#define ExceptionStack 12
#define ExceptionGeneral 13
#define ExceptionPageFault 14
#define ExceptionNpxError 16
#define ExceptionAlignment 17

struct NameValueList ExceptionList[] =


{
{ "DivideError", ExceptionDivideError, },
{ "SingleStep", ExceptionDebugInterrupt, },
{ "NonMaskable", ExceptionNMI, },

469
The C Programs

{ "Type 3 Trap", ExceptionBreakpoint, },


{ "Overflow", ExceptionINTO, },
{ "Bounds Limit", ExceptionBound, },
{ "Invalid Opcode", ExceptionInvalidOpcode, },
{ "No NPX present", ExceptionNoNPX, },
{ "Double Fault", ExceptionDoubleFault, },
{ "Segment Overrun", ExceptionNpxSegmentOverrun, },
{ "Invalid TSS", ExceptionInvalidTSS, },
{ "No Segment", ExceptionNoSegment, },
{ "Stack Exception", ExceptionStack, },
{ "General Exception", ExceptionGeneral, },
{ "Page Fault", ExceptionPageFault, },
{ "NPX Error", ExceptionNpxError, },
{ "Alignment Exception", ExceptionAlignment, },
{"" ,0, },
};

struct NameValueList SetupMessageList[] =


{
{ MsgOK, SetupStatusOK, },
{ MsgError, SetupStatusError, },
{ MsgTimeOut, SetupStatusTimeOut, },
{ MsgStub, SetupStatusStub, },
{ MsgInactive, SetupStatusInactive,},
{ MsgDeleted, SetupStatusDeleted, },
{ MsgReserved, SetupStatusReserved,},
{ MsgNotFound, SetupStatusNotFound,},
{ MsgNul, SetupStatusNul, },
{"" ,0, },
};

470
Introduction to AutoBios

7.2 The Misc.c File


The Misc.c file contains functions which are used by various modules. Many of the functions used by
the Setup and Watch commands in Sysvue reside in this file. The register snapshot routines are in here,
as well as most of the support functions for the 8042 keyboard controller chip.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Misc. functions
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Misc.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This module includes miscellaneous functions used
// [Description] by various modules.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/* L O C A L C O N S T A N T S */

/* P R O G R A M S */

/*========== return the cmos system memory size =====*/

unsigned GetCmosSystemMemorySize()
{
unsigned Temp = InCmos(CmosRegBaseMemHigh); Temp <<= 8;
return(Temp |= InCmos(CmosRegBaseMemLow));
}

471
The C Programs

/*========== return the cmos extended memory size =====*/

unsigned GetCmosExtendedMemorySize()
{
unsigned Temp = InCmos(CmosRegExtMemHigh); Temp <<= 8;
return(Temp |= InCmos(CmosRegExtMemLow));
}

/*==== return the cmos extended found memory size =====*/

unsigned GetCmosExtendedMemory()
{
unsigned Temp = InCmos(CmosRegExtMemFoundHigh); Temp <<= 8;
return(Temp |= InCmos(CmosRegExtMemFoundLow));
}

/*----------- display sys mem size -----------*/

void DisplaySystemMemory(void)
{
unsigned j;
printf("%5d",j = GetCmosSystemMemorySize());
}

/*----------- display ext mem size -----------*/

void DisplayExtendedMemory(void)
{
unsigned j;
printf("%5d",j = GetCmosExtendedMemorySize());
}

/*----------- set sys mem size -----------*/

void SetSystemMemory(unsigned sys_size)


{
OutCmos(CmosRegBaseMemLow,(char)sys_size);
OutCmos(CmosRegBaseMemHigh,(char)(sys_size >> 8));
CalcCmosChecksum();
}

/*----------- set ext mem size -----------*/

void SetExtendedMemory(unsigned ext_size)


{
OutCmos(CmosRegExtMemLow,(char)ext_size);
OutCmos(CmosRegExtMemHigh,(char)(ext_size >> 8));
CalcCmosChecksum();
}

472
Introduction to AutoBios

7.3 The Pod.c File


The Pod.C (Power On Diagnostics)file contains power-up diagnostics and initializing routines. This file
inits some of the peripherals and also calls the setups for most of the other function calls. A general
convention to develop (it has been implemented for some cases) is to examine the status returned from a
function call setup routine. to determine the degree of success in initializing a device (such as video,
disk, keyboard, etc.) This returned status can then be used to display an enhanced message during the
POD.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Power on diagnostics
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] POD.C
//
// [Language] MSVC 1.5
//
// [Description] This module does the power on diagnostics and
// [Description] initialization. When it finishes, it does a
// [Description] bootstrap to load the system.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

// I N C L U D E F I L E S

#include "Bios.h"

// F U N C T I O N P R O T O T Y P E S

void PortWrite(struct PortTable *Ptr);


void interrupt far UnexpectedInterrupt(InterruptRegisters);
unsigned CreateSystemObjectRoutine(ActionArgument);
unsigned LoadVectors(ActionArgument);
unsigned InitPeripherals(ActionArgument);
unsigned ActionRoutine(struct ActionItemList * ActionTable);
unsigned MemoryTestRoutine(ActionArgument);
unsigned RomScanRoutine(ActionArgument);

473
The C Programs

unsigned RomCheckSumRoutine(ActionArgument);
unsigned PrintSignonMessages(ActionArgument);
unsigned DummyActionTrue(ActionArgument);
unsigned GamePortSetup(ActionArgument);

// G L O B A L V A R I A B L E S

// G L O B A L C O N S T A N T S

// L O C A L D E F I N I T I O N S

#define PIOportB 0x61

//--- Port Initialization Tables --------

struct PortTable
{
unsigned char Port;
unsigned char Value;
};

#define DMA1 0x00


#define DMA2 0xc0

static struct PortTable DmaInitTable[] =


{
{ DMA1+ 8,0x04, }, // disable dma #1
{ DMA2+16,0x04, }, // disable dma #2
{ DMA1+13,0x00, }, // master clear
{ DMA2+26,0x00, },
{ DMA1+ 8,0x00, }, // now do dma setup
{ DMA2+16,0x00, },
{ DMA1+11,0x40, }, // set the channel defaults
{ DMA2+22,0xc0, },
{ DMA1+11,0x41, },
{ DMA2+22,0x41, },
{ DMA1+11,0x42, },
{ DMA2+22,0x42, },
{ DMA1+11,0x43, },
{ DMA2+22,0x43, },
{ DMA2+20,0x00, }, // enable cascade of ch# 0
{ 0, 0, },
};

static struct PortTable PICInitTable[] =


{
{ 0xf1,0x00, }, // issue reset to any 287 present
{ 0x20,0x11, }, // icw1 - 8259 #1
{ 0x21,0x08, }, // icw2
{ 0x21,0x04, }, // icw3
{ 0x21,0x01, }, // icw4
{ 0x21,0xff, }, // disable all interrupts

{ 0xa0,0x11, }, // icw1 - 8259 #2


{ 0xa1,0x70, }, // icw2
{ 0xa1,0x02, }, // icw3

474
Introduction to AutoBios

{ 0xa1,0x01, }, // icw4
{ 0xa1,0xff, }, // disable all interrupts
{ 0, 0, },
};

static struct PortTable PIOInitTable[] =


{
// put Real AT Pio values here !!!!!!
{ 0x63,0x99, }, // control reg
{ 0x61,0x70, }, // disable parity checkers
{ 0, 0, },
};

static struct PortTable PITInitTable[] =


{
{ 0x43,0x36, }, // load control reg
{ 0x40,0xff, }, // load count byte 1
{ 0x40,0xff, }, // load count byte 2
{ 0x43,0xb6, }, // load control reg
{ 0x42,0x33, }, // load count byte 1
{ 0x42,0x05, }, // load count byte 2
{ 0, 0, },
};

//---------------------------------------

struct ActionItemList InitTable[] = {


{ MsgCreateSystemObject, CreateSystemObjectRoutine, },
{ MsgLoadDefaultVectors, LoadVectors, },
{ MsgEquipment, EquipmentSetup, },
{ MsgInitPeripherals, InitPeripherals, },

#if CfgVideo
{ MsgVideo, VideoSetup, },
#endif

// If the serial port is used for the SysVue console,


// setup the serial ports now.
#if (CfgConsoleInSerial || CfgConsoleOutSerial)
{ MsgCommService, CommSetup, },
{ MsgCommConsoleService, SysVueConsoleSetup, },
#endif

{ "", PrintSignonMessages, },

// These dummys provide a signon message after the setup has been performed

#if CfgVideo
{ MsgVideo, DummyActionTrue, },
#endif

#if (CfgConsoleInSerial || CfgConsoleOutSerial)


{ MsgSysVueConsole, DummyActionTrue, },
#endif

475
The C Programs

{ MsgEquipmentService, DummyActionTrue, },

// ---------------------------------------------------------

{ MsgTimerService, TimerSetup, },
{ MsgKeyboardService, KeyboardSetup, },
{ MsgSysVue, SysVueSetup, },
{ MsgMemorySizeService, MemSizeSetup, },
{ MsgTimeOfDayService, TimeOfDaySetup, },

//#if CfgPrintScreen
{ MsgPrintScreenService, PrintScreenSetup, },
//#endif

{ MsgSystemServices, SystemServicesSetup, },
{ MsgBootstrapService, BootSetup, },
{ MsgSizeAndTestMemory, MemoryTestRoutine, },
{ MsgMoveSystemObject, MoveSysObjectRoutine, },
{ MsgExtendedMemory, ExtMemTest, },
{ MsgRomChecksum, RomCheckSumRoutine, },

// If the serial port is not used for the SysVue console,


// setup the serial ports now.
#if !(CfgConsoleInSerial || CfgConsoleOutSerial)
{ MsgCommService, CommSetup, },
#endif

{ MsgLptService, LptSetup, },

#if CfgGame
{ MsgGame Port Check, GamePortSetup, },
#endif

{ MsgFloppyDiskService, FDiskSetup, },
{ MsgHardDiskService, HDiskSetup, },
{ MsgRomScan, RomScanRoutine, },
{ "",0, },
};

// P R O G R A M

// Biostop module already has found 64k of ram to operate with.

void BiosPod(void)
{
struct _BiosRam far * LowRam = 0;
struct _SystemObject far * System;
struct _BiosObject far * Bios;
void (interrupt far * Boot) (void);

LoadDS();

// Preset the Video Vector to be non-destructive


LowRam->IntVector[0x10] = (void near *) DummyIret;

476
Introduction to AutoBios

// use top of 1st 64k for system segment


MemorySizeWord = 64;

CheckPoint(0x01);

// Set post status to warm to minimize sign on's

#if CfgQuietPost
ResetFlag = 0x1234;
#endif

if(!ActionRoutine(InitTable)); // printf("\nInitialization Failure");

CheckPoint(0x02);

// re-enable the rtc in case scan module disabled it


//outp(0x21,inp(0x21) & ~(BIT0 | BIT2));

// Purge the keyboard buffer of any residue


while(kbhit()) { GetChar();}; // get any pending keys

Bios = GetBiosObject();
Bios->FlagMaster[Snap].Master = SnapMasterPattern;
Bios->FlagMaster[Watch].Master = WatchMasterPattern;
Bios->FlagMaster[Log].Master = LogMasterPattern;

//=-=-=-=-=-= now do the boot =-=-=-=-=-=-=-=-=

while (True) // stay in this loop forever


{
#if CfgKeyboardStyleAT
EnableKeyboard();
Send8042(Opcode8042RdCmd); // read the command byte
WaitToRx8042(); inp(Port8042Data);
#endif

outp(0xa1,inp(0xa1) & ~BIT1); // Enable IRQ2/IRQ9


outp(0x21,inp(0x21) & ~BIT1); // make sure kb interrupt is enabled
_enable(); beep();

// need some new code to boot from a list in the cfg block parms

printf("%q\nBooting Disk\n"); Boot = LowRam->IntVector[0x19]; (* Boot) ();


printf("%q\nBooting SysVue\n"); Boot = LowRam->IntVector[0x18]; (* Boot) ();
printf("%q\nBooting Alternate Device\n"); Boot = LowRam->IntVector[0x18]; (*
Boot) ();

}
}

//---------- port write loop routine ---------

void PortWrite(struct PortTable *Ptr)


{ while(Ptr->Port) { outp(Ptr->Port,Ptr->Value); Ptr++; }; };

477
The C Programs

//------ Unexpected Interrupt Handler ----------

void interrupt far UnexpectedInterrupt(InterruptRegisters)


{
unsigned char far * Codestream;
unsigned SrcPtr = GetCS();
Codestream = MK_FP(Reg.RegCS,Reg.RegIP);
SrcPtr -= 0xf000;
_enable();

_asm
{
_asm mov ax,0f000h
_asm push ax
_asm mov ax,OFFSET templabel
_asm push ax
_asm retf
};

templabel:
if(SrcPtr != 0x0f) // These may be PIC spurious signals
{
LoadDS();

#if CfgUnexpecIntDisplay
printf("\nUnexpected Interrupt %4x at %p",SrcPtr,Codestream);
if(ValueExists(SrcPtr,ExceptionList))
{
printf(" - Type is: %s", GetName(SrcPtr,ExceptionList));
};
#endif

#if CfgUnexpecIntTrap
Trap(); // optional for debugging
#endif
};
};

//---------------------------------------------------------------

void interrupt far SysError(unsigned xyz)


{
LoadDS();
printf("\nSystem Error %4X",xyz);
};

//---------------- Action Routine ------------------------

unsigned ActionRoutine(struct ActionItemList * ActionTable)


{
// Declare a pointer variable for the function call by pointer
unsigned (* fptr) (ActionArgument);

// Declare an index to use stepping through the Init Table


unsigned Index = 0;

478
Introduction to AutoBios

unsigned Result;
unsigned char far * TempPtr; // used for results of get name checks
LoadDS();

//CheckPoint(0x03);
// If not a NULL PTR, return indicating actions not performed
if(!ActionTable) return(False);

// Step through the Action Table until the end is found


while (* ActionTable[Index].ActionMessage || ActionTable[Index].DoRoutine)
{
//CheckPoint(0x05);
// If an initialize routine is specified for this item
if((fptr = ActionTable[Index].DoRoutine) != 0)
{
//CheckPoint(0x06);
// if cold boot, print the ActionMessage
if (Cold()) printf("%s",ActionTable[Index].ActionMessage);

// Call the Init Routine, and look for a Return Status reply

Result = (* fptr)(&ActionTable[Index]);

if (Cold())
{
if((TempPtr = GetName(Result,SetupMessageList)) != 0)

printf("%s",TempPtr);
}
else // !Cold
{
switch (Result)
{
case SetupStatusOK:
case SetupStatusStub:
case SetupStatusNul:
// Treat these cases as succesful, so no error print
break;

default:
printf("%s",ActionTable[Index].ActionMessage);
if((TempPtr = GetName(Result,SetupMessageList)) != 0)

printf("%s",TempPtr);
break;
}
}
}
else
{
//CheckPoint(0x012);
// An Init Routine associated with the name was not specified
//printf("\nAction Item: \"%s\" Not found in Action Table \"%s\"",
//
ActionTable[Index].ActionString,ActionTable[0].ActionString);
};

479
The C Programs

// Increment the table index to inspect the next item


Index++;

//CheckPoint(0x013);
}
return(True);
};

//--------------------------------------------------------------

unsigned CreateSystemObjectRoutine(ActionArgument)
{
struct _SystemObject far * System;
LoadDS();

CheckPoint(0x014);

//struct BiosObject far * Me;


System = CreateSystemObject(CfgSystemObjectSize);

SystemSegmentPointer = FP_SEG(System);

// Now allocate a BiosObject in the system pool area


System->Bios_Ptr = AcquireObject(BiosObject, "BiosObject" ,BiosObjectType);

CheckPoint(0x015);

return(SetupStatusNul);
};
//-----------------------------------------------------------

unsigned MoveSysObjectRoutine(ActionArgument)
{
struct _SystemObject far * System;
unsigned long OldPtr = (unsigned long)(GetSystemObject());

if(MemorySizeWord > 64)


{
// Clear old SystemSegmentPointer to permit a new Object to be created

SystemSegmentPointer = 0;

// Create a new System Object at the top of available System Memory


System = CreateSystemObject(CfgSystemObjectSize);

// Save the pointer in low ram


SystemSegmentPointer = FP_SEG(System);

// Now replicate the BiosObject in the system pool area


System->Bios_Ptr = AcquireObject(BiosObject,"BiosObject",BiosObjectType);

printf("%qFrom Segment %p to %p",OldPtr,System);


}
else
{
printf("%qNo Movement Needed");

480
Introduction to AutoBios

}
return(SetupStatusOK);
};

//---------------------------------------------------------------

void interrupt far DummyEOI1(void);


void interrupt far DummyEOI2(void);

void interrupt far DummyEOI1(void)


{
// disable offending interrupt
_asm
{
mov al, 0x0b
out 0x20,al
jmp $+2
in al,0x20
mov ah,al ; save it for masking
or al,al
jz finish1 ; not a hardware interrup
in al,0x21
or al,ah
jmp $+2
out 0x21,al
finish1:
};
SendEOI1();
}

void interrupt far DummyEOI2(void)


{
// disable offending interrupt
_asm
{
mov al, 0x0b
out 0xa0,al
jmp $+2
in al,0xa0
mov ah,al ; save it for masking
or al,al
jz finish2 ; not a hardware interrup
in al,0xa1
or al,ah
jmp $+2
out 0xa1,al
finish2:
};

SendEOI2();
};

unsigned LoadVectors(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
unsigned Index;

481
The C Programs

unsigned long UnexpectedEntry = (unsigned long)


((void near *) UnexpectedInterrupt);

LoadDS();

CheckPoint(0x016);

//-- load default interrupt vectors --

// load software defaults


_disable();

// Load Interrupts 0 -> 1E with unexpected handler


for(Index = 0; Index < 32; Index++)
{
// Build destination with CS: indicating source
// LowRam->IntVector[Index] = (void near *)UnexpectedInterrupt;
// The ISR rebases the CS:
#if CfgUnexpecIntHandler
LowRam->IntVector[Index] = (void far *) UnexpectedEntry;
UnexpectedEntry += 0x00010000;
UnexpectedEntry -= 0x00000010;
#else
LowRam->IntVector[Index] = (void far *) DummyIret;
#endif

CheckPoint(0x017);

// replace the video interrupt with safe dummy


LowRam->IntVector[0x10] = (void near *) DummyIret;
LowRam->IntVector[0] = (void near *) Divide; // div by zero interrupt
LowRam->IntVector[2] = (void near *) IntNMI; // NMI interrupt

// Load PIC 1 vectors with eoi & iret


for(Index = 8; Index <= 15; Index++)
{
LowRam->IntVector[Index] = (void near *) DummyEOI1;
}

#if CfgPlatformAT
// Load PIC 2 vectors with eoi & iret
for(Index = 0x70; Index <= 0x77; Index++)
{
LowRam->IntVector[Index] = (void near *) DummyEOI2;
}

// Intercept IRQ9 and redirect it to the IRQ2 vector


LowRam->IntVector[0x71] = (void near *) ReDirect; // AT PIC 2 Redirect
LowRam->IntVector[0x75] = (void near *) Int287; // AT 80287 Int
#endif

482
Introduction to AutoBios

_enable();

CheckPoint(0x018);

return(SetupStatusOK);
};

//----------------------------------------------------------

unsigned DummyActionTrue(ActionArgument) { return(SetupStatusOK); };

//----------------------------------------------------------

unsigned PrintSignonMessages(ActionArgument)
{
#if CfgUserSignonMessage
printf("%s",UserMessage0);
printf("%s",UserMessage1);
printf("%s",UserMessage2);
printf("%s",UserMessage3);
printf("%s",UserMessage4);
printf("%s",UserMessage5);
printf("%s",UserMessage6);
printf("%s",UserMessage7);

#else
printf("\a\n%s\nVersion %s - %s - Part # %s - %s",
(void far *)OwnerID,
(void far *)VersionID,
(void far *)CustomerID,
(void far *)PartNrID,
(void far *)DateStamp);
printf("%q\nBios at...............%4x",GetCS());
#endif
return(SetupStatusNul);
};

//-----------------------------------------------------

// Size and Test Ram - from 64K up to Top of Installed Memory

//-------------------------------------------------------

unsigned MemoryTestRoutine(ActionArgument)
{
register Index = 0;
printf("%q %4d",Index);
for (Index = 64;
(Index < CfgMaxMem) &&
(RamTestOK(Index << 6,CfgMemTestGranularity,CfgMemTestPatternBias));
MemorySizeWord = (Index += CfgMemTestGranularity),
printf("%q\b\b\b\b\b %4d",Index));
return(SetupStatusNul);
};

/*-----------------------------------------------------

483
The C Programs

Check for optional rom modules from c8000 -> beginning of bios
in 2k increments. A valid module has'55aa' in the first 2 locations,
length indicator (length/512) in the 3rd location, and test/init.
Code starts in the 4th location. These modules may adjust the mem
size downward to reserve System ram memory.

--------------------------------------------------------*/

unsigned RomScanRoutine(ActionArgument)
{
unsigned Index;
LoadDS();

#if (CfgRomScanPrimaryEnd > CfgRomScanPrimaryStart)


printf("%qFrom %4x to %4x..",
CfgRomScanPrimaryStart,CfgRomScanPrimaryEnd);
for (Index = CfgRomScanPrimaryStart;
Index < CfgRomScanPrimaryEnd ;Index = RomScan(Index));
#endif

#if (CfgRomScanSecondaryEnd > CfgRomScanSecondaryStart)


printf("%qFrom %4x to %4x..",
CfgRomScanSecondaryStart,CfgRomScanSecondaryEnd);
for (Index = CfgRomScanSecondaryStart;
Index < CfgRomScanSecondaryEnd ;Index = RomScan(Index));
#endif
return(SetupStatusNul);
};

//-------- do a checksum on the rom bios prom ----------

unsigned RomCheckSumRoutine(ActionArgument)
{
return(CheckSumBiosOK()?SetupStatusOK:SetupStatusError);
}
//------------------------------------------------------

unsigned InitPeripherals(ActionArgument)
{
//------- setup the 8255 if one exists ------------

CheckPoint(0x019);

PortWrite(PIOInitTable);

//---------- setup the dma controllers ---------

CheckPoint(0x020);

PortWrite(DmaInitTable);

//------- setup the 8259 interrupt controller(s) -------

CheckPoint(0x021);

484
Introduction to AutoBios

PortWrite(PICInitTable);

if(ResetFlag == 0x1234) // Issue a reset to the hard drive controller if


warm boot
{
outp(0x3f6,0x04);
DelayCall(10,Microseconds);
outp(0x3f6,0);
};

//-------------- setup the timer -------------

CheckPoint(0x022);

PortWrite(PITInitTable);

_enable(); // allow any stray interrupts to be reset

CheckPoint(0x023);

return(SetupStatusOK);
};

//-------- check for game port ------------

unsigned GamePortSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;

if ((inp(0x0201) & 0x0f) == 0 )


{
LowRam->EquipFlag.GamePort = 1;
return(SetupStatusOK);
};
return(SetupStatusNotFound);
}

//---------------------------------------------------------

//================= end =====================

485
Introduction to AutoBios

7.4 The Equipment Driver


The Equipment Configuration Driver is an Interrupt Function Call (0x11) that is used by DOS and other
programs to determine the options which are present in a system. It is called with no input parameters
and returns a value in the AX register describing the system options. The POD reads the configuration
dipswitch and stores this value along with an adapter configuration byte into the word at 0040:0010.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] equipment function
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Equi.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] Interrupt 0x11 - get equipment configuration
//
// This function call returns an equipment configuration word.
//
// The equip_flag variable is set during the power on.
//
// Returns the Equipment Word in AX:
//
// Bit Description
// 15,14 number of printers attached
// 13 = 0
// 12 = 1 = game port attached
// 11,10,9 number of rs232 cards attached
// 8 = 0
// 7,6 number of diskette drives
// 00=1, 01=2, 10=3, 11=4 only if bit 0 = 1
// 5,4 initial video mode
// 00 - no video adapter
// 01 - 40x25 bw using color card
// 10 - 80x25 bw using color card
// 11 - 80x25 bw using bw card
// 3,2 not used
// 1 0/1 = no 8087/8087
// 0 0/1 = boot from int 18/floppy disk
//
// [Arguments] None
//
// [Return] Equipment word in AX
//

487
The C Programs

// [History] 2.00 04/11/94 Original


//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* G L O B A L S */

/* L O C A L D E F I N I T I O N S */

#define device DeviceMaskEquipment

/* P R O G R A M */

unsigned EquipmentSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
LoadDS();

CheckPoint(0xa0);

LowRam->EquipByte = ReadSwitches(); // Get Switches or CMOS

_disable();
LowRam->IntVector[0x11]= (void near *)EquipmentFunctionCall;
_enable();

CheckPoint(0xa1);

return(True);
}

void EquipCall(struct _IRegs far * Regs);

void interrupt far EquipmentFunctionCall(InterruptRegisters)


{
InterruptEnvelope(EquipCall,DeviceEquipment,0);
};

void EquipCall(struct _IRegs far * Regs)


{
Regs->RegAX = EquipmentWord;
};

488
Introduction to AutoBios

7.5 The Memory Size Function


The Memory Size Driver is an Interrupt (0x12) Function Call that is used by various programs (including
DOS) to determine how much RAM is in the system. It is called with no arguments and returns a value
in the AX register indicating the system (lower 640K) RAM size in 1 Kbyte granules.

//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] memory size function
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Mem.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] Interrupt 12h - get memory size
//
// This function call returns the amount of System RAM in AX.
// The value indicates the number of 1024 byte blocks of RAM.
//
// [Arguments] None
//
// [Return] Mem size in AX
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

#define device DeviceMaskMemory

/* P R O G R A M */

unsigned MemSizeSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
LoadDS();
_disable();
LowRam->IntVector[0x12]= (void near *) MemSizeFunctionCall;
_enable();

489
The C Programs

return(SetupStatusOK);
}

void MemCall(struct _IRegs far * Regs);

void interrupt far MemSizeFunctionCall(InterruptRegisters)


{
InterruptEnvelope(MemCall,DeviceMemory,0);
};

void MemCall(struct _IRegs far * Regs)


{
Regs->RegAX = MemorySizeWord;
};

490
Introduction to AutoBios

7.6 The Keyboard Driver


The Keyboard Driver is used to obtain keyboard input from the keyboard.

If a non-standard keyboard or alternate input device is being used, it is suggested that the keyboard
function call structure be retained. The application will then be independent of the hardware
characteristics of the actual input device, and may be exercised in a development environment with the
standard keyboard input device.

//-------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Keyboard Driver
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Keyboard.c
//
// [Language] MSVC 1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

static unsigned TranslateFromColumn(unsigned ScanCode);


static void assemble_alt_numeric(unsigned ScanCode);
unsigned LoadBuffer(unsigned DataWord);
void interrupt far KeyboardFunctionCall(InterruptRegisters);
void interrupt far KeyboardInterruptServiceRoutine(void);

/* G L O B A L V A R I A B L E S */

491
The C Programs

/* G L O B A L C O N S T A N T S */

/* L O C A L D E F I N I T I O N S */

#define Device DeviceMaskKeyboard

#define KeyStrokePort 0x60

#if defined(CfgKBXT)
//#if (CfgChipName == AMD286LX)
// #define KeyControlPort 0x64
//#else
#define KeyControlPort 0x61
//#endif
#else
#define KeyControlPort 0x61
#endif

#define OpcodeWaitForKey 0x00


#define OpcodeCheckForKey 0x01
#define OpcodeGetFlags 0x02
#define OpcodeSetTypematic 0x03
#define OpcodeStoreKeyData 0x05
#define OpcodeReadExtendedInput 0x10
#define OpcodeReadExtendedStatus 0x11
#define OpcodeReadExtendedShift 0x12

#define BreakCode 0x80 /* add to key to get break code */


#define TabKey 15
#define CtrlKey 29
#define LeftShiftKey 42
#define RightShiftKey 54
#define PrtScrKey 55
#define AltKey 56
#define CapsKey 58
#define F1Key 59
#define F2Key 60
#define F3Key 61
#define F4Key 62
#define F5Key 63
#define F6Key 64
#define F7Key 65
#define F8Key 66
#define F9Key 67
#define FKey10 68
#define FKey11 87
#define FKey12 88
#define NumKey 69
#define ScrollKey 70
#define NumPad0Key 82
#define NumPad1Key 79
#define NumPad2Key 80
#define NumPad3Key 81
#define NumPad4Key 75
#define NumPad5Key 76

492
Introduction to AutoBios

#define NumPad6Key 77
#define NumPad7Key 71
#define NumPad8Key 72
#define NumPad9Key 73

#define MinusKey 74
#define PlusKey 78
#define InsertKey 82
#define DeleteKey 83
#define SysReqKey 84

#define AckCode 0xfa


#define ResendCode 0xfe

enum { BaseCol, ShiftCol, CtrlCol, AltCol };

/* L O C A L C O N S T A N T S */

/*======== This is the keyboard table ====================*/


extern char KbTable[92][4];
#if(0==1) ; this table is in kbtable.asm
char KbTable[92][4] ={
/* This table covers all keys.
** Some keys are pre-checked for special handling.
** Some special keys are padded out in this table.
** The format is: base,upper,ctrl,alt cases.
** The alt cases are handled as extended codes.
*/
{0 ,0 ,0 ,0 }, /* base 0 padding for indexing*/
{27 ,27 ,27 ,-1 }, /* key 1 - Escape key*/
{'1','!',-1 ,120 }, /* key 2 - '1'*/
{'2','@',0 ,121 }, /* key 3 - '2' - special handling */
{'3','#',-1 ,122 }, /* key 4 - '3'*/
{'4','$',-1 ,123 }, /* key 5 - '4'*/
{'5','%',-1 ,124 }, /* key 6 - '5'*/
{'6','^',30 ,125 }, /* key 7 - '6'*/
{'7','&',-1 ,126 }, /* key 8 - '7'*/
{'8','*',-1 ,127 }, /* key 9 - '8'*/
{'9','(',-1 ,128 }, /* key 10 - '9'*/
{'0',')',-1 ,129 }, /* key 11 - '0'*/
{'-','_',31 ,130 }, /* key 12 - '-'*/
{'=','+',-1 ,131 }, /* key 13 - '='*/
{8 ,8 ,127, -1 }, /* key 14 - backspace*/
{9 ,-1 ,-1 , -1 }, /* key 15 - tab*/
{'q','Q',17 , 16 }, /* key 16 - 'Q'*/
{'w','W',23 , 17 }, /* key 17 - 'W'*/
{'e','E',5 , 18 }, /* key 18 - 'E'*/
{'r','R',18 , 19 }, /* key 19 - 'R'*/
{'t','T',20 , 20 }, /* key 20 - 'T'*/
{'y','Y',25 , 21 }, /* key 21 - 'Y'*/
{'u','U',21 , 22 }, /* key 22 - 'U'*/
{'i','I',9 , 23 }, /* key 23 - 'I'*/
{'o','O',15 , 24 }, /* key 24 - 'O'*/
{'p','P',16 , 25 }, /* key 25 - 'P'*/
{'[','{',27 , -1 }, /* key 26 - '['*/
{']','}',29 , -1 }, /* key 27 - ']'*/

493
The C Programs

{13 ,13 ,10 , -1 }, /* key 28 - CR*/


{-1 ,-1 ,-1 , -1 }, /* key 29 - control shift */
{'a','A',1 , 30 }, /* key 30 - 'A'*/
{'s','S',19 , 31 }, /* key 31 - 'S'*/
{'d','D',4 , 32 }, /* key 32 - 'D'*/
{'f','F',6 , 33 }, /* key 33 - 'F'*/
{'g','G',7 , 34 }, /* key 34 - 'G'*/
{'h','H',8 , 35 }, /* key 35 - 'H'*/
{'j','J',10 , 36 }, /* key 36 - 'J'*/
{'k','K',11 , 37 }, /* key 37 - 'K'*/
{'l','L',12 , 38 }, /* key 38 - 'L'*/
{';',':',-1 , -1 }, /* key 39 - ';'*/
{39,'"' ,-1 , -1 }, /* key 40 - '''*/
{'`','~',-1 , -1 }, /* key 41 - '`'*/
{-1 ,-1 ,-1 , -1 }, /* key 42 - left shift */
{92,'|',28 , -1 }, /* key 43 - '\'*/
{'z','Z',26 , 44 }, /* key 44 - 'Z'*/
{'x','X',24 , 45 }, /* key 45 - 'X'*/
{'c','C',3 , 46 }, /* key 46 - 'C'*/
{'v','V',22 , 47 }, /* key 47 - 'V'*/
{'b','B',2 , 48 }, /* key 48 - 'B'*/
{'n','N',14 , 49 }, /* key 49 - 'N'*/
{'m','M',13 , 50 }, /* key 50 - 'M'*/
{',','<',-1 , -1 }, /* key 51 - ','*/
{'.','>',-1 , -1 }, /* key 52 - '.'*/
{'/','?',-1 , -1 }, /* key 53 - '/'*/
{-1 ,-1 ,-1 , -1 }, /* key 54 - right shift - */
{'*',-1,114, -1 }, /* key 55 - prt-scr - */
{-1 ,-1 ,-1, -1 }, /* key 56 - Alt - */
{32 ,32 ,32 , 32 }, /* key 57 - space bar*/
{-1 ,-1 ,-1, -1 }, /* key 58 - caps-lock - */
/* function key cases*/
{59 ,84 ,94 ,104 }, /* key 59 - F1Key*/
{60 ,85 ,95 ,105 }, /* key 60 - F2Key*/
{61 ,86 ,96 ,106 }, /* key 61 - F3Key*/
{62 ,87 ,97 ,107 }, /* key 62 - F4Key*/
{63 ,88 ,98 ,108 }, /* key 63 - F5Key*/
{64 ,89 ,99 ,109 }, /* key 64 - F6Key*/
{65 ,90 ,100,110 }, /* key 65 - F7Key*/
{66 ,91 ,101,111 }, /* key 66 - F8Key*/
{67 ,92 ,102,112 }, /* key 67 - F9Key*/
{68 ,93 ,103,113 }, /* key 68 - F10Key*/
{-1 ,-1 ,-1 ,-1 }, /* key 69 - num-lock - */
{-1 ,-1 ,-1 ,-1 }, /* key 70 - scroll-lock - */
/* num key pad - cases are base,upper,ctrl,alt*/
{71 ,'7',119,-1 }, /* key 71 - home*/
{72 ,'8',-1 ,-1 }, /* key 72 - cursor up*/
{73 ,'9',132,-1 }, /* key 73 - page up*/
{'-','-',-1 ,-1 }, /* key 74 - minus sign*/
{75 ,'4',115,-1 }, /* key 75 - cursor left*/
{-1 ,'5',-1 ,-1 }, /* key 76 - center key*/
{77 ,'6',116,-1 }, /* key 77 - cursor right*/
{'+','+',-1 ,-1 }, /* key 78 - plus sign*/
{79 ,'1',117,-1 }, /* key 79 - end*/
{80 ,'2',-1 ,-1 }, /* key 80 - cursor down*/
{81 ,'3',118,-1 }, /* key 81 - page down*/

494
Introduction to AutoBios

{82 ,'0',-1 ,-1 }, /* key 82 - insert */


{83 ,'.',-1 ,-1 }, /* key 83 - delete */
{-1 , -1,-1 ,-1 }, /* key 84 - sys key */
{-1 , -1,-1 ,-1 }, /* key 85 */
{-1 , -1,-1 ,-1 }, /* key 86 */
{133,135,137,139 }, /* key 87 - F11Key */
{134,136,138,140 }, /* key 88 - F12Key */
};

#endif
/* P R O G R A M */

/*==========================================*/
/*==========================================*/
/* Interrupt 16h - Keyboard function call */
/*==========================================*/
/*==========================================*/
/*-----------------------------------------------*/

unsigned KeyboardSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();
unsigned status = SetupStatusOK;

LoadDS();

_disable();
LowRam->IntVector[0x16]= (void near *)KeyboardFunctionCall;
#if CfgKeyboard
LowRam->IntVector[0x09]= (void near *)KeyboardInterruptServiceRoutine;
#endif
// The Dummy Iret is installed since the keyboard is installed
// before the System Services, which will replace this vector.
LowRam->IntVector[0x15]= (void near *)DummyIret;

_enable();
LowRam->KbBufferHead = 0x1e;
LowRam->KbBufferTail = 0x1e;
LowRam->KbBufferStart = 0x1e;
LowRam->KbBufferEnd = 0x3e;

#if CfgKeyboard
outp(0x21,inp(0x21) & ~0x03);
#if CfgKeyboardStyleAT
if(!Reset8042()) { status = SetupStatusError; printf("...Reset 8042
failed..."); };
#else

outp(KeyControlPort,inp(KeyControlPort) | 0xc0);
outp(KeyControlPort,inp(KeyControlPort) & ~ 0x80);

inp(KeyStrokePort); /* purge the keyboard */


#endif

495
The C Programs

#if CfgKeyboardStyleAT
EnableKeyboard();
#endif
#endif
LowRam->KbFlagByte = 0; /* reset the flags */
LowRam->KbFlagByte1 = 0;
LowRam->KbFlagByte2 = 0;
LowRam->KbFlagByte3 = 0;
Bios->DevicesInstalled |= Device;
return(status);
}

/*==========================================*/

void KbCall(struct _IRegs far * Regs);

void interrupt far KeyboardFunctionCall(InterruptRegisters)


{
InterruptEnvelope(KbCall,0,0);
};

void KbCall(struct _IRegs far * Regs)


{
struct _BiosRam far * LowRam = 0;
unsigned far * BufferItem;

_enable ();

switch(Regs->RegAH)
{
case OpcodeWaitForKey:

while (LowRam->KbBufferHead == LowRam->KbBufferTail)


{
_enable();
NoOpcode; NoOpcode; NoOpcode;
_disable();
};

Regs->RegAX = *(BufferItem = MK_FP(0x40,LowRam->KbBufferHead));

LowRam->KbBufferHead += 2;

if (LowRam->KbBufferHead >= LowRam->KbBufferEnd)


LowRam->KbBufferHead = LowRam->KbBufferStart;
_enable();
break;

case OpcodeCheckForKey:
_disable();
Regs->RegFlags &= ~ZeroBit; /* clear only the zero bit in the
flags */

Regs->RegAX = *(BufferItem = MK_FP(0x40,LowRam->KbBufferHead));

496
Introduction to AutoBios

if (LowRam->KbBufferHead == LowRam->KbBufferTail) Regs->RegFlags |= ZeroBit;


_enable();
break;

case OpcodeStoreKeyData:
_disable();
Regs->RegAL = 0; Regs->RegFlags &= ~CarryBit;
if(!LoadBuffer(Regs->RegCX)) { Regs->RegAL = 1; Regs->RegFlags |=
CarryBit; };
_enable();
break;

case OpcodeReadExtendedInput:
//printf("\nKB - Read Extended Input Call");
while (LowRam->KbBufferHead == LowRam->KbBufferTail)
{
_enable();
NoOpcode; NoOpcode; NoOpcode;
_disable();
};

Regs->RegAX = *(BufferItem = MK_FP(0x40,LowRam->KbBufferHead));

LowRam->KbBufferHead += 2;

if (LowRam->KbBufferHead >= LowRam->KbBufferEnd)


LowRam->KbBufferHead = LowRam->KbBufferStart;

if((Regs->RegAL == 0xf0) && (Regs->RegAH != 0)) Regs->RegAL = 0;


_enable();
break;

case OpcodeReadExtendedStatus:
//printf("\nKB - Read Extended Status Call");
_disable();
Regs->RegFlags &= ~ZeroBit; /* clear only the zero bit in the flags */

Regs->RegAX = *(BufferItem = MK_FP(0x40,LowRam->KbBufferHead));

if (LowRam->KbBufferHead == LowRam->KbBufferTail) Regs->RegFlags |= ZeroBit;


_enable();

if((Regs->RegAL == 0xf0) && (Regs->RegAH != 0)) Regs->RegAL = 0;


break;

case OpcodeReadExtendedShift:
//printf("\nKB - Read Extended Shift Call");
Regs->RegAH = (LowRam->KbFlagByte1 & 0xf3) | (LowRam->KbFlagByte3 & 0x0c);
Regs->RegAL = LowRam->KbFlagByte;
break;

case OpcodeGetFlags:
Regs->RegAX = (Regs->RegAX & 0xff00) | LowRam->KbFlagByte;
break;

default:

497
The C Programs

printf("\nKB - Unknown function %4X",Regs->RegAX);


break;
}
}

/*======================================================*/

/* ==== keyboard hardware interrupt service routine ==== */

void KbIntCall(struct _IRegs far * Regs);

void interrupt far KeyboardInterruptServiceRoutine(InterruptRegisters)


{
InterruptEnvelope(KbIntCall,0,0);
};

void KbIntCall(struct _IRegs far * Regs)


{
#if CfgKeyboard
struct _BiosRam far * LowRam = 0;

unsigned far * BfrPtr;


unsigned ScanCode,ScanByte,col;
unsigned ScanWord;
unsigned temp;
void (interrupt far * InterruptCall) (void);

_enable();

#if CfgKeyboardStyleAT
DisableKeyboard(); /* only if AT */
#endif

/* get scan code from input port */


ScanCode = (char)(inp(KeyStrokePort));
ScanWord = -1; /* preset scan word to default no-load */

#if CfgKeyboardStyleAT
#else
outp(KeyControlPort,inp(KeyControlPort) | 0x80);
outp(KeyControlPort,inp(KeyControlPort) & ~0x80);
#endif

// Call interrupt 15h, function 4fh, to allow alternate processing


// of scan code, if returns false, process scan code normally.
// If returns true, then skip processing the scan code
if (!KeyboardIntercept(ScanCode))
{
switch (ScanCode)
{
/* first do all the special handling keys */

case AckCode: LowRam->KbFlag2.AckRxed = 1; break;

case ResendCode: LowRam->KbFlag2.ResendRxed = 1; break;

498
Introduction to AutoBios

case SysReqKey:
#if CfgEnableKeySysReq
// to be added later
#endif
break;

case TabKey:
if((LowRam->KbFlag.LeftShift) || (LowRam->KbFlag.RightShift))
ScanWord = 15*256; else ScanWord = 15*256+9;
break;

case CtrlKey: LowRam->KbFlag.CtrlShift = 1; break;

case BreakCode+CtrlKey: LowRam->KbFlag.CtrlShift = 0; break;

case LeftShiftKey: LowRam->KbFlag.LeftShift = 1; break;

case BreakCode+LeftShiftKey: LowRam->KbFlag.LeftShift = 0; break;

case RightShiftKey: LowRam->KbFlag.RightShift = 1; break;

case BreakCode+RightShiftKey: LowRam->KbFlag.RightShift = 0; break;

case PrtScrKey:
if(LowRam->KbFlag.CtrlShift) ScanWord = 114*256;
else
{
if(LowRam->KbFlag.LeftShift || LowRam->KbFlag.RightShift )
{
#if CfgEnableKeyPrintScreen
(void far *)InterruptCall = LowRam->IntVector[0x05];
(* InterruptCall) ();
#endif
}
else ScanWord = 55*256+'*';
}
break;

case BreakCode+PrtScrKey: break;

case AltKey:
LowRam->KbFlag.AltShift = 1;
/* if(!LowRam->KB_FLAG & alt_shift) */
LowRam->ALT_INPUT = 0;
break;

case BreakCode+AltKey:
LowRam->KbFlag.AltShift = 0;
if(LowRam->ALT_INPUT) ScanWord = LowRam->ALT_INPUT;
break;

case CapsKey:
if (!LowRam->KbFlag1.CapsShift)
/* if key not depressed */
{
LowRam->KbFlag.CapsState ^= 1;

499
The C Programs

LowRam->KbFlag1.CapsShift = 1;
}
break;

case BreakCode+CapsKey: LowRam->KbFlag1.CapsShift = 0; break;

case NumKey:
if (!LowRam->KbFlag1.NumShift)
/* if key not depressed */
{
LowRam->KbFlag1.NumShift = 1;
LowRam->KbFlag.NumState ^= 1;
}
if(LowRam->KbFlag.CtrlShift)
/* do pause mode */
{
LowRam->KbFlag1.HoldState = 1;
if(LowRam->CRT_MODE != 7)
{
outp(0x3d8,LowRam->CRT_MODE_SET);
}
SendEOI1();

#if CfgKeyboardStyleAT
EnableKeyboard();
#endif

/* loop here until the pause condition is completed by another key in */


while (LowRam->KbFlag1.HoldState) {}
}
break;

case BreakCode+NumKey: LowRam->KbFlag1.NumShift = 0; break;

case ScrollKey:
if (!LowRam->KbFlag1.ScrollShift)
/* if key not depressed */
{
LowRam->KbFlag1.ScrollShift = 1;

if(!LowRam->KbFlag.CtrlShift && !LowRam->KbFlag.AltShift)


{
/* don't change state if ctrl or alt keys down */
LowRam->KbFlag.ScrollState ^= 1;
}
}

if(LowRam->KbFlag.CtrlShift)
{
SendEOI1();

#if CfgKeyboardStyleAT
EnableKeyboard();
#endif

if(LowRam->KbFlag.AltShift) /* Invoke Int 18 (SysVue, if enabled.) */

500
Introduction to AutoBios

{
(void far *)InterruptCall = LowRam->IntVector[0x18];
(* InterruptCall) ();
}
else /* break condition */
{
LowRam->BIOS_BREAK = 0x80;
#if CfgEnableKeyCtrlBreak
(void far *)InterruptCall = LowRam->IntVector[0x1B];
(* InterruptCall) ();
#endif
}
}
break;

case BreakCode+ScrollKey: LowRam->KbFlag1.ScrollShift = 0; break;

case InsertKey:
if (LowRam->KbFlag.AltShift)
{
assemble_alt_numeric(ScanCode);
}
else
{
if (!LowRam->KbFlag.InsertState)
{
LowRam->KbFlag.InsertState ^= 1; /* toggle insert state */
LowRam->KbFlag1.InsertShift = 1;
}
/*
// If in either num_state or shift_state, but not bithe, code = '0'
// else code = 0
*/
if(!LowRam->KbFlag.NumState)
{
if (!LowRam->KbFlag.LeftShift && !LowRam->KbFlag.RightShift)
ScanWord = InsertKey*256;
else
ScanWord = InsertKey*256+'0';
}
else
{
if (LowRam->KbFlag.LeftShift || LowRam->KbFlag.RightShift)
ScanWord = InsertKey*256;
else
ScanWord = InsertKey*256+'0';
}
}
break;

case BreakCode+InsertKey: LowRam->KbFlag1.InsertShift = 0; break;

case MinusKey: ScanWord = 74*256+'-'; break;

case PlusKey: ScanWord = 78*256+'+'; break;

501
The C Programs

case DeleteKey:
if((LowRam->KbFlag.CtrlShift) && (LowRam->KbFlag.AltShift))
{
#if CfgEnableKeyCtrlAltDel
if (!LowRam->KbFlag.LeftShift && !LowRam->KbFlag.RightShift)
{
LowRam->RESET_FLAG = 0x1234; /* warm boot */
}
else
{
LowRam->RESET_FLAG = 0; /* cold boot */
}
_disable();
InCmos(0x00); /* set NMI mask */
CmdColdBoot(0);
#endif
}
else
{
if(LowRam->KbFlag.NumState)
{
if(!LowRam->KbFlag.LeftShift && !LowRam->KbFlag.RightShift)
ScanWord = 83*256+'.';
else
ScanWord = 83*256;
}
else
{
if(LowRam->KbFlag.LeftShift && LowRam->KbFlag.RightShift)
ScanWord = 83*256+'.'; else ScanWord = 83*256;
}
}
break;

case BreakCode+DeleteKey: break;

default: /* not a special handling key */

if ((ScanCode & 0x80) == 0)


/* do only the makes for these */
{
ScanCode &= 0x7f; /* clear the break bit */

/* release the hold state if it is active */


if(LowRam->KbFlag1.HoldState) LowRam->KbFlag1.HoldState = 0;
else
{
switch (ScanCode)
{
case NumPad0Key:
case NumPad1Key:
case NumPad2Key:
case NumPad3Key:
case NumPad4Key:
case NumPad5Key:
case NumPad6Key:

502
Introduction to AutoBios

case NumPad7Key:
case NumPad8Key:
case NumPad9Key:
if (LowRam->KbFlag.AltShift) assemble_alt_numeric(ScanCode);
else
{
col = 0; /* BASE = 0 (all extended codes) */
if (LowRam->KbFlag.AltShift)
col = AltCol; /* ALT = 3 (all suppressed) */
else if (LowRam->KbFlag.CtrlShift)
col = CtrlCol; /* CTRL = 2 (all extended codes */

if (LowRam->KbFlag.NumState)
ScanWord = KbTable[ScanCode][1];
else
ScanWord = KbTable[ScanCode][col] << 8;
}
break;

case F1Key:
case F2Key:
case F3Key:
case F4Key:
case F5Key:
case F6Key:
case F7Key:
case F8Key:
case F9Key:
case FKey10:
case FKey11:
case FKey12:
ScanWord = TranslateFromColumn(ScanCode);
if ((ScanWord & 0xff00) == 0)
ScanWord = ScanWord << 8;
break;

default:
ScanWord = TranslateFromColumn(ScanCode);

/* if not an extended code return */


if((ScanWord & 0xff00) == 0)
{
ScanByte = (char)ScanWord;
/* caps lock correction */

if(LowRam->KbFlag.CapsState)
{
if (((ScanByte >= 'A') && (ScanByte <= 'Z')) ||
((ScanByte >= 'a') && (ScanByte <= 'z')))
ScanByte ^= 0x20;
}
ScanWord = (ScanCode << 8) | ScanByte;
}
break;
}
}

503
The C Programs

break;
}
}
if(ScanWord != -1) /* load scan word into buffer */
{
if(!LoadBuffer(ScanWord)) beep();
}
}
/* read the in service register to see if eoi is needed */
_disable();
outp(0x20,0x0b);
if((inp(0x20) & 0x02) != 0)
{
SendEOI1();

#if CfgKeyboardStyleAT
EnableKeyboard(); /* only if AT */
#endif
}
_enable();
#if CfgKeyboardStyleAT
//UpdateLEDs(); /* only if AT */
#endif
#endif
}

/*========== end of keyboard isr routine ===========*/

unsigned LoadBuffer(unsigned DataWord)


{
struct _BiosRam far * LowRam = 0;
unsigned Temp;
unsigned far * BufferItem;
unsigned ReturnValue = False;

// If a serial port may also be the console input device, then


// disable interrupts during buffer load time
#if CfgConsoleInSerial
_disable();
#endif

/* increment the temporary tail pointer */


Temp = LowRam->KbBufferTail; Temp += 2;
/* check for wrap-around and reset to start if needed */
if (Temp == LowRam->KbBufferEnd) Temp = LowRam->KbBufferStart;
/* if overwrite will not happen, then store the scan word */
if (Temp != LowRam->KbBufferHead)
{
*(BufferItem = MK_FP(0x40,LowRam->KbBufferTail)) = DataWord;

/* now update the tail */


LowRam->KbBufferTail = Temp;
ReturnValue = True;
}

// If a serial port was also enabled for the console input device,

504
Introduction to AutoBios

// we had previously disabled interrupts during buffer load time


#if CfgConsoleInSerial
_enable();
#endif

return(ReturnValue);
};

unsigned TranslateFromColumn(unsigned ScanCode)


{
struct _BiosRam far * LowRam = 0;
unsigned TranslateCol = BaseCol;
if (LowRam->KbFlag.AltShift)
return(KbTable[ScanCode][AltCol] << 8);
else
{
if (LowRam->KbFlag.CtrlShift) TranslateCol = CtrlCol;
else
{
if (LowRam->KbFlag.LeftShift || LowRam->KbFlag.RightShift)
TranslateCol = ShiftCol;
}
}
return (KbTable[ScanCode][TranslateCol]);
}

/*---------------------------------------------*/

void assemble_alt_numeric(unsigned ScanCode)


{
struct _BiosRam far * LowRam = 0;
char code;
code = KbTable[ScanCode][1];
if ((code >= '0') && (code <= '9'))
(LowRam->ALT_INPUT *= 10) + (code & 0x0f);
}

/*-- update the keyboard leds if state has changed --*/

#if CfgKeyboardStyleAT

void UpdateLEDs()
{
struct _BiosRam far * LowRam = 0;
if(LowRam->KbFlag2.ScrollLED ||
LowRam->KbFlag2.NumLED ||
LowRam->KbFlag2.CapsLED)
{
/* check update busy bit */
if (!LowRam->KbFlag2.UpdateInProgress)
{
EnableKeyboard();
LowRam->KbFlag2.UpdateInProgress = 1; /* set update busy */
if(Send8042Data((char)0xed) != False) /* send the led command */
{
DelayCall(10,Milliseconds);

505
The C Programs

LowRam->KbFlagByte2 &= 0xF8; /* build new led bits */


LowRam->KbFlagByte2 |= (LowRam->KbFlagByte & 0x70) >> 4;
SendEOI1();
EnableKeyboard();
/* send the led code */
if(Send8042Data((char)(LowRam->Kb.LEDs)) != True)
{
/* send enable if we had a tx error */
Send8042Data((char)0xF4);
}
}
LowRam->KbFlag2.UpdateInProgress = 0; /* clear update busy */
}
_enable();
}
}

void DisableKeyboard() { Send8042((char)0xad); };

void EnableKeyboard()
{
/*Send8042(0x60); Send8042Data(0x21); */
if(!Send8042((char)0xae)) printf("X");
};

#endif

//--------------------------------------------------------------------

// The Keyboard handler, right after getting an Int 09,


// calls interrupt 15h, function 4fh, to allow alternate processing
// of scan code, if returns false, process scan code normally.
// If returns true, then skip processing the scan code

unsigned KeyboardIntercept(unsigned ScanCode) // ( proc uses ds si,Me:FAR PTR


KBRegs)
{
#if CfgKeyboardIntercept
_asm mov ah,04fh
_asm mov al,BYTE PTR ScanCode
_asm stc
_asm int 15h
_asm mov BYTE PTR ScanCode,al
_asm jc NoAction
_asm mov ax,True
_asm jmp Done
_asm NoAction:
#endif
_asm mov ax,False
_asm Done:
};

/*=======================================================*/

506
Introduction to AutoBios

507
Introduction to AutoBios

7.7 The Video Driver


The Video Driver is used to operate the CRT display.

If a video adapter is not installed in a system, it is wise to retain the video function, and internally modify
it to direct output to an alternate device. This permits character oriented video output (such as the
"write_tty" command) to retain PC compatibility during the development phases. As an example, the
video driver might relay characters to a serial channel output routine, but the application could be
exercised on a system with a video device installed.
Note: Screen flickering - some early generation video adapters do not have clean memory-write/refresh-
read timing and flickering may be observed when updating the screen. Most of the currently available
adapters, in our experience, seem to minimize this flickering effect. If you observe flickering, the general
method to pursue to minimize this is to sample the horizontal re-trace status, (usually bit 0 of the status
port, 3BA or 3DA), and write into display memory only when the adapter is in retrace (moving the
blanked beam from right to left to start a new line). The vertical sync time can also be used for writing.
Note: 24 line scrolling - The standard Write-TTY function scrolls all 25 lines. A 24 line scroll may be a
desirable option in order to maintain a "status" line at the bottom of the screen. This may be
accomplished by modifying the Write-TTY function to either always scroll 24 (or 25) or to sense a flag
(or variable) to determine how many lines should be scrolled.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Video Driver
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CRT.C
//
// [Language] MSVC 1.5
//
// [Description] This driver manages the video display.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-------------------------------------------------------------------------
/* I N C L U D E F I L E S */

#include "Bios.h"

509
The C Programs

/* F U N C T I O N P R O T O T Y P E S */

void Load6845Byte(unsigned,char);
void Load6845Word(unsigned,unsigned);
unsigned expand_byte(char,char);
unsigned CheckMode(unsigned);
unsigned swap(unsigned);
void VideoCall(struct _IRegs far * Regs);

/* G L O B A L V A R I A B L E S */

/* G L O B A L C O N S T A N T S */

/* L O C A L D E F I N I T I O N S */

#define Device DeviceMaskVideo

enum { IsGraphicsMode, IsAlphaMode, };

#define ColorPort 0x03d4


#define MonoPort 0x03b4
#define EGAPort 0x03c0
#define MonoBuffer 0xb0000000
#define ColorBuffer 0xb8000000

enum { VideoModeVGA, VideoModeCGA40, VideoModeCGA80, VideoModeMono, };

/*=== command equates ===*/

#define OpCodeSetMode 0
#define OpCodeSetCursorShape 1
#define OpCodeSetCursor 2
#define OpCodeReadCursor 3
#define OpCodeReadLightPen 4
#define OpCodeSetActivePage 5
#define OpCodeScrollUp 6
#define OpCodeScrollDown 7
#define OpCodeReadAC 8
#define OpCodeWriteAC 9
#define OpCodeWriteC 10 /* 0A */
#define OpCodeSetColor 11 /* 0B */
#define OpCodeWritePixel 12 /* 0C */
#define OpCodeReadPixel 13 /* 0D */
#define OpCodeWriteTTY 14 /* 0E */
#define OpCodeReturnVideoState 15 /* 0F */
#define OpCodeWriteString 19 /* 13 */

/* L O C A L C O N S T A N T S */

/*------ constants ----------*/

extern char near VideoFont[128][8];

/*-- Define the indexes to the Video Parms Table --*/

510
Introduction to AutoBios

enum
{
HorzTotal,
HorzEnable,
StartHorzBlank,
StopHorzBlank,
StartHorzRetrace,
StopHorzRetrace,
VerticalTotal,
OverFlow,
PresetRowScan,
MaxScanLine,
CursorStart,
CursorEnd,
StartAddressHigh,
StartAddressLow,
CursorLocationHigh,
CursorLocationLow,
};

char _based(_segname("_CODE")) VideoParms[8][16] = {


{ 0x38,40,0x2d,10,0x1f,6,0x19,0x1c,2,7, 6, 7,0,0,0,0 },
{ 0x38,40,0x2d,10,0x1f,6,0x19,0x1c,2,7, 6, 7,0,0,0,0 },
{ 0x71,80,0x5a,10,0x1f,6,0x19,0x1c,2,7, 6, 7,0,0,0,0 },
{ 0x71,80,0x5a,10,0x1f,6,0x19,0x1c,2,7, 6, 7,0,0,0,0 },
{ 0x71,80,0x5a,10,0x1f,6,0x19,0x1c,2,7, 6, 7,0,0,0,0 },
{ 0x38,40,0x2d,10,0x7f,6,0x64,0x70,2,1, 6, 7,0,0,0,0 },
{ 0x38,40,0x2d,10,0x7f,6,0x64,0x70,2,1, 6, 7,0,0,0,0 },
{ 0x61,80,0x52,15,0x19,6,0x19,0x19,2,13,11,12,0,0,0,0 },
};

// We do not use the length table in BiosTop.asm because


// it only has four entries.
static unsigned _based(_segname("_CODE")) length_table[8] =
{ 2048,2048,4096,4096,16384,16384,16384,4096 };

static char _based(_segname("_CODE")) column_table[8] =


{ 40,40,80,80,40,40,80,80 };

static char _based(_segname("_CODE")) mode_table[8] =


{ 0x2c,0x28,0x2d,0x29,0x2a,0x2e,0x1e,0x29 };

struct _Video
{
char c;
char attrib;
};

/* P R O G R A M */

unsigned BufferAt(unsigned);

511
The C Programs

unsigned BufferAt(unsigned TestLocation)


{
// Create far * to buffer area
char far * BuffAddress = MK_FP(TestLocation,0);
// save current char of buffer
char Temp = * BuffAddress;
// store complement of previous character
* BuffAddress = ~Temp;
if (*BuffAddress == ~Temp)
{
BuffAddress = Temp; return(True);
}
else
{
BuffAddress = Temp; return(False);
}
}

/*------------- video setup ---------------------*/

unsigned VideoSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();
unsigned Temp;
//unsigned JumperVideo;

LoadDS();

CheckPoint(0xc0);
#if CfgVideo
/* reset any video cards */
outp(ColorPort + 4, 0); outp(MonoPort + 4, 1);
inp(MonoPort + 6); inp(ColorPort + 6); outp(EGAPort, 0);

/* load vector for this routine */


_disable();
LowRam->IntVector[0x10]=(void near *) VideoFunctionCall;
LowRam->IntVector[0x1D]=(void far *) VideoParms;
_enable();
/* set default port address to color board in case we have an EGA */
LowRam->ADDR_6845 = ColorPort;

/* determine type of video */

//if(JumperVideo = GetVideoJumper() != LowRam->EquipFlag.VideoMode)


//{
// check for existing video by sampling buffers
//

//};

switch (LowRam->EquipFlag.VideoMode)
{
case VideoModeMono:

512
Introduction to AutoBios

// could test for video buffer @ b000


if(BufferAt(0xb00))
{
LowRam->ADDR_6845 = MonoPort;
VideoSetMode(2);
}
else
{
VideoSetMode(3);
}
break;

case VideoModeCGA80:
// could test for video buffer @ b800
if(BufferAt(0xb800))
{
VideoSetMode(3);
}
else
{
LowRam->ADDR_6845 = MonoPort;
VideoSetMode(2);
}
break;

case VideoModeCGA40:
// could test for video buffer @ b800
if(BufferAt(0xb800))
{
VideoSetMode(1);
}
else
{
LowRam->ADDR_6845 = MonoPort;
VideoSetMode(2);
}
break;
}

/* Scan every through the video adapter ranges */


// could test for video buffer @ a000
#if CfgVideoPrimaryVGAEnd > CfgVideoPrimaryVGAStart
for (Temp = CfgVideoPrimaryVGAStart;
Temp <= CfgVideoPrimaryVGAEnd;
Temp = (unsigned)RomScan(Temp));
#endif

#if CfgVideoSecondaryVGAEnd > CfgVideoSecondaryVGAStart


for (Temp = CfgVideoSecondaryVGAStart;
Temp < CfgVideoSecondaryVGAEnd;
Temp = RomScan(Temp));
#endif

// Set True if you want to force clear the screen if VGA


#if CfgVideoClearScreen
VideoClearScreen();

513
The C Programs

#endif

CheckPoint(0xc1);
Bios->DevicesInstalled |= Device;
#endif
return(SetupStatusNul);
}

/*=== ===*/
/*=== MAIN VIDEO ROUTINE ===*/
/*=== ===*/

void interrupt far VideoFunctionCall(InterruptRegisters)


{
InterruptEnvelope(VideoCall,0,0);
};

//-----------------------------------------------

struct GraphicsCell
{
union
{
unsigned vword; /* video cell word */
unsigned char vchar; /* video character */
unsigned char vattr; /* video attribute */
};
};

struct TextCell
{
union
{
unsigned vword; /* video cell word */
unsigned char vchar; /* video character */
unsigned char vattr; /* video attribute */
};
};

extern struct _ScreenArray


{
union
{
struct TextCell AtTextCursor[8][25][80];
struct TextCell AtText40Cursor[8][25][40];
struct GraphicsCell AtGraphicsCursor[8][25][80];
};
};

void VideoCall(struct _IRegs far * Regs)


{
struct _BiosRam far * LowRam = 0;

union
{
struct _ScreenArray far * Ptr;

514
Introduction to AutoBios

unsigned SegOffWords[2];
}Screen;

#define Segment SegOffWords[1]


unsigned LocalCX,LocalBX;
unsigned j,i,RegIndex;
char far * ParmAddress;
unsigned FillWord;
unsigned Page = LowRam->ActivePage;
unsigned Row = LowRam->Cursor[Page].Row;
unsigned Col = LowRam->Cursor[Page].Col;
unsigned LineCount;
char TempAL;
unsigned Attribute;
unsigned Temp,TempCursor,FillLength;
char outchar;
//unsigned Port;
//unsigned RedirectCount;

_enable();

CheckPoint(0xc2);

if(LowRam->ADDR_6845)
{
if (LowRam->ADDR_6845 == MonoPort) Screen.Ptr = (void far *)MonoBuffer;
else Screen.Ptr = (void far *)ColorBuffer;

switch (Regs->RegAH)
{

/*=============================================*/
/*=== ===*/
/*=== AH = 0 = set mode ===*/
/*=== AL = mode to be selected (0-7) ===*/
/*=== ===*/
/*=============================================*/

case OpCodeSetMode:

switch(LowRam->EquipFlag.VideoMode)
{
case VideoModeMono:
LowRam->CRT_MODE = 7; /* if mono, force mode 7 */
LowRam->ADDR_6845 = MonoPort; Screen.Ptr = (void far *)MonoBuffer;
break;

default:
LowRam->ADDR_6845 = ColorPort; Screen.Ptr = (void far *)ColorBuffer;

if (Regs->RegAL != 7)
LowRam->CRT_MODE = Regs->RegAL; /* if color, use selected mode */
else
{
if (LowRam->EquipFlag.VideoMode == VideoModeCGA80)
LowRam->CRT_MODE = 0; else LowRam->CRT_MODE = 2;

515
The C Programs

};
break;
};

LowRam->CRT_MODE_SET = mode_table[LowRam->CRT_MODE];
outp((LowRam->ADDR_6845) + 4, LowRam->CRT_MODE_SET);

ParmAddress = LowRam->IntVector[0x1D];

LowRam->CursorEndLine = VideoParms[LowRam->CRT_MODE][CursorEnd];
LowRam->CursorStartLine = VideoParms[LowRam->CRT_MODE][CursorStart];

for (RegIndex=0;RegIndex < 16;RegIndex++)


{
Load6845Byte(RegIndex,VideoParms[LowRam->CRT_MODE][RegIndex]);
}
LowRam->CRT_START = 0;
LowRam->ActivePage = 0; /* set active page to zero */

/* enable video and correct port setting */

outp((LowRam->ADDR_6845) + 4,mode_table[LowRam->CRT_MODE]);
LowRam->CRT_MODE_SET = mode_table[LowRam->CRT_MODE];
LowRam->CRT_COLS = column_table[LowRam->CRT_MODE];
LowRam->CRT_LENGTH = length_table[LowRam->CRT_MODE];

/* clear all cursor positions */


for (i = 0; i < 8; LowRam->CursorWord[i++] = 0);

if (LowRam->CRT_MODE == 6) /* set pallette register */


{
outp((LowRam->ADDR_6845) + 5,0x3f);
LowRam->CRT_PALLETTE = 0x3f;
}
else
{
outp((LowRam->ADDR_6845) + 5,0x30);
LowRam->CRT_PALLETTE = 0x30;
}

if (CheckMode(IsGraphicsMode)) FillWord = 0; else FillWord = 0x0720;

FillLength = 2 * LowRam->CRT_LENGTH;
LowRam->CursorMode = 0x0607;

Col = 0; Row = 0;
while (Row < 26)
{
Screen.Ptr->AtTextCursor[Page][Row][Col++].vword = 0x0720; //FillWord;
if(Col >79) {Col = 0; Row++;};
}
break;

/*===========================================*/
/*=== ===*/
/*=== AH = 1 = set the cursor shape ===*/

516
Introduction to AutoBios

/*=== ===*/
/*=== CH = start line ===*/
/*=== CL = stop line ===*/
/*=== ===*/
/*===========================================*/

case OpCodeSetCursorShape:

LowRam->CursorMode = Regs->RegCX; Load6845Word(10,Regs->RegCX);

break;

/*=====================================*/
/*=== ===*/
/*=== AH = 2 = set cursor position ===*/
/*=== ===*/
/*=== DH = row | ===*/
/*=== DL = column | ===*/
/*=== BH = page | ===*/
/*=== | ===*/
/*=====================================*/

case OpCodeSetCursor:

LowRam->CursorWord[Regs->RegBH] = Regs->RegDX;

if (LowRam->ActivePage == Regs->RegBH)

Load6845Word(14,((LowRam->CRT_START) +
(((Regs->RegDH * LowRam->CRT_COLS) + (Regs->RegDL) ) << 1) >>1 ));

break;

/*=============================================*/
/*=== ===*/
/*=== AH = 3 = read cursor position ===*/
/*=== ===*/
/*=== BH = page | DH = row ===*/
/*=== | DL = column ===*/
/*=== | CX = cursor mode ===*/
/*=== | ===*/
/*=============================================*/

case OpCodeReadCursor:
Regs->RegCX = LowRam->CursorMode;
Regs->RegDX = LowRam->CursorWord[Regs->RegBH];
break;

/*=============================================*/
/*=== ===*/
/*=== AH = 4 = read light pen position ===*/
/*=== ===*/
/*=== | AH = 0 = no info ===*/
/*=== | AH = 1 = info ===*/
/*=== | DH = row ===*/
/*=== | DL = column ===*/

517
The C Programs

/*=== | CH = raster line ===*/


/*=== | BX = horz. position ===*/
/*=== | ===*/
/*=============================================*/

case OpCodeReadLightPen:
Regs->RegAH = 0; /* set no light pen return code */
break;

/*==========================================*/
/*=== ===*/
/*=== AH = 5 = set active page ===*/
/*=== ===*/
/*=== AL = active page # | ===*/
/*=== | ===*/
/*==========================================*/

case OpCodeSetActivePage:

LowRam->ActivePage = Regs->RegAL;
LowRam->CRT_START = LowRam->CRT_LENGTH * Regs->RegAL;
Regs->RegDX = LowRam->CursorWord[Regs->RegAL];
Load6845Word(12,LowRam->CRT_START / 2);
Load6845Word(14,(LowRam->CRT_START +
(((Regs->RegDH * LowRam->CRT_COLS ) + (Regs->RegDL) ) << 1)
>>1 ));

break;

/*=============================================*/
/*=== ===*/
/*=== AH = 6 = scroll up ===*/
/*=== ===*/
/*=== AL = # rows to scroll (0 = blank ) ===*/
/*=== CX = row,col of upper left corner ===*/
/*=== DX = row,col of lower right corner ===*/
/*=== BH = attribute for blanked line ===*/
/*=== ===*/
/*=============================================*/

case OpCodeScrollUp:
if (CheckMode(IsGraphicsMode))
{
#if CfgVideoGraf
if (!(Regs->RegAL)) /* blank the field */
{
i = Regs->RegDH - Regs->RegCH;
for (LineCount = 0; LineCount <= i; LineCount++)
{
for (Row = Regs->RegCH; Row <= Regs->RegDH; Row++)
{
ClearGraphicsRow(Screen.Segment,
((Row * 320) + (Regs->RegCL)),
(Regs->RegDL) - (Regs->RegCL) + 1,0);
}
}

518
Introduction to AutoBios

}
else /* scroll the field */
{
/* i will = the # of rows to scroll */
i = Regs->RegAL;

for (LineCount = 0;LineCount < i;LineCount++)


{
for (Row = Regs->RegCH; Row < Regs->RegDH; Row++)
{
MoveGraphicsRow(Screen.Segment,
((Row + 1) * 320) + (Regs->RegCL),
(Row * 320) + (Regs->RegCL),
(Regs->RegDL) - (Regs->RegCL)+1);
}
Row = Regs->RegDH;
ClearGraphicsRow(Screen.Segment,
(Row * 320) + (Regs->RegCL),
(Regs->RegDL) - (Regs->RegCL) + 1,0);
}
}
#endif
}
else /* alpha mode scroll */
{
if (!(Regs->RegAL)) /* blank the field */
{
for (LineCount = 0; LineCount <= (unsigned)(Regs->RegDH - Regs->RegCH);
LineCount++)
{
for (Row = Regs->RegCH; Row <= Regs->RegDH; Row++)
{
for(Col = Regs->RegCL; Col <= Regs->RegDL; Col++)
{
Screen.Ptr->AtTextCursor[Page][Row][Col].vword =
(Regs->RegBH) << 8 | 0x20;
};
}
}
}
else /* scroll the field */
//--
{
for (LineCount = 0; LineCount < Regs->RegAL; LineCount++)
{
for (Row = Regs->RegCH; Row < Regs->RegDH; Row++)
{
for(Col = Regs->RegCL; Col <= Regs->RegDL; Col++)
{
Screen.Ptr->AtTextCursor[Page][Row][Col].vword =
Screen.Ptr->AtTextCursor[Page][Row+1][Col].vword;
};
}
for(Col = Regs->RegCL; Col <= Regs->RegDL; Col++)
{
Screen.Ptr->AtTextCursor[Page][Regs->RegDH][Col].vword =

519
The C Programs

(Regs->RegBH) << 8 | 0x20;


};
}
}
}

break;

/*===================================================*/
/*=== AH = 7 = scroll down ===*/
/*=== ===*/
/*=== AL = # rows to scroll (0 = blank window) ===*/
/*=== CX = row,col of upper left corner ===*/
/*=== DX = row,col of lower right corner ===*/
/*=== BH = attribute for blanked line ===*/
/*=== ===*/
/*===================================================*/

case OpCodeScrollDown:

if (CheckMode(IsGraphicsMode))
{
#if CfgVideoGraf
if (!(Regs->RegAL)) /* blank the field */
{
i = Regs->RegDH - Regs->RegCH;
for (LineCount = 0; LineCount <= i; LineCount++)
{
for (Row = Regs->RegCH; Row <= Regs->RegDH; Row++)
{
ClearGraphicsRow(Screen.Segment,
((Row*320)+(Regs->RegCL)),
(Regs->RegDL)-(Regs->RegCL)+1,0);
}
}
}
else /* scroll the field */
{
for (LineCount = 0; LineCount < Regs->RegAL;
LineCount++)
{
for (Row = Regs->RegDH; Row > Regs->RegCH; Row--)
{
MoveGraphicsRow(Screen.Segment,
((Row - 1) * 320) + (Regs->RegCL),
(Row * 320) + (Regs->RegCL),
Regs->RegDL-Regs->RegCL+1);
}
Row = Regs->RegCH;
ClearGraphicsRow(Screen.Segment,
(Row * 320) + (Regs->RegCL),
(Regs->RegDL)-(Regs->RegCL)+1,0);
}
}
#endif
}

520
Introduction to AutoBios

else
{
if (!(Regs->RegAL)) /* blank the field */
{
for (LineCount = 0; LineCount <= (unsigned)(Regs->RegDH - Regs->RegCH);
LineCount++)
{
for (Row = Regs->RegCH; Row <= Regs->RegDH; Row++)
{
for(Col = Regs->RegCL; Col <= Regs->RegDL; Col++)
{
Screen.Ptr->AtTextCursor[Page][Row][Col].vword =
(Regs->RegBH) << 8 | 0x20;
}
}
}
}
else /* scroll the field */
{
for (LineCount = 0; LineCount < Regs->RegAL; LineCount++)
{
for (Row = Regs->RegDH; Row > Regs->RegCH; Row--)
{
for(Col = Regs->RegCL; Col <= Regs->RegDL; Col++)
{
Screen.Ptr->AtTextCursor[Page][Row+1][Col].vword =
Screen.Ptr->AtTextCursor[Page][Row][Col].vword;
};
}
for(Col = Regs->RegCL; Col <= Regs->RegDL; Col++)
{
Screen.Ptr->AtTextCursor[Page][Regs->RegCH][Col].vword =
(Regs->RegBH) << 8 | 0x20;
};
}
}
}

break;

/*=============================================*/
/*=== ===*/
/*=== AH = 8 = read attr and char at cursor ===*/
/*=== ===*/
/*=== BH = page # | AL = char ===*/
/*=== for alpha only | AH = attrib ===*/
/*=============================================*/

case OpCodeReadAC:

if (CheckMode(IsGraphicsMode))
{
#if CfgVideoGraf
for (j = 0; j < 128; j++)
{
Temp = True;

521
The C Programs

for (i=0; i <= 7; i++)


{
/* if mode is 640 x 200 */
if(LowRam->CRT_MODE == 6)
{
if(peekb(MK_FP(Screen.Segment,
(Row * 320) + ((i & 0xfe) * 40) + Col +
((i & 1) * 0x2000))) != VideoFont[Regs->RegAX & 0x007f][i])
Temp = False;
}
else /* 320 x 200 mode */
{
if(peek(MK_FP(Screen.Segment,
(Row * 320) + ((i & 0xfe) * 40) + (Col * 2) +
((i & 1) * 0x2000))) != expand_byte(VideoFont[Regs->RegAX & 0x007f]
[i],3))
Temp = False;
}
if (Temp != False)
{
Regs->RegAL = j;
break; /* get out with the find */
}
}
}
#endif
}
else /* --- alpha read --- */
{
Regs->RegAX = Screen.Ptr->AtTextCursor[Page][Row][Col].vword;
}

break;

/*==============================================*/
/*=== ===*/
/*=== AH = 9 = write attr and char at cursor ===*/
/*=== ===*/
/*=== BH = page # | ===*/
/*=== for alpha only| ===*/
/*=== CX = # write | ===*/
/*=== AL = character | ===*/
/*=== BL = attribute | ===*/
/*=== | ===*/
/*==============================================*/

case OpCodeWriteAC:

if(CheckMode(IsGraphicsMode))
{
#if CfgVideoGraf
for (i=0; i <= 7; i++)
{
/* if the mode is 640 x 200 */
if(LowRam->CRT_MODE == 6)
{

522
Introduction to AutoBios

pokeb(MK_FP(Screen.Segment,
(Row * 320) + ((i & 0xfe) * 40) +
Col +
((i & 1) * 0x2000)),
VideoFont[Regs->RegAX & 0x007f][i]);
}
else
{

/* if the mode is 320 x 200 */

poke(MK_FP(Screen.Segment,
(Row * 320) + ((i & 0xfe) * 40) +
(Col * 2) +
((i & 1) * 0x2000)),
expand_byte(VideoFont[Regs->RegAX & 0x007f][i],
(char)(Regs->RegBX & 0x83)));
}
}
#endif
}
else
{
i = Regs->RegCX;
while (i--)
{
Screen.Ptr->AtTextCursor[Page][Row][Col++].vword =
(Regs->RegBL << 8) | (Regs->RegAL);
if(Col >79) {Col = 0; Row++;};
}
}

break;

/*===============================================*/
/*=== ===*/
/*=== AH = 10 = write char at cursor position ===*/
/*=== ===*/
/*=== BH = page # ===*/
/*=== for alpha only| ===*/
/*=== CX = # to write ===*/
/*=== AL = character ===*/
/*=== ===*/
/*===============================================*/

case OpCodeWriteC:

if(CheckMode(IsGraphicsMode))
{
#if CfgVideoGraf
for (i=0; i <= 7; i++)
{
/* if the mode is 640 x 200 */
if(LowRam->CRT_MODE == 6)
{
//ScreenPtr->AtTextCursor[][][] = VideoFont[Regs->regAL][i]

523
The C Programs

pokeb(MK_FP(Screen.Segment,
(Row * 320) + ((i & 0xfe) * 40) +
Col +
((i & 1) * 0x2000)),
VideoFont[Regs->RegAX & 0x007f][i]);
}
else
{

/* if the mode is 320 x 200 */


//ScreenPtr->AtTextCursor[][][] = VideoFont[Regs->regAL][i]
poke(MK_FP(Screen.Segment,
(Row * 320) + ((i & 0xfe) * 40) +
(Col * 2) +
((i & 1) * 0x2000)),
expand_byte(VideoFont[Regs->RegAX & 0x007f][i],3));
}
}
#endif
}
else
{
i = Regs->RegCX;
while (i--)
{
Screen.Ptr->AtTextCursor[Page][Row][Col++].vchar = Regs->RegAL;
if(Col >79) {Col = 0; Row++;};
}
}
break;

/*==============================================*/
/*=== ===*/
/*=== AH = 11 = set color for MRES graphics ===*/
/*=== ===*/
/*=== BH = 0 ===*/
/*=== BL = background color ===*/
/*=== ===*/
/*=== BH = 1 ===*/
/*=== BL = pallette select ===*/
/*=== ===*/
/*==============================================*/

case OpCodeSetColor:
/* get current pallette value */
if(!(Regs->RegBH)) /* this is color 0 */
{
/* turn off low 5 bits of current color */
LowRam->CRT_PALLETTE &= 0xe0;
LowRam->CRT_PALLETTE |= (Regs->RegBX & 0x1f);
/* turn off high three bits of input */
}
else /* select pallette */
{
LowRam->CRT_PALLETTE &= 0xdf; /* turn off pallete select bit */
if((Regs->RegBX & BIT0))

524
Introduction to AutoBios

LowRam->CRT_PALLETTE |= 0x20; /* turn on pallette select bit */


}
outp((LowRam->ADDR_6845) + 5,LowRam->CRT_PALLETTE);
break;

/*===========================================*/
/*=== ===*/
/*=== AH = 12 = write pixel ===*/
/*=== ===*/
/*=== DX = row 0-199 ===*/
/*=== CX = column 0-639 ===*/
/*=== AL = pixel value (1 or 2 bits) ===*/
/*=== bit 7 = 1 = XOR lower bits ===*/
/*=== ===*/
/*===========================================*/

case OpCodeWritePixel:

/* calc row address for even/odd */


Row = Regs->RegDX * 40 + ((Regs->RegDX & 1) * (0x2000-40));
if(LowRam->CRT_MODE == 6) /* write one 1 bit */
{
/* col variable is used for bit mask */
Col = 1 << (Regs->RegCX % 8);
/* calc address for 1 bit in 8 */
Row += Regs->RegCX / 8;

pokeb(MK_FP(Screen.Segment,Row),((peekb(MK_FP(Screen.Segment,Row)
& ~Col) |
((Regs->RegAX & 0x0001) << (Regs->RegCX % 8)))));

}
else /* write 2 bits */
{
/* col variable is used for bit mask */
Col = 3 << (Regs->RegCX % 4);

/* calc address for 2 bits in 8 */


Row += Regs->RegCX/4;

pokeb(MK_FP(Screen.Segment,Row),((peekb(MK_FP(Screen.Segment,Row)
& ~Col) | ((Regs->RegAX & 0x0003) << (Regs->RegCX % 4)))));

break;

/*==========================================*/
/*=== ===*/
/*=== AH = 13 = read pixel ===*/
/*=== ===*/
/*=== DX = row 0-199 | AL = pixel ===*/
/*=== CX = column 0-639 | ===*/
/*=== | ===*/
/*==========================================*/

525
The C Programs

case OpCodeReadPixel:

/* calc row address for even/odd */


Row = Regs->RegDX * 40 + ((Regs->RegDX & 1) * (0x2000-40));

if(LowRam->CRT_MODE == 6) /* read one 1 bit */


{

/* calc address for 1 bit in 8 */


Row += Regs->RegCX/8;

Regs->RegAL = ((peekb(MK_FP(Screen.Segment,Row)
>> (Regs->RegCX % 8)) & 1));

}
else /* read 2 bits */
{

/* calc address for 2 bits in 8 */


Row += Regs->RegCX/4;

Regs->RegAL = ((peekb(MK_FP(Screen.Segment,Row)
>> (Regs->RegCX % 4)) & 3));

break;

/*=========================================*/
/*=== ===*/
/*=== AH = 14 = write tty ===*/
/*=== ===*/
/*=== AL = character to write ===*/
/*=== BL = fground color in graphics ===*/
/*=== use active page ===*/
/*=========================================*/

case OpCodeWriteTTY:

#if CfgConsoleOutSerial
//send al to com port
TempAL = Regs->RegAL;
_asm
{
push dx
push bx
push cx
mov dx,CfgSysVueConsolePort
add dx,5

mov bl,10 ; outer counter


local4:
xor cx,cx ; inner counter
local5:
in al,dx

526
Introduction to AutoBios

and al,0x60
cmp al,0x60
je local10
loop local5
dec bl
jnz local4

local10:

mov al,TempAL
mov dx,CfgSysVueConsolePort
out dx,al

pop cx
pop bx
pop dx

}
#endif

#if CfgConsoleOutVideo
switch (Regs->RegAL)
{
case '\a': /* bell */
beep();
break;

case '\b': /* backspace */


if (Col !=0) Col--;
break;

case '\r': /* carriage_return */


Col = 0;
break;

case '\n': /* line_feed */


if (Row == 24)
{
/* find the fill attribute */
Attribute = VideoReadAC() >> 8;

/* set bh to blank line attribute */


VideoScrollUp(1,Attribute,0,(24 << 8) | (LowRam->CRT_COLS - 1));
}
else
{
Row++;
}
break;

default: /* any other character */

VideoWriteChar(Regs->RegAL);
Col++;
if (Col >= LowRam->CRT_COLS)
{

527
The C Programs

Col = 0;
if (Row == 24)
{
/* find the fill attribute */
Attribute = VideoReadAC() >> 8;
VideoScrollUp(1,Attribute,0,(24 << 8) | (LowRam->CRT_COLS - 1));
}
else
{
Row++;
}
}
break;
}

Temp = (Row << 8) | (Col & 0x00ff);


LowRam->CursorWord[LowRam->ActivePage] = Temp;

Load6845Word(14,(LowRam->CRT_START +
((Row * LowRam->CRT_COLS) + Col ) << 1) >>1 );

#endif

break;

/*===========================================*/
/*=== ===*/
/*=== AH = 15 = return video state ===*/
/*=== ===*/
/*=== AH = # of cols ===*/
/*=== AL = mode ===*/
/*=== BH = page ===*/
/*=== ===*/
/*===========================================*/

case OpCodeReturnVideoState:

Regs->RegAH = LowRam->CRT_COLS;
Regs->RegAL = LowRam->CRT_MODE;
Regs->RegBH = LowRam->ActivePage;

break;

/*====================================================*/
/*=== ===*/
/*=== AH = 19 = write string ===*/
/*=== ===*/
/*=== ES:BP = pointer to string ===*/
/*=== CX = length of string ===*/
/*=== DX = cursor position ===*/
/*=== BH = page # ===*/
/*=== ===*/
/*=== AL = 0 = write string - don't move cursor ===*/
/*=== BL = attribute ===*/
/*=== AL = 1 = write string - move cursor ===*/
/*=== BL = attribute ===*/

528
Introduction to AutoBios

/*=== AL = 2 = write char and attribute ===*/


/*=== - don't move cursor ===*/
/*=== AL = 3 = write char and attribute ===*/
/*=== - move cursor ===*/
/*=== ===*/
/*====================================================*/

case OpCodeWriteString:

/* if count > 0 and opcode 0-3 */


if ((Regs->RegCX) && (Regs->RegAL <= 3))
{
/* save current cursor for this page */
TempCursor = LowRam->CursorWord[Regs->RegBH];

/* set cursor to callers position */


VideoSetCursor(Regs->RegDX);
Row = Regs->RegDH;
Col = Regs->RegDL;

for (i = 0; i < Regs->RegCX; i++)


{
outchar = peekb(MK_FP(Regs->RegES,Regs->RegBP+i));

if ((outchar == '\b' ) ||
(outchar == '\r' ) ||
(outchar == '\n' ))
{
VideoWriteTty(outchar);
Row = LowRam->Cursor[Page].Row;
Col = LowRam->Cursor[Page].Col;
}
else
{
LocalCX = 1;
LocalBX = Regs->RegBX;
if (Regs->RegAL > 2)
{
LocalBX = peekb(MK_FP(Regs->RegES,Regs->RegBP));
Regs->RegBP++;
}
VideoWriteAC(outchar,Regs->RegBX);
Col++;
if (Col >> (LowRam->CRT_COLS))
{
Row++;
if (Row >=25)
{
Col = 0;
VideoWriteTty('\n');
Row--;
}
}
/* update cursor */
VideoSetCursor((Row << 8) | Col);
}

529
The C Programs

}
/* restore original cursor */
if (!(Regs->RegAX & 1))
{
LowRam->CursorWord[Regs->RegBH] = TempCursor;
VideoSetCursor(TempCursor);
}
}
break;

/*===========================================*/
/*=== ===*/
/*=== default case for invalid opcodes ===*/
/*=== ===*/
/*===========================================*/
default:
break;
}
}

CheckPoint(0xc4);
}

/*=============================================*/
/*=== ===*/
/*=== SUPPORTING FUNCTIONS ===*/
/*=== ===*/
/*=============================================*/

/*---
**--- return alpha or graphics mode flag
*/

unsigned CheckMode(unsigned match)


{
struct _BiosRam far * LowRam = 0;
switch(match)
{
case IsGraphicsMode:
return(((LowRam->CRT_MODE >= 4) && (LowRam->CRT_MODE <= 6))?True:False);
break;

case IsAlphaMode:
return(((LowRam->CRT_MODE >= 4) && (LowRam->CRT_MODE <= 6))?False:True);
break;

default:
return(False);
}
}

/*---
**--- expand the byte for medium res.

530
Introduction to AutoBios

**--- double the input byte to an output integer


*/
#if CfgVideoGraf
unsigned expand_byte(char the_byte, char color)
{
unsigned Temp = 0;
unsigned mask = 0x80;
while (mask)
{
Temp = Temp << 2;
if ((the_byte & mask))
if(!(color & BIT7))
Temp |= (color & 0x03);
else
Temp ^= (color & 0x03);
mask = mask >> 1;
}
return(((Temp >> 8) & 0x00ff) | ((Temp <<8 ) & 0xff00));
}
#endif
/*---------------------------------------------------*/
/*--- ---*/
/*--- load a word into the 6845 reg 'n' and 'n'+1 --*/
/*--- ---*/
/*---------------------------------------------------*/

void Load6845Word (unsigned address,unsigned value)


{
Load6845Byte(address, (char)(value >> 8));
Load6845Byte(address + 1, (char)value);
}

/*------------------------------------------------*/
/*--- ---*/
/*--- load a byte into the 6845 reg 'n' ---*/
/*--- ---*/
/*------------------------------------------------*/

void Load6845Byte(unsigned address,char value)


{
struct _BiosRam far * LowRam = 0;
outp(LowRam->ADDR_6845, address);
outp(((LowRam->ADDR_6845) + 1),value);
}

531
Introduction to AutoBios

7.8 The Floppy Disk Driver


The Floppy Disk Driver is used to operate the floppy disk.
This driver structure has been organized to support up to four (4) floppy disk drives. The normal AT
style disk controller does not provide the motor and select logic to do so. Two possible options are to:
1. Install a second controller at an alternate address and sense which port address should be referenced
for each drive. This would entail declaring a "port" variable which would be used on the inport and
outport commands.
2. Install a controller which does support four drive configurations. If such a controller is not
commercially available, one may design and construct such a device by duplicating the standard
functions and adding the required motor and select logic. Since newer LSI based floppy disk
controllers (such as the Intel 82072) simplify this task, one may wish to consider this alternative.
Presuming that the new perpendicular-recording 4 Mbyte floppy disk drives will become desired options,
the disk parameter tables are organized for easy expansion. By inspecting the defined tables in the source
file, one will observe that some entries are already included for the 4 Mb drives. Take note that these
drive parameters (and the 4Mb drives) have not been installed or tested on the Bios development system,
so that some additional development work will be required to implement the 4 Mb drive type.
The standard location in the CMOS RAM for storing the drive types for Drive A: and B: is cell 10 hex.
We have chosen the "reserved" cell 11 hex for storing the type byte for floppy Drives C: and D:. If these
should conflict with some other use, they may be re-assigned as you wish.
For those of you who are creating diskless systems, our PromKit publication provides additional
information on how the standard floppy disk driver may be replaced / chained / enhanced so a different
physical device may be used for a logical floppy disk.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Floppy Disk Driver
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Disk.C
//
// [Language] MSVC 1.5
//
// [Description] This module supports 360 to 2.88 floppy drives.
//
// [Arguments] Registers
//
// [Return] Registers
// Carry Flag set if error condition
//

533
The C Programs

// [History] 2.00 04/11/94 Original


//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

#include "Bios.h"

// F U N C T I O N P R O T O T Y P E S

//================ function prototypes ===================

static unsigned SendCommandOK(unsigned);


static void MotorOn(struct _FDiskRegs far *);
static unsigned CalcSectors(struct _FDiskRegs far *);
static unsigned IntReceived(void);
static unsigned RecalOK(struct _FDiskRegs far *);
static unsigned SeekOK(struct _FDiskRegs far *);
static unsigned GetFdcStatusOK(struct _FDiskRegs far *);
static unsigned ChangeLineActive(struct _FDiskRegs far *);
static unsigned ResultsReadOK(void);
static unsigned StatusCheckOK(void);
static unsigned DmaSetupOK(struct _FDiskRegs far *);
static void SendRate(struct _FDiskRegs far *);
static unsigned RetryNeeded(struct _FDiskRegs far *);
static unsigned MediaChanged(struct _FDiskRegs far *);
static void WaitForHead(struct _FDiskRegs far *);
static unsigned ReadID(void far *);
static unsigned RecalSeekStatusOK(void);
static unsigned SendSpecifyCommandOK(void);
static void FdcReset(struct _FDiskRegs far *);
static void PurgeFdc(void);
static unsigned InitControllerOK(struct _FDiskRegs far *);

// L O C A L D E F I N I T I O N S

#define GetParm(index) FDiskTable[Me->DriveType][Me->MediaType].index


#define Device DeviceMaskDisk

#define ErrorNone 0x00


#define ErrorCommand 0x01
#define ErrorAddress 0x02
#define ErrorWriteProtect 0x03
#define ErrorSector 0x04
#define ErrorMediaChange 0x06
#define ErrorOverrun 0x08
#define ErrorBoundary 0x09
#define ErrorMediaType 0x0c
#define ErrorCRC 0x10
#define ErrorFDC 0x20
#define ErrorSeek 0x40
#define ErrorTimeOut 0x80

// function code definitions

#define OpcodeReset 0x00

534
Introduction to AutoBios

#define OpcodeReadStatus 0x01


#define OpcodeReadSectors 0x02
#define OpcodeWriteSectors 0x03
#define OpcodeVerifySectors 0x04
#define OpcodeFormatTrack 0x05
#define OpcodeReadDiskParms 0x08
#define OpcodeReadDiskType 0x15
#define OpcodeReadDiskChange 0x16
#define OpcodeSetFormat 0x17
#define OpcodeSetMedia 0x18
#define OpcodeBadFunction 0x19

// 765 and 82077A port definitions

//#define FdcStatusA 0x3f0 // Status Register A (R)


//#define FdcStatusB 0x3f1 // Status Register B (R)
#define FdcDOR 0x3f2 // Digital Output Register (R/W)
//#define FdcTapeDrive 0x3f3 // Tape Drive Register (R/W)
#define FdcMSR 0x3f4 // Main Status Register (R)
#define FdcDataReg 0x3f5 // Data Register (R/W)
#define FdcDigiInput 0x3f7 // Digital Input Register (R)
#define FdcConfigPort 0x3f7 // Configuration Control Reg (W)

// 765 and 82077A port bitfield definitions

#define RqmBit BIT7


#define DioBit BIT6
#define BusyBit BIT4
#define DiskChangeBit BIT7

// 8237 DMA port definitions

#define DmaMaskPort 0x0a


#define DmaModePort 0x0b
#define DmaFlffPort 0x0c
#define DmaAddressPort 0x04
#define DmaBasePort 0x05
#define DmaPagePort 0x81

// 8237 DMA literal definitions

#define DmaOpcodeOn 0x02


#define DmaOpcodeOff 0x06
#define DmaOpcodeRx 0x46
#define DmaOpcodeTx 0x4a
#define DmaOpcodeVerify 0x42
#define DmaDirTx 0x01
#define DmaDirRx 0x00

// FDC commands

#define OpcodeFdcRead 0xe6


#define OpcodeFdcWrite 0xc5
#define OpcodeFdcVerify 0xf6
#define OpcodeFdcFormat 0x4d
#define OpcodeFdcReadID 0x4a

535
The C Programs

//
// The following Enumerations are all the same, permitting more
// descriptive entries as to their meaning in various tables

enum { TypeNone, Type360, Type1200, Type720, Type1440, Type2880 };


enum { DriveNone, Drive360, Drive1200, Drive720, Drive1440, Drive2880 };
enum { MediaNone, Media360, Media1200, Media720, Media1440, Media2880 };

// This list permits using either twist or non-twist cable


// without having to change the default drive select "1" which
// is normally factory preset for PC compatible drives.

#if CfgDiskCableSwap
// This is non-twist cable mapping
// Useful only for Drive A: unless changing select jumpers

char _based(_segname("_CODE")) CableMap[4]={ 0x2d, 0x1c, 0x8f, 0x4e };

#else
// This is normal mapping
char _based(_segname("_CODE")) CableMap[4]={ 0x1c, 0x2d, 0x4e, 0x8f };

#endif

char _based(_segname("_CODE")) SequenceTable[8][4]= {


// This table covers the sequence of media type to try for
// each Drive type in establishing the media in the Drive.
// The media is defaulted to the first item in this table
// for a particular Drive type. When we attempt retries, we
// step through the possible media types until we come
// to "none" marking the end of the table.

/* TypeNone */ {TypeNone,TypeNone,TypeNone,TypeNone},
/* Type360 */ {Type360, TypeNone,TypeNone,TypeNone},
/* Type1200 */ {Type1200,Type360, TypeNone,TypeNone},
/* Type720 */ {Type720, TypeNone,TypeNone,TypeNone},
/* Type1440 */ {Type1440,Type720, TypeNone,TypeNone},
/* Type2880 */ {Type2880,Type1440,Type720, TypeNone},
/* TypeSpare */ {TypeNone,TypeNone,TypeNone,TypeNone},
/* TypeSpare */ {TypeNone,TypeNone,TypeNone,TypeNone},
};

//
// These definitions provide descriptive names for values in the
// DiskTable below, and for standard values used by the Driver.

#define Specify1 0xaf


#define Specify2 2
#define OffTime 25
#define BytesPerSector 512
#define FdcBytesPerSectorCode 2
#define FillByte 0xf6
#define SettleTime 15

536
Introduction to AutoBios

#define StartTime 8
#define Sectors08 8
#define Sectors09 9
#define Sectors15 15
#define Sectors18 18
#define Sectors36 36

#define MaxTrax40 39
#define MaxTrax80 79

#define SingleStep False


#define DoubleStep True

#define DTL -1

enum { Rate500, Rate300, Rate250, Rate1000 };

//=== These is Floppy Disk Parameter Table =====


//
// The table is organized as an Array of up to 8 Drive types,
// each supporting up to 8 media types.
// Each item is 8 bytes long

struct DiskItem
{
char DriveID;
char MediaID;
char MaxTracks;
char SectorsTrack;
char DataRate;
char Step;
char Gap;
char Gap3;
};

struct DiskItem _based(_segname("_CODE")) FDiskTable[8][8]= {


// this entry is for compatibility with the XT disk Driver
{
// ---- Drive type 0 = None (Default to 360) ----

{Drive360,Media360,MaxTrax40,Sectors09,Rate250,SingleStep,0x2a,0x50,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
},

{
// ---- Drive type 1 = 360 ----

// 0 = no media in 360 kb Drive


{0,0,0,0,0,0,0,0,},

537
The C Programs

// 1 = 360 kb media in 360 kb Drive


{Drive360,Media360,MaxTrax40,Sectors09,Rate250,SingleStep,0x2a,0x50,},

// 2-7 not used


{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
},

{
// ---- Drive type 2 = 1.2 ------

// 0 = no media in 1.2 mb Drive


{0,0,0,0,0,0,0,0,},

// 1 = 360 kb media in 1.2 mb Drive


{Drive1200,Media360,MaxTrax40,Sectors09,Rate300,DoubleStep,0x2a,0x50,},

// 2 = 1.2 mb media in 1.2 mb Drive


{Drive1200,Media1200,MaxTrax80,Sectors15,Rate500,SingleStep,0x1b,0x54,},

// 3-7 = not used


{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
},

{
// ---- Drive type 3 = 720 ------

// 0 = no media in 720 kb Drive


{0,0,0,0,0,0,0,0,},

// 1-2 = not used


{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},

// 3 = 720 kb media in 720 kb Drive


{Drive720,Media720,MaxTrax80,Sectors09,Rate250,SingleStep,0x2a,0x50,},

// 4-7 = not used


{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
},

538
Introduction to AutoBios

{
// ---- Drive type 4 = 1.44 ------

// 0 = no media in 1.44 mb Drive


{0,0,0,0,0,0,0,0,},

// 1-2 = not used


{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},

// 3 = 720 kb media in 1.44 mb Drive


{Drive1440,Media720,MaxTrax80,Sectors09,Rate250,SingleStep,0x2a,0x50,},

// 4 = 1.44 kb media in 1.44 mb Drive


{Drive1440,Media1440,MaxTrax80,Sectors18,Rate500,SingleStep,0x1b,0x6c,},

// 5-7 = not used


{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
},

//---- Drive type 5 = 2.88 ------

// The 2.88 Meg Drives have not been tested.


// These tables are included as a help to integrating 2.88 Drives into
// your system. The correct parameters must be determined in conjunction
// with the Drive manufacturers specifications.

// 0 = no media in 2.88 mb Drive


{0,0,0,0,0,0,0,0,},

// 1-2 not used


{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},

// 3 = 720 kb media in 2.88 mb Drive


{Drive2880,Media720,MaxTrax80,Sectors09,Rate250,SingleStep,0x2a,0x50,},

// 4 = 1.44 kb media in 2.88 mb Drive


{Drive2880,Media720,MaxTrax80,Sectors18,Rate500,SingleStep,0x1b,0x6c,},

// 5 = 2.88 kb media in 2.88 mb Drive


{Drive2880,Media2880,MaxTrax80,Sectors36,Rate1000,SingleStep,0x1b,0x53,},

// 6-7 not used


{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
},

{
//---- Drive type 6 = reserved ------

{0,0,0,0,0,0,0,0,},

539
The C Programs

{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
},

{
//---- Drive type 7 = reserved ------

{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,},
},
};

// P R O G R A M

/*

This Driver uses a Drive/media ID byte fielded as follows:

bit 7 0/1 = media not established / established

bit 6-4 media type


000 = no established media
001 = 360 (40/80 Track)
010 = 1.2 (80 Track)
011 = 720 (80 Track)
100 = 1.4 (80 Track)
101 = 2.8 (80 Track)
110 - 111 reserved

bit 3 = 0/1 = Drive not established / established

bit 2-0 Drive type


000 no established Drive type
001 = 360 (40 Track)
010 = 1.2 (80 Track)
011 = 720 (80 Track)
100 = 1.4 (80 Track)
101 = 2.8 (80 Track)
110 - 111 reserved

The Drive/media bytes are located at 40:90-91 for up to two Drives.


*/

540
Introduction to AutoBios

//======================================================
//=================== START OF CODE ====================
//======================================================

struct _FDiskRegs
{
unsigned DriveType:3;
unsigned DriveTrash:13;
unsigned FdcCommand;
unsigned DmaCommand;
unsigned DmaDirectionWrite;
unsigned Sector_Track;
unsigned MediaType:3;
unsigned MediaTrash:13;
unsigned OpCode;
unsigned Drive;
unsigned NrSectors;
unsigned LocalES;
unsigned LocalBX;
unsigned Head;
unsigned Sector;
unsigned Track;
unsigned MaxTrack;
unsigned MaxSectors;
unsigned Index;
unsigned TryCount;
unsigned MediaIndex;
unsigned WaitForMotor;
unsigned EndTrack,EndHead,EndSector,NumSectors,SectorsTrack;
union
{
char WidthChar[4];
unsigned WidthWord[2];
unsigned long WidthLong[1];
}XfrAddress;
unsigned XfrLength;
};

// P R O G R A M

//-------------- setup the controller -----------

unsigned FDiskSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();
unsigned i, condition = SetupStatusOK;
_enable();
LoadDS();

LowRam->IntVector[0x13] = (void near *)FDiskFunctionCall;

Bios->DevicesInstalled |= Device;

LowRam->IntVector[0x0e] = (void near *)FDiskISR;


LowRam->IntVector[0x1E] = (void far *) FDiskTable;

541
The C Programs

LowRam->SeekStatusByte = 0; // clear seek status


LowRam->MotorStatusByte = 0; // clear motor status
LowRam->DiskStatusByte = 0; // clear disk status

LowRam->MOTOR_COUNT = 25; // set motor count

LowRam->DiskID[0].MediaEst = 0; // clear Drive 0 state


LowRam->DiskID[1].MediaEst = 0; // clear Drive 1 state

if(LowRam->DiskID[0].DriveType = (char)CmosType(0))
LowRam->DiskID[0].DriveEst = True;
if(LowRam->DiskID[1].DriveType = (char)CmosType(1))
LowRam->DiskID[1].DriveEst = True;
if(!CallDiskReset(0)) { condition = SetupStatusError; };
LowRam->MOTOR_COUNT = 0xff;
outp(FdcDOR,CableMap[0]); // turn on Drive a: motor for faster boot

// unmask the IRQ


outp(0x21,inp(0x21) & ~0x40);
return(condition);
}

//========================================================
//========================================================
//========================================================
//======== BEGINNING OF MAIN ROUTINES ===================
//========================================================
//========================================================
//========================================================

void DiskCall(struct _IRegs far * Regs);

void interrupt far FDiskFunctionCall(InterruptRegisters)


{
InterruptEnvelope(DiskCall,Device,0);
};

void DiskCall(struct _IRegs far * Regs)


{
struct _FDiskRegs FDiskRegs;
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();
struct _FDiskRegs far * Me = &FDiskRegs;
unsigned TempES, TempBX, TempCount;
_enable();

TempES = Regs->RegES; TempBX = Regs->RegBX;

Me->OpCode = Regs->RegAH;
Me->Drive = Regs->RegDL;
Me->NrSectors = Regs->RegAL;
Me->Head = Regs->RegDH;
Me->Sector = Regs->RegCL;
Me->Track = Regs->RegCH;
Me->LocalES = Regs->RegES;

542
Introduction to AutoBios

Me->LocalBX = Regs->RegBX;
Me->DriveType = LowRam->DiskID[Me->Drive].DriveType;

Regs->RegFlags &= ~CarryBit; // clear the carry flag for returns

LowRam->DiskStatusByte = 0; // clear status

if ((Regs->RegAH == 0x08) && (Regs->RegDL >= 0x80))


{
printsnapstring(MsgOpcodeHardDiskCall);
Regs->RegAH = 0x01; Regs->RegFlags |= CarryBit;
}
else
{
if ((Regs->RegAH) && (Regs->RegDL > LowRam->EquipFlag.NrDrives))
{ // bad function code because of Drive number

LowRam->DiskStatusByte = ErrorCommand;
Regs->RegAH = OpcodeBadFunction;
Regs->RegFlags |= CarryBit; // set return error flag
}
else
{

// make sure any residual status is unloaded


PurgeFdc();
// set the data rate register to a default value
//outp(FdcConfigPort,Rate250);

// insure that the floppy disk interrupt is enable at the 8259


outp(0x21,inp(0x21) & ~0x40);

switch (Me->OpCode)
{
case OpcodeReset: printsnapstring(MsgOpcodeReset);
FdcReset(Me);
Regs->RegAH = LowRam->DiskStatusByte;
if (Regs->RegAH) Regs->RegFlags |= CarryBit;
break;

case OpcodeReadStatus:
printsnapstring(MsgOpcodeReadStatus);
Regs->RegAH = LowRam->DiskStatusByte;
if (Regs->RegAH) Regs->RegFlags |= CarryBit;
break;

case OpcodeReadSectors:
printsnapstring(MsgOpcodeReadSectors);
Me->WaitForMotor = False;
Me->FdcCommand = OpcodeFdcRead;
Me->DmaCommand = DmaOpcodeRx;
Me->DmaDirectionWrite = False;
goto read_write_verify;

case OpcodeWriteSectors:
printsnapstring(MsgOpcodeWriteSectors);

543
The C Programs

Me->WaitForMotor = True;
Me->FdcCommand = OpcodeFdcWrite;
Me->DmaCommand = DmaOpcodeTx;
Me->DmaDirectionWrite = True;
goto read_write_verify;

case OpcodeVerifySectors:
printsnapstring(MsgOpcodeVerifySectors);
Me->WaitForMotor = False;
Me->FdcCommand = OpcodeFdcVerify;
Me->DmaCommand = DmaOpcodeVerify;
Me->DmaDirectionWrite = False;
goto read_write_verify;

read_write_verify:
// if a media change sensed, then de-establish media
if (MediaChanged(Me))
{
LowRam->DiskID[Me->Drive].MediaEst = False;
LowRam->DiskID[Me->Drive].MediaType = 0;
Me->MediaIndex = 0;
}
Me->TryCount = 3;

do // this is the major loop, try the major operation 3 times


{
// if media not established, then set media type = Drive type
// set MediaIndex = 0, set media type by index

if (!LowRam->DiskID[Me->Drive].MediaEst)
{
// set the media index for the first possible type of media
LowRam->DiskID[Me->Drive].MediaType = SequenceTable[Me->DriveType][0];
// set the media type according to the Drive type [index = 0]
Me->MediaType = LowRam->DiskID[Me->Drive].MediaType;

}
do // this is the minor loop
// do until we run out of RetryNeededs
{

PurgeFdc(); // make sure any residual status is unloaded

LowRam->DiskStatusByte = 0;

// set up Drive and media indexes before doing the dma setup,
// which needs to know how many bytes per Sector for calcing xfr length
Me->DriveType = LowRam->DiskID[Me->Drive].DriveType;
Me->MediaType = LowRam->DiskID[Me->Drive].MediaType;
if (DmaSetupOK(Me))
{
// send the specify command
SendSpecifyCommandOK();

SendRate(Me);

544
Introduction to AutoBios

if (InitControllerOK(Me))
if (SendCommandOK(Me->Track))
if (SendCommandOK(Me->Head))
if (SendCommandOK(Me->Sector))
if (SendCommandOK(FdcBytesPerSectorCode))
if (SendCommandOK(GetParm(SectorsTrack)))
if (SendCommandOK(GetParm(Gap)))
if (SendCommandOK(DTL))
if (GetFdcStatusOK(Me))
{

// get out with good operation


LowRam->DiskID[Me->Drive].MediaEst = True; break;
}
}
}
while (RetryNeeded(Me));
}
while ((--Me->TryCount > 0) &&
(!LowRam->DiskID[Me->Drive].MediaEst) &&
(!(LowRam->DiskStatusByte & ErrorTimeOut)));

Regs->RegAH = LowRam->DiskStatusByte;
Regs->RegAL = CalcSectors(Me);
if (Regs->RegAH) Regs->RegFlags |= CarryBit;
break;

case OpcodeFormatTrack :
printsnapstring(MsgOpcodeFormatTrack);
Me->FdcCommand = OpcodeFdcFormat;
Me->DmaCommand = DmaOpcodeTx;
Me->DmaDirectionWrite = True;
// if media not established, then set media type = Drive type
if (!LowRam->DiskID[Me->Drive].MediaEst)
LowRam->DiskID[Me->Drive].MediaType = LowRam->DiskID[Me->Drive].DriveType;

Me->WaitForMotor = True;
if (MediaChanged(Me)) // check for media change
{
SendSpecifyCommandOK();
SendRate(Me);
if (DmaSetupOK(Me))
{
if (InitControllerOK(Me))
{
if (SendCommandOK(FdcBytesPerSectorCode))
{
if (SendCommandOK(GetParm(SectorsTrack)))
{
if (SendCommandOK(GetParm(Gap3)))
{
SendCommandOK(FillByte); // send command
GetFdcStatusOK(Me);
}
}

545
The C Programs

}
}
}
}
Regs->RegAH = LowRam->DiskStatusByte;
if (Regs->RegAH) Regs->RegFlags |= CarryBit;
break;

case OpcodeReadDiskParms :
printsnapstring(MsgOpcodeReadDiskParms);
if (!LowRam->EquipFlag.DiskPresent) Regs->RegFlags = 1;
else
{
if (!CmosType(Me->Drive)) Regs->RegFlags = 1;
else
{
Me->DriveType = CmosType(Me->Drive);
Regs->RegAX = 0;
Regs->RegBH = 0;
Regs->RegBL = Me->DriveType;
Regs->RegCL = FDiskTable[Me->DriveType][Me->DriveType].SectorsTrack;
Regs->RegCH = FDiskTable[Me->DriveType][Me->DriveType].MaxTracks;
Regs->RegDH = 01;
Regs->RegDL = LowRam->EquipFlag.NrDrives +1;

// Build Parm Table Item for Caller

Bios->FDiskParmTable.SpecifyByte1 = Specify1;
Bios->FDiskParmTable.SpecifyByte2 = Specify2;
Bios->FDiskParmTable.MotorWait = OffTime;
Bios->FDiskParmTable.BytesPerSectorCode = FdcBytesPerSectorCode;
Bios->FDiskParmTable.SectorsTrack = Regs->RegCL;
Bios->FDiskParmTable.Gap = FDiskTable[Me->DriveType][Me->DriveType].Gap;
Bios->FDiskParmTable.Dtl = DTL;
Bios->FDiskParmTable.Gap3 = FDiskTable[Me->DriveType][Me-
>DriveType].Gap3;
Bios->FDiskParmTable.FillCharByte = FillByte;
Bios->FDiskParmTable.HeadSettle = SettleTime;
Bios->FDiskParmTable.MotorStart = StartTime;

Regs->RegES = FP_SEG(Bios);
Regs->RegDI = &Bios->FDiskParmTable;
}
}
break;

case OpcodeReadDiskType :
printsnapstring(MsgOpcodeReadDiskType);
Regs->RegAH = 00; // no Drive

if (LowRam->DiskID[Me->Drive].DriveType != TypeNone)
{
if (LowRam->DiskID[Me->Drive].DriveType == Type360)
{
Regs->RegAH = 0x01; // 40 Track, no change line
}

546
Introduction to AutoBios

else
{
Regs->RegAH = 0x02; // 80 Track, change line
}
}
break;

case OpcodeReadDiskChange :
printsnapstring(MsgOpcodeReadDiskChange);
// if no Drive - then return a timeout condition
if (LowRam->DiskID[Me->Drive].DriveType == TypeNone)
{
LowRam->DiskStatusByte |= ErrorTimeOut;
}
else
{
// if 360 k Drive - always return disk change
if (LowRam->DiskID[Me->Drive].DriveType == Type360)
LowRam->DiskStatusByte = ErrorMediaChange;
else
// if 720, 1.4, or 2.8 Drive - read the change line
if (ChangeLineActive(Me)) LowRam->DiskStatusByte = ErrorMediaChange;
}
Regs->RegAH = LowRam->DiskStatusByte;
if (Regs->RegAH) Regs->RegFlags |= CarryBit;
break;

case OpcodeSetFormat : printsnapstring(MsgOpcodeSetFormat);


// set Drive to requested format/media
Me->DriveType = LowRam->DiskID[Me->Drive].DriveType;

switch (Regs->RegAL) // use requested type for switch


{
case 1: // 360/360
if(Me->DriveType == Type360)
LowRam->DiskID[Me->Drive].MediaType = Type360;
LowRam->DiskID[Me->Drive].MediaEst = True;
//LowRam->DiskID[Me->Drive].DriveType = Type360;
break;

case 2: // 360/1.2
if(Me->DriveType == Type1200)
LowRam->DiskID[Me->Drive].MediaType = Type360;
LowRam->DiskID[Me->Drive].MediaEst = True;
//LowRam->DiskID[Me->Drive].DriveType = Type1200;
break;

case 3: // 1.2/1.2
if(Me->DriveType == Type1200)
LowRam->DiskID[Me->Drive].MediaType = Type1200;
LowRam->DiskID[Me->Drive].MediaEst = True;
//LowRam->DiskID[Me->Drive].DriveType = Type1200;
break;

case 4: // 720/720
if(Me->DriveType == Type720)

547
The C Programs

LowRam->DiskID[Me->Drive].MediaType = Type720;
LowRam->DiskID[Me->Drive].MediaEst = True;
//LowRam->DiskID[Me->Drive].DriveType = Type720;
break;

default: printsnapstring(MsgOpcodeDefault);
LowRam->DiskStatusByte = ErrorCommand; // bad command
break;
}
Regs->RegAH = LowRam->DiskStatusByte;
if (Regs->RegAH) Regs->RegFlags |= CarryBit;
break;

case OpcodeSetMedia: printsnapstring(MsgOpcodeSetMedia);


// get the max Tracks called for
Me->MaxTrack = Regs->RegCH | ((Regs->RegCX << 2) & 0x300);
// get the max Sectors called for
Me->MaxSectors = Regs->RegCL & 0x3f;
if (CmosType(Me->Drive))
{
Me->DriveType = CmosType(Me->Drive);
// Me->DriveType = LowRam->DISK_ID[Me->Drive];
// use the transition table for this Drive
for (Me->Index= 0;SequenceTable[Me->DriveType][Me->Index] != 0;Me->Index+
+)
{
Me->MediaType = SequenceTable[Me->DriveType][Me->Index];
if ((Me->MaxSectors == (unsigned)FDiskTable[Me->DriveType][Me-
>MediaType].SectorsTrack) && \
(Me->MaxTrack == (unsigned)FDiskTable[Me->DriveType][Me-
>MediaType].MaxTracks))
{
// return the disk parms ptr to the caller
Regs->RegDI = FP_OFF(FDiskTable[Me->DriveType][Me-
>MediaType].SectorsTrack);
Regs->RegES = GetCS();
// set the LowRam->DISK_ID[] to the established supported media
LowRam->DiskID[Me->Drive].DriveType = (char)Me->DriveType;
LowRam->DiskID[Me->Drive].MediaType = (char)Me->MediaType;
LowRam->DiskID[Me->Drive].DriveEst = True;
LowRam->DiskID[Me->Drive].MediaEst = True;

// need a break to say OK here !!!


goto set_media_exit;
}
}
if (!SequenceTable[Me->DriveType][Me->Index])
LowRam->DiskStatusByte = ErrorMediaType;
}
set_media_exit:
Regs->RegAH = LowRam->DiskStatusByte;
if (Regs->RegAH) Regs->RegFlags |= CarryBit;
break;

default : printsnapstring(MsgOpcodeBadCommand);
LowRam->DiskStatusByte = ErrorCommand;

548
Introduction to AutoBios

Regs->RegAH = OpcodeBadFunction;
Regs->RegFlags |= CarryBit; // set return error flag

} // end of switch
}
}
LowRam->MOTOR_COUNT = OffTime; // set motor count
} // end of disk_io

//=======================================================
//========================================================

// Send a byte to the FDC.


// Returns True if successful, False if not.

//--------------------------------------------------------

unsigned SendCommandOK(unsigned parm)


{
struct _BiosRam far * LowRam = 0;
unsigned long TimeOutMark = SetTimeoutCount(20); // 1 second delay
do
{
if((inp(FdcMSR) & 0xc0) == RqmBit)
{
outp(FdcDataReg,(char)parm);
DelayCall(1,Milliseconds);
return (True);
}
} while (LowRam->TimerLong < TimeOutMark);
LowRam->DiskStatusByte |= ErrorTimeOut;
return (False);
}
//==========================================================

// Send the specify command to the FDC.

//--------------------------------------------------------

unsigned SendSpecifyCommandOK(void)
{
if(!SendCommandOK(3)) return(False);
if(!SendCommandOK(Specify1)) return(False);
if(!SendCommandOK(Specify2)) return(False);
return(True);
}
//=======================================================

// Reset the disk system

void FdcReset(struct _FDiskRegs far * Me)


{
struct _BiosRam far * LowRam = 0;
unsigned i;
unsigned status = ((unsigned)LowRam->MotorStatusByte << 4) | 0x08;

549
The C Programs

// Say Recal will be needed whenever we do a reset


LowRam->SeekStatusByte &= 0xf0; //~(1 << Me->Drive);

// Start the reset by setting the reset/ bit low in the DOR
outp(FdcDOR,status);

// Insure at least 10 msec. delay for hardware reset


DelayCall(10,Milliseconds); // i = 100; while(i) {i--; };

// Complete the reset by setting the reset/ bit high in the DOR
outp(FdcDOR,status | 0x04);

// wait for interrupt request


if (!IntReceived())
{
LowRam->DiskStatusByte |= ErrorFDC; return;
}

for (i = 0xc0; i < 0xc4; i++) // number of Drives


{
// send command
if (!SendCommandOK(8))
{
LowRam->DiskStatusByte |= ErrorFDC; return;
}
// check ResultsReadOK
if (!ResultsReadOK())
{
LowRam->DiskStatusByte |= ErrorFDC; return;
}
else
{
if(LowRam->FDC_STATUS[0] != i)
{
LowRam->DiskStatusByte |= ErrorFDC; return;
}
}
}
SendSpecifyCommandOK();
}

/*======================================================

Turn motor on and wait for motor start up time if this is a


write operation. Proceed immediately if a read operation.
1. save the last state of the motor.
2. turn on the selected motor.
3. if not a write, exit immediately.
3. if a write, if the same motor was already on, exit,
else wait for the delay.

--------------------------------------------------------*/

void MotorOn(struct _FDiskRegs far * Me)

550
Introduction to AutoBios

{
struct _BiosRam far * LowRam = 0;
char LastMotor;

// hit timer with max on-count


LowRam->MOTOR_COUNT = 0xff;

// Remember the last motor that was on


LastMotor = LowRam->MotorStatusByte;

// Select the new motor, and save its condition


LowRam->MotorStatusByte = CableMap[Me->Drive];
outp(FdcDOR,CableMap[Me->Drive]);

if((LastMotor != CableMap[Me->Drive]) && Me->WaitForMotor)


{
// delay for a write and a motor start
// force a delay in 1/8 seconds
// delay = (resolution,count) in milliseconds

DelayCall(125 * StartTime,Milliseconds);
LowRam->MOTOR_COUNT = 0xff;
// hit timer with max on-count
}
}

/*========================================================

Wait for the hardware interrupt request to occur.


Returns True if interrupt request rxed.
Returns False if no interrupt request - timeout.

--------------------------------------------------------*/

unsigned IntReceived(void)
{
struct _BiosRam far * LowRam = 0;
// this time out should be about 3 secs
unsigned long i = SetTimeOutCount(3 * 20);
do
{
// If interrupt pending, return to caller
if(LowRam->SeekStatus.IntFlag)
{
// reset the interrupt flag
LowRam->SeekStatus.IntFlag = False;
return (True);
}
//printf("\ri = %p",LowRam->TimerLong);
}
while (LowRam->TimerLong < i);
LowRam->DiskStatusByte |= ErrorTimeOut;
return (False);
}

/*========================================================

551
The C Programs

When the hardware interrupt occurs from the floppy disk,


this function sets bit 7 in the seek_status flag.

--------------------------------------------------------*/

void interrupt far FDiskISR(void)


{
struct _BiosRam far * LowRam = 0;
LowRam->SeekStatus.IntFlag = True;
SendEOI1(); // send eoi
}

/*====================================================================

Process the interrupt received after Recalibrate or seek.


Returns True if check was ok.
Returns False if not.

-------------------------------------------------------------------*/

unsigned StatusCheckOK (void)


{
struct _BiosRam far * LowRam = 0;
if (!IntReceived()) return (False);
if (!SendCommandOK(8)) return (False);
if (!ResultsReadOK()) return (False);

if ((LowRam->FDC_STATUS[0] & 0x60) == 0x60)


{
struct _BiosRam far * LowRam = 0;
LowRam->DiskStatusByte |= ErrorSeek;
return (False);
}
return (True);
}

/*==============================================================

Initialize dma controller for read, write, verify operations.


Returns True if successful, False if not.

----------------------------------------------------------------*/

unsigned DmaSetupOK (struct _FDiskRegs far *Me)


{
struct _BiosRam far * LowRam = 0;
union
{
unsigned char WidthChar[4];
unsigned WidthWord[2];
unsigned long WidthLong[1];
}dma_address;
unsigned length;

552
Introduction to AutoBios

// The DMA channel is not needed for a verify


if (Me->FdcCommand == OpcodeFdcVerify) return(True);
_disable(); // disable interrupts
outp(DmaFlffPort,Me->DmaCommand); // set the first/last ff
outp(DmaModePort,Me->DmaCommand); // output mode byte

if (Me->DmaCommand != (char)DmaOpcodeVerify)
{
Me->XfrAddress.WidthLong[0] = (unsigned long) Me->LocalES << 4;
Me->XfrAddress.WidthLong[0] += (unsigned long) Me->LocalBX;
}
Me->XfrLength = (Me->NrSectors * BytesPerSector) - 1;
outp(DmaAddressPort,Me->XfrAddress.WidthChar[0]); // output low address
outp(DmaAddressPort,Me->XfrAddress.WidthChar[1]); // output high address
outp(DmaPagePort,Me->XfrAddress.WidthChar[2]); // output page address
outp(DmaBasePort,Me->XfrLength & 0xff); // output low byte
outp(DmaBasePort,Me->XfrLength >> 8); // output high byte
_enable(); // enable interrupts
outp(DmaMaskPort,DmaOpcodeOn); // init disk channel

// now clear the upper word, to prepare for overflow check


Me->XfrAddress.WidthWord[1] = 0;
Me->XfrAddress.WidthLong[0] += Me->XfrLength;;
if (Me->XfrAddress.WidthLong[0] & 0xffff0000) // test for overflow
{ // overflow
LowRam->DiskStatusByte = ErrorBoundary;
return (False);
}
return (True);
}

/*==========================================================

Move the Head to the selected Track.


Returns True if successful, False if not.

--------------------------------------------------------*/

unsigned SeekOK(struct _FDiskRegs far * Me)


{
struct _BiosRam far * LowRam = 0;

if (!(LowRam->SeekStatusByte & (1 << Me->Drive))) // need Recal


{
LowRam->SeekStatusByte |= (1 << Me->Drive); // mark Recal will be done

// Try 2 attemps at Recalibrate, then if failed, return error


if (!RecalOK(Me))
{
LowRam->DiskStatusByte = 0;
if (!RecalOK(Me)) return (False);
}
LowRam->LastTrack[Me->Drive] = 0; // clear Track number
// if we want Track zero, then just wait for Head and exit
if (!Me->Track) { WaitForHead(Me); return (True); }

553
The C Programs

}
// A 1.2MB drive needs to double-step for 360k media
if (FDiskTable[Me->DriveType][Me->MediaType].Step) Me->Track *= 2;

// If already on correct track, return without doing the seek


if (LowRam->LastTrack[Me->Drive] == (char)Me->Track) return(True);

// update new position


LowRam->LastTrack[Me->Drive] = (char)Me->Track;

// Do the seek and wait for completion


if (!SendCommandOK(0x0f)) return (False);
if (!SendCommandOK(Me->Drive)) return (False);
if (!SendCommandOK(Me->Track)) return (False);
if (!RecalSeekStatusOK()) return (False);
WaitForHead(Me);
return (True);
}

/*=========================================================

Recalibrate the Drive.


Returns True if Recal was good.
Returns False if Recal was not good.

--------------------------------------------------------*/

unsigned RecalOK(struct _FDiskRegs far * Me)


{
if (!SendCommandOK(7)) return (False);
if (!SendCommandOK(Me->Drive)) return (False);
if (!RecalSeekStatusOK()) return (False);
return (True); // return with no error
}

/*=======================================================

Read anything from the controller following an interrupt.


This may include up to seven bytes of status.
Returns True if successful, False if not.

--------------------------------------------------------*/

#define TimerLongCounter (*((unsigned long far *) 0x0000046c))

unsigned ResultsReadOK(void)
{
struct _BiosRam far * LowRam = 0;
unsigned count = 0; unsigned long TimeOutCount;
do
{
TimeOutCount = SetTimeOutCount(20); // about 1 second
while ((inp(FdcMSR) & 0xc0) != 0xc0)
{
if(TimerLongCounter >= TimeOutCount)
{

554
Introduction to AutoBios

LowRam->DiskStatusByte |= ErrorTimeOut;
return(False);
};
}
LowRam->FDC_STATUS[count] = (char)inp(FdcDataReg);
DelayCall(1,Milliseconds);

if (!(inp(FdcMSR) & BusyBit))


{
return(True);
};
} while (count++ < 7);

printf("\nToo Many Bytes Failure 5");


LowRam->DiskStatusByte |= ErrorFDC; // too many bytes
return (False);
};

/*=======================================================

Send the data-transfer-rate command to controller

--------------------------------------------------------*/

void SendRate(struct _FDiskRegs far * Me)


{
struct _BiosRam far * LowRam = 0;

outp(FdcConfigPort,FDiskTable[LowRam->DiskID[Me->Drive].DriveType]
[LowRam->DiskID[Me->Drive].MediaType].DataRate);
}

/*=======================================================

Process the interrupt received after Recalibrate or seek.


RecalSeekStatusOK
Returns True if successful, False if not.

--------------------------------------------------------*/

unsigned RecalSeekStatusOK (void)


{
struct _BiosRam far * LowRam = 0;
if (!IntReceived()) return (False);
if (!SendCommandOK(8)) return (False);
if (!ResultsReadOK()) return (False);
if ((LowRam->FDC_STATUS[0] & 0x60) == 0x60) // normal termination
{
LowRam->DiskStatusByte |= ErrorSeek;
return (False);
}
return (True);
}

/*===========================================================

555
The C Programs

Determine whether a Retry is necessary.


Returning a True says Retry again
Returning a False says don't Retry any more

--------------------------------------------------------- */

unsigned RetryNeeded(struct _FDiskRegs far * Me)


{
struct _BiosRam far * LowRam = 0;
char MediaType;
// if operation timed out - say no RetryNeeded
if ((LowRam->DiskStatusByte & ErrorTimeOut ) == ErrorTimeOut) return (False);
// if media is established - say no RetryNeeded
if (LowRam->DiskID[Me->Drive].MediaEst) return (False);

// we have to step through the media

// get the next possible media type for this Drive type
MediaType = SequenceTable[Me->DriveType][++Me->MediaIndex];

if (MediaType == TypeNone) // then at end of possibles


{
// Dis-establish media and return saying more retries are useless
LowRam->DiskID[Me->Drive].MediaEst = False;
LowRam->DiskID[Me->Drive].MediaType = 0;
return(False);
}

// insert the new media type into the LowRam->DISK_ID[] and return saying try
again
LowRam->DiskID[Me->Drive].MediaType = MediaType;
LowRam->DiskID[Me->Drive].MediaEst = False;

LowRam->DiskStatusByte = 0;
LowRam->FDC_STATUS[0] = 0;
return(True); // return saying RetryNeeded
}

/*========================================================

Purge the FDC of any status it is waiting to send.

--------------------------------------------------------*/

void PurgeFdc(void)
{
unsigned count = 0;
while (((inp(FdcMSR) & 0xc0) == 0xc0) && (++count < 50))
{
inp(FdcDataReg); // read status
DelayCall(1,Milliseconds);
}
}

/*=======================================================

556
Introduction to AutoBios

Read the state of the disk change line.


Returns True if change line active
False if change line inactive

--------------------------------------------------------*/

unsigned ChangeLineActive(struct _FDiskRegs far * Me)


{
MotorOn(Me);
return (((inp(FdcDigiInput) & DiskChangeBit))?True:False);
}

/*=======================================================

Execute the FDC read id command.


Returns True if OK, False if not read
--------------------------------------------------------*/

unsigned ReadID (struct _FDiskRegs far * Me)


{
if (!SendCommandOK(OpcodeFdcReadID)) return(False);
if (!SendCommandOK(Me->Head << 2 | Me->Drive)) return (False);
return (GetFdcStatusOK(Me));
}

/*======================================================

Wait for the Head to settle after a seek.

-------------------------------------------------------*/

void WaitForHead(struct _FDiskRegs far * Me)


{
struct _BiosRam far * LowRam = 0;
char wait;

wait = SettleTime; // get Head settle


if (Me->WaitForMotor) // if write
{ // yes
if (!wait) // wait zero ?
{ // yes
if (LowRam->DiskID[Me->Drive].DriveType <= 1)
wait = 0x14; // default 360 Head time
else
wait = 0x0f; // default others Head time
}
}
else
{
if (!wait) // is wait zero ?
return; // yes, return
}
DelayCall(wait,Milliseconds);
}

/*=========================================================

557
The C Programs

Checks for a media change, reset media changes and check


media changes.

Returns:
True if media changed, False if not changed

-------------------------------------------------------*/

unsigned MediaChanged(struct _FDiskRegs far * Me)


{
struct _BiosRam far * LowRam = 0;
unsigned TempTrack;
if (!ChangeLineActive(Me)) return (False);
// clear media established and media type
LowRam->DiskID[Me->Drive].MediaEst = False;

// Say Recal needed if there was a diskchange


LowRam->SeekStatusByte &= ~(1 << Me->Drive);

// turn off motor status

MotorOn(Me);
FdcReset(Me);
TempTrack = Me->Track;
Me->Track = 0;
SeekOK(Me);
Me->Track = 1;
SeekOK(Me);
Me->Track = TempTrack;
LowRam->DiskStatusByte = ErrorMediaChange;

if (!ChangeLineActive(Me)) LowRam->DiskStatusByte = ErrorTimeOut;


return (True);
}

/*==============================================================

Wait until an operation is complete, then get the FDC status


Return True if successful, False if error encountered.

---------------------------------------------------------------*/

unsigned GetFdcStatusOK(struct _FDiskRegs far * Me)


{
struct _BiosRam far * LowRam = 0;
unsigned Status,ErrorTimeOutFlag;
Status = 0;
ErrorTimeOutFlag = IntReceived();
if (!ResultsReadOK()) return (False);
if (!ErrorTimeOutFlag)
{ if (!LowRam->DiskStatusByte) return(True); else return(False); }
if (!(LowRam->FDC_STATUS[0] & 0xc0))
{ if (!LowRam->DiskStatusByte) return(True); else return(False); }
if ((LowRam->FDC_STATUS[0] & 0xc0) != 0x40)
{ printf("\nGet Status Error 6");

558
Introduction to AutoBios

LowRam->DiskStatusByte |= ErrorFDC; return(False); }

if ((LowRam->FDC_STATUS[1] & BIT7)) Status |= ErrorSector;


else if ((LowRam->FDC_STATUS[1] & BIT5)) Status |= ErrorCRC;
else if ((LowRam->FDC_STATUS[1] & BIT4)) Status |= ErrorOverrun;
else if ((LowRam->FDC_STATUS[1] & BIT2)) Status |= ErrorSector;
else if ((LowRam->FDC_STATUS[1] & BIT1)) Status |= ErrorWriteProtect;
else if ((LowRam->FDC_STATUS[1] & BIT0)) Status |= ErrorAddress;
else {printf("\nGet Status Error 7"); Status |= ErrorFDC;};
LowRam->DiskStatusByte |= Status;
if (LowRam->DiskStatusByte) return(False);
else return(True);
}

/*========================================================

Seek to the requested Track and initialize the controller


Returns True if OK, False if not ok.

--------------------------------------------------------*/

unsigned InitControllerOK(struct _FDiskRegs far * Me)


{
MotorOn(Me);
if (!SeekOK(Me)) return (False);
if (!SendCommandOK(Me->FdcCommand)) return(False);
if (!SendCommandOK(((Me->Head <<2) & BIT2) | Me->Drive)) return(False);
return (True);
}

/*=======================================================

calculate number of Sectors that were actually transferred.

returns:
number of Sectors transferred

--------------------------------------------------------*/

unsigned CalcSectors (struct _FDiskRegs far * Me)


{
struct _BiosRam far * LowRam = 0;
if (LowRam->DiskStatusByte) return (0);
Me->SectorsTrack = GetParm(SectorsTrack);
Me->EndTrack = LowRam->FDC_STATUS[3];
Me->EndHead = LowRam->FDC_STATUS[4];
Me->EndSector = LowRam->FDC_STATUS[5];
Me->NumSectors = 0;
if (Me->EndHead == Me->Head)
{
if (Me->EndTrack == Me->Track)
{
// do nothing
}
else
{

559
The C Programs

Me->NumSectors += Me->SectorsTrack;
Me->NumSectors += Me->SectorsTrack;
}
}
else // different head
{
Me->NumSectors += Me->SectorsTrack;
}
Me->NumSectors += (Me->EndSector - Me->Sector);
return(Me->NumSectors);
}

//====================================================

560
Introduction to AutoBios

7.9 The Hard Disk Driver


The Hard Disk Driver is used to operate an optional hard disk drive. This driver supports the standard
AT type of hard disk controller, which may be an original MFM type drive, or an IDE drive. IDE drives
use the same ports, command set, and interface as a generic AT disk controller. Other disk interfaces
such as SCSI, ESDI, and SMD may require drastically different hardware level interaction, but the Bios
register interface should remain the same as in this driver. If you are developing any of these drivers, this
module may be used as a starting point, since the functional requirements at the Bios function call
interface remain the same.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] AT/IDE Hard Disk Driver
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Hard.C
//
// [Language] MSVC 1.5
//
// [Description] Interrupt 13h - hard disk driver
//
// AH = 0 - do a reset on the controller, set recal needed
//
// AH = 1 - read the last operation status into AL
//
//--------------- for the following operations -------------
//
// DL = drive number (0x80-0x81)
// DH = head number
// CH = track number
// CL = sector number (except for Format)
// AL = number of sectors (except for Format)
// ES:BX - data buffer address (except for Format)
//
//
// AH = 2 - read sectors
//
// AH = 3 - write sectors
//
// AH = 4 - verify sectors
//
// The above commands return in AL the # of sectors succesful
//
// AH = 5 - format track

561
The C Programs

// ES:BX points to (4 sector bytes) // # of sectors


// Each field (1 per sector) =
// C = Cylinder (track ) number
// H = head number
// R = sector number
// N = number of bytes per sector encoded as:
// 00 = 128 bytes per sector
// 01 = 256 bytes per sector
// 02 = 512 bytes per sector
// 03 = 1024 bytes per sector
//
// AH = 6 - not used
//
// AH = 7 - not used
//
// AH = 8 - Return the Drive Parameters
//
// AH = 9 - Initialize the drive pair
//
// AH = 10 - Read Long
//
// AH = 11 - Write Long
//
// AH = 12 - Seek
//
// AH = 13 - Alternate disk reset
//
// AH = 14 - not used
//
// AH = 15 - not used
//
// AH = 16 - test drive ready
//
// AH = 17 - Recalibrate
//
// AH = 18 - not used
//
// AH = 19 - not used
//
// AH = 20 - controller diagnostic
//
// AH = 21 - read drive type
//
//
// Returns:
// Carry Flag Clear = good operation - AH = 0
// Carry Flag Set = Failure - AH = failure code
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//--------------------------------------------------------------------

562
Introduction to AutoBios

// I N C L U D E F I L E S

#include "Bios.h"

// F U N C T I O N P R O T O T Y P E S

//================ function prototypes ===================

//void interrupt far HDiskFunctionCall(InterruptRegisters);


//void interrupt far HDiskISR (void);

static unsigned Busy(struct _Variables far *);


static unsigned DmaOverrun(struct _Variables far *);
static unsigned IntReceived(struct _Variables far *);
static unsigned ReadyForData(struct _Variables far *);
static unsigned HDiskStatusOK(struct _Variables far *);
static unsigned StatusByteOK(struct _Variables far *);
static unsigned ErrorByteOK(struct _Variables far *);
static unsigned SendCommand(struct _Variables far *);

// G L O B A L V A R I A B L E S

// G L O B A L C O N S T A N T S

extern struct HDTable _based(_segname("_CODE")) HDiskTable[50];

// L O C A L D E F I N I T I O N S

#define OUTPUT_REQ_BIT 0x08


#define ecc_mode 0x02

//--- Function Call OpCode Definitions ---

#define OpcodeReset 0x00


#define OpcodeReadStatus 0x01
#define OpcodeReadSectors 0x02
#define OpcodeWriteSectors 0x03
#define OpcodeVerifySectors 0x04
#define OpcodeFormatTrack 0x05
#define OpcodeBadFunction 0x06
#define OpcodeGetParms 0x08
#define OpcodeInitDrive 0x09
#define OpcodeReadLong 0x0a
#define OpcodeWriteLong 0x0b
#define OpcodeSeek 0x0c
#define OpcodeAltReset 0x0d
#define OpcodeTestDriveReady 0x10
#define OpcodeRecalibrate 0x11
#define OpcodeDiagnostic 0x14
#define OpcodeGetDiskType 0x15
#define OpcodeParkHeads 0x19
#define OpcodeFormatUnit 0x1a
#define OpcodeBadCommand 0x1b

//---- Function Call Error Return Code Definitions ---

563
The C Programs

#define OpcodeErrorNone 0x00


#define OpcodeErrorCommand 0x01
#define OpcodeErrorAddress 0x02
#define OpcodeErrorSector 0x04
#define OpcodeErrorReset 0x05
#define OpcodeErrorParms 0x07
#define OpcodeErrorOverrun 0x08
#define OpcodeErrorBoundary 0x09
#define OpcodeErrorSectorFlag 0x0a
#define OpcodeErrorCylinder 0x0b
#define OpcodeErrorFormat 0x0d
#define OpcodeErrorController 0x0e
#define OpcodeErrorArbitration 0x0f
#define OpcodeErrorECC 0x10
#define OpcodeErrorSoftECC 0x11
#define OpcodeErrorHDC 0x20
#define OpcodeErrorSeek 0x40
#define OpcodeErrorTimeOut 0x80
#define OpcodeErrorNotReady 0xaa
#define OpcodeErrorUndefined 0xbb
#define OpcodeErrorWriteFault 0xcc
#define OpcodeErrorStatus 0xe0
#define OpcodeErrorSense 0xff

//----------- I/O port definitions -----------

#define HD_REG_PORT 0x3f6

#define PortReadData 0x1f0


#define PortReadErrorRegister 0x1f1
#define PortReadSectorCount 0x1f2
#define PortReadSectorNumber 0x1f3
#define PortReadCylinderLow 0x1f4
#define PortReadCylinderHigh 0x1f5
#define PortReadSizeDriveHead 0x1f6
#define PortReadStatus 0x1f7

#define PortWriteData 0x1f0


#define PortWritePreComp 0x1f1
#define PortWriteSectorCount 0x1f2
#define PortWriteSectorNumber 0x1f3
#define PortWriteCylinderLow 0x1f4
#define PortWriteCylinderHigh 0x1f5
#define PortWriteSizeDriveHead 0x1f6
#define PortWriteCommand 0x1f7

// The Task Register "Frame" Indices correspond to the Ports

//----- Controller Internal Command Codes ----

#define HdcOpcodeRecal 0x10


#define HdcOpcodeRead 0x20
#define HdcOpcodeReadLong 0x22
#define HdcOpcodeWrite 0x30
#define HdcOpcodeWriteLong 0x32
#define HdcOpcodeVerify 0x40

564
Introduction to AutoBios

#define HdcOpcodeFormat 0x50


#define HdcOpcodeInit 0x60
#define HdcOpcodeSeek 0x70
#define HdcOpcodeDiag 0x90
#define HdcOpcodeSetParm 0x91

//----- Controller Internal Status Codes ----

#define HdcStatusError 0x01


#define HdcStatusIndex 0x02
#define HdcStatusSoftECC 0x04
#define GdcStatusDMA 0x08
#define HdcStatusSeekComplete 0x10
#define HdcStatusWriteFault 0x20
#define HdcStatusReady 0x40
#define HdcStatusBusy 0x80

//----- Controller Internal Error Codes ----

#define HdcErrorRecord 0x01


#define HdcErrorTrack0 0x02
#define HdcErrorAbort 0x04
#define HdcErrorID 0x10
#define HdcErrorECC 0x40
#define HdcErrorBadBlock 0x80
#define HdcErrorUndefined 0xBB

// L O C A L C O N S T A N T S

#define Device DeviceMaskHard

// P R O G R A M

struct _Variables
{
char Frame[8]; // The command block
struct HDTable far * ParmTable; // ptr to the drive parm table
char far * XfrAddress;
unsigned long delay_count;
//unsigned index;
char temp;
unsigned count;
struct _BiosRam far * LowRam;
struct _IRegs far * Regs;
};

//-------------- setup the controller -----------

unsigned HDiskSetup(ActionArgument)
{
struct _BiosObject far * Bios = GetBiosObject();
struct _BiosRam far * LowRam = 0;
unsigned drive_type;
unsigned condition = SetupStatusError;
LoadDS();

565
The C Programs

Bios->DevicesInstalled |= Device;

#if CfgHard
LowRam->HD_NUM = 0; // clear number of drives
LowRam->HD_CONTROL = 0; // clear control byte
LowRam->HD_STATUS1 = 0; // clear disk status

//printf("\nChecking CMOS");
// Check to See if the CMOS is valid
if (!((InCmos(CmosRegDiagnosticStatus) & \
(CmosRegBitBadBat | CmosRegBitBadSum | CmosRegBitBadCfg)) != 0))
{
LoadUserDriveParms(); // Get the type 47 & 48 values

// get disk type for drive 1 from cmos

if (drive_type = CmosType((unsigned char)0x80))


// there are 1 or more drives
{
// move floppy vector to interrupt 40
_disable();
LowRam->IntVector[0x40] = LowRam->IntVector[0x13];
LowRam->IntVector[0x13] = (void far *) FDiskChain;
LowRam->IntVector[0x76] = (void near *) HDiskISR;
LowRam->IntVector[0x41] = (void far *) HDiskTable;
LowRam->IntVector[0x46] = (void far *) HDiskTable;
//printf("\nEnabling IRQ14");
outp(0xa1,inp(0xa1) & ~0x40); // enable IRQ 14
//printf("\nEnabling IRQ0");
outp(0x21,inp(0x21) & ~0x01); // enable IRQ 0
//printf("\nEnabled Hard Disk Interrupt");
_enable();
//printf("\nEnabling all interrupts");
// set pointer to table[type] into int 41 vector

switch(drive_type)
{
case 47:
LowRam->IntVector[0x41] = &Bios->HardDrive47;
break;

case 48:
LowRam->IntVector[0x41] = &Bios->HardDrive48;
break;

default:
LowRam->IntVector[0x41] = &HDiskTable[drive_type-1];
};

LowRam->HD_NUM = 1; // say there is one drive

// Check for another drive

if (drive_type = CmosType((unsigned char)0x81))


// there are 1 or more drives
{

566
Introduction to AutoBios

// set pointer to table[type] into int 46 vector

switch(drive_type)
{
case 47:
LowRam->IntVector[0x46] = &Bios->HardDrive47;
break;

case 48:
LowRam->IntVector[0x46] = &Bios->HardDrive48;
break;

default:
LowRam->IntVector[0x46] = &HDiskTable[drive_type-1];
};
LowRam->HD_NUM = 2; // say there are two drives
}

// test the hard disk controller


// printf("\nCalling Hard Disk Diagnostic");
if (CallDiskDiagnostic())
{
//printf("\nCalling Hard Disk Reset");
// do a reset on the hard drive
if (CallDiskReset(0x80)) condition = SetupStatusOK;
};
//printf("\nReturned from Diagnostic and/or reset");
}
}
return(condition);
#else
return(SetupStatusStub);
#endif
}

//=================================================
//======== BEGINNING OF MAIN ROUTINES ============
//=================================================

// handle the floppy disk function service call

void HardCall(struct _IRegs far * Regs);

void interrupt far HDiskFunctionCall(InterruptRegisters)


{
InterruptEnvelope(HardCall,Device,0);
};

void HardCall(struct _IRegs far * Regs)


{
struct _BiosRam far * LowRam = 0;
struct _Variables Vars;

Vars.LowRam = 0;
Vars.Regs = Regs;
//-----------------

567
The C Programs

outp(0xa1,inp(0xa1) & ~0x40); // enable IRQ 14

_enable();

Regs->RegFlags &= ~CarryBit; // clear the carry flag for returns

LowRam->HD_STATUS1 = 0; // clear status

// set precomp - varies for drive zero or one !!!

// Invalid Hard Drive Number, No Hard Drives Present, Not Enough Drives
if ((Regs->RegDL > 0x81) || (!LowRam->HD_NUM) ||
((Regs->RegDL & 0x7f) > (LowRam->HD_NUM - 1)))
Regs->RegAH = OpcodeBadCommand;

if (Regs->RegDL == 0x80)
/*Drive 0 */ Vars.ParmTable = LowRam->IntVector[0x41];
else /*Drive 1*/ Vars.ParmTable = LowRam->IntVector[0x46];

// set the control byte


LowRam->HD_CONTROL = (char)(LowRam->HD_CONTROL & 0xc0) |
Vars.ParmTable->Control;

// set the register port


outp(HD_REG_PORT,Vars.ParmTable->Control);
LowRam->HD_INT_FLAG = False;

// build the frame


Vars.Frame[1] = (char)(Vars.ParmTable->PreComp >> 2);
Vars.Frame[2] = Regs->RegAL; // sector count
Vars.Frame[3] = Regs->RegCL & 0x3F; // sector number
Vars.Frame[4] = Regs->RegCH; // cyl low
Vars.Frame[5] = Regs->RegCL >> 6; // cyl high
Vars.Frame[6] = (((Regs->RegDL & 0x01) << 4) |
((Regs->RegDH) & 0x0f) | 0xA0);
Vars.Frame[7] = 0; // pre-clear this item

// Normalize es:bx to xfr_seg:xfr_off = xxxx:000x

Vars.XfrAddress = MK_FP(Regs->RegES + (Regs->RegBX >> 4),Regs->RegBX &


0x000f);

// now execute the CASE for the selected function

switch (Regs->RegAH)
{
case OpcodeReset: printsnapstring(MsgOpcodeReset);

CallDiskReset(0); // do a reset on the Floppy controller first

outp(0xa1,inp(0xa1) & ~0x40); // enable IRQ 14


outp(0x21,inp(0x21) & ~0x01); // re-enable timer

outp(HD_REG_PORT, 4); // reset the controller

568
Introduction to AutoBios

DelayCall(100,Microseconds);

// set the head, and clear the reset bit


outp(HD_REG_PORT,LowRam->HD_CONTROL & 0x0f);

if(Busy(&Vars))
{
struct _BiosRam far * LowRam = 0;
LowRam->HD_STATUS1 = OpcodeErrorReset;

}
else
{
if(inp(PortReadErrorRegister) != 0x01)
{
LowRam->HD_STATUS1 = OpcodeErrorReset;
}
else
{
CallDiskInitDrive(0x80);
CallDiskRecalibrate(0x80);

// if two drives, do the next one


if (LowRam->HD_NUM > 1)
{

CallDiskInitDrive(0x81);
CallDiskRecalibrate(0x81);
}
LowRam->HD_STATUS1 = 0; // clear the error bits
}
LowRam->HD_STATUS1 = 0; // clear the error bits
}
break;

case OpcodeReadStatus:
printsnapstring(MsgOpcodeReadStatus);
Regs->RegAL = LowRam->HD_STATUS1;
break;

case OpcodeReadSectors:
printsnapstring(MsgOpcodeReadSectors);
Vars.Frame[7] = HdcOpcodeRead;
if(Vars.Frame[2] == 0) { LowRam->HD_STATUS1 = OpcodeErrorCommand; break; }
if(!DmaOverrun(&Vars))
{
if(SendCommand(&Vars))
{
// do this loop for each sector
do
{
if(!IntReceived(&Vars)) break;
// do the sector transfer
RepeatIn(Vars.XfrAddress,PortReadData,256);
Vars.XfrAddress += 512;
if (!HDiskStatusOK(&Vars)) break;

569
The C Programs

}
while(--Vars.Frame[2] != 0);
}
}

break;

case OpcodeWriteSectors:
printsnapstring(MsgOpcodeWriteSectors);
Vars.Frame[7] = HdcOpcodeWrite;

if(Vars.Frame[2] == 0) { LowRam->HD_STATUS1 = OpcodeErrorCommand; break; }

// check for transfer overrun


if(!DmaOverrun(&Vars))
{
if(SendCommand(&Vars))
{
// wait for data request
if(ReadyForData(&Vars))
{
// do this loop for each sector
do
{
// do the sector transfer
RepeatOut(Vars.XfrAddress,PortWriteData,256);
Vars.XfrAddress += 512;
if(!IntReceived(&Vars)) break; // wait for completion
if (!HDiskStatusOK(&Vars)) break;
}
while(((LowRam->HD_STATUS & 0X08) != 0) && (--Vars.Frame[2] != 0));
if(inp(PortReadSectorCount) != 0)
{
LowRam->HD_STATUS1 = (unsigned char)OpcodeErrorUndefined;
}
}
}
}
break;

case OpcodeVerifySectors:
printsnapstring(MsgOpcodeVerifySectors);
Vars.Frame[7] = HdcOpcodeVerify;
if(SendCommand(&Vars))
{
if (IntReceived(&Vars)) HDiskStatusOK(&Vars);
}
break;

case OpcodeFormatTrack:
printsnapstring(MsgOpcodeFormatTrack);
Vars.Frame[7] = HdcOpcodeFormat;
Vars.Frame[2] = Vars.ParmTable->Sectors;
if(SendCommand(&Vars))
{
// wait for data request interrupt

570
Introduction to AutoBios

if(ReadyForData(&Vars))
{
// do this loop for each sector
do
{
// do the sector transfer
RepeatOut(Vars.XfrAddress,PortWriteData,256);
Vars.XfrAddress += 512;

if(!IntReceived(&Vars)) break; // wait for completion

if (!HDiskStatusOK(&Vars)) break;

}
while(((LowRam->HD_STATUS & 0x08) != 0) && (--Vars.Frame[2] != 0));
// if the controller is still asking for more data,then it is an error
if(inp(PortReadSectorCount) != 0)
LowRam->HD_STATUS1 = (unsigned char)OpcodeErrorUndefined;
}
}
break;

case OpcodeGetParms: printsnapstring(MsgOpcodeGetParms);


// build ch = max cyls, cl = max sectors
// get lower 8 bits of max cyls
Regs->RegAX = Vars.ParmTable->Cyls - 1; //.....................
Regs->RegCH = Regs->RegAL;
Regs->RegCL = (Regs->RegAX & 0x0300) >> 2;

// get max sectors


Regs->RegCL |= (Vars.ParmTable->Sectors & 0x3f);

// build dh = max heads, dl = # drives


Regs->RegDH = Vars.ParmTable->Heads - 1;
Regs->RegDL = Vars.LowRam->HD_NUM;

Regs->RegAX = 0;
break;

case OpcodeInitDrive: printsnapstring(MsgOpcodeInitDrive);


Vars.Frame[7] = (unsigned char)HdcOpcodeSetParm;
// set max heads
Vars.Frame[6] = ((Vars.Frame[6] & (unsigned char)0xf0)) |
(unsigned char)(Vars.ParmTable->Heads - 1);
// set sector count
Vars.Frame[2] = Vars.ParmTable->Sectors;
// set low cylinder = 0
Vars.Frame[4] = 0;
// set high cylinder = 0
Vars.Frame[5] = 0;

if(SendCommand(&Vars))
{
if(!Busy(&Vars)) HDiskStatusOK(&Vars);
}
break;

571
The C Programs

case OpcodeReadLong: printsnapstring(MsgOpcodeReadLong);


Vars.Frame[7] = HdcOpcodeReadLong;

if(Vars.Frame[2] == 0) { Vars.LowRam->HD_STATUS1 = OpcodeErrorCommand;


break; }

// check for transfer overrun


if(!DmaOverrun(&Vars))
{
// command phase
if(SendCommand(&Vars))
{
// output_commands
// do this loop for each sector
do
{
if(!IntReceived(&Vars)) break;
// wait for data ready interrupt
{
// do the sector transfer
RepeatIn(Vars.XfrAddress,PortReadData,256);
Vars.XfrAddress += 512;

// read the 4 extra bytes


* Vars.XfrAddress++ = (char)inp(PortReadData);
* Vars.XfrAddress++ = (char)inp(PortReadData);
* Vars.XfrAddress++ = (char)inp(PortReadData);
* Vars.XfrAddress++ = (char)inp(PortReadData);

}
if (!HDiskStatusOK(&Vars)) break;
}
while(--Vars.Frame[2] > 0);
}
}
break;

case OpcodeWriteLong: printsnapstring(MsgOpcodeWriteLong);


Vars.Frame[7] = HdcOpcodeWriteLong;

if(Vars.Frame[2] == 0) { Vars.LowRam->HD_STATUS1 = OpcodeErrorCommand;


break; }

// check for transfer overrun


if(!DmaOverrun(&Vars))
{
if(SendCommand(&Vars))
{
// wait for data request interrupt
if(ReadyForData(&Vars))
{
// do this loop for each sector
do
{
// do the sector transfer

572
Introduction to AutoBios

RepeatOut(Vars.XfrAddress,PortWriteData,256);
Vars.XfrAddress += 512;

// ecc mode - send 4 more bytes


outp(PortWriteData,* Vars.XfrAddress++);
outp(PortWriteData,* Vars.XfrAddress++);
outp(PortWriteData,* Vars.XfrAddress++);
outp(PortWriteData,* Vars.XfrAddress++);

if(!IntReceived(&Vars)) break; // wait for completion

if (!HDiskStatusOK(&Vars)) break;

}
while(((Vars.LowRam->HD_STATUS & 0x08) != 0) && (--Vars.Frame[2] != 0));
// if the controller still asking for more then an error.
if(inp(PortReadSectorCount) != 0)
Vars.LowRam->HD_STATUS1 = (unsigned char)OpcodeErrorUndefined;
}
}
}
break;

case OpcodeSeek: printsnapstring(MsgOpcodeSeek);

Vars.Frame[7] = HdcOpcodeSeek;
if(SendCommand(&Vars))
{
if(IntReceived(&Vars)) HDiskStatusOK(&Vars);
if(Vars.LowRam->HD_STATUS1 == OpcodeErrorSeek) Vars.LowRam->HD_STATUS1 = 0;
}
break;

case OpcodeAltReset: printsnapstring(MsgOpcodeAltReset);


break;

case OpcodeTestDriveReady:
printsnapstring(MsgOpcodeTestDriveReady);

if(!Busy(&Vars))
{
outp(PortWriteSizeDriveHead,Vars.Frame[6]); HDiskStatusOK(&Vars);
}
break;

case OpcodeRecalibrate:
printsnapstring(MsgOpcodeRecalibrate);

Vars.Frame[7] = HdcOpcodeRecal;
if(!SendCommand(&Vars)) { break; };
if(!IntReceived(&Vars))
{
if(!IntReceived(&Vars))
{
break;
};

573
The C Programs

};
HDiskStatusOK(&Vars);
if(Vars.LowRam->HD_STATUS1 == OpcodeErrorSeek) Vars.LowRam->HD_STATUS1 = 0;
break;

case OpcodeDiagnostic:
printsnapstring(MsgOpcodeDiagnostic);

// make sure interrupts are disabled when changing the interrupt mask
_disable();
outp(0xa1,inp(0xa1) & ~0x40);
outp(0x21,inp(0x21) & ~0x04);
_enable();
if(Busy(&Vars)) // Not ok to start diag
{

}
else
{
outp(PortWriteCommand,HdcOpcodeDiag);
if (!Busy(&Vars)) // wait for completion
{
if ((Vars.LowRam->HD_ERROR = (char)inp(PortReadErrorRegister)) != 1)
{
Vars.LowRam->HD_STATUS1 = OpcodeErrorHDC;
}
}
else
{
LowRam->HD_STATUS1 = (unsigned char)OpcodeErrorTimeOut;
}
}
break;

case OpcodeGetDiskType:
printsnapstring(MsgOpcodeGetDiskType);

Regs->RegCX = GetHighOfLong(Vars.ParmTable->Cyls - 1) *
Vars.ParmTable->Heads * Vars.ParmTable->Sectors;

Regs->RegDX = (Vars.ParmTable->Cyls - 1) *
Vars.ParmTable->Heads * Vars.ParmTable->Sectors;

Regs->RegAX = 0x0300;
break;

default : // invalid function code - return bad code


Vars.LowRam->HD_STATUS1 = OpcodeErrorCommand;
Regs->RegAH = OpcodeErrorCommand;
break;

} // end of switch

Regs->RegAH = LowRam->HD_STATUS1;
if(Regs->RegAH) Regs->RegFlags |= 1;

574
Introduction to AutoBios

outp(0xa1,inp(0xa1) | 0x40); // disable IRQ 14


}

//====================================================

void interrupt far HDiskISR (void)


{
#ifdef CfgHard
struct _BiosRam far * LowRam = 0;
LowRam->HD_INT_FLAG = True;
SendEOI2(); // send eoi
#endif
}

//====================================================

// check for the controller Busy


unsigned Busy(struct _Variables far * Vars)
{
struct _BiosRam far * LowRam = 0;
unsigned long delay_count;
_enable();
// get current count and add 2 secs to it
delay_count = SetTimeOutCount(3 * 20);
LowRam->HD_STATUS1 = OpcodeErrorNone; // clear status byte

do
{
if ((inp(PortReadStatus) & 0x80) == 0) return(False);
}
while (LowRam->TimerLong < delay_count);

LowRam->HD_STATUS1 = (unsigned char)OpcodeErrorTimeOut;


// set time out error
return(True); // return Busy condition to caller
}

//======================================================
//
// Wait for the hardware interrupt to occur. Time-out and
// return if no interrupt.
//
// Returns True if Rxed, False if timeout - not received
//
//-----------------------------------------------------

unsigned IntReceived(struct _Variables far * Vars)


{
unsigned long delay_count;
struct _BiosRam far * LowRam = 0;
_enable();
// this time out should be 2 secs
delay_count = SetTimeOutCount(2 * 20);

do

575
The C Programs

{
if(LowRam->HD_INT_FLAG)
{
LowRam->HD_INT_FLAG = False; LowRam->HD_STATUS1 = 0; return (True);
}
}
while ((LowRam->TimerLong < delay_count));
// LowRam->HD_INT_FLAG = False;
LowRam->HD_STATUS1 |= OpcodeErrorTimeOut;
return(False);
}

//======================================================
//
// Wait for the data request. Time-out and
// return if no request.
//
// Returns True if controller is ready to accept data.
// Returns False if not ready - timeout.
//
//-----------------------------------------------------

unsigned ReadyForData(struct _Variables far * Vars)


{
unsigned long delay_count;
struct _BiosRam far * LowRam = 0;
_enable();
// this time out should be 2 secs
delay_count = SetTimeOutCount(2 * 20);

do
{ if((inp(PortReadStatus) & OUTPUT_REQ_BIT) != 0) { return(True); } }
while (LowRam->TimerLong < delay_count);
LowRam->HD_STATUS1 = (unsigned char)OpcodeErrorTimeOut;
return (False);
}

//=================================================

//--------------------------------------------------
// Checks the Hard Disk Status,
// Returns True if OK, False if not OK

unsigned HDiskStatusOK(struct _Variables far * Vars)


{
if(!StatusByteOK(Vars)) return(False);
if((inp(PortReadStatus) & 0x01) == 0) return(True);
return(ErrorByteOK(Vars));
}

//----------------------------------------------------
//
//
// Checks the Status byte from the controller and

576
Introduction to AutoBios

// Returns True if OK, False if Not OK


//

unsigned StatusByteOK(struct _Variables far * Vars)


{
unsigned temp;
struct _BiosRam far * LowRam = 0;
LowRam->HD_STATUS1 = 0; // start with a clear
temp = LowRam->HD_STATUS = (char)inp(PortReadStatus);

if( (temp & HdcStatusBusy))


return(True);

if( (temp & HdcStatusWriteFault))


{
LowRam->HD_STATUS1 = (unsigned char)OpcodeErrorWriteFault;
return(False);
}

if(!(temp & HdcStatusReady))


{
LowRam->HD_STATUS1 = (unsigned char)OpcodeErrorNotReady;
return(False);
}

if(!(temp & HdcStatusSeekComplete))


{ LowRam->HD_STATUS1 = OpcodeErrorSeek; return(False); }

if( (temp & HdcStatusSoftECC))


{ LowRam->HD_STATUS1 = OpcodeErrorSoftECC; }

return(True);
}

//-----------------------------------------------------

static unsigned char _based(_segname("_CODE")) HdcErrorTable[8] =


{
HdcErrorBadBlock, // 0x80 - bad block
HdcErrorECC, // 0x40 - bad data ecc
HdcErrorUndefined, // 0x20 - not used
HdcErrorID, // 0x10 - id not found
HdcErrorUndefined, // 0x08 - not used
HdcErrorAbort, // 0x04 - aborted command
HdcErrorTrack0, // 0x02 - trk 0 not found on recalibrate
HdcErrorRecord, // 0x01 - data address mark not found
};

//------------------------------------------
// Reads the Error Byte from the Controller
// Returns True if OK, False if not OK

unsigned ErrorByteOK(struct _Variables far * Vars)


{
unsigned temp;

577
The C Programs

unsigned index = 0;
struct _BiosRam far * LowRam = 0;
temp = LowRam->HD_ERROR = (char)inp(PortReadErrorRegister);

while((temp & 0xff) != 0)


{
if((temp & 0x80) != 0)
{
LowRam->HD_STATUS1 = HdcErrorTable[index];
return(False);
}
temp <<= 1; index++;
};
return (True);
}

//---------------------------------------------------------
// check for transfer overrun
// if ecc mode than use 7f04 as max, else use 8000
// Returns True if an Overrun condition is detected

unsigned DmaOverrun(struct _Variables far * Vars)


{
struct _BiosRam far * LowRam = 0;
if (Vars->Frame[2] < 0x7f) return(False); // always ok
if((Vars->Frame[7] & ecc_mode) != 0)
{
if ((Vars->Frame[2] == 0x7f) && ((unsigned long)Vars->XfrAddress < 4))
return(False);
}
else
{
if(Vars->Frame[2] == 0x7f) return(False);
if((Vars->Frame[2] == 0x80) && ((unsigned long)Vars->XfrAddress == 0))
return(False);
}
LowRam->HD_STATUS1 = OpcodeErrorOverrun;
return(True);
}

//----------------------------------------------------
// Returns True if successful, False if not

unsigned SendCommand(struct _Variables far * Vars)


{
unsigned long count;
struct _BiosRam far * LowRam = 0;
count = 10000;

// check for time out on drive being ready

do
{
// check for controller and drive ready
if (!Busy(Vars))
{

578
Introduction to AutoBios

// select drive
outp(PortWriteSizeDriveHead,Vars->Frame[6]);
if (StatusByteOK(Vars))
{
// reset the interrupt flag byte
LowRam->HD_INT_FLAG = False;

// enable the interrupts


_disable();
outp(0xa1,inp(0xa1) & ~0x40); outp(0x21,inp(0x21) & ~0x04);
_enable();

// check for retries


if((LowRam->HD_CONTROL & 0xc0) != 0)
{
if(((Vars->Frame[7] & 0xf0) >= 0x20) && ((Vars->Frame[7] & 0xf0) <=
0x40))
Vars->Frame[7] |= 0x01;
}

outp(PortWritePreComp,Vars->Frame[1]);
outp(PortWriteSectorCount,Vars->Frame[2]);
outp(PortWriteSectorNumber,Vars->Frame[3]);
outp(PortWriteCylinderLow,Vars->Frame[4]);
outp(PortWriteCylinderHigh,Vars->Frame[5]);
outp(PortWriteSizeDriveHead,Vars->Frame[6]);
outp(PortWriteCommand,Vars->Frame[7]);
return(True);
}
}
}
while(count-- > 0);
return(False);
}

//====================================================
//====================================================
//====================================================

579
Introduction to AutoBios

7.10 The Bootstrap Driver


The Boot.c File is the bootstrap function call routine which is used to load DOS from a floppy disk
device. The boot routine attempts to read the boot sector of the specified drive and if successful transfers
control to the loaded routine (which in turn loads the remainder of the operating system).
To allow flexibility in the way the system attempts to boot, there is a "boot_list" in the boot program
which defines the drives which will be used in the boot process. This list may specify the hard or floppy
drives in any order.
If your Boot requirements are non-standard or specific to a dedicated application, you may wish to
modify the standard boot routine. All the standard system initialization has been done by the POD when
the boot routine is finally called. A specialized boot program may load an operating system or start
executing an application directly. If one is not using an operating system to support an application, one
must not design and code the application so that it makes reference to non-existent operating system
features!
The boot routine should exit if the boot process is not completed. This will allow the POD routine to
attempt an alternate path, such as defaulting to SysVue.
Some types of boot devices (SCSI adapters, Network booters, or XT style hard drive controllers, for
example) may substitute their own boot programs to replace the Bios' boot routine.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bootstrap routine
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Boot.C
//
// [Language] MSVC 1.0/1.5
//
// [Category] Bios BIOS Function
//
// [Description] This module does the bootstrap load to get DOS loaded
// [Description] and running.
//
// We look at the boot list to determine what drives should be used for the
// boot attempts. The boot sector is loaded into 0000:7c00 and control is
// transferred to that address.
// If the boot cannot be performed, then we exit.
//
// [Arguments] None
//
// [Return] If Boot Not Successful
//

581
The C Programs

// [History] 2.00 04/11/94 Original


//
//------------------------------------------------------------------------

// I N C L U D E F I L E S

#include "Bios.h"

// F U N C T I O N P R O T O T Y P E S

unsigned _boot(void);

// G L O B A L V A R I A B L E S

struct BOOT_SECTOR_BUFFER { unsigned BootBufferSpace[256]; };

// L O C A L C O N S T A N T S

// this is the list of possible boot devices, in the order in which they
// should be tried.
// If all the named drives are tried and fail, then exit
// The list is terminated by a -1

unsigned _based(_segname("_TEXT")) BootList[4][3] =


{
{0x00,0x80,0xff},
{0x80,0x00,0xff},
{0x00,0xff,0xff},
{0x80,0xff,0xff},
};

// L O C A L D E F I N I T I O N S

#define device DeviceMaskBoot


#define boot_retrys 3

// P R O G R A M

unsigned BootSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
LoadDS();

#if (CfgDisk || CfgHard)


LowRam->IntVector[0x19]=(void near *)Boot;
return(SetupStatusOK);
#else
return(SetupStatusStub);
#endif

//----------- The boot routine ------------------

582
Introduction to AutoBios

void interrupt far Boot(InterruptRegisters)


{
unsigned BootOrder = InCmos(CmosRegOptionFlags) & CmosRegBitBootOrder;
unsigned i,BootDrive,BootIndex;
struct _BiosRam far * LowRam = 0;
struct BiosObject far * Bios = GetBiosObject();
struct BOOT_SECTOR_BUFFER far * BootBuffer = (void far *)0x00007c00;
unsigned char far * SignatureBuffer =
(unsigned char far *) 0x00007c00 + CfgBootSignatureLoc;
//char BootSignature[] = { CfgBootSignature };
LoadDS();

#if (CfgDisk || CfgHard)


printf("%q\n----------- Booting ------------\n");

// preset the boot sector to Trap Instructions


for (i = 0; i < 256; BootBuffer->BootBufferSpace[i++] = 0xcccc);

for(BootIndex = 0; BootList[BootOrder][BootIndex] != -1; BootIndex++)


{
BootDrive = BootList[BootOrder][BootIndex];

for (i = 0; i < boot_retrys; i++)


{
if(CallDiskReset(BootDrive))
{
if(CallDiskRead(BootDrive,1,0,0,1,(unsigned char far *)BootBuffer))
{
LowRam->RESET_FLAG = 0; // clear reset flag
_enable();

if(BootBuffer->BootBufferSpace[255] == 0xaa55)
{
#if CfgBootSignatureCheck
// If a hard drive, allow booting
if(StrCmp(SignatureBuffer,CfgBootSignature) || BootDrive == 0x80)
{
// needs to pass drive # in DL to DOS
BootJump((unsigned char)BootDrive);
}
else
{
printf("Unauthorized Boot Diskette.\n");
}
#else
// needs to pass drive # in DL to DOS
BootJump((unsigned char)BootDrive);
#endif
}
else
{
printf("\nBoot Sector Signature was not the expected 55AA");
printf("\nDo you want to continue anyway ? (Y/N) ");
if (ToUpper((unsigned char)GetCharEcho()) == 'Y')
BootJump((unsigned char)BootDrive);

583
The C Programs

}
}
}
}
}
#else
#if (CfgBootUser)
printf("\n--- Jumping to User Specified Location %p",CfgBootUserLocation);
BootJump(CfgBootUserLocation)
#else
printf("\n---- No User Boot Specified -------\n");
#endif
#endif
};

//---------- This is the Boot Jump to 0000:7c00 -------

void BootJump(unsigned char drive)


{
void (far * BootLocation) (void);
BootLocation = (void far *)0x00007c00;
_asm mov dl,drive
(*BootLocation)();
};

//================= end =======================

584
Introduction to AutoBios

7.11 The System Services Driver


This function originally supported the cassette tape interface of the original PC. Tape support was
deleted from the XT and later versions, and a variety of operations were added to this interrupt, which are
now more correctly described as System Services. This function call returns a cassette error condition to
the caller. The AT class systems use an extended set of functions codes for AT-level specific functions
for joystick input, virtual mode control, multi-tasking hooks, sys-request functions, etc.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] System Services (Cassette) function
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] SysSrv.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This module returns an error condition in AX in
// [Description] the event a user program calls this function.
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* G L O B A L S */

void SystemConfigurationTable(void);

/* L O C A L D E F I N T I O N S */

#define Device DeviceMaskSysSrv

#define OpcodeKeyboardIntercept 0x4F

#define OpcodeOpenDevice 0x80


#define OpcodeCloseDevice 0x81
#define OpcodeProgramTerminate 0x82
#define OpcodeEventWait 0x83
#define OpcodeJoystick 0x84
#define OpcodeSysReqKey 0x85
#define OpcodeWait 0x86

585
The C Programs

#define OpcodeMoveBlock 0x87


#define OpcodeGetExtendedMemorySize 0x88
#define OpcodeSwitchToProtectedMode 0x89
#define OpcodeDeviceBusy 0x90
#define OpcodeInterruptComplete 0x91
#define OpcodeGetSystemConfigParms 0xC0

#define device DeviceMaskSysSrv

/* P R O G R A M */

/*-------------------------------------------------------*/

unsigned SystemServicesSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();
LoadDS();
_disable();
LowRam->IntVector[0x15]= (void near *)SystemServicesFunctionCall;
_enable();
Bios->DevicesInstalled |= Device;
return(SetupStatusOK);
}

/*-------------------------------------------------------*/

//------- Swap the Stack ---------

void SysSrvCall(struct _IRegs far * Regs);

void interrupt far SystemServicesFunctionCall(InterruptRegisters)


{
InterruptEnvelope(SysSrvCall,DeviceSysSrv,0);
};

void SysSrvCall(struct _IRegs far * Regs)


{
struct _BiosRam far * LowRam = 0;

_enable();

switch (Regs->RegAH)
{
case OpcodeOpenDevice:
printsnapstring(MsgOpcodeOpenDevice);
Regs->RegAH = 0x00; Regs->RegFlags &= ~CarryBit;
break;

case OpcodeCloseDevice:
printsnapstring(MsgOpcodeCloseDevice);
Regs->RegAH = 0x00; Regs->RegFlags &= ~CarryBit;
break;

586
Introduction to AutoBios

case OpcodeProgramTerminate:
printsnapstring(MsgOpcodeProgramTerminate);
Regs->RegAH = 0x00; Regs->RegFlags &= ~CarryBit;
break;

case OpcodeEventWait: printsnapstring(MsgOpcodeEventWait);


if((LowRam->RtcWaitFlag & 0x01) != 0)
{
Regs->RegFlags |= CarryBit;
}
else
{
outp(0xa1,inp(0xa1) & 0xfe);
LowRam->UserFlagSegment = Regs->RegES;
LowRam->UserFlagOffset = Regs->RegBX;
LowRam->RtcLow = Regs->RegCX;
LowRam->RtcHigh =Regs->RegDX;
LowRam->RtcWaitFlag = 1;
/* enable PIE in cmos chip */
OutCmos(CmosRegStatusB,(InCmos(CmosRegStatusB) & 0x7f) | 0x40);
}
break;

case OpcodeJoystick: printsnapstring(MsgOpcodeJoystick);


Regs->RegAX = 0;
Regs->RegBX = 0;
Regs->RegCX = 0;
Regs->RegDX = 0;
Regs->RegFlags &= ~CarryBit;
break;

case OpcodeSysReqKey: printsnapstring(MsgOpcodeSysReqKey);


Regs->RegAH = 0x00;
Regs->RegFlags &= ~CarryBit;
break;

case OpcodeWait: printsnapstring(MsgOpcodeWait);


if((LowRam->RtcWaitFlag & 0x01) != 0) Regs->RegFlags |= CarryBit;
else
{
_disable();
outp(0xa1,inp(0xa1) & 0xfe);
LowRam->UserFlagSegment = Regs->RegDS;
LowRam->UserFlagOffset = LowRam->RtcWaitFlag;
LowRam->RtcHigh = Regs->RegCX;
LowRam->RtcLow = Regs->RegDX;
LowRam->RtcWaitFlag = 1;
/* enable PIE in cmos chip */
OutCmos(CmosRegStatusB,(InCmos(CmosRegStatusB) & 0x7f) | 0x40);
_enable();
do { } while((LowRam->RtcWaitFlag & 0x80) == 0);
LowRam->RtcWaitFlag = 0;
}
break;

587
The C Programs

case OpcodeDeviceBusy:
printsnapstring(MsgOpcodeDeviceBusy);
Regs->RegAH = 0x00;
Regs->RegFlags &= ~CarryBit;
break;

case OpcodeInterruptComplete:
printsnapstring(MsgOpcodeInterruptComplete);
Regs->RegAH = 0x00;
Regs->RegFlags &= ~CarryBit;
break;

case OpcodeMoveBlock: printsnapstring(MsgOpcodeMoveBlock);


Regs->RegAH = VirtualMove(Regs->RegCX,MK_FP(Regs->RegES,Regs->RegSI));
if (Regs->RegAH != 0) Regs->RegFlags |= CarryBit;
break;

case OpcodeSwitchToProtectedMode:
printsnapstring(MsgOpcodeSwitchToVirtualMode);
Regs->RegAH = VirtualMode(Regs->RegBX,MK_FP(Regs->RegES,Regs->RegSI));
if (Regs->RegAH != 0) Regs->RegFlags |= CarryBit;
break;

case OpcodeGetExtendedMemorySize:
printsnapstring(MsgOpcodeGetExtMemSize);
Regs->RegAH = InCmos(CmosRegExtMemFoundHigh);
Regs->RegAL = InCmos(CmosRegExtMemFoundLow);
Regs->RegFlags &= ~CarryBit;
break;

case OpcodeGetSystemConfigParms:
printsnapstring(MsgOpcodeReturnSystemParms);
Regs->RegES = GetCS();
Regs->RegBX = (unsigned)&SystemConfigurationTable;
Regs->RegFlags &= ~CarryBit;
Regs->RegAH = 0x00;
Regs->RegFlags &= ~CarryBit;
break;

#if CfgSysSrvKeyboardIntercept
#endif

default: printsnapstring(MsgOpcodeDefault);
case OpcodeKeyboardIntercept: // Omit any printing if from Keyboard
Regs->RegAH = 0x86;
Regs->RegFlags |= CarryBit;
break;
}
}

//====== These are the Virtual Mode Support Routines =========

#define CodeSegLow 0x0000


#define CodeSegHigh 0x0f

void Exception(void);

588
Introduction to AutoBios

void Exception()
{
outp(CfgVirtualErrorPort,2);
Shutdown();
};

LDT_ENTRY RomIDT[] =
{
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
{ (unsigned)Exception,offsetof(MoveGDT,MoveCS),0,0x87,0,},
};

LDT_ENTRY RomIDTDescriptor =
{ sizeof(RomIDT), RomIDT, CodeSegHigh, 0x93, 0 };

// Note this and clean it up by symbolizing ???


LDT_ENTRY NullRomIDTDescriptor =
{ /*sizeof(RomIDT)*/0x400, 0, 0, 0x93, 0 };

unsigned NormalGateA20(unsigned value)


{
if(Send8042(Opcode8042WrOut)) { if(Send8042Data(value)) return(True); };
return(False);
};

void PrintDescriptor(char far *name,LDT_ENTRY far * Vptr)

589
The C Programs

{
printf("\nName: %s - Limit: %4X - Base: %4X%4X - Access: %2X",
name,Vptr->LimitLow,Vptr->BaseMid,Vptr->BaseLow,
Vptr->Access);

};

// returns a 24 bit address in DX:AX

unsigned long Build24BitAddress(unsigned xseg, unsigned xoff)


{
unsigned long Temp = 0;
Temp = xseg; Temp <<= 4; Temp += xoff;
return(Temp);
};

//------- build the global Descriptor tables ---------------

void BuildDescriptor(MoveGDT far * Vptr)


{
union
{
unsigned TempShort[2];
unsigned long TempLong;
} Temp;
union
{
unsigned TempShort[2];
unsigned long TempLong;
} Temp2;

//-- build a dynamic GDT Descriptor

Temp.TempLong = Build24BitAddress(FP_SEG(Vptr),FP_OFF(Vptr));

Vptr->MoveGDTDescriptor.LimitLow = sizeof(MoveGDT);
Vptr->MoveGDTDescriptor.BaseLow = Temp.TempShort[0];
Vptr->MoveGDTDescriptor.BaseMid = Temp.TempShort[1];
Vptr->MoveGDTDescriptor.Access = 0x93;
Vptr->MoveGDTDescriptor.Reserved = 0;

printf("\nVptr = %p",Vptr);
PrintDescriptor("GDT",&Vptr->MoveGDTDescriptor);

//-- build a CS: Descriptor

Vptr->MoveCS.LimitLow = (unsigned)-1;
Vptr->MoveCS.BaseLow = CodeSegLow;
Vptr->MoveCS.BaseMid = CodeSegHigh;
Vptr->MoveCS.Access = 0x9b;
Vptr->MoveCS.Reserved = 0;

PrintDescriptor("CS ",&Vptr->MoveCS);

//-- build a SS: Descriptor

590
Introduction to AutoBios

Temp.TempLong = Build24BitAddress(GetSS(),0);
Vptr->MoveSS.LimitLow = (unsigned)-1;
Vptr->MoveSS.BaseLow = Temp.TempShort[0];
Vptr->MoveSS.BaseMid = Temp.TempShort[1];
Vptr->MoveSS.Access = 0x93;
Vptr->MoveSS.Reserved = 0;

PrintDescriptor("SS ",&Vptr->MoveSS);
PrintDescriptor("IDT",&RomIDTDescriptor);

};

//----------------------------------------------------------
//
// Test Ram - size, test, and clear
//
//---------------------------------------------------------
// returns True/False in AX - size in cmos(30 and 31)
// note: these are all near procs, since they can be
// called from the Bios CS: only. After we do a restart,
// we are also in the Bios CS:, so we automatically connect
// with the right return address.
// The ram test is a combination of a block-move (Bios ->
// test area) followed by a block compare.
//

unsigned TestExtendedMemoryOK(void)
{
struct _VirtualObject far * VirtObjectPtr = GetVirtualObject();
struct StructureMoveGDT far * Vptr = &VirtObjectPtr->VirtualTestGDT;
union
{
unsigned TempShort[2];
unsigned long TempLong;
} Temp;

_disable(); // disable interrupts/execeptions

// Clear the reporting cells for ext mem size


OutCmos(CmosRegExtMemFoundLow,0);
OutCmos(CmosRegExtMemFoundHigh,0);

outp(CfgVirtualErrorPort,0); // clear the error reporting cell

// Note: Interesting point:


// It takes the 8042 a discrete amount of time to actually enable the A20
// address line after this command is given. It is given in some
// publications as > 20 useconds. If the extended mem tests cause a system
// crash, it may be because A20 has not switched yet, and < 1Mb ram
// is getting trashed. See the delay routines in the wrap enable/disable
// functions.

if(!ChipFunction(ChipFastGateA20,ChipEnable))

591
The C Programs

{
if(!NormalGateA20(EnableA20Command))
{
outp(CfgVirtualErrorPort,3);
printf("\nGate a20 loop fail");
return(False);
};
};

OutCmos(CmosRegRestartStatus,2); // set restart type 2

//------ build a complete GDT table set ------


// Once we do this, we can't do any interrupts, because the LIDT changes
// the interrput vector table base. Since we set it up for exceptions,
// we won't be able to do video interrupts.

//--- This builds the GDT, IDT, CS and SS descriptors

BuildDescriptor(Vptr);

//-- build a DS: Descriptor = Virtual Object

Temp.TempLong = Build24BitAddress(FP_SEG(Vptr),FP_OFF(Vptr));
Vptr->MoveDS.LimitLow = (unsigned)-1;
Vptr->MoveDS.BaseLow = Temp.TempShort[0];
Vptr->MoveDS.BaseMid = Temp.TempShort[1];
Vptr->MoveDS.Access = 0x93;
Vptr->MoveDS.Reserved = 0;

PrintDescriptor("DS ",&Vptr->MoveDS);

//-- build a ES: Descriptor

Temp.TempLong = Build24BitAddress(GetES(),0);
Vptr->MoveES.LimitLow = (unsigned)-1;
Vptr->MoveES.BaseLow = Temp.TempShort[0];
Vptr->MoveES.BaseMid = Temp.TempShort[1];
Vptr->MoveES.Access = 0x93;
Vptr->MoveES.Reserved = 0;

PrintDescriptor("ES ",&Vptr->MoveES);

printf("\n");

return(VirtualTestMasm(Vptr)); // call asm portion of the test

};

//--------------------------------------------------------------------
//-------- move virtual block - function code 15h ----------

unsigned VirtualMove(unsigned Count, MoveGDT far * Vptr)


{

// debug print the desciptor block on entry

592
Introduction to AutoBios

printf("\nBlock on Entry @ %p",Vptr);


PrintDescriptor("NUL",&Vptr->MoveNullDescriptor);
PrintDescriptor("GDT",&Vptr->MoveGDTDescriptor);
PrintDescriptor("DS ",&Vptr->MoveDS);
PrintDescriptor("ES ",&Vptr->MoveES);
PrintDescriptor("CS ",&Vptr->MoveCS);
PrintDescriptor("SS ",&Vptr->MoveSS);
printf("\n");

_disable(); // disable interrupts/exceptions

outp(CfgVirtualErrorPort,0); // clear the error bucket

if(!ChipFunction(ChipFastGateA20, ChipEnable))
{
NormalGateA20(EnableA20Command);
};

OutCmos(CmosRegRestartStatus,9); // set restart type 9

BuildDescriptor(Vptr); //(es:si)

//Vptr->MoveDS.Access = 0x93; // Added to insure user descriptors are OK


//Vptr->MoveES.Access = 0x93;

PrintDescriptor("DS ",&Vptr->MoveDS);
PrintDescriptor("ES ",&Vptr->MoveES);

printf("\nCount is: %4X",Count);


//pause();
/* for debug return(0x86); */

return(VirtualMoveMasm(Count,Vptr)); // call asm portion of the move

};

//--------- switch to virtual mode -----------------


// Int 15, function 89
// void virtual_mode(bhbl,seg,off)
// called with bh = 8259 #1 index
// called with bl = 8259 #2 index
// called with es = segment of pointer to global Descriptor. table
// called with si = offset of pointer to global Descriptor. table
// returns with ax = 0 = ok, else not zero = error
// all other registers destroyed !!!!

unsigned VirtualMode(unsigned InterruptIndex,ModeGDT far * Vptr)


{

_disable(); // disable interrupts/execeptions

if(!ChipFunction(ChipFastGateA20, ChipEnable))
{
NormalGateA20(EnableA20Command);

593
The C Programs

}
// reload the 8259 interrupt controllers because we have changed
// the base address of the IDT (the interrupt vectors).

outp(inta00,0x11);
outp(inta01,InterruptIndex >> 8);
outp(inta01,0x04);
outp(inta01,0xff);

outp(intb00,0x11);
outp(intb01,InterruptIndex);
outp(intb01,0x02);
outp(intb01,0xff);
outp(intb01,0x01);
outp(intb01,0xff);

//-- build a Bios: Descriptor

Vptr->ModeBios.LimitLow = (unsigned)-1;
Vptr->ModeBios.BaseLow = CodeSegLow;
Vptr->ModeBios.BaseMid = CodeSegHigh;
Vptr->ModeBios.Access = 0x9b;
Vptr->ModeBios.Reserved = 0;

PrintDescriptor("Bio",&Vptr->ModeBios);
PrintDescriptor("CS ",&Vptr->ModeCS);
PrintDescriptor("DS ",&Vptr->ModeDS);
PrintDescriptor("SS ",&Vptr->ModeSS);
PrintDescriptor("ES ",&Vptr->ModeES);

return(VirtualModeMasm(Vptr)); // call asm portion


};

594
Introduction to AutoBios

7.12 The Printer Driver


The Parallel Printer Driver is an Interrupt (0x17) function call that is used to communicate with the
printer. A parallel printer is one which has a "Centronics" interface and is referred to as LPT1, 2, or 3.
The printer driver provides simple commands to initialize the printer or send a character to the printer.
Although a hardware interrupt line (IRQ7) is normally assigned for the parallel printer port, interrupt
operation is not supported by the standard Bios driver. The typical printer adapter has logic to support
the use of the interrupt, but it is not clear how the interrupt would be used if there is more than one
printer port installed. Some print spooling programs may possibly use the interrupt, but we are not aware
of it. There may also be logic in some printer adapters to disable the output data latch, thereby allowing
a bi-directional data capability. The control logic to use such a feature is not a standard Bios function.

//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] LPT driver
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] LPT.C
//
// [Language] MSVC 1.5
//
// [Description] Int 0x17 - parallel printer driver
//
// Input:
//
// AH = 0 print the character in AL
// on return, ah = 1 if character could not be printed
// (time out).
// Other bits set as on normal Status call
//
// AH = 1 initialize the printer Port
// returns with AH set with printer Status
//
// AH = 2 read the printer Status into (ah)
// 7 6 5 4 3 2 1 0
// | | | | | | | +-- time out
// | | | | | | +------ unused
// | | | | | +---------- unused
// | | | | +-------------- 1 = i/o error
// | | | +------------------ 1 = selected
// | | +---------------------- 1 = out of paper
// | +-------------------------- 1 = acknowledge
// +------------------------------ 1 = not busy
//

595
The C Programs

// DX = printer to be used (0,1,2)


//
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

static void scan_lpt(unsigned);

/* G L O B A L V A R I A B L E S */

/* G L O B A L C O N S T A N T S */

/* L O C A L D E F I N I T I O N S */

enum { PrintCharacter, InitPort, ReadStatus, };

#define Device DeviceMaskLpt

/* P R O G R A M */

unsigned LptSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();

LoadDS();

LowRam->IntVector[0x17]= (void near *) PrinterFunctionCall;

Bios->DevicesInstalled |= Device;
scan_lpt(0x3bc); scan_lpt(0x378); scan_lpt(0x278);
return(SetupStatusOK);
}

void scan_lpt(unsigned Port)


{
struct _BiosRam far * LowRam = 0;
unsigned Temp;
outp(Port,0x55);
_disable(); /* used for a bus delay */
_enable();
if (inp(Port) == 0x55)
{
LowRam->EquipFlag.NrLptPorts++;
for (Temp = 0; ((Temp < 3) && LowRam->LPT_LIST[Temp]); Temp++);

596
Introduction to AutoBios

if(Temp < 3)
{
LowRam->LPT_LIST[Temp] = Port;
LowRam->LPT_TIMEOUT_LIST[Temp] = 0xff;
};
/* init the Port automatically */
/* _asm { _asm mov dx,Temp _asm mov ah,1 _asm int 0x17 }; */
}
}

/*=======================================================================*/

void LptCall(struct _IRegs far * Regs);

void interrupt far PrinterFunctionCall(InterruptRegisters)


{
InterruptEnvelope(LptCall,Device,0);
};

void LptCall(struct _IRegs far * Regs)


{
struct _BiosRam far * LowRam = 0;
unsigned Port,Status;
unsigned long TimeDelay;

_enable();

if ((Regs->RegDX < 3) && (Port = LowRam->LPT_LIST[Regs->RegDX]))


{
switch (Regs->RegAH)
{
default: /* if opcode is out of range, dec ah by 2 */
Regs->RegAH -= 0x02;
break;

case PrintCharacter: printsnapstring(MsgOpcodeSendChar);


Regs->RegAH = 0;
/* make the loop = count * tics * 16, so that a count == 1 second */
TimeDelay = LowRam->LPT_TIMEOUT_LIST[Regs->RegDX] * 16;
TimeDelay += ReadTimer();
do
{
if ((inp(Port+1) & 0x80)) /* Status == not busy */
{
outp(Port,Regs->RegAL); /* output character to Port */
outp(Port+2, 0x0d); /* set strobe high */
outp(Port+2, 0x0c); /* set strobe low */
inp(Port+1); /* pre-charge the line if +busy is floating */
Status = (inp(Port+1) & 0x00f8) ^ 0x48;
Regs->RegAH = Status;
break;
}
} while (ReadTimer() < TimeDelay);
break;

case InitPort: printsnapstring(MsgOpcodeInitPort);

597
The C Programs

Regs->RegAH = 0;
outp (Port+2, 0x08); /* set init line low */
/* wait for the next timer transition */
DelayCall(100,Microseconds);
//while(ReadTimer() == ReadTimer());
outp (Port+2, 0x0c); /* set init line high */
goto read_Status;

case ReadStatus:
printsnapstring(MsgOpcodeReadStatus);
Regs->RegAH = 0;
read_Status:
Regs->RegAH = (inp(Port+1) & 0xf8) ^ 0x48;
}
}
}

/*====================================================================*/

598
Introduction to AutoBios

7.13 The Serial Channel Driver


The Comm Driver is an Interrupt (0x14) Function Call that is used to communicate with the serial port
adapters.
Note - The most common problem involved with serial devices on the Com ports is the incorrect use of
the control signals, CTS, RTS, DTR, and DSR. If you experience problems in communication, try
jumpering CTS to RTS, and DSR to DTR.
This may help to localize and correct the problem.
The extended function calls available on some PS/2 machines are not included in this standard driver.
These are relatively simple to add if you wish to enhance your Com Driver.
Note - The standard serial port Bios driver does not support interrupt driven operation. Most tele-
communication software packages will replace the Bios driver with their own driver.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Serial Port Driver
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Comm.C
//
// [Language] MSVC 1.5
//
// [Purpose] Provides Serial Channel Low-Level Support
//
// [Description] Interrupt 0x14 -- Serial Port Driver
//
// [//] Provides a function call for initializing, sending data, receiving
data,
// [//] and reading the status of an asynchronous adapter.
//
// [//] Upon Entry:
//
// [//] DX = Logical Async device # (0,1,2,3) for COM1,2,3,4
//
// [//] OpcodeComInit the Port:
// [//] AH = 00h
// [//] AL = initialization parameters:
//
// [//] Bit Meaning
// [//] ----- -----------
// [//] Bits 7,6,5
// [//] 0 0 0 110 Baud

599
The C Programs

// [//] 0 0 1 150
// [//] 0 1 0 300
// [//] 0 1 1 600
// [//] 1 0 0 1200
// [//] 1 0 1 2400
// [//] 1 1 0 4800
// [//] 1 1 1 9600
//
// [//] Bits 4,3
// [//] 0 0 No parity
// [//] 0 1 Odd parity
// [//] 1 0 No parity
// [//] 1 1 Even parity
//
// [//] Bit 2
// [//] 0 One stop bit
// [//] 1 Two stop bits
//
// [//] Bits 1,0
// [//] 0 0 5 bits/char
// [//] 0 1 6 bits/char
// [//] 1 0 7 bits/char
// [//] 1 1 8 bits/char
//
// [//] Send a character:
// [//] AH = 01h
// [//] AL = the character to send
//
// [//] Receive a character:
// [//] AH = 02h
//
// [//] Read the Port status:
// [//] AH = 03h
//
// [//] Upon Exit:
//
// [//] For 'OpcodeComInit the Port' (AH=0):
// [//] AH = Line status
// [//] Bit Meaning if = 1
// [//] --- --------------
// [//] 7 Time out
// [//] 6 Tx Empty (TEMT)
// [//] 5 Tx Holding Register Empty (THRE)
// [//] 4 Break Interrupt (BI)
// [//] 3 Framing Error (FE)
// [//] 2 Parity Error (PE)
// [//] 1 Overrun Error (OE)
// [//] 0 Data Ready (DR)
//
// [//] AL = Modem status
// [//] Bit Meaning if = 1
// [//] --- --------------
// [//] 7 Data Carrier Detect (DCD)
// [//] 6 Ring Indicator (RI)
// [//] 5 Data Set Ready (DSR)
// [//] 4 Clear To Send (CTS)

600
Introduction to AutoBios

// [//] 3 Delta Data Carrier Detect (DDCD)


// [//] 2 Trailing Edge Ring Indicator (TERI)
// [//] 1 Delta Data Set Ready (DDSR)
// [//] 0 Delta Clear To Send (DCTS)
//
// [//] For 'Send a character (AH = 1):
// [//] AL = unchanged (character that was sent)
// [//] AH = Completion code
// [//] 1XXX XXXX - Time out, char not sent
// [//] 0YYY YYYY - Tx Successful, Bits 6 - 0 = Line status
//
// [//] For 'Receive a character (AH = 2):
// [//] AL = The received char, if successful
// [//] AH = Completion code
// [//] 1XXX XXXX - Time out, no char received
// [//] 000Y YYY0 - Data received, but error detected
// [//] See Line status Bit Definitions
//
// [//] For 'Get Port status' (AH=3):
// [//] AH = Line status (see above)
// [//] AL = Modem status (see above)
//
// [//] Global Variables:
//
// [//] Async_adapter_Port_list (word // [] 4):
//
// [//] Word 0 = adapter address of COM1
// [//] Word 1 = adapter address of COM2
// [//] Word 2 = adapter address of COM3
// [//] Word 3 = adapter address of COM4
//
// [//] These four words contain the hardware Port addresses of the async
// [//] adapters. Four async adapters can be supPorted although the operating
// [//] system may only recognize COM 1,2.
//
// [//] Async_TimeOut_count (byte // [] 4):
//
// [//] Byte 0 = time out count value for COM1
// [//] Byte 1 = time out count value for COM2
// [//] Byte 2 = time out count value for COM3
// [//] Byte 3 = time out count value for COM4
//
// [//] The time outs for no response use the contents of these cells
// [//] for a count.
//
// [//] Registers Modified:
// [//] AX is modified
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

601
The C Programs

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

static void scan_comm(unsigned);

/* G L O B A L V A R I A B L E S */

/* G L O B A L C O N S T A N T S */

unsigned _based(_segname("_CODE")) baud_table[8] =


{1047, 768, 384, 192, 96, 48, 24, 12 };

/* L O C A L D E F I N I T I O N S */

#define device DeviceMaskCom

/* 8250/16450 register offsets from base address */

#define TxDataReg 0x00


#define RxDataReg 0x00
#define DivLsbReg 0x00
#define DivMsbReg 0x01
#define IntEnbReg 0x01
#define IntIdReg 0x02
#define LineCtrlReg 0x03
#define ModemCtrlReg 0x04
#define LineStatusReg 0x05
#define ModemStatusReg 0x06

/* 8250/16450 register bit definitions */

#define TxRdyBit 0x60


#define RxRdyBit 0x01
#define DsrBit 0x20
#define DtrBit 0x01
#define CtsBit 0x10
#define RtsBit 0x02

/* opcode definitions */

#define OpcodeComInit 0x00


#define OpcodeComSend 0x01
#define OpcodeComRecv 0x02
#define OpcodeComStatus 0x03

#define timeout_bit 0x80

#define Device DeviceMaskCom

/* P R O G R A M */

/*
// SCAN Com Ports -

602
Introduction to AutoBios

// This routine is called to determine how many Ports are in the system
*/

unsigned CommSetup(ActionArgument)
{
unsigned Temp;
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();

LoadDS();
_disable();
LowRam->IntVector[0x14]= (void near *)CommFunctionCall;
_enable();
#if CfgComm
scan_comm(0x3f8); scan_comm(0x2f8); scan_comm(0x3e8); scan_comm(0x2e8);
Bios->DevicesInstalled |= Device;
return(SetupStatusOK);
#else
return(SetupStatusStub);
#endif
}

#if CfgComm
void scan_comm(unsigned Port)
{
struct _BiosRam far * LowRam = 0;
unsigned Temp;
outp(Port+3,0x55);
NoOpcode; NoOpcode; NoOpcode; /* NoOpcodes for bus delay */
if (inp(Port+3) == 0x55)
{
LowRam->EquipFlag.NrComPorts++;
for (Temp = 0;((Temp < 4) && (LowRam->COMM_LIST[Temp] != 0));Temp++);
if(Temp < 4)
{
LowRam->COMM_LIST[Temp] = Port;
LowRam->COMM_TIMEOUT_LIST[Temp] = 0xff;
};

//?????????????????????????????????/
/* init the Port to 9600 baud */
_asm { _asm mov ax,0x00e3 _asm mov dx,Temp _asm int 0x14 };
//_asm { _asm mov ax,CfgComm1Init _asm mov dx,Temp _asm int 0x14 };
}
}
#endif

/*-------------------------------------------------------------------*/

void CommCall(struct _IRegs far * Regs);

void interrupt far CommFunctionCall(InterruptRegisters)


{
InterruptEnvelope(CommCall,Device,0);
};

603
The C Programs

void CommCall(struct _IRegs far * Regs)


{
#if !CfgComm
Regs->RegAX = 0x8000;
#else

struct _BiosRam far * LowRam = 0;


unsigned Port,TimeOut,Divisor;
unsigned long TimeOutCounter;

_enable();

if ((Regs->RegDX <= 3) && ((Port = LowRam->COMM_LIST[Regs->RegDX]) != 0))


{
/* get the time out parameter */
TimeOut = LowRam->COMM_TIMEOUT_LIST[Regs->RegDX];

/* scale to use as a major loop counter */


TimeOut *= 10; /* figure 1 count = 500 millisec = 10 clock ticks */

switch(Regs->RegAH)
{
case OpcodeComInit: printsnapstring(MsgOpcodeInitPort);
Regs->RegAH = 00;
/* set Divisor latch enable */
outp(Port+LineCtrlReg,0x80);
/* get the Divisor */
Divisor = baud_table[(Regs->RegAL >> 5) & 0x07];
/* load the baud rate Divisor into the 8250 */
outp(Port+DivLsbReg,Divisor);
outp(Port+DivMsbReg,(Divisor >> 8));
/* set length,parity,stop bits */
outp(Port+LineCtrlReg,(Regs->RegAL & 0x1f));
/* set DTR and RTS lines */
outp(Port+ModemCtrlReg,(0x08 | DtrBit | RtsBit));
Regs->RegAH = (char)inp(Port+LineStatusReg);
Regs->RegAL = (char)inp(Port+ModemStatusReg);
break;

case OpcodeComSend: printsnapstring(MsgOpcodeSendChar);

/* start with clean return status */


Regs->RegAH = 0x00;

/* set dtr and rts */


outp(Port+ModemCtrlReg,
inp(Port+ModemCtrlReg) | DtrBit | RtsBit);
/* check dsr and cts */

TimeOutCounter = SetTimeOutCount(TimeOut);

while(((inp(Port+ModemStatusReg) & (DsrBit| CtsBit))


!= (DsrBit| CtsBit)))
{
if (LowRam->TimerLong >= TimeOutCounter)

604
Introduction to AutoBios

{ Regs->RegAH |= timeout_bit; break;}


}
if (Regs->RegAH == 0) /* OK - no timeout */
{
TimeOutCounter = SetTimeOutCount(TimeOut);
while((inp(Port+LineStatusReg) & TxRdyBit) != TxRdyBit)
{
if (LowRam->TimerLong >= TimeOutCounter)
{Regs->RegAH |= timeout_bit; break;}
}
if (Regs->RegAH == 0) /* OK - no timeout */
{
outp(Port+TxDataReg,Regs->RegAL);
/* return the status in AH */
Regs->RegAH = (char)inp(Port+LineStatusReg);
}
}
break;

case OpcodeComRecv: printsnapstring(MsgOpcodeReadChar);

/* start with clean return status */


Regs->RegAH = 00;

/* set DTR out */


outp(Port+ModemCtrlReg, inp(Port+ModemCtrlReg) | DtrBit);

/* check DSR */
TimeOutCounter = SetTimeOutCount(TimeOut);
while(((inp(Port+ModemStatusReg) & DsrBit) != DsrBit))
{
if (LowRam->TimerLong >= TimeOutCounter)
{Regs->RegAH |= timeout_bit; break;}
}
if (Regs->RegAH == 0) /* OK - no timeout */
{

/* check for data ready */


TimeOutCounter = SetTimeOutCount(TimeOut);
while(((inp(Port+LineStatusReg) & RxRdyBit) != RxRdyBit))
{
if (LowRam->TimerLong >= TimeOutCounter)
{Regs->RegAH |= timeout_bit; break;}
}
if (Regs->RegAH == 0) /* OK - no timeout */
{
Regs->RegAH = (char)(inp(Port+LineStatusReg) & 0x1e);
Regs->RegAL = (char)inp(Port+RxDataReg);
}
}
break;

case OpcodeComStatus:
printsnapstring(MsgOpcodeReadStatus);

Regs->RegAH = (char)inp(Port+LineStatusReg);

605
The C Programs

Regs->RegAL = (char)inp(Port+ModemStatusReg);
break;

default: printsnapstring(MsgOpcodeBadCommand);

;
}
}
#endif
}

//-------------------------------------------------------------------
// This section is used if the serial port is enabled as a SysVue
// console device
// Note: this code is a template and has not yet been tested

void LoadBuffer(unsigned);

void interrupt far SysVueConsoleISR(InterruptRegisters);


void interrupt far SysVueConsoleCall(InterruptRegisters);

#if CfgConsoleInSerial

unsigned SysVueConsoleSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
unsigned status = True;
unsigned Divisor;

LoadDS();

_disable();

LowRam->IntVector[CfgSysVueConsoleIRQ + 8]= (void near *)SysVueConsoleISR;


LowRam->IntVector[0x10]=(void near *) SysVueConsoleCall;
_enable();

outp(0x21,inp(0x21) & ~(1 << CfgSysVueConsoleIRQ));

// init the port for 9600 baud

/* set Divisor latch enable */


outp(CfgSysVueConsolePort+LineCtrlReg,0x80);
/* get the Divisor */
Divisor = baud_table[(CfgSysVueConsoleInit >> 5) & 0x07];
/* load the baud rate Divisor into the 8250 */
outp(CfgSysVueConsolePort+DivLsbReg,Divisor);
outp(CfgSysVueConsolePort+DivMsbReg,(Divisor >> 8));
/* set length,parity,stop bits */
outp(CfgSysVueConsolePort+LineCtrlReg,(CfgSysVueConsoleInit & 0x1f));
/* set DTR and RTS lines */
outp(CfgSysVueConsolePort+ModemCtrlReg,(0x08 | DtrBit | RtsBit));
/* enable rx interrupt */
outp(CfgSysVueConsolePort+IntEnbReg,0x01);

606
Introduction to AutoBios

return(SetupStatusOK);
};

void SysVueConsoleInt(struct _IRegs far * Regs);

void interrupt far SysVueConsoleISR(InterruptRegisters)


{
InterruptEnvelope(SysVueConsoleInt,0,0);
};

void SysVueConsoleInt(struct _IRegs far * Regs)


{
struct _BiosRam far * LowRam = 0;

_enable();

// get the incoming ASCII code from the serial port and place
// it in the Keyboard Buffer

LoadBuffer((unsigned) inp(CfgSysVueConsolePort));

// Send an EOI to the PIC


SendEOI1();
}
#endif

void SysVueConsoleService(struct _IRegs far * Regs);

void interrupt far SysVueConsoleCall(InterruptRegisters)


{
InterruptEnvelope(SysVueConsoleService,0,0);
};

void SysVueConsoleService(struct _IRegs far * Regs)


{
char TempAL;

//send al to com port


TempAL = Regs->RegAL;
_asm
{
push dx
push bx
push cx
mov dx,CfgSysVueConsolePort
add dx,5

mov bl,10 ; outer counter


local4:
xor cx,cx ; inner counter
local5:
in al,dx
and al,0x60
cmp al,0x60

607
The C Programs

je local10
loop local5
dec bl
jnz local4

local10:

mov al,TempAL
mov dx,CfgSysVueConsolePort
out dx,al

pop cx
pop bx
pop dx

}
};

/*======================================================*/

608
Introduction to AutoBios

7.14 The Timer Interrupt Service


The Timer Interrupt is called by the hardware real-time clock every 5n.nnn milliseconds to increment the
time count. This count is used by DOS to calculate the time of day.
Note - A user supplied routine may be linked to the timer interrupt routine, using interrupt 1C. This user
routine should be of minimal execution time, since other interrupts are disabled while it is running. If it
retains control too long, other interrupts may be missed.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Real time clock service routine
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Tmr.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] Interrupt 0x08 This routine services the real time
// [Description] clock interrupt.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

void interrupt far RTC_INT(void);

/* G L O B A L S */

/* C O N S T A N T S */

/* D E F I N E S */

#define Device DeviceMaskTimer

609
The C Programs

/* P R O G R A M */

unsigned TimerSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();
LoadDS();
_disable();
LowRam->IntVector[0x1C]= (void near *)DummyIret;
LowRam->IntVector[0x08]= (void near *)TimerISR;
#if CfgCmos
LowRam->IntVector[0x4A]= (void near *)DummyIret;
LowRam->IntVector[0x70]= (void near *)RTC_INT;
#endif

// Enable the 8259 to allow the timer interrupts to be seen


//outp(0x21,inp(0x21) & ~BIT0);

_enable();
Bios->DevicesInstalled |= Device;
return(SetupStatusOK);
}

//===============================================

void interrupt far TimerISR(void)


{
struct _BiosRam far * LowRam = 0;
void (interrupt far * Clock_Chain) (void) = LowRam->IntVector[0x1C];
_enable();
LoadDS();
/* increment timer count check for 24 hour value */
if(++LowRam->TimerLong >= TimerLongMax)
{ LowRam->TimerLong = 0; LowRam->TimerOverflow = 1; }

if(!--LowRam->MOTOR_COUNT) /* turn off any FD motors */


{
LowRam->MotorStatusByte &= 0xf0; outp(0x3f2,0x0c);
}
(* Clock_Chain) ();
_disable();
SendEOI1(); // Send EOI to PIC
}

//=========== ALARM Interrupt Handler ===================


//
// This routine handles the Periodic Interrupt from the clock chip.
// the frequency is 1024 Interrupts per second, or 976 usecs/interrupt.

// Interrupts are enabled by calling Int 1A, event or alarm function calls.
// For events, the ISR will decrement the counter and set the specified
// location to 0x8000.
// The user must provide the address of an alarm routine to be executed
// when the alarm interrupt occurs.

610
Introduction to AutoBios

#if CfgCmos

void interrupt far RTC_INT(void)


{
struct _BiosRam far * LowRam = 0;
void (interrupt far * RTC_Chain) (void) = LowRam->IntVector[0x4A];

#define Periodic 0x40


#define Alarm 0x20

#define EnableRegister CmosRegStatusB


#define FlagRegister CmosRegStatusC

unsigned flags;

while((flags = InCmos(FlagRegister) & InCmos(EnableRegister)) != 0)


{
if((flags & Periodic) != 0)
{
// decrement the wait count by the standard interval
if((LowRam->RtcLong -= 976) < 0) // if count underflows, then it's a find
{
// Turn off the Periodic Interrupt Enable
OutCmos(CmosRegStatusB,(char)(InCmos(CmosRegStatusB) & 0xbf));
LowRam->RtcWaitFlag = 0;
LowRam->UserFlagOffset = 0x8000;
}
}
if((flags & Alarm) != 0)
{
// Enable NMI
outp(CmosRegPort,CmosRegStatusD);
_enable();
// call user interrupt 4A
_asm push dx;
(* RTC_Chain) ();
_asm pop dx;
_disable();
}
};
// enable NMI
outp(CmosRegPort,CmosRegStatusD & 0x7f);
// Send EOI to both controllers
SendEOI2();
}

#endif

611
Introduction to AutoBios

7.15 The Time Of Day Driver


The Time of Day Function is used to read and set the timer counter, which is incremented by the timer
interrupt.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios Time Of Day function
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Tod.C
//
// [Language] MSVC 1.5
//
// [Description] Interrupt 0x1A - Time of Day function call -
// read/set the clock
//
//
// Interrupt 1AH - Time of Day function call
// read/set the internal clock or the 6818 clock chip
//
// AH = 0 - read the clock.
// returns:
// CX = high word of count
// DX = low word of count
// AL = 0 if no 24 hour rollover since last read
//
// AH = 1 - set the clock
// CX = high word of count
// DX = low word of count
//
// AH = 2 - read the time from the 6818 clock
// returns:
// CH = BCD hours
// CL = BCD minutes
// DH = BCD seconds
// CY flag if 6818 not running
//
// AH = 3 - set the time to the 6818 clock
// CH = BCD hours
// CL = BCD minutes
// DH = BCD seconds
// DL = 0/1 = normal/daylight time
//
// AH = 4 - read the date from the 6818 clock

613
The C Programs

// returns:
// CH = BCD century
// CL = BCD year
// DH = BCD month
// DL = BCD day
// CY flag if 6818 not running
//
// AH = 5 - set the date to the 6818 clock
// CH = BCD century
// CL = BCD year
// DH = BCD month
// DL = BCD day
//
// AH = 6 - set the 6818 alarm
// CH = BCD hours from set time
// CL = BCD minutes from set time
// DH = BCD seconds from set time
// returns:
// CY flag if alarm already set
// NOTE: function 6 is hooked through Int. 4ah, user replaceable.
//
//
// AH = 7 - reset the 6818 alarm off
//
// [History] 2.00 04/11/94 Original
//
//--------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

unsigned UpdateInProgress(void);
unsigned InitializeRealTimeClock(void);

void _time_of_day(void);

/* G L O B A L S */

/* L O C A L D E F I N I T I O N S */

#define Device DeviceMaskTod

#define OpcodeReadTimeCounter 0x00


#define OpcodeSetTimeCounter 0x01
#define OpcodeReadRTC 0x02
#define OpcodeSetRTC 0x03
#define OpcodeReadDate 0x04
#define OpcodeSetDate 0x05
#define OpcodeSetAlarm 0x06
#define OpcodeResetAlarm 0x07

/* P R O G R A M */

614
Introduction to AutoBios

unsigned TimeOfDaySetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();
LoadDS();
_disable();
LowRam->IntVector[0x1A]= (void near *)TimeOfDayFunctionCall;
_enable();
Bios->DevicesInstalled |= Device;
if(!SetTimerCount()) return(SetupStatusError);
return(SetupStatusOK);
}

#define device DeviceMaskTod

void TodCall(struct _IRegs far * Regs);

void interrupt far TimeOfDayFunctionCall(InterruptRegisters)


{
InterruptEnvelope(TodCall,DeviceTod,0);
};

void TodCall(struct _IRegs far * Regs)


{
struct _BiosRam far * LowRam = 0;
_enable();

switch(Regs->RegAH)
{
case OpcodeReadTimeCounter:
printsnapstring(MsgOpcodeReadCurrentClock);
_disable();
Regs->RegAL = (char)LowRam->TimerOverflow;
Regs->RegDX = LowRam->TimerLow;
Regs->RegCX = LowRam->TimerHigh;
LowRam->TimerOverflow = 0;
_enable();
break;

case OpcodeSetTimeCounter:
printsnapstring(MsgOpcodeSetTimeCounter);
_disable();
LowRam->TimerLow = Regs->RegDX;
LowRam->TimerHigh = Regs->RegCX;
LowRam->TimerOverflow = 0;
_enable();
break;

default: printsnapstring(MsgOpcodeBadCommand);
Regs->RegFlags |= CarryBit;
break;

#if CfgCmos
case OpcodeReadRTC: printsnapstring(MsgOpcodeReadTime);

615
The C Programs

Regs->RegFlags &= ~CarryBit;


if (UpdateInProgress()) Regs->RegFlags |= CarryBit;
else
{
Regs->RegDH = InCmos(CmosRegSeconds);
Regs->RegCH = InCmos(CmosRegHours);
Regs->RegCL = InCmos(CmosRegMinutes);
Regs->RegDL = InCmos(CmosRegStatusB) & CmosRegBitDaylight;
}
break;

case OpcodeSetRTC: printsnapstring(MsgOpcodeSetTime);


if (UpdateInProgress()) InitializeRealTimeClock();
OutCmos(CmosRegSeconds,Regs->RegDH);
OutCmos(CmosRegMinutes,Regs->RegCL);
OutCmos(CmosRegHours,Regs->RegCH);
OutCmos(CmosRegStatusB,(InCmos(CmosRegStatusB) & 0x30) | \
(Regs->RegDL & CmosRegBitDaylight) | 2);
break;

case OpcodeReadDate: printsnapstring(MsgOpcodeReadDate);


Regs->RegFlags &= ~CarryBit;
if (UpdateInProgress()) Regs->RegFlags |= CarryBit;
else
{
Regs->RegCH = InCmos(CmosRegCentury);
Regs->RegCL = InCmos(CmosRegYear);
Regs->RegDH = InCmos(CmosRegMonth);
Regs->RegDL = InCmos(CmosRegDayOfMonth);
}
break;

case OpcodeSetDate: printsnapstring(MsgOpcodeSetDate);


if (UpdateInProgress()) InitializeRealTimeClock();
else
{
OutCmos(CmosRegDayOfWeek,0);
OutCmos(CmosRegDayOfMonth,Regs->RegDL);
OutCmos(CmosRegMonth,Regs->RegDH);
OutCmos(CmosRegYear,Regs->RegCL);
OutCmos(CmosRegCentury,Regs->RegCH);
OutCmos(CmosRegStatusB,(InCmos(CmosRegStatusB) & 0x7f));
}
break;

case OpcodeSetAlarm: printsnapstring(MsgOpcodeSetAlarm);


Regs->RegFlags &= ~CarryBit;
if((InCmos(CmosRegStatusB) & 0x20) != 0) { Regs->RegAX = 0; Regs->RegFlags
|= CarryBit; }
else
{
if(!UpdateInProgress()) InitializeRealTimeClock();
OutCmos(CmosRegSecondAlarm,Regs->RegDH);
OutCmos(CmosRegMinuteAlarm,Regs->RegCL);
OutCmos(CmosRegHourAlarm,Regs->RegCH);
outp(0xa1,inp(0xa1) | 0xfe);

616
Introduction to AutoBios

OutCmos(CmosRegStatusB,(InCmos(CmosRegStatusB) & 0x7f) | 0x20);


}
break;

case OpcodeResetAlarm:
printsnapstring(MsgOpcodeResetAlarm);
OutCmos(CmosRegStatusB,InCmos(CmosRegStatusB) & 0x57);
break;
#endif
}
};

/*--------------------------------------------------

An update cycle can take up to 1984us


This function returns True if an update is in progress,
False if the clock/calendar can be read/set.

-----------------------------------------------------*/

#if CfgCmos

unsigned UpdateInProgress(void)
{
unsigned j = 0;
while(j++ < 2000) { if (!(InCmos(CmosRegStatusA) & BIT7)) return(False); };
return(True);
}

unsigned InitializeRealTimeClock(void)
{
OutCmos(CmosRegStatusA,0x26);
OutCmos(CmosRegStatusB,0x82);
InCmos(CmosRegStatusC);
InCmos(CmosRegStatusD);
return(True);
}

#endif

617
Introduction to AutoBios

7.16 The 8042 Controller Support


The Bios8042.c module contains functions used to communicate with the 8042 keyboard controller used
in AT Class platforms.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] 8042 Keyboard Controller functions
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Bios8042.C
//
// [Language] MSVC 1.0/1.5
//
// [Category] Bios Keyboard Controller Support
//
// [Description] This module includes AT keyboard controller functions.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/*======== keyboard controller support ================/

The 8042 keyboard controller uses ports 0x60 and 0x64.


0x60 = data in and out
0x64 = status in.
The status bits are:
Bit Description
7 Parity error 0 = odd (no error), 1 = even
6 rx timeout 1 = error
5 tx timeout 1 = error
4 inhibit 0/1 = inhibit/not inhibited
3 data/command port 60 = data/command
2 system flag 0= powerup, 1= reset
1 inp bfr full 0/1 = empty/full
0 out bfr full 0/1 = empty/full

619
The C Programs

8042 commands (to port 64):

0x60 write next byte (0x64) to controller: (use 0x45)


Bit Description
7 always 0
6 1 = PC compatibility mode
5 1 = PC mode
4 1 = disable keyboard
3 1 = inhibit override
2 0 = reset system flag
1 always 0
0 1 = enable out bfr full int. (IRQ1)

0xaa self test 8042


returns 0x55 in out bfr (0x60) if OK

x0c0 read 8042 input port into out bfr (0x60)


bit Description of input port
7 0/1 = keylock switch locked/not locked
6 0/1 = CGA/MDA vidoe jumper
5 0/1 Mfg Jumper present/absent
4 0/1 system ram = 512/256 K

0xd1 write next byte (0x64) to controller


bit Description
7 kb data out line
6 kb clock out line
1 Gate A20
0 1 = reset system

/==================================================*/

/*------- reset the 8042 ------- */

unsigned Reset8042()
{
unsigned stat = True;
unsigned long jj; /* 1 second delay counter */
/* mask out interrupts in case they are still enabled */
outp(0x21,inp(0x21) | 0x02);
/* purge the 8042's output buffer */
inp(0x60);
/* reset the 8042 */
if(!Send8042(0xaa)) stat = False;
if(!WaitToRx8042()) stat = False;

// If the reset test is enabled, wait for a response


#if CfgKeyboardResetTest
jj = SetTimeOutCount(20); /* 1 second delay */
do
{
stat = False;
if(inp(0x60) == 0x55) { stat = True; break; };
} while (LowRam->TimerLong < jj);

620
Introduction to AutoBios

#endif

/* configure 8042 */
if(!Send8042(0x60)) stat = False;
if(!Send8042Data(0x45)) stat = False;
//if(!Send8042Data(0x65)) stat = False; // for PS/2
DelayCall(20,Milliseconds); // delay for AMI, Everex, Award
outp(0x21,inp(0x21) & ~0x02);
return(stat);
}

/*---- this gets the video jumper byte from the 8042 ----*/

/* returns 2 = CGA, 3 = MDA */

unsigned GetVideoJumper()
{
#if CfgPlatformAT
unsigned temp = 0;
outp(0x21,inp(0x21) | 0x02);
WaitToSend8042();
Send8042((char)0xc0); /* read the jumper command */
WaitToRx8042();
temp = inp(0x60);
outp(0x21,inp(0x21) & ~0x02);
if ((temp & 0x40) == 0) return(2);
/* return CGA index value, else */
return(3); /* return MDA index value */
#else
return(ReadSwitches() >> 4 & 0x03);
#endif
}

/*---- wait until 8042 ready to accept another byte ----*/

unsigned WaitToSend8042(void)
{
struct _BiosRam far * LowRam = 0;
unsigned long jj = SetTimeOutCount(20); /* 1 second delay */

do
{
if((inp(0x64) & 0x02) == 0) return(True);
} while (LowRam->TimerLong < jj);
return(False);
}

/*--- wait for 8042 output buffer to be loaded ----*/

unsigned WaitToRx8042()
{
struct _BiosRam far * LowRam = 0;
unsigned long jj = SetTimeOutCount(20); /* 1 second delay */

do
{

621
The C Programs

if((inp(0x64) & 0x01) != 0) return(True);


} while (LowRam->TimerLong < jj);
return(False);
}

/*--- send a command and wait until accepted ---*/

unsigned Send8042(char value)


{
unsigned trys = 10;
while (trys-- > 0)
{
if(WaitToSend8042()) { outp(0x64,value); return(True); };
};
return(False);
}

/*--- check buffer ready and send data ---*/

unsigned Send8042Data(char value)


{
unsigned trys = 10;
while (trys-- > 0)
{
if(WaitToSend8042()) { outp(0x60,value); return(True); }
}
return(False);
}

622
Introduction to AutoBios

7.17 The Acquire/Release Object Functions


The Object.c module contains the routines used to Create a System Object, and the Acquire and Release
memory objects used by the device drivers.
AutoBios creates a "System Object" at the top of system ram to be used for data storage for the device
drivers. Within the system object, auxiallry rotuines provide for reserving and releasing blocks of
memory to be used by the device drivers. These objects typically contain the variables, flags, buffers,
etc., used by a device driver. This allows the device drivers to be written in such a manner as to
minimize the use of the callers stack. It also simplifies structuring the device drivers so they are
inherently recursive.

/*************************************************************************
*
* [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
*
* [Product Name] AutoBios
*
* [Module Name] Object primitives
*
* [Version] 2.00
*
* [Author] John O. Foster
*
* [Date] 04/11/94
*
* [File Name] Object.C
*
* [Language] MSVC 1.0/1.5
*
* [Description] This module contains the primitive Object operators
* 1. Create a system Object
* 2. Allocate from system Object
* 3. Release from system Object
*
* [Arguments]
*
* [Return]
*
* [History] 2.00 04/11/94 Original
*
******************************************************************************
*********************/

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/* G L O B A L V A R I A B L E S */

//extern unsigned test_block;

623
The C Programs

/* G L O B A L C O N S T A N T S */

/* L O C A L D E F I N I T I O N S */
/* P R O G R A M */
/*
// NOTE: We build an initial set of Object in the 1st 64k.
// Later, after we have sized memory and determined where to place
// the final Object, a rebuild rather than a simple block-move is
// required because of the far pointers we use.
// The move system segment routine will have to do a complete rebuild !

// This function creates the primary system Object by stealing space at


// the top of system ram (as determined by the mem-size parameter) in
// 1K blocks and initializing the pointers to the primary (or system)
// ram pool. It should be used on Power-on from Bios before DOS is loaded.
// It may be used by rom-scan programs for Brand-X Bios.
*/

// Comments for future changes -


// void far *CreateSystemObject(unsigned BlockSize,unsigned far * MemTopPtr)
// MemTopPtr = 0000:0413 for Bios or 55AA modules
// xxxx.yyyy for DOS exe's
// Seg Ptr = 0000:040e for Bios
// aaaa:bbbb for DOS and 55AA Modules
// End Comments

void far *CreateSystemObject(unsigned BlockSize)


{
struct _SystemObject far * System = GetSystemObject();

// If the SystemSegmentPointer is != 0, then assume that


// a system object already exists.
// When creating the second system object after the memory sizing
// reset the pointer to zero.

// This logic allows a standalone module to load up after bootup and


// use the existing system object from the Bios.

// A case exists where a Bios stand-alone .EXE module is used with


// other Bios. Here, a system object will need to be created based
// on a DOS Data group.

// if(System = MK_FP(SystemSegmentPointer,0) == 0)
if(!System)
{

/* Using BlockSize, round up to next 1K boundary */

//CheckPoint(0x50); // entered create system object routine

BlockSize += 1023; BlockSize &= ~1023;

//CheckPoint(0x51); // rounded up block size to 1K modulus

// To build at the top of system memory before DOS is loaded


// decrease memory size by n 1K blocks

624
Introduction to AutoBios

MemorySizeWord -= (BlockSize/1024);

//CheckPoint(0x52); // decreased memory size word by block size

/* point to space above new mem-size */

SystemSegmentPointer = MemorySizeWord * 64;

//CheckPoint(0x53); // set system segment pointer

/* set system Object pointer to start of system Object */

//CheckPoint(0x55); // setting System to start of Object

System = GetSystemObject();

//CheckPoint(0x56); // Clearing Object

/* Insert Object size, so we can do a clear on the system Object */


System->ObjectLength = BlockSize;
ClearObject(System);

//CheckPoint(0x57); // Loading Object

/* Insert Object size on the fresh Object so we can use it */


System->ObjectLength = BlockSize;

/* Insert System Object name */


StrCpy(System->ObjectName,"SystemObject");

//CheckPoint(0x58); // Loaded Object Name String

// Mark this System Object as Native to the Bios (as opposed


// to being a System Object created by loading a StandAlone
// driver and using the DOS Data Area
System->ObjectStatusFlags.Native = 1;

/* set pool delimiters */


System->PoolStart = System->PoolCurrentOpen = (void far *)&System-
>PoolBlock;

//CheckPoint(0x59); // Set Pool Parameters

System->PoolEnd = MK_FP(SystemSegmentPointer,BlockSize);

//CheckPoint(0x5a); // Returning to Caller

}
return(System);
}

/*============ Object Operators ===================*/

/*
** block size is passed as number of bytes needed.

625
The C Programs

** the current routine is recursive, not re-entrant !


*/

void far *acquire_system_block(char far * name,


unsigned BlockSize, unsigned object_type)
{
struct _SystemObject far * System = GetSystemObject();
struct _Object far * Object;
PushInterruptStatus;
_disable();
/* unconditionally round block up to next paragraph */

//CheckPoint(0x60); // acquire system block

BlockSize += 15; BlockSize &= ~15;

if ((System->PoolCurrentOpen + (BlockSize/16)) < System->PoolEnd)


{
/* this open space is allocatable */
Object = (void far *)System->PoolCurrentOpen;
System->PoolCurrentOpen += (BlockSize/16); /* think in paragraphs */
Object->ObjectLength = BlockSize;
Object->ObjectType = object_type;
/* scan thread and set flink about here */
StrCpy(Object->ObjectName,name);
/*Object->ObjectHandle = id; */
PopInterruptStatus;

//CheckPoint(0x61); // pop previous interrupt condition and return

return(Object);
}
PopInterruptStatus;
return(0); // A NULL Ptr indicates no acquire performed
};

unsigned ReleaseObject(struct Object far * Object)


{
struct _SystemObject far * System = GetSystemObject();
_disable();
if((unsigned long)Object < (unsigned long)System->PoolCurrentOpen)
(unsigned long)System->PoolCurrentOpen = (unsigned long)Object;
return(ClearObject(Object));
}

626
Introduction to AutoBios

7.18 The Printf Function


The printf function is similar in syntax to the standard C function, but with additions to handle snapshots,
watches, and cold-boot conditions. It does not support the format type specifiers which have no useful
application in a Bios. Printf provides a familiar tools for C programmers to add messages, debug
information, additional SysVue functions, etc.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios printf routines
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] Printf.c
//
// [Language] MSVC 1.0/1.5
//
// [Description] This routine implements a subset of the standard
// [Description] printf function, modified for Bios use
// [Description] in Bios applications. The Cold/Warm and Watch
// [Description] capabilities are additions.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* P R O T O T Y P E S */

static void put16(unsigned, unsigned);


static void putptr(unsigned long);
static void put10(unsigned, unsigned);
static void puthex(unsigned);
static void putdecimal(unsigned);
static void putcountedchar(char c);

//static unsigned cold(void);

627
The C Programs

/* D E F I N I T I O N S */

/* P R O G R A M */

/*================ I/O Functions ===================*/

/* This function counts chars after a newline, for tabbing purposes */

void putcountedchar(char c)
{
// colcounter // must be somewhere permanent !!! later

};

/* This function outputs an unsigned value as (length) Hex characters */

void put16(unsigned value,unsigned length)


{
unsigned char buff[12]; unsigned digits = 0;
do
{
if ((buff[digits] = (value % 16 + '0')) > '9') buff[digits] += 7;
digits++; value /= 16;
} while (value);
if(digits > length) digits = length;
while (length-- > digits) PutChar('0');
while (digits) PutChar(buff[--digits]);
}

/* This function outputs an unsigned long value as 4:4 Hex */

void putptr(unsigned long value)


{ put16((unsigned)(value >> 16),4); PutChar(':'); put16((unsigned)value,4); }

/* This function outputs an unsigned value as (length) Decimal */

void put10(unsigned value,unsigned length)


{
unsigned char buff[12]; unsigned digits = 0;
do { buff[digits++] = value % 10 + '0'; value /= 10; } while (value);
while (length-- > digits) PutChar(' ');
while (digits) PutChar(buff[--digits]);
}

/* This function outputs an unsigned value as (variable length) Hex */

void puthex(unsigned value)


{
if(value >= 16) puthex(value / 16); value %= 16;
if (value >= 10) PutChar((char)(value + 'A' - 10));
else PutChar((char)(value + '0'));
};

/* This function outputs an unsigned value as (variable length) Decimal */

void putdecimal(unsigned value)

628
Introduction to AutoBios

{ if(value >= 10) putdecimal(value / 10); PutChar((char)(value % 10 + '0')); }

/* This function returns True if a Cold-Boot sequence */

unsigned cold(void) { return(ResetFlag != 0x1234?True:False); };

void putstring(char far * Ptr)


{
while(*Ptr) { PutChar(*Ptr++); };
}

/*===== simplified printf function for SysVue and Bios ======

See the cases below for the supported specifiers.


Text encoded (no magic characters) cases of \n, \r, \b, etc will
be recognized so that user may create text strings outside of
C pre-processor if desired.

==============================================================*/

unsigned printf(char far * FormatPtr,...)


{
va_list ArgPtr;
unsigned print_flag = True; unsigned width = 10;
char c;
char HexSum = 0;
va_start(ArgPtr,FormatPtr);

while ((c = *FormatPtr++) && print_flag)


{
switch(c)
{
case '%':
width = 0; /* reset width */
if(*FormatPtr)
{
// get the width specifier, if included
while(IsDigit(*FormatPtr)) { width += *FormatPtr++ - '0'; };

c = *FormatPtr++;
switch(c)
{
/* %c is for character */
case 'c': case 'C': PutChar((char)(va_arg(ArgPtr,int))); break;

/* %d is for decimal integer */


case 'd': case 'D':
if(width) put10(va_arg(ArgPtr,unsigned),width);
else putdecimal(va_arg(ArgPtr,unsigned));
break;

/* %x is for hex */
case 'x': case 'X':
// Build running additive checksum for hex value prints before
// ArgPtr gets advanced to the next argument

629
The C Programs

HexSum += *ArgPtr;
if (width) put16(va_arg(ArgPtr,unsigned),width);
else puthex(va_arg(ArgPtr,unsigned));
break;

/* %s is for string */
/* This is recursive, the string might have format codes in it ! */
case 's': case 'S': printf(va_arg(ArgPtr,char far *)); break;

/* %p is for pointer 0000:0000 */


case 'p': case 'P': putptr(va_arg(ArgPtr,unsigned long)); break;
break;

case 'a': case 'A': /* put printable alphanumeric else "." */


c = (char)(va_arg(ArgPtr,int));
PutChar((char)(IsPrint(c) ? (c) : '.'));
break;

/* %q is print only if cold-boot */


case 'q': if(!cold()) print_flag = False; break;

/* %w is print if WatchFlag is on */
case 'w': case 'W':
if (!WatchActive()) print_flag = False;
break;

/* %n is print if SnapFlag is on */
case 'n': case 'N':
if (!SnapActive()) print_flag = False;
break;

case '%': PutChar('%'); break;

default:
// unrecognized format specifier
break;
}
}
break;

case '\\': /* this processes unconverted "magic" numbers */


if(*FormatPtr)
{
c = *FormatPtr++;
switch(c)
{
case 'n': PutChar('\n'); /* fall through to '\r' */
case 'r': PutChar('\r'); break;
case 't': PutChar('\t'); break;
case 'v': PutChar('\v'); break;
case 'b': PutChar('\b'); break;
case 'f': PutChar('\f'); break;
case 'a': PutChar('\a'); break;
case 0x27: PutChar('\''); break;
case '"': PutChar('\"'); break;
case 0x5c: PutChar('\\'); break;

630
Introduction to AutoBios

case '%': break;


default: PutChar(c); break;
}
}
break;

default:
if (c == '\n') { PutChar('\n'); PutChar('\r'); } else PutChar(c);
break;
}
}
return(HexSum & 255);
}

// print the implied string

unsigned printsnapstring(char far * StringPtr)


{
printf("%n%s", StringPtr);
}

631
Introduction to AutoBios

7.19 The Pause Function


This function displays a message, and waits until a key is pressed. It may be used to improve readability
for multi-screen displays.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Display Pause routine
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] PAUSE.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/*---------- pause and wait for key ---------*/

void Pause(void)
{
while(kbhit()) { GetChar();}; // get any pending keys
printf("\n>--- Hit Any Key to Continue ---<");
while(!kbhit()) { }; GetChar();
}

633
Introduction to AutoBios

7.20 The KbHit Function


This function does a wait until a key is depresssed.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Check for key depressed routine
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] KbHit.c
//
// [Language]MSVC 1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"
/*
** check to see if any key present at console device --
** returns true if a key waiting
*/

unsigned kbhit(void)
{
_asm
{
mov ax,0x0100
int 0x16
mov ax,False
jz kbno
mov ax,True
kbno:
};
}

635
The C Programs

636
Introduction to AutoBios

7.21 The StrTok Function


The String to Token function analyzes a text string, and is used to separate the string into tokens, as
defined by a delimiter list. It is used in parsing a command string.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] String to Token Routine
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] StrTok.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
// StrTok examines a string, detecting a series of zero or more tokens
// separated by one or more control characters from the Control list
// of separators. The first call is made with the pointer to the string
// to be examined, and the separation character following the token
// is replaced with a null to mark the end of the token. A pointer to
// the beginning of the token is returned. The value of NextToken is also
// updated to point to the next token in the string. Subsequent calls
// are made with String = NULL, and the NextToken value is used to advance
// through the string until no more tokens remain, in which case, a NULL
// is returned.
//
// This routine is an adaptation of the standard library function,
// modified for re-entrancy for Bios use.
//
// [Arguments]
// A pointer to the string, a pointer to the separation characters list,
// and a pointer to the intermediate NextToken save location.
// [Return]
// A far pointer to the detected token, and an updated NextToken value.
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

// I N C L U D E F I L E S

#include "Bios.h"

// P R O G R A M

637
The C Programs

char far * StrTok(VueRegSet,char far * String)


{
// if a string was not specified, use the saved pointer
if (!String) String = Me->NextTokenPtr;

// If NextTokenPtr value was bad, get out !!


if(!String) return(NULL);

// Increment the string pointer to the next non-delimiter


while (StrChr(DelimiterList,*String) && *String) String++;

// Save the pointer as the start of this token


Me->ThisTokenPtr = String;

if(!*String) return(NULL); // end of string found

// find end of this token


while(!StrChr(DelimiterList,*String) && *String) String++;

// If not at end of string, insert a 0 at end of token,


// and remeber next char position
if(*String == '\0') String = 0; else *String++ = '\0';

// Save the beginning of the next token


Me->NextTokenPtr = String;

// Return the pointer to the current argument


return(Me->ThisTokenPtr);
}

//-------------------------------------------------------

638
Introduction to AutoBios

7.22 The StrStr Function


The String in a String function looks for the existence of one string in a second string.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] String in a String Function
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] StrStr.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
// char far *StrStr(char far *string1,char far *string2)
// checks to see if string2 occurs in string1.
// If true, it returns a pointer to the location in string1.
// If not, it returns a NULL.
//
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* P R O G R A M */

// locate string p occuring somewhere in string s

char far *StrStr(char far *s,char far *p)


{
if (*p != EOS)
{
while ((s = StrChr(s,*p)) != NULL)
{
if (StrMatch(s,p) != NULL) return(s);
};
};

639
The C Programs

return(NULL);
}

640
Introduction to AutoBios

7.23 The StrCmp Function


The String Compare function checks two text string for equality. This function is case-insensitive.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] String Compare Function
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] StrCmp.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] Compare the two strings for lexical order. Ends the
// [Description] comparison when the following occurs: (1) strings
// [Description] differ, or (2) the end of the strings is reached.
// [Description] For the purposes of the comparison, upper case
// [Description] characters are converted to lower case.
//
// unsigned StrCmp(char far *stringa, char far *stringb)
//
// Exit values:
// returns True if strings compare
// returns False if strings do not compare
//
// This is somewhat similar to the standard function "strnicmp"
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* P R O G R A M */

unsigned StrCmp (char far *p, char far *s)


{
while(*p && *s)
{ if(ToUpper(*p++) != ToUpper(*s++)) return(False); };
if(ToUpper(*p) == ToUpper(*s)) return(True);
return(False);
}

641
The C Programs

642
Introduction to AutoBios

7.24 The Print Screen Driver


The Print Screen Function is used to print the screen contents to LPT1.
Some additions and enhancements could be:
 Creating an "active_printer" flag (in system ram) which could be used to direct screen prints to LPT2
or LPT3.
 Providing a screen print function to output on a serial channel.
 Using this module as a guideline for creating a print-screen to disk-file applications program.
There are various public-domain print-screen functions which support video adapters other than MDA
and CGA. An EGA print-screen routine for instance, has been circulated on various Bulletin Board
Systems. The logic of one of these could be adapted to replace the standard print screen function, if
desired.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Print Screen function
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] PrtScr.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] Interrupt 0x05 - Print Screen Handler
// This module copies the contents of the screen buffer to the printer.
//
// [Arguments] None
//
// [Return] None
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

unsigned LptPrint(char,unsigned);

643
The C Programs

/* G L O B A L S */

#define Device DeviceMaskPrtScr

/* P R O G R A M */

unsigned PrintScreenSetup(ActionArgument)
{
struct _BiosRam far * LowRam = 0;
struct _BiosObject far * Bios = GetBiosObject();
struct _PrtScrRegs far * Me;

LoadDS();

#if !CfgPrintScreen
LowRam->IntVector[0x05]= (void near *) DummyIret;
return(SetupStatusStub);
#else
LowRam->IntVector[0x05]= (void near *) PrintScreenFunctionCall;
Bios->DevicesInstalled |= Device;
return(SetupStatusOK);
#endif
}

#if CfgPrintScreen
void PrtScrCall(struct _IRegs far * Regs);

void interrupt far PrintScreenFunctionCall(InterruptRegisters)


{
InterruptEnvelope(PrtScrCall,DevicePrtScr,0);
};

void PrtScrCall(struct _IRegs far * Regs)


{
#if CfgPrintScreen
struct _BiosRam far * LowRam = 0;
unsigned OldCursor;
char Row,Col,CurrentChar,ColumnsPerLine;
unsigned Error;
unsigned Busy;

_enable();

/* Check to see if we are Recursing and will need another Object */

Error = False;

if (!Busy) /* check status byte */


{
Busy = True; /* set status = busy */
ColumnsPerLine = (char)VideoGetCols();

/* send cr-lf */
if(LptPrint(0,0x0d) & 0x01) Error = True;
else if(LptPrint(0,0x0a) & 0x01) Error = True;

644
Introduction to AutoBios

/* read and save old cursor position, reset cursor to 0,0 */


OldCursor = VideoGetCursor(); VideoSetCursor(0);

for (Row = 0; (Row < 25) && !Error; Row++)


{
for (Col = 0; (Col < ColumnsPerLine) && !Error; Col++)
{
/* set cursor position */
VideoSetCursor((Row << 8) | Col);
/* read character at cursor */
CurrentChar = (char)VideoReadAC(0);
/* print character */
if (CurrentChar == 0) CurrentChar = 0x20;
if(LptPrint(0,CurrentChar) & 0x01) Error = True;
}
/* do the cr-lf at end of Columns */
if(LptPrint(0,0x0d) & 0x01) Error = True;
else if(LptPrint(0,0x0a) & 0x01) Error = True;
}
/* reset cursor to original position */
VideoSetCursor(OldCursor);
/* clear status = not busy, FF = print error */
if(Error) Busy = True; Busy = False;
}
#endif
}

unsigned LptPrint(char c,unsigned port)


{
_asm push dx
_asm xor ah,ah
_asm mov al,c
_asm mov dx,port
_asm int 0x17
_asm mov al,ah
_asm xor ah,ah
_asm pop dx
};

#endif

645
Introduction to AutoBios

8. SysVue
This section includes the top SysVue File, and the supporting command files.

8.1 The SysVue Program


The SysVue.c file is the source code for SysVue, the resident monitor/debugger program. SysVue allows
the user to gain access to the system features from any program. If the bootstrap operation is
unsuccessful, program control may be automatically transferred to SysVue.
SysVue has some Watch features built-in to assist in development/debugging. The "Watch" command is
used to set and clear specific bits in the watch selection variable. These bits are checked when "watch" is
"on" and display commands embedded in the various function routines are enabled. These display
commands are:
"printf("%wtext");
These watch commands check to see if the corresponding "device" bit is set in the watch flag variable. If
so, the command is executed. When developing and debugging code, this feature is extremely handy.
For a final version, one may wish to delete the watch calls (see Commom.Plt) to save space and increase
speed.
The SysVue "SI" command is used to display pertinent data about the Bios and the system. It is
especially handy for tech support communications, allowing the user to use the "SI" command to display
and convey commonly requested information to the technically oriented person. Since it also shows
configuration information, it permits a quick peek at the current system configuration.
The system Setup is accomplished by the use of the:
 "Time" and "Date" commands to set the clock\calendar
 "Drive" to set the number and type of floppy and hard drives
 "Video" to set the type of video adapter
 "Mem" to set the size of system and extended memory
 "Npx" to declare the presence of the numeric processor
 "Types" to display the hard disk types in the resident type table
 "Cmos" to display the checksum value of the CMOS RAM
The redirection command ">",">con",">lpt" are used to copy the screen output to a printing device. This
allows generating audit trails when involved in debugging, and with "watch" enabled, can provide a
wealth of data concerning internal Bios operation. Since one can re-compile the Bios with additional
"watch_xxx()" commands, debugging aids can easily be placed where desired.
The "Trace" and "e" (for execute) commands allow a detailed single-step trail to be generated when
required. Once a problem area is located with "watch" features, this single stepping can provide lowest
level tracing of system action. Single stepping does NOT sense when the stack-segment or stack-pointers
are changed, so unpredictable results may occur when these registers are changed.

647
The C Programs

The "Int" command allows the execution of an interrupt, using the register values set with the "Rxx"
commands. This permits specialized execution of bios functions from within sysvue. With the watch
function enabled, this is a handy debugging aid.
SysVue may also be expanded with new commands as desired.
An easy way for you to generate documentation of your version of SysVue is to use the ">LPT"
command to provide hard copy of the various screens and menus. These printouts may then be integrated
into the user documentation you create.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Bios version of SysVue
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] SysVue.C
//
// [Language] MSVC 1.5
//
// [Description] This is the SysVue module which is a Bios-resident
// [Description] debug/monitor program.
//
// NOTE:
// Entry to SysVue is by CTRL-ALT-BREAK.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

//void interrupt far SysTrace(InterruptRegisters);

void syntax_error(VueRegSet);
static unsigned ExecuteCommand(void far *);

/* G L O B A L V A R I A B L E S */

648
Introduction to AutoBios

/*------ external data (variables) declarations ---------*/

/* G L O B A L C O N S T A N T S */

/* L O C A L D E F I N I T I O N S */

/* L O C A L C O N S T A N T S */

// this is a list of the commands for SysVue

char near * NullString = "";

void NoCommand(VueRegSet) { printf("\nNo Such Command"); };

struct SysVueCommandList CommandList[] =


{
{ "Break"," Use Ctrl-X to Break into SysVue",CmdHelp, },
{ "HELP"," | ? | /H | /HELP - help screen",CmdHelp, },
{ "?"," after any Command will display help for that command",CmdHelp, },
{ "/H","",CmdHelp, },
{ "/HELP","",CmdHelp, },
{ "CHIP"," displays the Chip Configuration Registers",CmdChip, },
{ "X"," - Object Dump - Display Active Object Information",CmdObjectDump, },
{ "B"," - Boot Sector Dump",CmdBootDump,},
{ "C","[A][B][W][D] <range> <address> - compare",CmdCompare, },
{ "CA","",CmdCompareAscii, },
{ "CB","", CmdCompareByte, },
{ "CW","",CmdCompareWord,},
{ "CD","",CmdCompareDouble,},
/* {"CHK"," <range> - checksum",CmdChecksum, }, */
{ "CLS"," - Clear Screen", CmdCLS, },
{ "CMOS"," - display the CMOS checksum",CmdCmos,},
{ "COLD"," - (Ctl-Alt-Del) equivalent, with Sign-On Messages",CmdColdBoot, },
{ "DATE"," [xx xx xxxx] - Display or Set Date", CmdDate, },
{ "D","[A][B][W][D][<range>] - dump memory",CmdDump, },
{ "DA","",CmdDumpAscii,},
{ "DB","",CmdDumpByte,},
{ "DW","",CmdDumpWord,},
{ "DD","",CmdDumpDouble,},
{ "DEVICES"," display installed drivers (devices)",CmdDevices, },
{ "DEV","",CmdDevices, },
{ "DRIVE"," [0-3 | A-D] [type] - display/set drives",CmdDrive, },
{ "DRIVES","",CmdDrive, },
{ "E","[A][B][W][D] <address> [<list>] - enter",CmdEnter, },
{ "EA","",CmdEnterAscii,},
{ "EB","",CmdEnterByte,},
{ "EW","",CmdEnterWord,},
{ "ED","",CmdEnterDouble, },
{ "EXIT"," - exit from SysVue",CmdExit, },
{ "F","[A][B][W][D] <range> <list> - fill",CmdFill, },
{ "FA","",CmdFillAscii,},
{ "FB","",CmdFillByte,},
{ "FW","",CmdFillWord,},
{ "FD","",CmdFillDouble,},
{ "H"," <value> <value> - hex add/sub",CmdHex, },

649
The C Programs

{ "I","[B][W] <address> - In port",CmdInPort, },


{ "IN","",CmdInPort, },
{ "IB","",CmdInPortByte,},
{ "IW","",CmdInPortWord,},
{ "INCMOS"," <address> - Read a CMOS location",CmdInPortCmos, },
{ "IC","",CmdInPortCmos, },
/* { "INT"," <value> - Interrupt",CmdInterrupt, }, */
{ "LOG"," [All|None|No|Off|On|List|Device Name(s)..] - Enable/Disable
Logging",CmdLog, },
{ "M"," <range> <address> - move",CmdMove, },
{ "MEM"," [sys,ext] - display/set memory sizes",CmdMem, },
/* { "MEMTEST"," run a quick dual-bank pattern check",CmdMemTest, }, */
/* { "MODE"," Select 16/32 Register-Display mode for 386 and
above"",CmdMode1632, }, */
{ "O","[B][W] <address> <value> - Out port",CmdOutPort, },
{ "OUT","",CmdOutPort, },
{ "OB","",CmdOutPortByte,},
{ "OW","",CmdOutPortWord,},
{ "OUTCMOS"," <address> <value> - Write a CMOS location",CmdOutPortCmos, },
{ "OC","",CmdOutPortCmos, },
{ "ORDER"," [A|C] - Boot device to try first",CmdOrder, },
{ "QUIT"," - exit from SysVue",CmdExit, },
{ "R","[[reg] [value]] - Display/Change CPU Registers",
CmdRegDisplay, },
{ "REG","", CmdRegDisplay, },
{ "RAX","",CmdRAX,},
{ "RBX","",CmdRBX,},
{ "RCX","",CmdRCX,},
{ "RDX","",CmdRDX,},
{ "RSP","",CmdRSP,},
{ "RBP","",CmdRBP,},
{ "RSI","",CmdRSI,},
{ "RDI","",CmdRDI,},
{ "RDS","",CmdRDS,},
{ "RES","",CmdRES,},
{ "RSS","",CmdRSS,},
{ "RCS","",CmdRCS,},
{ "RIP","",CmdRIP,},
{ "RF" ,"",CmdRF, },
{ "RHEX"," <range> - read Intel hex",CmdRHex, },
{ "SCAN"," - Run Test Rom-Scan for Video & Adapters",CmdScan, },
{ "SI"," - Display System Information",CmdSysInfo, },
{ "S","[A][B][W][D] <range> <key> <mask> - search",CmdSearch, },
{ "SA","",CmdSearchAscii,},
{ "SB","",CmdSearchByte,},
{ "SW","",CmdSearchWord,},
{ "SD","",CmdSearchDouble,},
{ "SNAP"," [All|None|No|Off|On|List|Device Name(s)..] - Enable/Disable
Snapshots",CmdSnap, },
{ "TIME"," [xx xx xx] - Display or Set Time",CmdTime, },
/* { "T","",CmdTrace,}, */
/* { "TRACE"," [count] - Trace count steps or until anykey hit",CmdTrace, },
*/
{ "TYPE"," Display the Hard Drive Type Table",CmdTypes, },
{ "TYPES","",CmdTypes, },

650
Introduction to AutoBios

{ "USER"," [47|48] [Cyls,Heads,Sectors] - Display/Set the User Hard Drive


Parms",CmdUser, },
{ "V"," Dumps the Interrupt Vector List",CmdVectors, },
{ "VIDEO"," Display/Set the Expected Video Display Device Type",CmdVideo, },
{ "WATCH"," [All|None|No|Off|On|List|Device Name(s)..] - Enable/Disable
Watches",CmdWatch, },
{ "WARM"," - (Ctl-Alt-Del) equivalent, without Sign-On Messages",CmdWarmBoot,
},
{ "WHEX"," <range> - write Intel hex",CmdWHex, },
{ ">LPT","> - redirect console output",CmdToLpt, },
{ ">CON","> - redirect console output",CmdToCon, },
{ ">","",CmdToCon,},
{ "","",NoCommand,}, /* list terminator */
{ 0,0,0,},
};

/* This table is used for register token-value searches */

// This is a list of the delimiter characters to be accepted when


// parsing command lines. A zero value marks the end of the list.

char DelimiterList[]= { ' ',',',0 };

/* P R O G R A M */

#define Device DeviceMaskSysVue

/*========= SysVue Setup Routine ==========*/

// This routine is called by the POD to effect the installation of SysVue by


patching Interrupt 18.

unsigned SysVueSetup(ActionArgument)
{
VueRegSet;
struct _BiosRam far * Vectors = 0;
struct _SystemObject far * System = GetSystemObject();
struct _BiosObject far * Bios = GetBiosObject();

/* Setup a Default SysVue Object */

Me = (struct _SysVueObject far


*)AcquireObject(SysVueObject,"SysVueObject",SysVueObjectType);
Me->ObjectStatusFlags.InUse = False;
Me->ObjectStatusFlags.Permanent = True;
System->SysVueObjectPtr = Me;

Bios->FlagMaster[Snap].Master = SnapMasterPattern;
Bios->FlagMaster[Watch].Master = WatchMasterPattern;

_disable();
Vectors->IntVector[0x18]= (void near *) SysVue;
_enable();
Bios->DevicesInstalled |= Device;

651
The C Programs

return(SetupStatusOK);
}

/*==============================================*/
/*==============================================*/
/*======= SysVue Main Routine ==================*/
/*==============================================*/
/*==============================================*/

void SysVueMain(struct _IRegs far * Regs);

// Entry from a Divide Error

void interrupt far Divide(InterruptRegisters)


{
InterruptEnvelope(SysVueMain,0,OriginDivide);
};

// Entry from the BreakKey


void interrupt far SysBreakKey(InterruptRegisters)
{
InterruptEnvelope(SysVueMain,0,OriginBreakKey);
};

// Entry from a SysError


//void interrupt far SysError(InterruptRegisters)
//{
// InterruptEnvelope(SysVueMain,0,OriginSysError);
//};

// Entry from an Interrupt 18


void interrupt far SysVue(InterruptRegisters)
{
InterruptEnvelope(SysVueMain,0,OriginBoot);
};

// Entry from a Trap (Int 3)


void interrupt far SysTrap(InterruptRegisters)
{
InterruptEnvelope(SysVueMain,0,OriginTrap);
};

// Entry from a single step interrupt


void interrupt far SysTrace(InterruptRegisters)
{
InterruptEnvelope(SysVueMain,0,OriginTrace);
};

// Entry from a SysKey


void interrupt far SysKey(InterruptRegisters)
{
InterruptEnvelope(SysVueMain,0,OriginKey);
};

void SysVueMain(struct _IRegs far * Regs,unsigned device,unsigned origin)

652
Introduction to AutoBios

{
register i;
struct _BiosRam far * Vectors = 0;
struct _SystemObject far * System = GetSystemObject();
struct _SysVueObject far * Me = System->SysVueObjectPtr;
void far * OldMe;

/* If no block exists, or existing block is in use, Allocate one */


if((!Me) || Me->ObjectStatusFlags.InUse)
{
OldMe = Me; /* Save pointer to current object */
Me = (struct _SysVueObject far
*)AcquireObject(SysVueObject,"SysVueObject",ProcessObjectType);
Me->OldMe = OldMe; /* save so we can Decurse */
if(!System->SysVueObjectPtr) Me->ObjectStatusFlags.Permanent = True;
System->SysVueObjectPtr = Me;
}
Me->ObjectStatusFlags.InUse = True;
Me->RegsPtr = Regs;
Me->BiosObjectPtr = System->Bios_Ptr;

_enable();

if(Me->SysVueBusy) printf("\nSysVue Already Active");


else
{
/* variables will be referenced in sys seg */
Me->ExitFlag = False;
Me->SysVueBusy=True;

// chain the break vector through SysVue logic: if the break flag is
// set by the sysbreak isr, return a true from the csts routine to
// abort the op in progress. when exiting SysVue: de-chain the vector
// back to the original state for normal operation.

_disable();
Me->SysVueBreakChain = Vectors->IntVector[0x1B];
Vectors->IntVector[0x1B]= (void near*)SysBreak;
_enable();

if(NameExists(origin,OriginList))
printf("\nSysVue entered from %s Origin",GetName(origin,OriginList));

// move the stacked registers into the saves so we know where we came from

//printf("\nSaving Registers");
//MemCpy(&Me->RegSaves,Regs,sizeof(struct _IRegs));
//printf("\nSaving Registers Complete");

if(origin == OriginTrace) // de-chain trace vector


{
// set_vector(0x1,FP_OFF(BiosObject->SysVueTraceChain),FP_SEG(BiosObject-
>SysVueTraceChain));

// if(peek(0x26a,0x316) == 0x0beb)
//{

653
The C Programs

// place for option of silent trace until condition


// Me->TraceCount = 1;

DisplayRegistersAndFlags(Regs);
//printf("\n %4x:%4x %2x %2x",Regs->RegCS,Regs->RegIP,
//MK_FP(Regs->RegCS,Regs->RegIP),MK_FP(Regs->RegCS,Regs->RegIP+1));
// lword(cs);printf(":");lword(ip);printf(" ");
// lbyte(peekb(cs,ip));
// printf(" ");
// lword(peek(cs,ip+1));

//}
if(--Me->TraceCount != 0)
{
if(ConsoleBreak())
{
Me->ExitFlag = False;
Me->TraceCount=1;
}
else
{
// check for any key
if (kbhit())
{
Me->ExitFlag = False;
Me->TraceCount=1;
}
else
{
Me->ExitFlag = True;
//Me->RegSaves[pswsave] |= 0x0100; // set trace bit
// chain-in the trace vector
_disable();
Me->SysVueTraceChain = Vectors->IntVector[0x01];
Vectors->IntVector[0x01]= (void near *)SysTrace;
_enable();
}
}
}
}

if(origin == OriginTrap) // de-chain trap vector


{
// restore the trapped locations and decrement the pc value
// clear the trap saves and stuff
}

if(origin == OriginBoot)
{
Me->TraceCount = 1;
// restore the trapped locations and decrement the
// pc value
// clear the trap saves and stuff
}

Me->ModeSize = SizeIsByte; /* default to byte presentation mode */

654
Introduction to AutoBios

Me->ModeType = TypeHex; /* default to hex (not ascii) */


if(origin == OriginBoot)
{
printf("\nSysVue Copyright (c) John O. Foster 1988-1994 - All Rights
Reserved.");
}

if(origin == OriginDivide)
{
printf("\nDivide Overflow at location - %4x:%4x",Regs->RegCS,Regs->RegIP);
}

if(origin == OriginSysError)
{ printf("\nSystem Error, Type - %4x",Regs->RegAX); }

//======= this is the main loop to get commands =========

while (!Me->ExitFlag)
{
printf("\nSysVue>");
gets(Me->LineBuffer,sizeof(Me->LineBuffer),'\r');

if(Me->ArgC = BuildArguments(Me))
{
/* execute the command */
if(!ExecuteCommand(Me)) printf("\nUnrecognized Command");
}
else
{ printf("\nNo Command Seen"); }
}

//======= end of the main loop to get commands =========

// If tracing, we should link the trace vector here

// If trapping (breakpointing), we should link the trap vector here.

// set_vector(0x1b,FP_OFF(BiosObject->SysVueBreakChain),FP_SEG(BiosObject-
>SysVueBreakChain));

Me->ObjectStatusFlags.InUse = False;
Me->SysVueBusy = False; /* release Sysvue */

_disable();
Vectors->IntVector[0x1B]= Me->SysVueBreakChain;
_enable();
}
}

//======================================================================
//--- This function checks the command list, and executes the command --

unsigned ExecuteCommand(VueRegSet)
{
void (near * funct_ptr) (VueRegSet); unsigned j = 0;

655
The C Programs

while(StrLen(CommandList[j].CmdName)) /* look through the list */


{
if (StrCmp(Me->ArgV[0], CommandList[j].CmdName))
{
/* Any command followed by a ? mark will call one-line help */
if(StrCmp(Me->ArgV[1],"?")) printf("\b%s",CommandList[j].CmdHelpString);
else
{
funct_ptr = CommandList[j].Cmd; (* funct_ptr) (Me);
};
return(True);
}
j++;
};
return(False);
}

/*=========== Exit Commands ============*/

void CmdExit(VueRegSet) { printf("\nExiting SysVue"); Me->ExitFlag = True; };

/* dummy nmi interrupt routine */

void nmi_int(VueRegSet) { ; }

void syntax_error(VueRegSet) { printf("\nSyntax Error"); };

//-------------------------------------------------------------

656
Introduction to AutoBios

8.2 The SysVue Command Routines

8.2.1 The Calc Command


Calc acts as a simple hex calculator in that it returns the sum and the difference of two numbers entered as
arguments.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Calculator Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdCalc.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*========== Calculator Command =========*/

void CmdHex(VueRegSet)
{
printf("\n Sum is: %4x",Me->Token[1].Value.LongValue +
Me->Token[2].Value.LongValue);
printf("\nDifference is: %4x",Me->Token[1].Value.LongValue -
Me->Token[2].Value.LongValue);
}

657
Introduction to AutoBios

8.2.2 The Chksum Command


Chksum displays the calculated checksum and the stored checksum of the CMOS data included in the
checksum area. This is generally from cell 20 to cell 3f. It then allows the user to elect to update the
stored checksum if desired.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Checksum Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdChksm.c.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*========= Checksum Command ===========*/

void CmdChecksum(VueRegSet)
{
unsigned char sum = 0;
while ((Me->Token[0].Value.LongValue <=
Me->Token[1].Value.LongValue) && !ConsoleBreak());
{
sum += *Me->Token[0].Value.CharPtr++;
};
printf("\nChecksum = %2x",sum);
}

659
The C Programs

660
Introduction to AutoBios

8.2.3 The Chip Command


This command dumps the contents of the chipset defined for the Bios. Included in the dump is the name
and address of the register, present contents, and default value. An equivalent dump routine is also built
as a standalone executable file.

//***********************************************************************
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Chip Dump Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdChip.C
//
// [Description] This module dumps the contents of the chipset used.
//
// [History] 2.00 04/11/94 Original
//
//**********************************************************************

#include "Bios.h"
#include "chipc.tmp"

void CmdChip()
{
unsigned LineCounter = 1;
unsigned i = 0;
printf("\n%s Dump",ChipID);
printf("\nReg = Default Val Description");
while(StrLen(DumpList[i].ItemName))
{
printf("\n%2x = %2x %2x %s",
DumpList[i].ItemAddress,
DumpList[i].ItemDefault,
ReadChipRegister(DumpList[i].ItemAddress,
DumpList[i].ItemSize),
DumpList[i].ItemDescription);
if(!(LineCounter++ % 16)) Pause(); /* pause when the screen is full */
i++;
};
};

661
The C Programs

662
Introduction to AutoBios

8.2.4 The Cmos Command


Cmos display the contents of the CMOS data area, along with descriptive information about the locations.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue CMOS Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdCmos.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//--------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*=========== CMOS Command ================*/


void CmdCmos(VueRegSet)
{
unsigned sum,i,j,k;
unsigned LineCounter = 0;
i = 0;
printf("\nReg# Value Name");
while(StrLen(CmosList[i].Name))
{
printf("\n %2x = %2x %s",
CmosList[i].Value & 0x7f,InCmos(CmosList[i].Value),CmosList[i].Name);
i++;
if(!(++LineCounter % 20)) Pause();
};

sum = 0;
for(j = 0x10; j < 0x2e; j++) { sum += InCmos(j); }

663
The C Programs

printf("\nCalculated CMOS checksum: %4x",sum);


printf("\n Actual CMOS checksum: %2x%2x",
(InCmos(CmosRegChecksumHigh)),InCmos(CmosRegChecksumLow));
printf("\nDo you want to Re-calculate the CMOS Checksum (Y/N) ? :");
if(ToUpper(GetCharEcho()) == 'Y')
{
printf("\nRe-calculating CMOS Checksum .....Done");
OutCmos(CmosRegChecksumLow,sum);
OutCmos(CmosRegChecksumHigh,sum >> 8);
}
}

664
Introduction to AutoBios

8.2.5 The Clear Screen Command


CLS does a secreen clear, repositioning the cursor at the top left of the screen.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Clear Screen Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdCLS.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/*======= Clear Screen Command ===========*/

void CmdCLS(VueRegSet)
{
#if CfgANSI
printf("\033[2J");
#else
VideoSetMode(VideoGetMode());
#endif
};

665
Introduction to AutoBios

8.2.6 The Comp Command


The Compare command compares the data in two blocks of memory and displays the differences.

//----------------------------------------------------------------------
//

// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.


//
// [Product Name] AutoBios
//
// [Module Name] SysVue Compare Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdComp.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [History] 2.00 04/11/94 Original
//
//--------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/*============ COMPARE COMMANDS =======*/

void CmdCompareAscii(VueRegSet)
{ Me->ModeSize = SizeIsByte; Me->ModeType = TypeAscii; CmdCompare(VueSet); };

void CmdCompareByte(VueRegSet)
{ Me->ModeSize = SizeIsByte; Me->ModeType = TypeHex; CmdCompare(VueSet); };

void CmdCompareWord(VueRegSet)
{ Me->ModeSize = SizeIsWord; Me->ModeType = TypeHex; CmdCompare(VueSet); };

void CmdCompareDouble(VueRegSet)
{ Me->ModeSize = SizeIsLong; Me->ModeType = TypeHex; CmdCompare(VueSet); };

void CmdCompare(VueRegSet)
{
//printf("\nReached compare routine");
while ((Me->Token[1].Value.LongValue <= Me->Token[2].Value.LongValue) && !
ConsoleBreak())
{
if(Me->ModeType == TypeAscii)
{
//printf("\nComparing Ascii");

667
The C Programs

if (*Me->Token[1].Value.CharPtr != *Me->Token[3].Value.CharPtr)
{
printf("\n%p > %c %c < %p",
Me->Token[1].Value.LongValue,*Me->Token[1].Value.CharPtr,
*Me->Token[3].Value.CharPtr, Me->Token[3].Value.LongValue);
}
/* Point to the next location */
Me->Token[1].Value.CharPtr++; Me->Token[3].Value.CharPtr++;
}
else
{
switch(Me->ModeSize)
{
default:
case SizeIsByte:
//printf("\nComparing Bytes");
if (*Me->Token[1].Value.CharPtr != *Me->Token[3].Value.CharPtr)
{
printf("\n%p > %2x %2x < %p",
Me->Token[1].Value.LongValue, *Me->Token[1].Value.CharPtr,
*Me->Token[3].Value.CharPtr, Me->Token[3].Value.LongValue);
}
/* Point to the next location */
//printf("\nIncrementing Pointers");
Me->Token[1].Value.CharPtr++; Me->Token[3].Value.CharPtr++;
break;

case SizeIsWord:
//printf("\nComparing Words");
if (*Me->Token[1].Value.WordPtr != *Me->Token[3].Value.WordPtr)
{
printf("\n%p > %2x %2x < %p",
Me->Token[1].Value.LongValue, *Me->Token[1].Value.WordPtr,
*Me->Token[3].Value.WordPtr, Me->Token[3].Value.LongValue);
}
/* Point to the next location */
Me->Token[1].Value.WordPtr++; Me->Token[3].Value.WordPtr++;
break;

case SizeIsLong:
//printf("\nComparing Longs");
if (*Me->Token[1].Value.LongPtr != *Me->Token[3].Value.LongPtr)
{
printf("\n%p > %2x %2x < %p",
Me->Token[1].Value.LongValue, *Me->Token[1].Value.LongPtr,
*Me->Token[3].Value.LongPtr, Me->Token[3].Value.LongValue);
}
/* Point to the next location */
Me->Token[1].Value.LongPtr++; Me->Token[3].Value.LongPtr++;
break;
}
}
}
//printf("\nExiting Compare");
}

668
Introduction to AutoBios

669
Introduction to AutoBios

8.2.7 The Date Command


The Date command displays the current date, and allows a new date to be entered.

//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Date Command
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdDate.C
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*------- set date -------------*/

void CmdDate(VueRegSet)
{
unsigned Month,Day,Year;
if(Me->ArgC > 1) // if anything entered
{
printf("\nGoing to Parse: %s",Me->ArgV[1]);
Month = ParseDigitString(Me->ArgV[1],1);
Day = ParseDigitString(Me->ArgV[1],2);
Year = ParseDigitString(Me->ArgV[1],3);
printf("\n%2d:%2d:%2d",Month,Day,Year);

if(!ClockSetDate(Month,Day,Year)) printf("Error setting date");


}

printf("\nCurrent Date is - ");DisplayDate();


}

671
The C Programs

672
Introduction to AutoBios

8.2.8 The Drives Command


The Drives command displays the hard and floppy drive assignments, and allows them to be changed or
updated.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Disk Drives Command
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdDrive.C
//
// [Description]
//
// NOTE:
// Entry to SysVue is by CTRL-ALT-BREAK.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*------- set drives -----------*/

void CmdDrive(VueRegSet)
{
register Temp,DecValue;
unsigned Mask, Key, HardCell;

unsigned DiskMaskTable[2] = { 0x70, 0x07, };


unsigned HardMaskTable[2] = { 0xf0, 0x0f, };
unsigned HardCellTable[2] =
{ CmosRegExtendedDriveC, CmosRegExtendedDriveD, };

if(Me->ArgC > 1) /* There were command line arguments */


{
switch((unsigned char)*Me->ArgV[1])
{

673
The C Programs

case 'A':
case 'B':
if(NameExists(Me->ArgV[2],DiskList))
{
Temp = *Me->ArgV[1] - 'A';
Key = GetValue(Me->ArgV[2],DiskList); Key |= (Key << 4);
Mask = DiskMaskTable[Temp]; Key &= Mask;
ResetCmosBits(CmosRegDiskDriveType,Mask);
SetCmosBits(CmosRegDiskDriveType,Key);
}
else
{
beep();
return;
};
break;

//------- these are for hard disks ---------

case 'C':
case 'D':
Temp = *Me->ArgV[1] - 'C';
HardCell = HardCellTable[Temp];
if(IsDecimalString(Me->ArgV[2]))
{
DecValue = AsciiToDec(Me->ArgV[2]);
if(DecValue < 49)
{
if(DecValue > 15) { Key = 15; }
else
if(DecValue < 15) { Key = DecValue; DecValue = 0; }
else
if(DecValue == 15) { Key = 0; DecValue = 0; };

Key |= (Key << 4);


Mask = HardMaskTable[Temp]; Key &= Mask;

ResetCmosBits(CmosRegHardDriveType,Mask);
SetCmosBits(CmosRegHardDriveType,Key);
OutCmos(HardCell,DecValue);
} else beep();
} else beep();
break;

if(InCmos(CmosRegDiskDriveType) != 0)
SetCmosBits(CmosRegEquipment,0x01);
else
ResetCmosBits(CmosRegEquipment,0x01);

};
CalcCmosChecksum(); // recalc checksum
}
printf("\nOptions for Drive A: and B: are:\n");
PrintNames(DiskList);
printf("\nOptions for Hard drives C: and D: are Type 0 - 48");
printf("\nFor list of hard drive types, enter ""Types""");

674
Introduction to AutoBios

DisplayDrives();
}

675
Introduction to AutoBios

8.2.9 The Dump Command


Dump displays areas of memory. Data may be displayed as ASCII text, hex bytes, words or doublewords.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Dump Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdDump.C
//
// [Category] SysVue Command Implementation
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* P R O G R A M */

/*============ D Commands =================*/

void CmdDumpAscii(VueRegSet)
{ Me->ModeType = TypeAscii; CmdDump(Me); };

void CmdDumpByte(VueRegSet)
{ Me->ModeSize = SizeIsByte; Me->ModeType = TypeHex; CmdDump(Me); };

//void CmdBootDump(VueRegSet)
//{ Me->ModeSize = SizeIsByte; Me->ModeType = TypeHex; CmdBootDump(Me); };

void CmdDumpWord(VueRegSet)
{ Me->ModeSize = SizeIsWord; Me->ModeType = TypeHex; CmdDump(Me); };

void CmdDumpDouble(VueRegSet)
{ Me->ModeSize = SizeIsLong; Me->ModeType = TypeHex; CmdDump(Me); };

void CmdDump(VueRegSet)
{

677
The C Programs

union
{
void far * Ptr;
unsigned long PtrAsLong;
};

unsigned LineCounter = 1;
unsigned i;
if(!Me->Token[1].ValueMask.LongMask)
Me->Token[1].Value.LongValue = Me->LastDumpSave;

switch(Me->ModeType)
{
case TypeAscii:
// if start and end are the same, then bump the end
if(Me->Token[2].Value.WordValue[1] == Me->Token[1].Value.WordValue[1])
Me->Token[2].Value.LongValue = Me->Token[1].Value.LongValue + 1023;
;

//if(!Me->Token[2].ValueMask.LongMask)
// Me->Token[2].Value.LongValue =Me->Token[1].Value.LongValue + 1023;

while((Me->Token[1].Value.LongValue < Me->Token[2].Value.LongValue)


&& !ConsoleBreak())
{
printf("\n%p ",Me->Token[1].Value.LongValue);

do
{
printf("%a",*Me->Token[1].Value.CharPtr++);
//if(!(LineCounter++ % 20)) Pause(); /* pause when the screen is full */
} while ((Me->Token[1].Value.LongValue % 64));
};
break;

case TypeHex:

//if(!Me->Token[2].ValueMask.LongMask)
// Me->Token[2].Value.LongValue = Me->Token[1].Value.LongValue + 255;

//if(!Me->Token[2].ValueMask.WordMask[1])
// Me->Token[2].Value.WordValue[1] = Me->Token[1].Value.WordValue[1];

// if start and end are the same, then bump the end
if(Me->Token[2].Value.WordValue[1] == Me->Token[1].Value.WordValue[1])
Me->Token[2].Value.LongValue = Me->Token[1].Value.LongValue + 255;
;

while(Me->Token[1].Value.WordValue[0] < Me->Token[2].Value.WordValue[0]


&& !ConsoleBreak())
{
printf("\n%p ",Me->Token[1].Value.LongValue);
do
{

678
Introduction to AutoBios

switch(Me->ModeSize)
{
case SizeIsByte: printf("%2x ",*Me->Token[1].Value.CharPtr++); break;
case SizeIsWord: printf("%4x ",*Me->Token[1].Value.WordPtr++); break;
case SizeIsLong: printf("%p " ,*Me->Token[1].Value.LongPtr++); break;
};
if(!(Me->Token[1].Value.WordValue[0] % 4)) printf(" ");
}
while ((Me->Token[1].Value.LongValue % 16));
printf(" ");
for (i = - 16; i != 0; printf("%a",*(Me->Token[1].Value.CharPtr + i)), i+
+);
if(!(LineCounter++ % 20)) Pause();
};
break;
};
Me->LastDumpSave = Me->Token[2].Value.LongValue + 1;
}

/*----- dump the boot sector ------*/

void CmdBootDump(VueRegSet)
{
unsigned i;

// debug force to boot sector buffer


Me->Token[1].Value.LongValue = 0x00007c00;
Me->Token[2].Value.LongValue = 0x00007dff;
CmdDumpByte(Me);
};

679
Introduction to AutoBios

8.2.10 The Enter Command


Enter is used to input data to selected Ram locations.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Enter Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdEnter.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This is the SysVue Enter Command.
//
// NOTE:
// Entry to SysVue is by CTRL-ALT-BREAK.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

//static void enter(void far *);

/* F U N C T I O N P R O T O T Y P E S */

/*=========== Enter Commands ============*/

// this would be the case for an Execute Command which may not be
// implemented

//void ENTER_(VueRegSet)
//{
//struct _BiosRam far * LowRam = 0;
// struct SYSTEM_Object far * System = GetSystemObject();
//struct BIOS_Object far * BiosObject = System->Bios_Ptr;
// if e<enter> then it is execute else it is enter

681
The C Programs

// if (!Me->ArgV[1]) // e<enter> is execute


// {
//Me->ExitFlag = true;
//Me->TraceCount = -1;
//Me->RegSaves[pswsave] |= 0x0100; // set trace bit
// chain-in the trace vector
//_disable();
//BiosObject->SysVueTraceChain = LowRam->IntVector[0x01];
//LowRam->IntVector[0x01]=SysTrace;
//_enable();
// }

//}

void CmdEnter(VueRegSet)
{
unsigned inchar = ' ',Temp;
if(*Me->Token[2].Value.CharPtr)
{
switch(Me->ModeSize)
{
case SizeIsByte:
*Me->Token[1].Value.CharPtr = Me->Token[2].Value.LongValue;
break;

case SizeIsWord:
*Me->Token[1].Value.WordPtr = Me->Token[2].Value.LongValue;
break;

case SizeIsLong:
*Me->Token[1].Value.LongPtr = Me->Token[2].Value.LongValue;
}
}
else
{
printf("\n%p",Me->Token[1].Value.LongValue);
/* solicit input */
Temp = inchar;

while (Temp == ' ')


{
switch (Me->ModeSize)
{
case SizeIsByte: printf(" %2x-",*Me->Token[1].Value.CharPtr); break;
case SizeIsWord: printf(" %4x-",*Me->Token[1].Value.WordPtr); break;
case SizeIsLong: printf(" %p-", *Me->Token[1].Value.LongPtr); break;
}
//-- use a separate "enter buffer" to solicit the input so the address
//-- tokens are not disturbed

/* terminate this on a cr */
if(Temp = gets(Me->EnterBuffer,sizeof(Me->EnterBuffer),' ') == '\n') break;
printf(" -- Me->EnterBuffer = %s -- ",Me->EnterBuffer);

682
Introduction to AutoBios

// do an asci2hex on the string,


printf(" -- StrLen = %2x -- ",StrLen(Me->EnterBuffer));
if(StrLen(Me->EnterBuffer) != 0) // don't store an empty string
{
Me->EnterValue = AsciiToHex(Me->EnterBuffer);
printf("\nValue = .%4x. ",Me->EnterValue);

switch (Me->ModeSize)
{
case SizeIsByte: *Me->Token[1].Value.CharPtr = Me->EnterValue; break;
case SizeIsWord: *Me->Token[1].Value.WordPtr = Me->EnterValue; break;
case SizeIsLong: *Me->Token[1].Value.LongPtr = Me->EnterValue; break;
}
}

// increment the pointer


Me->Token[1].Value.CharPtr += Me->ModeSize;

if (Me->Token[0].Value.WordValue[0] % 8)
printf("\n%p",Me->Token[0].Value.LongValue);
}
printf('\n');
}
}

void CmdEnterAscii(VueRegSet)
{ Me->ModeType = TypeAscii; CmdEnter(VueSet); };

void CmdEnterByte(VueRegSet)
{ Me->ModeSize = SizeIsByte; Me->ModeType = TypeHex; CmdEnter(VueSet); };

void CmdEnterWord(VueRegSet)
{ Me->ModeSize = SizeIsWord; Me->ModeType = TypeHex; CmdEnter(VueSet); };

void CmdEnterDouble(VueRegSet)
{ Me->ModeSize = SizeIsLong; Me->ModeType = TypeHex; CmdEnter(VueSet); };

683
Introduction to AutoBios

8.2.11 The Fill Command


Fill is used to fill an area of Ram with a repeating byte or pattern.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Fill
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdFill.C
//
// [Description]
//
// [NOTE] Entry to SysVue is by CTRL-ALT-BREAK.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*========== Fill Commands ============*/

void CmdFill(VueRegSet)
{
while ((Me->Token[1].Value.LongValue <= Me->Token[2].Value.LongValue)
&& !ConsoleBreak())
{
switch (Me->ModeSize)
{
case SizeIsByte: *Me->Token[1].Value.CharPtr++ = Me-
>Token[3].Value.LongValue; break;
case SizeIsWord: *Me->Token[1].Value.WordPtr++ = Me-
>Token[3].Value.LongValue; break;
case SizeIsLong: *Me->Token[1].Value.LongPtr++ = Me-
>Token[3].Value.LongValue; break;
}
}
}

685
The C Programs

void CmdFillAscii(VueRegSet)
{ Me->ModeSize = SizeIsByte; Me->ModeType == TypeAscii; CmdFill(VueSet); };

void CmdFillByte(VueRegSet)
{ Me->ModeSize = SizeIsByte; Me->ModeType == TypeHex; CmdFill(VueSet); };

void CmdFillWord(VueRegSet)
{ Me->ModeSize = SizeIsWord; Me->ModeType == TypeHex; CmdFill(VueSet); };

void CmdFillDouble(VueRegSet)
{ Me->ModeSize = SizeIsLong; Me->ModeType == TypeHex; CmdFill(VueSet); };

686
Introduction to AutoBios

8.2.12 The Help Command


The Help command displays a summary of the commands, and an example of the command argument
structure for each command. The help screen may also be displayed by entering the “?”.
Help for any command may be displayed by typing the command followed by “?”.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Help Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdHelp.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/*============= HELP =============*/

void CmdHelp(VueRegSet)
{
unsigned j = 0, LineCounter = 1;

while(StrLen(CommandList[j].CmdName)) /* look through the list */


{
if(StrLen(CommandList[j].CmdHelpString)) // check for help field in command
list
{
printf("\n%s%s", CommandList[j].CmdName, CommandList[j].CmdHelpString);
if(!(LineCounter++ % 20)) Pause(); /* pause when the screen is full */
}
j++;
}
}

687
The C Programs

688
Introduction to AutoBios

8.2.13 The Port In/Out Commands


The Port commands are used to read and write bytes or words to or from the I/O Ports.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] BiosVue Input and Output Commands
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdInOut.C
//
// [Language MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 1,00 01-01-92 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*======== Input from port Command ======*/

void CmdInPort(VueRegSet)
{
switch (Me->ModeSize)
{
case SizeIsByte: printf(" - %2x",inp (Me->Token[1].Value.WordValue[0]));
break;
case SizeIsWord: printf(" - %4x",inpw(Me->Token[1].Value.WordValue[0]));
break;
}
}

void CmdInPortByte(VueRegSet) { Me->ModeSize = SizeIsByte;


CmdInPort(VueSet); };

void CmdInportWord(VueRegSet) { Me->ModeSize = SizeIsWord;


CmdInport(VueSet); };

689
The C Programs

/*========= Output from Port Commands =========*/

void CmdOutPort(VueRegSet)
{
//if(!Me->TokenValid[1] || !Me->TokenValid[2]) { printf("\a"); return; };
switch (Me->ModeSize)
{
case SizeIsByte: outp (Me->Token[1].Value.LongValue,Me-
>Token[2].Value.LongValue); break;
case SizeIsWord: outpw(Me->Token[1].Value.LongValue,Me-
>Token[2].Value.LongValue); break;
}
}

void CmdOutPortByte(VueRegSet) { Me->ModeSize = SizeIsByte;


CmdOutPort(VueSet); };

void CmdOutPortWord(VueRegSet) { Me->ModeSize = SizeIsWord;


CmdOutPort(VueSet); };

/*======== Read from CMOS Command ======*/

void CmdInportCmos(VueRegSet)
{
outp(CmosRegPort,Me->Token[1].Value.LongValue);
printf(" - %2x",inp(CmosDataPort));
}

/*========= Write to CMOS Command =========*/

void CmdOutPortCmos(VueRegSet)
{
outp(CmosRegPort,Me->Token[1].Value.LongValue);
outp(CmosDataPort,Me->Token[2].Value.LongValue);
}

690
Introduction to AutoBios

8.2.14 The Interrupt Command


The Interrupt command provides a means to invoke an Interrupt from the command line. Control is
normally returned to SysVue upon the completion of the interrupt.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Interrupt Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdInt.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/*======= Int Command =================*/

// This command invokes the interrupt selected.

// this command should use a separate set of registers ????

void CmdInt(VueRegSet)
{
#if 0 == 1
unsigned longj;
/* get the interrupt number from the command line */

/* print the vector value */

if (Me->token_value[1] < 256)


{
printf("Interrupt is at ");

691
The C Programs

j = *(Me->token_value[1] * 4);

printf("%p ",j);

printf("Press X to confirm eXecution");

/* wait for confirmation */


Me->cc = getch();

if ((Me->cc == 'X') || (Me->cc == 'x'))


{
printf("\n"); // do a cr lf for a clean line
for (i = 0; i <= 13; i++) Reg.Array[i] = Me->RegSaves[i];

//BiosInt(Me->token_value[1],&Me->ax);
for (i = 0; i <= 13; i++) Me->RegSaves[i] = Reg.Array[i];

/* display the register upon return */


DisplayRegistersAndFlags(Regs);
}
}
else printf("Value Out of Range ");
#endif
};

692
Introduction to AutoBios

8.2.15 The Mem Command


The Mem command allows the Memory Size values stored in the CMOS Ram to be displayed and modified.

//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Memory Command
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdMem.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*------- set memory sizes ----------*/

void CmdMem(VueRegSet)
{

if(Me->ArgV[1]) /* if anything entered */


{
; //set_sys_mem(dec2bin(Me->Token[1].WordValue[0]));
}
if(Me->ArgV[3]) /* if anything entered */
{
; //set_ext_mem(dec2bin(Me->Token[2].WordValue[0]));
}
printf(" System Memory Size is - "); // display_sys_mem(VueSet);

693
The C Programs

694
Introduction to AutoBios

8.2.16 The Move Command


Move is used to copy data from one area of memory to another. It leave the original data unchanged.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Move Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdMove.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// NOTE:
// Entry to SysVue is by CTRL-ALT-BREAK.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*=== Move Command ===*/

void CmdMove(VueRegSet)
{
while ((Me->Token[1].Value.LongValue <= Me->Token[2].Value.LongValue) && !
ConsoleBreak())
{
*Me->Token[3].Value.CharPtr++ = *Me->Token[1].Value.CharPtr++;
};
}

695
Introduction to AutoBios

8.2.17 The Numeric Processor Command


The NPX command displays the NPX bit of the Cmos Ram, and allows it to be set or cleared.

//---------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue NPX Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdNPX.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*--- select NPX present/not present ----*/

void NPX(VueRegSet)
{
if(Me->ArgC > 1)
{
if((Me->Token[2].Value.CharValue[0] & 0x01))
OutCmos(CmosRegEquipment,InCmos(CmosRegEquipment) | 0x02);
else
OutCmos(CmosRegEquipment,InCmos(CmosRegEquipment) & ~0x02);
CalcCmosChecksum();
}
printf("Options are: 0 = No, 1 = Yes\n");
printf("NPX ");
DisplayNPX(VueSet);
}

697
The C Programs

698
Introduction to AutoBios

8.2.18 The Object Dump Command


The Object Dump command is used to display the System Object Ram area, as well as the allocated objects
within the system area.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue ObjectDump
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdOdump.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] Dump the Object Descriptors
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

// I N C L U D E F I L E S

#include "Bios.h"

// F U N C T I O N P R O T O T Y P E S

//========== Object Dump ==================

void CmdObjectDump(VueRegSet)
{
union
{
struct _SystemObject far * Ptr;
unsigned long Long;
}System;

struct _Object far * Object;


union { unsigned long temp; struct _Object far * me; } list;
System.Ptr = GetSystemObject();
list.me = (void far *)System.Ptr->PoolStart;

// Dump the summary of objects first


printf("\n Location Size Name");

699
The C Programs

printf("\n %p %p %s",
System,System.Ptr->ObjectLength,System.Ptr->ObjectName);
while (list.me->ObjectLength != 0)
{
printf("\n %p %p %s",
list.me,list.me->ObjectLength,list.me->ObjectName);
list.temp += list.me->ObjectLength;
}
printf("\nDo you want to Dump The Contents of the Objects (Y/N) ? :");

if(ToUpper(GetCharEcho()) == 'Y')
{
// Dump the System Object first
Me->Token[1].Value.LongValue = System.Long;
Me->Token[2].Value.LongValue = (unsigned long)&System.Ptr->PoolBlock;
Me->Token[1].ValueMask.LongMask =
Me->Token[2].ValueMask.LongMask = (unsigned long)-1;

CmdDump(Me); Pause();

// set system pointer to next block


System.Long = Me->Token[2].Value.LongValue;

// dump the remaining items


while((System.Ptr->ObjectLength) && (!ConsoleBreak()))
{

// Set next start address


Me->Token[1].Value.LongValue = System.Long;
// set next end address
Me->Token[2].Value.LongValue = Me->Token[1].Value.LongValue +
(unsigned)System.Ptr->ObjectLength;

Me->Token[1].ValueMask.LongMask =
Me->Token[2].ValueMask.LongMask = (unsigned long)-1;

CmdDump(Me); Pause();
// move system pointer to next block
System.Long += System.Ptr->ObjectLength;
};
}
}

700
Introduction to AutoBios

8.2.19 The Pipe Command


The Pipe commands are used to redirect console output to other devices.

//-------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Pipe (Redirection) Commands
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdPipe.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*=========== Re-direction commands ==============*/

void CmdToCon(VueRegSet)
{
struct _SystemObject far * System = GetSystemObject();
System->RedirectFlag = False;
};

void CmdToLpt(VueRegSet)
{
struct _SystemObject far * System = GetSystemObject();
System->RedirectFlag = True;
/*
// If you are watching the printer driver, it must not be
// copying screen output to the printer.
// An insidious recursion results, blowing the system away !
//if((Me->watch_flag & LPT) != 0) Me->watch_flag &= ~LPT;
*/

701
The C Programs

702
Introduction to AutoBios

8.2.20 The Read Hex Command


This commands read (inputs) data in Intel Hexadecimal text format.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Read Intel Hex
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdRHex.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This is Read Intel Hex Format Command.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

static char GetByte(VueRegSet);


static unsigned GetWord(VueRegSet);

/*========= Read Intel Hex =================*/

void CmdRHex(VueRegSet)
{

/* start looking for record marker */


printf("\CS:IP = %4x:%4x",Me->RegsPtr->RegCS,Me->RegsPtr->RegIP);
do
{
while(Me->HexInChar = GetChar() != ':') {}
Me->Sum = 0;
Me->CharCount = GetByte(VueSet);
Me->Token[1].Value.WordValue[0] = GetWord(VueSet);
Me->HexRecordType = GetByte(VueSet);

703
The C Programs

switch (Me->HexRecordType)
{
case IntelDataRecord:
if (Me->CharCount == 0)
{
Me->HexRecordType = IntelEOFRecord;
break;
}
while (Me->CharCount-- > 0)
{
*Me->Token[1].Value.CharPtr++ = GetByte(VueSet);
}
GetByte(VueSet);
if (Me->Sum != 0) Me->HexRecordType = IntelEOFRecord;
break;

case IntelEOFRecord:
/* return to SysVue main */
break;

case IntelAddressRecord:
/* set load address segment */
Me->Token[1].Value.WordValue[1] = GetWord(VueSet);
GetByte(VueSet);
if (Me->Sum != 0) Me->HexRecordType = IntelEOFRecord;
break;

case IntelStartRecord:
/* set cs:ip of reg set */
printf("\CS:IP = %4x:%4x",Me->RegsPtr->RegCS,Me->RegsPtr->RegIP);
Me->RegsPtr->RegCS = GetWord(VueSet);
Me->RegsPtr->RegIP = GetWord(VueSet);
printf("\CS:IP = %4x:%4x",Me->RegsPtr->RegCS,Me->RegsPtr->RegIP);
GetByte(VueSet);
if (Me->Sum != 0) Me->HexRecordType = IntelEOFRecord;
break;
}
}
while (Me->HexRecordType != IntelEOFRecord);
}

/*------- get a byte for rhex ---------*/

char GetByte(VueRegSet)
{
char cc,d;
cc = GetChar() - '0';
if (cc > 9) cc -= 7;
d = GetChar() - '0';
if (d > 9) d -= 7;
cc = cc << 4 | d;
Me->Sum += cc;
return (cc);
}

704
Introduction to AutoBios

/*------- get a word for rhex ---------*/

unsigned GetWord(VueRegSet)
{
return ((GetByte(VueSet) << 8) | GetByte(VueSet));
}

705
Introduction to AutoBios

8.2.21 The Search Command


Search is used to locate a data pattern in a specified area of memory.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Search Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdSearch.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] Search an address range for a keyword modified
// [Description] by the mask-word
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

void CmdSearch(VueRegSet);

/*========= Search Commands =================*/

void CmdSearchAscii(VueRegSet)
{ Me->ModeSize = SizeIsByte; Me->ModeType = TypeAscii; CmdSearch(VueSet); };

void CmdSearchByte(VueRegSet)
{ Me->ModeSize = SizeIsByte; Me->ModeType = TypeAscii; CmdSearch(VueSet); };

void CmdSearchWord(VueRegSet)
{ Me->ModeSize = SizeIsWord; Me->ModeType = TypeAscii; CmdSearch(VueSet); };

void CmdSearchDouble(VueRegSet)
{ Me->ModeSize = SizeIsLong; Me->ModeType = TypeAscii; CmdSearch(VueSet); };

void CmdSearch(VueRegSet)

707
The C Programs

{
/* if the mask is zero (default), set it to all ones */
if(!Me->Token[4].Value.LongValue) Me->Token[4].Value.LongValue = -1;
/* size the mask according to the data type */
switch (Me->ModeSize)
{
case SizeIsByte: Me->Token[4].Value.LongValue = 0x000000ff; break;
case SizeIsWord: Me->Token[4].Value.LongValue = 0x0000ffff; break;
case SizeIsLong: Me->Token[4].Value.LongValue = 0xffffffff; break;
}
while((Me->Token[1].Value.LongValue <= Me->Token[2].Value.LongValue) && !
ConsoleBreak())
{
if((((*Me->Token[1].Value.LongPtr) ^ Me->Token[3].Value.LongValue) &
Me->Token[4].Value.LongValue) == 0)
{
if(Me->ModeType == TypeAscii)
{
printf("\n%p %k",Me->Token[1].Value.LongValue,*Me-
>Token[1].Value.CharPtr);
}
else
{
switch (Me->ModeSize)
{
case SizeIsByte:
printf("\n%p %2x",Me->Token[1].Value.LongValue,*Me-
>Token[1].Value.CharPtr);
break;

case SizeIsWord:
printf("\n%p %4x",Me->Token[1].Value.LongValue,*Me-
>Token[1].Value.WordPtr);
break;

case SizeIsLong:
printf("\n%p %p",Me->Token[1].Value.LongValue,*Me-
>Token[1].Value.LongPtr);
}
}
}
Me->Token[1].Value.CharPtr++;
}
}

708
Introduction to AutoBios

8.2.22 The System Info Command


SysInfo (SI) displays data about the system.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue System Information Command
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdSI.C
//
// [Description]
//
// NOTE:
// Entry to SysVue is by CTRL-ALT-BREAK.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*===== Sys Info Command ===========*/

void CmdSysInfo(VueRegSet)
{
unsigned j, CalcedMemSize;
struct _BiosRam far * LowRam = 0;
struct _SystemObject far * System = GetSystemObject();

printf("\n Current Time: "); DisplayTime();


printf("\n Current Date: "); DisplayDate();
printf("\n Bios For: %s",(void far *)CustomerID);
printf("\n Bios Version: %s",(void far *)VersionID);
//printf("\n Bios Date: %8s",(void far *)DateStamp);
printf("\n Copyright: %s",(void far *)OwnerID);
printf("\n Bios Part Nr: %s",(void far *)PartNrID);
printf("\n Bios Size: 64k At Segment: %4x",GetCS());
printf("\n CPU: ");

709
The C Programs

// sense the type of CPU and display the result


switch(CpuType())
{
case 86: printf("8086/8088");break;
case 186: printf("80186/80188");break;
case 286: printf("80286");break;
case 386: printf("80386");break;
default: printf("Unknown");
}

printf("\n NPX: "); DisplayNPX();

printf("\n Com Ports: ");


for (j = 0; (j < 4) && (LowRam->COMM_LIST[j] != 0); j++)
{
if(LowRam->COMM_LIST[j] != 0) printf("%4x ",LowRam->COMM_LIST[j]);
};

printf("\n LPT Ports: ");


for (j = 0; (j < 3) && (LowRam->LPT_LIST[j] != 0); j++)
{
if(LowRam->LPT_LIST[j] != 0) printf("%4x ",LowRam->LPT_LIST[j]);
};

// display the disk drives in the system


DisplayDrives();

DisplayVideo();

printf("\nMemory Size System Extended");


printf("\n Expected: ");
DisplaySystemMemory();
printf(" ");
DisplayExtendedMemory();

// --- needs correction when system object is allocated by DOS ---


CalcedMemSize = MemorySizeWord;
if(System->ObjectStatusFlags.Native)
CalcedMemSize += (CfgSystemObjectSize/1024);
printf("\n Found: %4D",CalcedMemSize);
//----------------------------------------------------------------

printf(" %4D",j = GetCmosExtendedMemory());


}

710
Introduction to AutoBios

8.2.23 The Snap/Watch/Log Commands


These commands are used to enable/disable these functions on a devcie basis.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Snapshot Functions
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdSnap.C
//
// [Language] MSVC 1.5
//
// [ Description]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

void SpyCommand(VueRegSet,unsigned);

/* L O C A L C O N S T A N T S */

/* P R O G R A M S */

void CmdSnap(VueRegSet)
{
SpyCommand(VueSet,Snap);
}

void CmdWatch(VueRegSet)
{
SpyCommand(VueSet,Watch);
};

void CmdLog(VueRegSet)
{
SpyCommand(VueSet,Log);
};

void SpyCommand(VueRegSet,unsigned SpyType)

711
The C Programs

{
unsigned Index;
struct _BiosObject far * Bios = GetBiosObject();
unsigned Temp;

LoadDS();

if(Me->ArgC < 2)
{
printf("\nSelected %ss are: ",GetName(SpyType,SpyList));
if(!(Bios->FlagMaster[SpyType].Flag & Bios->FlagMaster[SpyType].Master))
{
printf("None");
}
else
{
for(Index = 0; Index < 15; Index++)
{
Temp = (Bios->FlagMaster[SpyType].Flag &
Bios->FlagMaster[SpyType].Master & BitList[Index].Value);
if(ValueExists(Temp,DeviceList))
{
printf("%s, ",GetName(Temp,DeviceList));
};
};
};
}
else
{
Index = 1;
if(StrCmp(Me->ArgV[1],"List"))
{
printf("\n"); PrintNames(DeviceList);
};
if(StrCmp(Me->ArgV[1],"All")) Bios->FlagMaster[SpyType].Flag = -1;
if(StrCmp(Me->ArgV[1],"None")) Bios->FlagMaster[SpyType].Flag = 0;
if(StrCmp(Me->ArgV[1],"No")) Bios->FlagMaster[SpyType].Flag = 0;
if(StrCmp(Me->ArgV[1],"Off"))
{
Bios->FlagMaster[SpyType].Save = Bios->FlagMaster[SpyType].Flag;
Bios->FlagMaster[SpyType].Flag = 0;
}

if(StrCmp(Me->ArgV[1],"On"))
{
if(!Bios->FlagMaster[SpyType].Save)
{
printf("\nNo %ss Selected\a",GetName(SpyType,SpyList));
}
else
{
Bios->FlagMaster[SpyType].Flag = Bios->FlagMaster[SpyType].Save;
};
}

while(Me->ArgV[Index])

712
Introduction to AutoBios

{
if(NameExists(Me->ArgV[Index],DeviceList))
{
Bios->FlagMaster[SpyType].Flag |= GetValue(Me->ArgV[Index],DeviceList);
}
Index++;
};
};
};

//--------- register snapshots ---------------

// this will execute if the "snap" bit for the specified device is set

/*------------------------------------------------------------*/

unsigned GetSavedSS(void)
{
struct _BiosObject far * Bios = GetBiosObject();

return(Bios->StackSaveSS);
}

unsigned GetSavedSP(void)
{
struct _BiosObject far * Bios = GetBiosObject();

return(Bios->StackSaveSP);
}

//----------------------------------------------------------

void SnapIn(struct _IRegs far * Regs,unsigned device)


{
struct _BiosObject far * Bios = GetBiosObject();
Bios->ActiveDevice |= device;
if(SnapActive())
{
DisplayRegisters(Regs,"->");
printf( "%s ",GetName(device,DeviceList));
}
}

void SnapOut(struct _IRegs far * Regs,unsigned device)


{
struct _BiosObject far * Bios = GetBiosObject();
if(SnapActive())
{
DisplayRegisters(Regs," ");
DisplayFlags(Regs->RegFlags);
}
Bios->ActiveDevice &= ~device;
}

713
The C Programs

//---------------------------------------------------

unsigned SnapWatchLogActive(unsigned Category)


{
struct _BiosObject far * Bios = GetBiosObject();
if(!(Bios->FlagMaster[Category].Flag & Bios->ActiveDevice
& Bios->FlagMaster[Category].Master))
return(False); else return(True);
}

unsigned SnapActive(void)
{
return(SnapWatchLogActive(Snap));
}

unsigned WatchActive(void)
{
return(SnapWatchLogActive(Watch));
};

unsigned LogActive(void)
{
return(SnapWatchLogActive(Log));
};

714
Introduction to AutoBios

8.2.24 The Time Command


The Time command is used to display and set the CMOS clock.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Display and Set Time Command
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdTime.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// NOTE:
// Entry to SysVue is by CTRL-ALT-BREAK.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*------- set time -------------*/

void CmdTime(VueRegSet)
{
unsigned Hours,Minutes,Seconds;
if(Me->ArgC > 1) // if anything entered
{
printf("\nGoing to Parse: %s",Me->ArgV[1]);
Hours = ParseDigitString(Me->ArgV[1],1);
Minutes = ParseDigitString(Me->ArgV[1],2);
Seconds = ParseDigitString(Me->ArgV[1],3);
printf("\n%2x:%2x:%2x",Hours,Minutes,Seconds);

if(!ClockSetTime(Hours,Minutes,Seconds)) printf("Error setting time");


}

715
The C Programs

printf("\nCurrent Time is - ");DisplayTime();


}

716
Introduction to AutoBios

8.2.25 The Trace Command


The trace commands is used to execute a user instruction in single-step mode, returning to SysVue adter its
execution.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Trace Command
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdTrace.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//------------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/*========== Trace Command ===========*/

void CmdTrace(VueRegSet)
{
#if (0 == 1)
struct _BiosRam far * Vectors = 0;
struct _SystemObject far * System = GetSystemObject();
//struct BiosObject far * Bios = System->Bios_Ptr;

Me->TraceCount = (unsigned)Me->Token[1].LongValue;
if(Me->TraceCount == 0) Me->TraceCount = 1;
Me->ExitFlag = True;
Me->RegSaves[pswsave] |= 0x0100; // set trace bit
// chain-in the trace vector
_disable();
Me->SysVueTraceChain = Vectors->IntVector[0x01];
Vectors->IntVector[0x01]=(void near *)SysTrace;

717
The C Programs

_enable();
#endif
}

718
Introduction to AutoBios

8.2.26 The Hard Drive Types Command


Types displays a list of the standard hard drive types from the hard drive type table.

//----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1997 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Display Hard Disk Types COmmand
//
// [Version] 3.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdTypes.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*------ list drive types from hdisk table ----*/

void CmdTypes(VueRegSet)
{
DisplayHardDiskTypes(VueSet);
};

unsigned HardCellTable[2][4] =
{
{ CmosRegDrive47CylLow, CmosRegDrive47CylHigh,
CmosRegDrive47Heads, CmosRegDrive47Sectors, },
{ CmosRegDrive48CylLow, CmosRegDrive48CylHigh,
CmosRegDrive48Heads, CmosRegDrive48Sectors, },
};

void CmdUser(VueRegSet)
{
struct BiosObject far * Bios = GetBiosObject();

719
The C Programs

unsigned Index,UserType,UserParms[5];
LoadDS();

if(Me->ArgC > 1)
{

for(Index = 1; Index < 5; Index++)


{
if(!IsDecimalString(Me->ArgV[Index])) { beep(); return; };
UserParms[Index] = AsciiToDec(Me->ArgV[Index]);
}

if(UserParms[1] < 47 || UserParms[1] > 48) { beep(); return; };


UserType = UserParms[1] -= 47; // will be 0 or 1

OutCmos(HardCellTable[UserType][0], UserParms[2]);
OutCmos(HardCellTable[UserType][1], UserParms[2] >> 8);
OutCmos(HardCellTable[UserType][2], UserParms[3]);
OutCmos(HardCellTable[UserType][3], UserParms[4]);
CalcCmosChecksum();
}
LoadUserDriveParms();
PrintHardDiskTitleBar();
DisplayUserHardTypes();

return;
};

void CmdOrder(VueRegSet)
{
struct BiosObject far * Bios = GetBiosObject();
unsigned Index,UserType,UserParms[5];
LoadDS();

if(Me->ArgC < 2)
{
printf(" - Boot Order is %s\n",GetName((InCmos(CmosRegOptionFlags) &
CmosRegBitBootOrder),BootOrderList));
}
else
{
if(NameExists(Me->ArgV[1],BootOrderList))
{
ResetCmosBits(CmosRegOptionFlags,CmosRegBitBootOrder);
SetCmosBits(CmosRegOptionFlags,GetValue(Me->ArgV[1],BootOrderList));
CalcCmosChecksum();
printf(" - Boot Order is %s\n",GetName((InCmos(CmosRegOptionFlags) &
CmosRegBitBootOrder),BootOrderList));
}
};
printf("\nBooting Order Options are:");
PrintNames(BootOrderList);
return;
};

720
Introduction to AutoBios

721
Introduction to AutoBios

8.2.27 The Vector Command


Vector displays the Interrtp Vector table in doubleword format.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Interrupt Vectors Dump Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdVctrs.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

void VlsiDump(VueRegSet);

/* P R O G R A M */

/*============ Vector Command =================*/

void Cmdvectors(VueRegSet)
{
unsigned i;
Me->Token[1].Value.LongValue = 0x00000000;
Me->Token[2].Value.LongValue = 0x0000013f;
while((Me->Token[1].Value.LongValue <= Me->Token[2].Value.LongValue) && !
ConsoleBreak())
{
printf("\n%p ",Me->Token[1].Value.LongValue);
do
{
printf("%p ",*Me->Token[1].Value.LongPtr++);
if((Me->Token[1].Value.CharValue[0] % 4) == 0) printf(" ");
}
while ((Me->Token[1].Value.CharValue[0] % 16) != 0);
printf(" ");
// for (i = - 16; i != 0; printf("%k",*(Me->Token[1].CharPtr + i)), i++);
}

723
The C Programs

Pause();
Me->Token[1].Value.LongValue = 0x00400000; Me->Token[2].Value.LongValue =
0x004000ff;
while((Me->Token[1].Value.LongValue <= Me->Token[2].Value.LongValue) && !
ConsoleBreak())
{
printf("\n%p ",Me->Token[1].Value.LongValue);
do
{
printf("%2X ",*Me->Token[1].Value.CharPtr++);
if((Me->Token[1].Value.LongValue % 4) == 0) printf(" ");
}
while ((Me->Token[1].Value.CharValue[0] % 16) != 0);
printf(" ");
for (i = - 16; i != 0; printf("%k",*(Me->Token[1].Value.CharPtr + i)), i++);
};
Pause();
CmdChip(Me);
}

724
Introduction to AutoBios

8.2.28 The Video Command


The Video command is used to display and set the default video type in the CMOS ram.

//------------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Video
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdVideo.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//-----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*------- set video type ----------*/

void CmdVideo(VueRegSet)
{
if(Me->ArgC > 1) /* if anything entered */
{
if(NameExists(Me->ArgV[1],DisplayList))
{
OutCmos(CmosRegEquipment,(InCmos(CmosRegEquipment) & 0xcf) |
(GetValue(Me->ArgV[1],DisplayList) << 4));
CalcCmosChecksum();
}
else beep();
}
else
{
printf(" Options are:\n"); PrintNames(DisplayList);
}

725
The C Programs

DisplayVideo(VueSet);
}

726
Introduction to AutoBios

8.2.29 The Write Hex Command


This command is used to output a block of data in Intel Hexadecimal formt.

//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue Write Intel Hex Command
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] CmdWHex.C
//
// [Language] MSVC 1.0/1.5
//
// [Description]
//
// NOTE:
// Entry to SysVue is by CTRL-ALT-BREAK.
//
// [Arguments]
//
// [Return]
//
// [History] 2.00 04/11/94 Original
//
//----------------------------------------------------------------------

/* I N C L U D E F I L E S */

#include "Bios.h"

/* F U N C T I O N P R O T O T Y P E S */

/*========= Write Intel Hex =================*/

void CmdWHex(VueRegSet)
{

// disregard if range = nul


if (Me->Token[1].Value.LongValue < Me->Token[2].Value.LongValue)
{
// write extended address record for segment
Me->Sum = 0;
printf("\nWriting Extended Address Record");
Me->Sum -= printf("\r\n:%2x%4x%2x%4x",2,0,2,*Me->Token[1].Value.WordPtr);
printf("%2x",Me->Sum);

while (Me->Token[1].Value.LongValue < Me->Token[2].Value.LongValue)

727
The C Programs

{
printf("\r\n:");

Me->CharCount = Me->Token[2].Value.LongValue -
Me->Token[1].Value.LongValue;

if(Me->CharCount > 16) Me->CharCount > 16 ;

Me->Sum = 0;
Me->Sum -= printf("%2x%4x%2x",Me->CharCount,*Me->Token[1].Value.WordPtr,0);

while (Me->CharCount-- > 0 && !ConsoleBreak())


{
Me->Sum -= printf("%2x",*Me->Token[1].Value.CharPtr++);
};
printf("%2x",Me->Sum);
}

// write start address record


if (Me->Token[3].ValueMask.LongMask)
{
Me->Sum = 0;
Me->Sum -= printf("\r\n:%2x%4x%2x",4,0,4);

Me->Sum -= printf("%4x",*Me->Token[3].Value.WordPtr++);
Me->Sum -= printf("%4x",*Me->Token[3].Value.WordPtr);
printf("%2x",Me->Sum);
}
printf("\r\n:00000001FF");
}
}

728
Introduction to AutoBios

9. StandAlones
9.1 The Concept of StandAlones
StandAlones are an optional way to build drivers and services which allow them to be loaded into RAM
as a 1.) a rom-scan module by the Bios before booting up the operating system or 2.) loading the module
as a TSR. This can be done for either testing modified modules or for replacing existing functions on an
existing machine.
The StandAlones are created using an envelope to surround the standard AutoBios function with the
structure neccassary to appear as a DOS.EXE program or as a Installable Device Driver conforming to
the Bios Rom-Scan format.
The Envelope also provides for additional functions such as finding and reserving space for the program
variables, and for the Terminate-Stay-Resident mode of operation.

9.2 The StandAlone Envelope

9.2.1 SaPrefix.asm
The Prefix block contains the 55AA signature needed by Rom-Scan and executes a call to a special
Main-like routine, and also defines a DOS entry point.
;
******************************************************************************
*********************
;
; [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] StandAlone Module Linking Prefix Module
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 1-31-94
;
; [Filename] SaPrefix.asm
;
; Functional Description:
;
; This module is used as a linking prefix for stand-alone versions
; of the Bios Drivers. It includes a 55AA header so the module
; may be built as a Rom-Scan Installable driver.
; The modules may also be loaded as DOS TSR's
;
;
; Version History:

729
The C Programs

;
;
******************************************************************************
*********************

include BiosPrfx.inc

.code

extrn RomStart:near
extrn DosStart:near
extrn EndOfCode:near

;========== This is start of the code section ===================

; This is the Rom-Scan Header


db 055h,0aah

; This is the block size - This will need to be set up to even


; modulus when the checksum is generated.
db 0

RomInit proc far


mov ax,DGROUP
mov ds,ax
call RomStart
ret
RomInit endp

end DosStart

730
Introduction to AutoBios

9.2.2 SaSuffix.asm
The Suffix block contains the definition for the Data area to be used when being loaded as a DOS TSR,
and the End Markers used to determine how much space to be retained by the module when returning to
DOS and keeping memory assigned to the module.
;
******************************************************************************
*********************
;
; [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
;
; [Product Name] AutoBios
;
; [Module Name] StandAlone Module Linking Prefix Module
;
; [Version] 2.00
;
; [Author] John O. Foster
;
; [Date] 1-31-94
;
; [Filename] SaPrefix.asm
;
; Functional Description:
;
; This module is used as a linking prefix for stand-alone versions
; of the Bios Drivers. It includes a 55AA header so the module
; may be built as a Rom-Scan Installable driver.
; The modules may also be loaded as DOS TSR's
;
;
; Version History:
;
;
******************************************************************************
*********************

include BiosPrfx.inc

.code

extrn RomStart:near
extrn DosStart:near
extrn EndOfCode:near

;========== This is start of the code section ===================

; This is the Rom-Scan Header


db 055h,0aah

; This is the block size - This will need to be set up to even


; modulus when the checksum is generated.
db 0

731
The C Programs

RomInit proc far


mov ax,DGROUP
mov ds,ax
call RomStart
ret
RomInit endp

end DosStart

732
Introduction to AutoBios

9.2.3 MainBody.c
The MainBody routines find and reserve space for the modules data variables. Depending on the mode
of loading the module, the space may be located in an existing AutoBios System Object, a new System
Object may be created, or the data area may be located in the DOS TSR area. This routine is generic and
is used as an include in a Mainxxx routine.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] StandAlone Load Envelope Routines
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainBody.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provides the body envelope for building the
// [Description] standalone version of Bios Drivers
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

void DosStart(void);
void RomStart(void);

extern char SystemDataBlock[CfgSystemObjectSize];

void LastLocation(void);
void EndOfCode(void);
void far * Last = &LastLocation;
void far * EndCode = &EndOfCode;
//void far * First = &MainStart;
void DosStart(void)
{

733
The C Programs

char far * BlockPtr;


struct _SystemObject far * System = 0;
unsigned Temp;
unsigned BlockSize = CfgSystemObjectSize;
LoadDS();

// This must be done after the LoadDS (DS needs to be = CS)


BlockPtr = &SystemDataBlock;

// Check to see if 0000:040e is zero, indicating we can use it


// for an Object Ptr
if(!SystemSegmentPointer)
{
printf("\nCreating New System Object for Module(s)\n");

//Simulate a System Object in the Data Area

// If the SystemSegmentPointer is != 0, then assume that


// a system object already exists.
// When creating the second system object after the memory sizing
// reset the pointer to zero.

// This logic allows a standalone module to load up after bootup and


// use the existing system object from Bios.

// A case exists where a Bios stand-alone .EXE module is used with


// other Bios. Here, a system object will need to be created based
// on a DOS Data group.

/* Using BlockSize, round up to next 1K boundary */

BlockSize += 1023;
BlockSize &= ~1023;

SystemSegmentPointer =
FP_SEG(BlockPtr) + (FP_OFF(BlockPtr) >> 4);

/* set system Object pointer to start of system Object */

System = GetSystemObject();

/* Insert Object size, so we can do a clear on the system Object */


System->ObjectLength = BlockSize;
ClearObject(System);

/* Insert Object size on the fresh Object so we can use it */


System->ObjectLength = BlockSize;

/* Insert System Object name */


StrCpy(System->ObjectName,"SystemObject");

/* set pool delimiters */


System->PoolStart = System->PoolCurrentOpen = (void far *)&System-
>PoolBlock;

System->PoolEnd = MK_FP(SystemSegmentPointer,BlockSize);

734
Introduction to AutoBios

/* Now allocate a BiosObject in the system pool area */


if(!(System->Bios_Ptr = AcquireObject
(BiosObject, "BiosObject" ,BiosObjectType)))
{
printf("\nAborting Load - Could not create Bios Object\n");
SystemSegmentPointer = 0;
// Return to DOS
_asm mov ah,0x4c
_asm mov al,0
_asm int 0x21
}

Destination(LoadMessage,0);

Temp = FP_OFF(Last);
Temp /= 16; Temp++;
//Keep
_asm mov ah,0x31
_asm mov al,0
_asm mov dx,Temp
_asm int 0x21
}
else
// If SystemSegmentPointer !=0, then check for the name field.
// If existing SystemObject, then use it.
{
System = GetSystemObject();
if(StrStr(System->ObjectName,"SystemObject"))
{
printf("\nLoading - Using existing System Object.\n");
printf("\n%s",LoadMessage);
Temp = FP_OFF(EndCode);
Temp /= 16; Temp++;
//Keep
_asm mov ah,0x31
_asm mov al,0
_asm mov dx,Temp
_asm int 0x21
}
else
{
// Try the Alternate Location

printf("\n Cannot Load - No System Object Available\n");


// Return to DOS
_asm mov ah,0x4c
_asm mov al,0
_asm int 0x21
};
};
};

void RomStart(void)
{

735
The C Programs

struct _SystemObject far * System;


LoadDS();

if(!SystemSegmentPointer)
{
printf("\nCreating New System Object\n");
if(!(System = CreateSystemObject(CfgSystemObjectSize)))
{
printf("\nAborting Load - Could not create System Object\n");
return;
};
printf("\nCreating Bios Object\n");
/* Now allocate a BiosObject in the system pool area */
if(!(System->Bios_Ptr = AcquireObject
(BiosObject, "BiosObject" ,BiosObjectType)))
{
printf("\nAborting Load - Could not create Bios Object\n");
return;
} ;
}
else
{
printf("\nUsing Existing System Object\n");
};
Destination(LoadMessage,0);
printf("\nSetup Completed");
};

736
Introduction to AutoBios

9.3 The StandAlone Mainxxx files


These files provide the entry points, and supporting routines for the device drivers to be created as
StanAlone modules, both TSR and Rom-Scan Installable. They can sense whether the StandAlone is
being lodaed from DOS or during the Rom-Scan, and will install the module accordingly.

9.3.1 SysVue Main


The SysVue StandAlone is created by using the MainVue.c file, as well as a sequence in the Makefile. A
review of the MainVue.c file will show how it is used to define arguments to be used by MainBody.c.
Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] SysVue StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainVue.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of SysVue
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination SysVueSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode 0

// Specify the meesage to be displayed when loading the module

737
The C Programs

char far * LoadMessage = "Loading SysVue Module.... ";

#include "Bios.h"

#include "MainBody.c"

738
Introduction to AutoBios

9.3.2 Floppy Disk Main


The Floppy Disk StandAlone is created by using the MainDisk.c file, as well as a sequence in the
Makefile. A review of the MainDisk.c file will show how it is used to define arguments to be used by
MainBody.c. Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Floppy Disk StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainDisk.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the floppy disk driver
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination FDiskSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskDisk

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Floppy Disk Module.... ";

#include "Bios.h"

#include "MainBody.c"

739
The C Programs

740
Introduction to AutoBios

9.3.3 Hard Disk Main


The Disk StandAlone is created by using the MainHard.c file, as well as a sequence in the Makefile. A
review of the MainHard.c file will show how it is used to define arguments to be used by MainBody.c.
Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Video StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainCrt.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Video driver
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination HDiskSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskHard

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Hard Disk Module.... ";

#include "Bios.h"

#include "MainBody.c"

741
The C Programs

742
Introduction to AutoBios

9.3.4 Comm Main


The Comm StandAlone is created by using the MainComm.c file, as well as a sequence in the Makefile.
A review of the MainComm.c file will show how it is used to define arguments to be used by
MainBody.c. Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Comm Driver StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainComm.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Comm driver
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination CommSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskCom

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Comm Module.... ";

#include "Bios.h"

#include "MainBody.c"

743
The C Programs

744
Introduction to AutoBios

9.3.5 Lpt Main


The Lpt StandAlone is created by using the MainLpt.c file, as well as a sequence in the Makefile. A
review of the MainLpt.c file will show how it is used to define arguments to be used by MainBody.c.
Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Lpt Driver StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainLpt.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Lpt driver
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination LptSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskLpt

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Lpt Module.... ";

#include "Bios.h"

#include "MainBody.c"

745
The C Programs

746
Introduction to AutoBios

9.3.6 Print Screen Main


The Prinr Screen StandAlone is created by using the MainPrSc.c file, as well as a sequence in the
Makefile. A review of the MainPrSc.c file will show how it is used to define arguments to be used by
MainBody.c. Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Lpt Driver StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainLpt.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Lpt driver
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination PrintScreenSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskPrtScr

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Print Screen Module.... ";

#include "Bios.h"

#include "MainBody.c"

747
The C Programs

748
Introduction to AutoBios

9.3.7 System Services Main


The System Services StandAlone is created by using the MainSySr.c file, as well as a sequence in the
Makefile. A review of the MainSySr.c file will show how it is used to define arguments to be used by
MainBody.c. Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] System Services StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainSySr.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the System Services driver
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination SystemServicesSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskSysSrv

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading System Services.... ";

#include "Bios.h"

#include "MainBody.c"

749
The C Programs

750
Introduction to AutoBios

9.3.8 Keyboard Main


The Keyboard StandAlone is created by using the MainKb.c file, as well as a sequence in the Makefile.
A review of the MainKb.c file will show how it is used to define arguments to be used by MainBody.c.
Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Keyboard StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainKb.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Keyboard driver
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination KeyboardSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskKeyboard

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Keyboard.... ";

#include "Bios.h"

#include "MainBody.c"

751
The C Programs

752
Introduction to AutoBios

9.3.9 Video Main


The Video StandAlone is created by using the MainCrt.c file, as well as a sequence in the Makefile. A
review of the MainCrt.c file will show how it is used to define arguments to be used by MainBody.c.
Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Video StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainCrt.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Video driver
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination VideoSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskVideo

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Video Module.... ";

#include "Bios.h"

#include "MainBody.c"

753
The C Programs

754
Introduction to AutoBios

9.3.10 Boot Main


The Boot StandAlone is created by using the MainBoot.c file, as well as a sequence in the Makefile. A
review of the MainBoot.c file will show how it is used to define arguments to be used by MainBody.c.
Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Boot Function StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainBoot.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Boot Function
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination BootSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskBoot

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Boot Function.... ";

#include "Bios.h"

#include "MainBody.c"

755
The C Programs

756
Introduction to AutoBios

9.3.11 Equipment Main


The Equipment StandAlone is created by using the MainEqui.c file, as well as a sequence in the
Makefile. A review of the MainEqui.c file will show how it is used to define arguments to be used by
MainBody.c. Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Equipment Call StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainEqui.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Equipment Call
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination EquipmentSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskEquipment

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Equipment Call.... ";

#include "Bios.h"

#include "MainBody.c"

757
The C Programs

758
Introduction to AutoBios

9.3.12 Memory Main


The Memory StandAlone is created by using the MainMem.c file, as well as a sequence in the Makefile.
A review of the MainMem.c file will show how it is used to define arguments to be used by MainBody.c.
Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] MemSize Call StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainMem.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the MemSize Call
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination MemSizeSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskMemory

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading MemSize Call.... ";

#include "Bios.h"

#include "MainBody.c"

759
The C Programs

760
Introduction to AutoBios

9.3.13 Timer Main


The Timer StandAlone is created by using the MainTmr.c file, as well as a sequence in the Makefile. A
review of the MainTmr.c file will show how it is used to define arguments to be used by MainBody.c.
Each StandAlone will have its own Mainxxxx.c file.
//-----------------------------------------------------------------------
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Timer Function StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainTmr.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Timer Function
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination TimerSetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskTimer

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Timer Function.... ";

#include "Bios.h"

#include "MainBody.c"

761
The C Programs

762
The StandAlone Mainxxx files

9.3.14 Time of Day Main


The Time of Day StandAlone is created by using the MainTOD.c file, as well as a sequence in
the Makefile. A review of the MainTOD.c file will show how it is used to define arguments to
be used by MainBody.c. Each StandAlone will have its own Mainxxxx.c file.
//----------------------------------------------------------------------
-
//
// [Copyright] Copyright (c) 1994 John O. Foster - All Rights Reserved.
//
// [Product Name] AutoBios
//
// [Module Name] Time Of Day Function StandAlone Envelope
//
// [Version] 2.00
//
// [Author] John O. Foster
//
// [Date] 04/11/94
//
// [File Name] MainTOD.C
//
// [Language] MSVC 1.0/1.5
//
// [Description] This provies the envelope for building the standalone
// [Description] version of the Time Of Day Function
//
// [Arguments] Registers
//
// [Return]
//
//
// [History] 2.00 04/11/94 Original
//
//---------------------------------------------------------------------

// I N C L U D E F I L E S

// The define line below may be changed to create a Mainxxxx.c for


// other bios drivers. A Link file and makefile additions are also
// required.

// Specify the Setup Routine to be executed


#define Destination TimeOfDaySetup

// Specify the Device Code for Snaps and Watches


#define DeviceCode DeviceMaskTOD

// Specify the meesage to be displayed when loading the module


char far * LoadMessage = "Loading Time Of Day Function.... ";

#include "Bios.h"

#include "MainBody.c"

763
The C Programs

764
The StandAlone Mainxxx files

9.4 The StandAlone Make Process files


These files are used by the makefile to perform the .EXE to .BIN conversion for the
StandAlone.exe files to be used as Rom-Scan Installable Modules. They are input script files for
the standard DOS Debug program, which loads the .EXE file and performs the relocation fixups,
then writes the file as a binary image. Because the modules are wriiten to be location
independent, they may be loaded at any location within the Bios normal Rom-Scan range.

9.4.1 SaBoot.Inp
nsaboot.exe
l
nsaboot.tmp
w cs:0
q

9.4.2 SaComm.Inp
nsacomm.exe
l
nsacomm.tmp
w cs:0
q

9.4.3 SaDisk.Inp
nsadisk.exe
l
nsadisk.tmp
w cs:0
q

9.4.4 SaEquip.Inp
nsaequip.exe
l
nsaequip.tmp
w cs:0
q

9.4.5 SaHard.Inp
nsahard.exe
l
nsahard.tmp

765
The C Programs

w cs:0
q

9.4.6 SaKb.Inp
nsakb.exe
l

nsakb.tmp
w cs:0
q

9.4.7 SaLpt.Inp
nsalpt.exe
l
nsalpt.tmp
w cs:0
q

9.4.8 SaMem.Inp
nsamem.exe
l
nsamem.tmp
w cs:0
q

9.4.9 SaPrtScr.Inp
nsaprtscr.exe
l
nsaprtscr.tmp
w cs:0
q

9.4.10 SaSysSrv.Inp
nsasyssrv.exe
l
nsasyssrv.tmp
w cs:0
q

766
The StandAlone Mainxxx files

9.4.11 SaSysVue.Inp
nsasysvue.exe
l
nsasysvue.tmp
w cs:0
q

9.4.12 SaTimer.Inp
nsatimer.exe
l
nsatimer.tmp
w cs:0
q

9.4.13 SaTOD.Inp
nsatod.exe
l
nsatod.tmp
w cs:0
q

9.4.14 SaVideo.Inp
nsavideo.exe
l
nsavideo.tmp
w cs:0
q

767
The StandAlone Mainxxx files

10. The Resource List


10.1 Hardware Devices

Prom Programmer
Needhams Electronics, Inc.
4539 Grove Avenue
Sacramento, CA 95841
(916) 972-8042
BBS (916) 972-8042
FAX (916) 972-9960

Prom Eraser
Walling

Prom Emulators
Technical Solutions
PO Box 462101
Garland TX 75046-2101

Voice or Fax: (214) 272-9392

769
Hardware Devices

771

You might also like