Loadable device drivers provide the ability to support additional hardware devices. Once loaded the device driver is no different in structure to a resident device driver which is linked into the IBMBIO.COM file. Normally device drivers are of 8080 type memory model, that is, the code and data segments are the same. Device drivers usually have the file extension .SYS. They may also be of type .COM or .EXE. The memory image must start with a device header, which is a data structure whose format is described in the following section.
The device drivers are of two types, Block and Character drivers.
Character devices perform sequential input/output. An application can open a channel to a character device to perform input/output to it. Each character device has a different name, for example MODEM.
Block devices perform random input/output to the disk drives in the system. They are not named but are mapped to the drive letters a:, b:, and so on. A single physical disk may be subdivided into several mapped units. The minimum block size is the physical sector size of the device. For example, often the diskette drives are units a: and b: and the first hard disk divided into partitions c: and d:. A block device driver may manage several physical units each with its own mapping. There may be multiple block device drivers each managing multiple units.
Structure of Device Driver Header
This is a double word pointer to the next device driver. The last driver in the chain has the special value FFFF:FFFF.
This field describes the device driver. Figure 6-2 defines the bits in the attribute field.
Figure 6-2 Structure of Character Device ATTRIBUTE Word in DRIVER HEADER
Figure 6-3 Structure of Block Device ATTRIBUTE Word in
This offset within the driver is the entry point of the strategy code. The strategy code is called by DR-DOS when a function is to be performed. DR-DOS passes a pointer to a request packet. The device driver stores the pointer in a queue. Registers must be preserved throughout this call.
This offset within the driver is the entry point of the interrupt code. The interrupt is called by DR-DOS to process a request packet previously set by a call to the strategy entry. The driver interprets the request packet, performs the function and returns to DR-DOS. Registers must be preserved unless the function uses them to return values.
For a character device this field contains the 8 byte ASCII name of the device. The name is padded with space characters to the 8 bytes. Only valid filename characters are allowed. For a block device the first byte of this field contains the number of units supported by this driver. DR-DOS fills in this field after the driver has been initialized.
This structure is of variable length depending on the function. The minimum size is 13 bytes which are defined as follows. The address of this packet is passed in the register pair ES:BX on the strategy call to the driver.
Structure of the Fixed Part of any Request Packet
Length of this packet in bytes
Unit number (block devices only)
Function number. Defined as follows
Structure of STATUS Word in REQUEST PACKET
Structure of the BPB (BIOS Parameter Block)
DR-DOS provides a number of functions for use in building device drivers. The functions are described in the following subsections.
The INIT function performs any hardware and software initialization for that driver, sets the ending address of the driver and sets the status word in the request header. For block devices INIT also sets the number of units and the pointer to the BPB array. By setting the ending address the driver can release memory no longer required or allocate more memory for data structures and buffers.
Structure of Request Header for INIT Function
This byte is set to the number of units supported by the driver (Block devices only).
This double word is set to point to the first available byte of memory following the driver. This allows a single driver to increase or decrease its memory space and enables DR-DOS to optimize the memory space allocated to loadable drivers. For the case where drivers are linked in one group each driver alters a variable that indicates the end of the groups memory and returns this value in the ENDADDR field. In this way each driver can allocate more data space. This variable is returned in the ENDADDR field as each driver is initialized. As the INIT function is only called once when the driver is installed, the INIT code may be placed at the end of the driver after the byte indicated by the ENDADDR value. This allows the code used for the INIT function to be discarded.
This double word field is set by block device drivers to point to an array of word length pointers to BPB structures. There is one entry in the array for each unit supported by this driver. These BPBs are read-only, so if more than one unit uses the same BPB the array pointer can point to the same structure.
On entry the double word BPBPTR points to a string that may contain options. The string is used for loadable drivers that have been loaded via the DEVICE= function in the CONFIG.SYS file. The string points to the first non-white space character following the DEVICE=.
This is set by DR-DOS to the logical drive to be assigned to the first unit supported by this driver.
The MEDIA CHECK function tests the unit to determine whether the media has been changed since the last I/O function. It is used with block devices only and the purpose is to improve performance. If the media in the unit has not been changed there is no need for DR-DOS to log in the drive again.
Structure of Request Header for MEDIA CHECK Function
MDB is the current media description byte as passed from DR-DOS. The function returns one of three values in the return field.
-1 Media HAS been changed.
0 Media MAY have been changed.
1 Media HAS NOT been changed.
If no hardware change line is available for the drive a simple timer should be used to return not changed for a couple of seconds after the last successful disk access. This improves performance on removable media where there is regular frequent access to the disk.
The BUILD BPB function is used with Block devices only. It is called by DR-DOS when a media change has been detected and DR-DOS needs to relog the disk. The driver should read the disk to determine its media type and return a pointer to the BPB it has selected or constructed.
Structure of Request Header for BUILD BPB Function
If the attribute field bit 13 is 0 for this driver DR-DOS passes a double word pointer TRFADDR to a sector buffer containing the first sector of the FAT. (Note that this must be the same sector for all disks to be supported.) The FAT ID byte is the first byte in this buffer and can be read by the drivers to set the BPB. If the bit 13 in the attribute field is set to 1 then the double word TRFADDR points to a sector buffer that can be used by the driver to read a sector from the disk and determine the BPB.
The structure of a BPB is described in section 6.4, BIOS Parameter Block.
Structure of Request Header for the Functions
INPUT, OUTPUT and OUTPUT with VERIFY
The INPUT function reads the specified number of characters from a character device or sectors from a block device. The driver returns in the count field the actual number of bytes or sectors transferred and sets the returned status word.
The OUTPUT function writes a specified number of characters to a character device or sectors to a block device. The driver returns in the count field the actual number of bytes or sectors transferred and sets the returned status word.
OUTPUT with VERIFY is the same function as OUTPUT, except that on a block device a read after write check is performed to verify that the data has been correctly written. IOCTL INPUT and OUTPUT perform the operation as for INPUT and OUTPUT but without error checking.
This function is available only for character devices and allows DR-DOS to input a character without removing it from the input buffer. The character is returned in the request header and the busy bit set to 0. If no character is available then the busy bit is returned as 1.
Structure of Request Header for NON-DESTRUCTIVE INPUT, NO WAIT Function
The INPUT FLUSH and OUTPUT FLUSH functions cause the input or output buffers used with character devices to be flushed. The status word is set to no error.
Structure of Request Header for INPUT FLUSH or
OUTPUT FLUSH Function
The OPEN and CLOSE functions are used by DR-DOS to inform the BIOS whenever a file is opened or closed on a block device, or when a character device is opened or closed.
Structure of Request Header for OPEN or CLOSE Function
This allows the BIOS to keep track of whether there are any open files on a device. If the BIOS manages local buffers, for example Track buffers, on a device with removable media then when the last file on a device is closed the BIOS should flush the local buffer. For a character device such as a printer the BIOS could send an escape sequence to reset the type face and force a form feed when the device is opened.
The REMOVABLE MEDIA function for block devices only reports whether the unit contains removable media. The busy bit in the status word is set to 1 if the media is permanent or to 0 if it is removable.
Structure of Request Header for REMOVABLE
The STATUS function for character devices tests if the output device is ready or if the buffer of an input device contains a character. It is used to ensure that a subsequent INPUT or OUTPUT function call would not have to wait within the driver for the hardware to complete. The function returns the busy bit in the status word as 0 if the device is ready for OUTPUT or INPUT and 1 if a subsequent INPUT or OUTPUT function would have to wait.
Structure of Request Header for INPUT STATUS
or OUTPUT STATUS Function
The Generic IOCTL function is the interface to the drivers for the DR-DOS function 44H IOCTL. The full interface for this function is described in Appendix A, Device I/O Control. The request header passes a double word pointer GENPB to the parameters passed by the application. The CX register is passed in the request header as the major and minor function numbers requested by the application.
Structure of Request Header for GENERIC IOCTL Function
The GET / SET LOGICAL DEVICE function allows an application to use block devices that map more than one logical unit to the same physical device. For example, in a system with one diskette drive the disk driver maps both drives A: and B: to the first diskette drive. The GET function returns 0 in the LOGICAL field if there is no mapping, otherwise it returns 1, 2, and so on, to indicate the current mapped unit. The SET call allows the application to pass the logical unit number required to be the current unit. The LOGICAL field is returned as for the GET function.
Structure of Request Header for GET/SET LOGICAL Function
[Front] [Prev Chapter] [Next Chapter]