Sun Java Solaris Communities My SDN Account Join SDN
 
White Paper

External BEF Interface Specification for Solaris x86 Realmode DDI

 
 

Version 1.7 (2/3/97)

 

1.0 Overview

 

On SPARC systems, the OBP provides the necessary support to allow booting from non-standard boot devices such as networks and CD-ROM drives. This capability is used during installation from a network or CD-ROM device, and by diskless (net-booting) Solaris clients.

On the x86 platform, booting is supported by the platform BIOS. Unfortunately, x86 BIOS is generally not capable of booting from network or CD-ROM devices. For this reason, Solaris for x86 requires auxiliary boot drivers that extend the capability of the platform BIOS. These boot drivers are called BEFs (BIOS Extension Files). Because they run in the "real mode" of the x86 processor, these boot drivers are also referred to as "realmode" drivers.

A BEF interfaces to the rest of the Solaris x86 boot system through the BEF interface described in this document.

There are two distinct parts to the BEF interface. The first part is an "Initialization" interface, which is used by the Solaris x86 boot system to load and install the BEF. The second part is an "Operational" interface which is used by the Solaris x86 boot system to perform a boot from the device.

2.0 Initialization Interface

The Initialization Interface of a BEF is used by the Solaris x86 boot system to load and install the BEF.

A BEF is not required to provide the initialization portion of the BEF interface, as long as it has some mechanism by which it may be loaded. For example, a BEF that was included in the PROM of a device might be able to install itself directly via the BIOS.

If a BEF wishes to be installed by the Solaris x86 boot system, however, it must provide the BEF Initialization Interface described in this section of the BEF interface document.

2.1 BEF Executable file

2.1.1 File Format

A BEF which is installed by the Solaris x86 boot system is in the form of an MS-DOS executable (EXE) file.

A BEF has a standard DOS EXE header, which should be a valid EXE header.

2.1.2 Boot media

At the present time, all BEFs must be delivered by SunSoft, since we have not specified an interface for 3rd parties to add their drivers to the Solaris x86 boot media (floppy or hard disk). In the near future, we will specify this interface, and 3rd party developers will be able to ship drivers directly to customers. The likely mechanism is that the 3rd party drivers will exist on a separate floppy, and the Solaris x86 boot system will provide the user with an opportunity to add these 3rd party drivers.

2.2 Loading

During the boot, the boot system loads the BEF from the boot media (floppy or hard disk) into memory.

Unlike the DOS loader, the boot system does not process the relocation header of the executable. If far pointers are used, the BEF must handle their relocation at run time. This is accomplished by using run-time initialization of far pointers based on the current value of the segment registers and the offset of the data/code into the segment.

2.3 BEF identification

2.3.1 Magic Number

The Solaris boot system checks for a signature to verify that a loaded BEF is valid. If this signature is not present, the Solaris boot system will not execute the BEF.

At offset BEF_EXTMAGOFF (0x1C) of the BEF text segment, the following four-byte value must be present:

#define BEF_SIGNATURE 0x2E626566

The BEF must also place a revision number into the revision field of the bdev_info structure (refer to Appendix 2).

2.4 Initialization Entry Point

The BEF initialization entry point must occur at offset BEF_ENTRY (0x20) of the BEF text segment.

The calling semantics for the initialization entry point emulate a long subroutine call, with input register AX set to one of the following operation codes:

#define BEF_LEGACYPROBE 1 /* probe for legacy devices */
#define BEF_INSTALL 2 /* install the given configurations */

The BEF returns a value in AX to indicate the return status of the call.

When the operation is BEF_LEGACYPROBE, the BEF returns 0 for success, or one of the error codes listed below for failure.

When the operation is BEF_INSTALL, the BEF returns the highest BIOS device code that was taken by the BEF (refer to section 2.7.3) or one of the error code listed below for failure.

#define BEF_FAIL (-1) /* unknown failure */
#define BEF_PROBEFAIL (-2) /* confirming probe failed for BEF_INSTALL */
#define BEF_RESFAIL (-3) /* not enough resources for devices */
#define BEF_BADFUNC (-4) /* invalid dispatch function */

2.5 bef_interface structure

On entry to the initialization entry point, ES:DI contains a pointer to a bef_interface structure, which looks like:

struct bef_interface {
int version;
int(far *resource)(int, char far *, DWORD far *, DWORD far *);
int(far *node)(int);
int(far *prop)(int, char far *, char far * far *, int far *, int);
int(far *putc)(int);
int(far *mem_adjust)(unsigned short, unsigned short);
unsigned short mem_base;
unsigned short mem_size;
};

The BEF should not write to any of the values in this structure. The elements of the structure are defined in sections 2.5.1 through 2.5.8.

2.5.1 BEF interface version

This is filled in by the configuration assistant with the version of the BEF interface that the running configuration assistant supports. This is the value of BEF_IF_VERS constant at the time the configuration assistant was built.

2.5.2 Resource callback function

The resource callback function is used by the probe and install operations to reserve and access resources such as I/O register space, interrupts, etc. The general idea is that the boot system attempts to prevent a BEF from having probe conflicts with other boards by carefully managing resource usage.

The resource function is called with C-subroutine calling semantics, and takes 4 parameters:

rc = (*resource)(fn|opts, char far *name, DWORD far *val, DWORD far *len);

The first parameter is a function code, which may be or'ed together with option flags. The valid function codes are:

#define RES_SET 0x01 /* set given resource */
#define RES_GET 0x02 /* get given resource */
#define RES_REL 0x03 /* release given resource */

Valid options flags are:

#define RES_SHARE 0x0100 /* resource may be shared w/ other devices */
#define RES_SILENT 0x0200 /* no complaint if resource conflict */

The next three parameters are far pointers to the resource name, value, and length. Detailed information on the resource callback function is provided in Appendix 1, which includes: a list of the supported resource names, respective value representations, and applicable resource-specific flags.

The return codes from the resource callback are:

#define RES_OK 0 /* .. op functioned normally */
#define RES_FAIL (-1) /* .. internal framework error */
#define RES_CONFLICT (-2) /* .. resource conflict */

Note: When RES_SILENT has been used in conjunction with a RES_SET call, the configuration assistant will not present any warning mesages to the user that might otherwise have been presented if it is returning a failure code of RES_CONFLICT.

2.5.3 Node callback functions

The node callback function is used by the probe and install operations to open and close a device node.

The node function is called with C-subroutine calling semantics, and takes 1 parameter, which is an operation code:

(*node)(op);
#define NODE_START 0x01 /* start a new node */
#define NODE_FREE 0x02 /* error occurred, free up node space */
#define NODE_DONE 0x03 /* node complete */

The return codes from the node callback are:

#define NODE_OK 0x00 /* op functioned normally */
#define NODE_FAIL (-1) /* .. generic failure */

2.5.4 Property callback function

The property callback function is used by the probe and install operations to retrieve and set properties associated with the current device node. The properties are created in/retrieved from the device tree that will be available to the operating system when the booting system transfers control to the kernel.

The property function is called with C-subroutine calling semantics, and takes 5 parameters:

rc = (*prop)(fn, char far *name, char far * far *val, int far *len, int bin);

The first parameter is a function code, The valid function codes are:

#define PROP_GET 1 /* .. Set a device property */
#define PROP_SET 2 /* .. Get a device property */

The next three parameters are far pointers to the property name, a pointer to a far pointer to the value, and a pointer to the length. The last parameter is a flag indicating whether to create a binary or a character property. The valid flag values are:

#define PROP_CHAR 0 /* property is a character string */
#define PROP_BIN 1 /* property is a set of binary bytes*/

When doing a PROP_GET function, the current node is searched for the requested property, followed by the /options node if the property was not found on the device node. If the property was found, the pointer pointed to by val is filled in with a pointer to the property and the int pointed to by len is filled in with the property length. If the property is not found, the pointer is set to NULL.

The return codes from the property callback are:

#define PROP_OK 0 /* .. op functioned normally */
#define PROP_FAIL (-1) /* .. generic failure */

2.5.5 Putc callback function

The putc callback function is used by the BEF to output a character to the system console.

The putc function is called with C-subroutine calling semantics,and takes 1 parameter, which is the character to be output to the console:

rc = (*putc)(int);

2.5.6 Mem_adjust callback function

The mem_adjust callback function is used by the BEF to either grow or shrink itself. One required parameter is the base of the BEF, which was supplied in the mem_base field.

The mem_adjust function is called with C-subroutine calling semantics, and takes 2 parameters, which are the paragraph base of the segment to be adjusted and the desired new size of the segment in paragraphs.

rc = (*mem_adjust)(ushort, ushort);

The return codes from the mem_adjust callback are:

#define MEM_OK 0 /* .. op functioned normally */
#define MEM_FAIL (-1) /* .. couldn't change to desired size */

2.5.7 mem_base

The paragraph address of memory allocated for the driver. Note that since the entire BEF file is loaded into memory, the EXE header for the BEF can be found at the mem_base address. The EXE header is useful for large model BEFs to use in setting up access to their data, etc.

2.5.8 mem_size

The amount of memory initially allocated for the driver in paragraphs.

2.6 Probe Operation

The LEGACYPROBE operation is used to find non-PNP ISA devices, that are also referred to as legacy devices. PNP ISA devices, and devices on other busses (ex. MC, EISA, PCI) are identified via bus enumeration functions performed automatically by the boot system.

For every possible location that a legacy device might exist the BEF performs the following steps:

NODE_START
RES_SET for all device resources (see 2.6.1)
if (RES_SET fails) NODE_FREE
Perform probe (see 2.6.2)
if (probe succeeded) NODE_DONE else NODE_FREE

2.6.1 device resources

The complete list of device resources (and corresponding values and flags) is included in Appendix 1.

2.6.2 Probing for a device

For legacy ISA devices, the probe code must actually read and write to device registers in an attempt to determine if the device is present. This can be dangerous (since there may be other devices at the address being probed), so the driver writer should be as careful to attempt any read-only verifications that are possible before writing to registers.

2.7 Install Operation

The INSTALL operation uses the RES_GET function to find the valid resources for this driver. The only probing the driver does at this point is to confirm that the given information is correct.

The install code loops until the NODE_START operation returns an error. For each iteration of the loop, install performs the following operations:

NODE_START
RES_GET for all device resources (see 2.7.1)
if (RES_GET fails) return (BEF_FAIL)
Perform confirmation checks (see 2.7.2)
if (confirmations failed) return (BEF_FAIL)
Install operational interfaces (see 2.7.3)
NODE_DONE

2.7.1 device resources

The complete list of device resources (and corresponding values and flags) is included in Appendix 1.

2.7.2 confirmation checks

On a bus that does include self-identifying information, the install routine should use this information to confirm that the resources returned by RES_GET match the self-identifying information of the device.

2.7.3 Install operational interfaces

When the driver is ready to install its operational interface, it performs the following steps:

A) Find available BIOS device code(s)

The BEF finds available codes by probing the BIOS (INT13 code 0xF8) until finding one that's not already taken. Valid device codes are in the range 0x10 to 0x7F.

Note that after a successful call to BEF_IDENT, dx contains a magic word. This is because we are not able to rely on all BIOSes to set the carry flag for calls to unsupported device numbers.

The following pseudo-code demonstrates the correct method for finding an available code:

for (dev = 0x10; dev != 0x7F; dev++)
{

dl = dev
ah = 0xF8 (BEF_IDENT)
INT 0x13
if (carry)
return(dev) /* free device code */

if (dx != BEF_IDENTMAGIC)

return(dev) /* free device code */

}

return(FAILURE)

B) Patches in an INT13 BIOS extension for the device.

The BEF patches into INT13 by saving the current vector in the interrupt vector table (located in memory starting at address 0), and patching in its own vector. When the BEF interrupt routine is called, it determines whether it handles the device number passed in the DX register. If it does, then it processes the interrupt, otherwise, it passes the interrupt to the old routine from the table.

C) If supporting a multi-channel device fill in user_bootpath.

The BEF should fill in the user_bootpath field of the bdev_info structure with a scsi channel component of the form "mscsi@<channel>,0" for each device on each channel that it supports. For single channel scsi controllers this should not be done.

3.0 Operational Interface

Once the BEF has been installed (either by the mechanisms described in section 2, or by some other means), the BEF must present the boot system with the operational interface described in this section.

All BEFs must provide the operational interface.

3.1 INT13 interface

All BEFs must provide an INT13 interface.

For INT13 operations, the operation code is stored in ah, and the BIOS device number is store in dl. If dl does not match a device number for the device, then the INT13 routine should pass the call on to the next device in the chain.

3.1.1 INT13 Commands supported by all BEFs

BEF_IDENT (0xF8):

Description:

All BEFs must support this command.

Returns pointers to controller ID string and bdev_info structure for device. bdev_info structure contains quite a bit of information which is obtained from probing, device configuration registers and/or other sources.

Input registers:

ah = 0xF8 dl = device number

Output registers:

ah = return status
0x00: Operation successful 0xBB: Undefined error occurred
carry = 0 successful, 1 if error occurred
es = BEF resident data segment
es:bx = pointer to bdev_info structure for device (see below)
es:cx = pointer to character string identifying controller dx = BEF_IDENTMAGIC (0xBEF1)

Note that after a successful call to BEF_IDENT, dx contains a magic word. This is because we are not able to rely on all BIOSes to set the carry flag for calls to unsupported device numbers (see section 2.7.3).

The description of the bdev_info structure is shown in Appendix 2.

BEF_RESET (0x00):

Description:

All BEFs must support this command.

For disk controllers, this is the standard BIOS "Disk Controller Reset" command, which should reset the HBA.

For network controllers, this entry point causes the following steps to occur:

BEF initializes the device hardware.

BEF patches in an INT 0xFB BIOS extension for the operation of the network device (described fully in section 3.2).

Input registers:

ah = 0x00 dl = device number

Output registers:

ah = return status
0x00: Operation successful 0xBB: Undefined error occurred
carry = 0 successful, 1 if error occurred

3.1.2 INT13 Commands supported only by Disk Controller BEFs

BEF_READ (0x02):

Description:

This command applies only to BEFs for disk controllers. BEFs for network controllers should return error when they receive this command.

This is a standard BIOS "Read Disk Sectors" command. Seeks to the specified location and reads a number of 512 byte disk sectors. The read data is placed into RAM at the location specified by ES:BX.

For devices with block sizes larger than 512 bytes, the request may call for a fragment of a block. In this case, the block should be read into a local buffer, and then the desired portion should be copied to the user buffer.

The bdev_info structure contains a number of fields that need to be checked by the BEF when a disk read is requested. This is necessary because the BEF may be taking over reads from the BIOS for the device in question. This is required because the BEF may use for the device differently from the BIOS (e.g. synchronous vs. non-synchronous, etc.), these fields tell the BEF what the BIOS was using as the device geometry of the disk device. The bdev_info fields are: cyls, heads, secs and bdev. Bdev is the device id that the BIOS was using to refer to the given disk. If the booting system has filled this field in with a value in the range 0x80 - 0x8f, the BEF must now take all responsibility for reads to the given disk whenever a request for a read with that device number is recieved. In addition to any requests for devices in the range returned from the BEF_INSTALL, call that installed the BEF. Reads that are to the "bdev" device should be interpreted as to a device with the geometry described by the "cyls", "heads" and "secs" fields of the bdev_info structure.

Input registers:

ah = 0x02
al = number of sectors to read
ch = lowest 8 bits of 10 bit cylinder number (0 based)
cl = bits 6 & 7: cylinder number bits 8 and 9
bits 0 - 5: starting sector number (1 based)
dh = bits 0 - 5: head number
dl = device number
es:bx = pointer where to place info read from disk
Output registers:

ah = return status
0x00: Operation successful
0x04: Requested sector not found
0xBB: Undefined error occurred

Output registers:

ah = return status

0x00: Operation successful 0x04: Requested sector not found

0xBB: Undefined error occurred BEF_GETPARMS (0x08):

Description:

This command applies only to BEFs for disk controllers. BEFs for network controllers should return error when they receive this command.

This is the standard BIOS "Read Disk Drive Parameters" command. Gets the driver parameters for the specified device.

Input registers:

ah = 0x08 dl = device number

Output registers:

ah = return status

0x00: Operation successful
0xBB: Undefined error occurred

carry = 0 successful, 1 if error occurred

ch = lowest 8 bits of 10 bit maximum cylinder number, 0 based
cl = bits 6 & 7: maximum cylinder number bits 8 and 9
bits 0 - 5: maximum sector number
dh = bits 0 - 5: maximum head number
dl = number of drives, 1 or 2

3.2 INT 0xFB Interface

All network controller BEFs must provide the INT 0xFB interface. The handler for the 0xFB interface is installed after the network device is reset with the INT 13 BEF_RESET (0x00) command.

The four commands described in sections 3.2.1 through 3.2.4 must be supported by all network BEF drivers.

3.2.1 CLOSE_CALL (0x02):

Description:

Called when the services of the real-mode driver are no longer needed. The driver should reset the hardware to its power-up state.

Input Registers:

AH = 0x02

Output Registers:

NONE
3.2.2 GET_ADDR_CALL (0x05):

Description:

Returns the MAC address for the device

Input Registers:

AH = 0x05

Output Registers

BX:CX:DX contains the address

ea[0] = (unsigned char)(bx / 256);
ea[1] = (unsigned char)(bx % 256);
ea[2] = (unsigned char)(cx / 256);
ea[3] = (unsigned char)(cx % 256);
ea[4] = (unsigned char)(dx / 256);
ea[5] = (unsigned char)(dx % 256);

3.2.3 SEND_CALL (0x03):

Description:

Takes a packet and sends it out to the network.

The packet is Ethernet-formatted so token ring drivers must translate it to the proper format before sending it out; that is, each packet begins with 6 bytes of destination and 6 bytes of source address. Token ring drivers may also need to add source routing information to the token ring header.

If the driver cannot send the packet (due to sychrnonization or resource shortage), the packet can be dropped. All protocols that use this interface must time out and retry transmission.

Input Registers:

AH = 0x03
BX:SI = packet buffer address
CX = length of outgoing packet

Output Registers:

NONE

3.2.4 RECEIVE_CALL (0x04):

Description:

Copies a received network packet into the buffer specified by DX:DI. If no receive packet is available, then returns immediately, with CX set to 0.

Input Registers:

AH = 0x04
CX = length of buffer
DX:DI = receive buffer address

Output Registers:

CX = number of bytes in received packet, 0 if no received packet is available.

APPENDIX 1: Details for Resource Callback Function

(*resource)(RES_SET | opts, char far *name, DWORD far *val, DWORD far *len);

Makes a reservation for the named resource on behalf of the current node. "name" is the resource name which is being reserved. "val" is an array of DWORDs in which the values of the resources are stored. "len" contains the number of DWORDs.

The following options may be ORed into the "RES_SET" function code:

#define RES_SHARE 0x0100 /* resource may be shared w/ other devices */
#define RES_SILENT 0x0200 /* if conflict occurrs, just fail silently */

The layout of the buffer pointed to by "val" is resource type specific: name len value buffer

Name Len value buffer
"addr" 1 PCI device address (bus no. << 8 or'd with PCI device/function byte). This resource is
only supported for PCI devices and can only be gotten and not set.
"slot" 2 PCI/EISA slot number in high/low half of the first word, slot flags (see "RES_SLOT_*", above) in second word.

NOTE: PCI cards have two slot numbers, a virtual EISA slot and a physical PCI slot. Also, "slot" can only be gotten, not set.

"name" 2 EISA device name (compressed form) in the first word, bus type in the second word. If the bus type is PCI, the compressed name consists of the concatenation of the 16-bit vendor and device names. If bus type is MCA, it consists of the 16-bit MCA device id.
"port" 3N 3-word tuple for each resource; Port address in first word, size (in bytes) in 2nd, and flags (see "RES_PORT_*", above) in third.
"irq" 2N 2-word tuple for each resource; IRQ number in first word, flags (see "RES_IRQ_*", above) in second.
"dma" 2N 2-word tuple for each resource; DMA channel number in 1st word, flags (see "RES_DMA_*", above) in second.
"mem" 3N 3-word tuple for each resource; memory addr in first word, size (in bytes) in 2nd, and flags (see "RES_MEM_*", above) in third.

Drivers must obey the following rules when using the RES_SET callback:

1. No more than one "name" resource can be set per device.

2. Reservations cannot be "interrupted". Once you start reserving resources of a given type, you must reserve all resources of that type before going on to the next type.

RES_SET returns 0 if the reservation is made successfully, RES_CONFLICT if the reservations conflicts with another device, or RES_FAIL if the interface protocol is violated.

(*resource)(RES_REL, char far *name, DWORD far *val, DWORD far *len);

Releases a reservation made by RES_SET. Arguments are the same as for RES_SET, except that no flags are specified. Returns 0 if it works, RES_FAIL if the specified resource is not currently reserved. You cannot release a "name" reservation; use NODE_FREE instead.

(*resource)(RES_GET, char far *name, DWORD far *val, DWORD far *len);

Returns the current device's assignments for the "name"d resource (as established by RES_SET or by the PnP BIOS/CM) in the "len" word "val"ue buffer. The value buffer is type-specific as described above. The "Len"gth word specifies the maximum value buffer size (in 32-bit words) upon entry, the number of words actually used upon return.

Returns 0 if the resource assignments are successfully returned even if there are no resources of the indicated type assigned to the current device ("len" is set to zero in this case). Returns RES_FAIL if something goes wrong.

Resource type flags:

These bits appear in the flags word of the value buffer
used with the RES_SET and RES_GET operations.

/* *** Memory flags *** */

#define RES_MEM_WRITE 0x0001 /* RAM if set, ROM otherwise */
#define RES_MEM_CACHED 0x0002 /* Cached memory if set */
#define RES_MEM_TYPE 0x0018 /* Memory type code: */
#define RES_MEM_TYPE_SYS 0x0000 /* .. system (local bus) memory */
#define RES_MEM_TYPE_EXP 0x0008 /* .. expansion bus memory */
#define RES_MEM_TYPE_VIR 0x0010 /* .. virtual memory */
#define RES_MEM_TYPE_OTH 0x0018 /* .. something else! */
#define RES_MEM_SHARE 0x0020 /* Memory may be shared */
#define RES_MEM_SIZE 0x0300 /* Memory size code */
#define RES_MEM_SIZE_BYTE 0x0000 /* .. 8 bits */
#define RES_MEM_SIZE_WORD 0x0100 /* .. 16 bits */
#define RES_MEM_SIZE_LONG 0x0200 /* .. 32 bits */
#define RES_MEM_SIZE_HUGE 0x0300 /* .. 64 bits */
#define RES_MEM_DECODE 0x0C00 /* Decode size (address bits) */
#define RES_MEM_CODE_1MB 0x0000 /* .. 20 bits (1MB address space) */
#define RES_MEM_CODE_16MB 0x0400 /* .. 24 bits (16MB address space) */
#define RES_MEM_CODE_4GB 0x0800 /* .. 32 bits (4GB address space) */

#define MemMask \
(RES_MEM_WRITE+RES_MEM_CACHED+RES_MEM_TYPE+RES_MEM_SIZE+RES_MEM_DECODE)

/* *** IRQ flags *** */

#define RES_IRQ_TRIGGER 0x0020 /* Level triggered if set */
#define RES_IRQ_SHARE 0x0040 /* Devices may share IRQ */

#define IrqMask (RES_IRQ_TRIGGER+RES_IRQ_SHARE)

/* *** DMA flags *** */

#define RES_DMA_SHARE 0x0040 /* DMA channel may be shared */
#define RES_DMA_SIZE 0x0C00 /* DMA transfer size */
#define RES_DMA_SIZE_8B 0x0000 /* .. 8 bits */
#define RES_DMA_SIZE_16B 0x0400 /* .. 16 bits */
#define RES_DMA_SIZE_32B 0x0800 /* .. 32 bits */
#define RES_DMA_SIZE_64B 0x0C00 /* .. 64 bit */
#define RES_DMA_TIME 0x3000 /* DMA timing code */
#define RES_DMA_TIME_ISA 0x0000 /* .. ISA compatible */
#define RES_DMA_TIME_A 0x1000 /* .. Type "A" */
#define RES_DMA_TIME_B 0x2000 /* .. Type "B" */
#define RES_DMA_TIME_C 0x3000 /* .. Burst */

#define DmaMask (RES_DMA_SIZE+RES_DMA_TIME)

/* *** I/O Port flags *** */

#define RES_PORT_SHARE 0x0040 /* Devices may share port */
#define PortMask (0)

/* *** Slot Flags *** */

#define RES_SLOT_DUPID 0x000F /* Duplicate config file number */
#define RES_SLOT_TYPE 0x0030 /* Slot type: */
#define RES_SLOT_TYPE_EXP 0x0000 /* .. expansion slot */
#define RES_SLOT_TYPE_MB 0x0010 /* .. embedded slot (motherboard) */
#define RES_SLOT_TYPE_VIR 0x0020 /* .. virtual slot */
#define RES_SLOT_NOREAD 0x0040 /* Not readable if set */
#define RES_SLOT_DUPPRES 0x0080 /* Duplicate .cfg present if set */
#define RES_SLOT_ENABSUP 0x0100 /* Board enable supported if set */
#define RES_SLOT_IOCHKERR 0x0200 /* IOCHKERR supported if set */
#define RES_SLOT_LOCK 0x0400 /* Configuration locked if set */
#define RES_SLOT_EISA 0x2000 /* EISA slot if set */
#define RES_SLOT_NOCFG 0x4000 /* No .cfg file if set */
#define RES_SLOT_CFGSTAT 0x8000 /* Configuration incomplete if set */

#define SlotMask \
(RES_SLOT_DUPID+RES_SLOT_TYPE+RES_SLOT_NOREAD+RES_SLOT_DUPPRES \
+RES_SLOT_ENABSUP+RES_SLOT_IOCHKERR+RES_SLOT_LOCK+RES_SLOT_NOCFG \
+RES_SLOT_CFGSTAT)

/* *** Bus Types *** */

#define RES_BUS_ISA 0x01 /* .. ISA (not self identifying) */
#define RES_BUS_EISA 0x02 /* .. EISA (treated as ISA) */
#define RES_BUS_PCI 0x04 /* .. PCI only */
#define RES_BUS_PCMCIA 0x08 /* .. PCMCIA */
#define RES_BUS_PNPISA 0x10 /* .. Plug-n-Play ISA */
#define RES_BUS_MCA 0x20 /* .. IBM Microchannel */

APPENDIX 2: bdev_info structure


struct bdev_info { /* Structure for storing information about boot devices */
/*
* The first few items here can also be treated as a single
* string. Do not put anything else in here unless it is
* intended to be part of the string.
*/
unchar vid[8]; /* For SCSI: Vendor ID from SC_INQUIRY command */
/* For NET: controller name */
unchar blank1; /* Blank character to separate fields */
unchar pid[16]; /* For SCSI: Product ID from SC_INQUIRY command */
/* For NET: string of form "I/O=%x IRQ=%d" */
unchar blank2; /* Blank character to separate fields */
unchar prl[4]; /* For SCSI: Product rev level from SC_INQUIRY */
/* For NET: leave blank */
unchar term; /* Null terminator for string */

/* End of composite string */
unchar reserved; /* reserved field */
ushort base_port; /* Base I/O address of adapter */

/* The following union contains a component structure for each type of
* device that is supported by the MDB spec. We currently support
* SCSI HBA's and network adapters.
*/
union {
struct { /* structure for storing information about SCSI devices */
ushort bsize; /* Device block size */
unchar targ; /* SCSI target number */
unchar lun; /* Device logical unit number */
unchar pdt; /* Peripheral device type */
unchar dtq; /* Device type qualifier */

} scsi; /* end of SCSI section */

struct { /* structure for storing information about network devices */

ushort irq_level; /* IRQ level used by device */
ushort mem_base; /* Segment address of base memory */
ushort mem_size; /* Segment size of base memory */
short index; /* multi-purpose field: */
/* slot# on mc/eisa machines, */
/* index into base_port array on isa */

} net; /* end of network section */

} MDBdev; /* end of union */

unchar dev_type; /* indicates type of MDB device */

#define MDB_SCSI_HBA 0x01
#define MDB_NET_CARD 0x02

unchar bios_dev; /* BIOS device ID number */
unchar hba_id[8]; /* For SCSI only: HBA ID string */
unchar pci_valid; /* 1 for PCI device, otherwise 0 */
unchar pci_bus; /* pci bus number */
ushort pci_ven_id; /* pci vendor id */
ushort pci_vdev_id; /* pci vendors device id */
unchar pci_dev; /* pci device (on bus) */
unchar pci_func; /* pci function (of devno) */
char user_bootpath[80]; /* user supplied bootpath */
ushort cyls; /* BIOS cylinders value */
unchar heads; /* BIOS heads value */
unchar secs; /* BIOS sectors value */
unchar bdev; /* BIOS device id value */
char junk[8]; /* DOS alignment problem insurance */

};