|
|
Block drivers buffer data being transferred between a user-level process and the device using the system buffer cache. Block drivers are normally written for disk drives and other mass storage devices.
In DDI versions prior to version 8 and on SCO OpenServer 5 systems, block drivers are characterized by the strategy(D2) or strategy(D2oddi) entry point routine that is used for I/O transfers.
Beginning with DDI 8, all non-STREAMS drivers use the biostart(D2) entry point for I/O transfers, so there is no structural difference between block and character drivers. A driver for a device can be opened once for block access and once for character access. The filesystem keeps a cache in memory of all data accessed by the block file; all the caching is handled outside of the device driver.
See Intro(D2) for a list of entry point routines used for block drivers in DDI versions prior to version 8.
DDI drivers for mass storage devices (either SCSI or non-SCSI) usually use SDI. This means using the entry point routines that are documented in Section D2sdi manual pages of the manual pages, with functions from Section D3sdi manual pages to supplement those in Section D3 manual pages, and accessing the structures documented in Section D4sdi manual pages as well as those documented in Section D4 manual pages. See Developing SDI storage drivers.
On SCO OpenServer 5 systems, block drivers use the following entry-point routines, documented in the Section D2oddi manual pages:
Block driver entry-point routines
Type | Routine | Purpose |
entry point | open(D2oddi) | start access to a block device |
close(D2oddi) | end access to a block device | |
strategy(D2oddi) | perform buffered I/O with device | |
print(D2oddi) | display messages on the console | |
physical I/O | read(D2oddi) | perform raw reads from a block device |
write(D2oddi) | perform raw writes to a block device | |
ioctl(D2oddi) | perform I/O control commands | |
dma_breakup(D3oddi) | size I/O request into usable chunks (DMA) | |
pio_breakup(D3oddi) | size I/O request into usable chunks (PIO) | |
device-specific | init(D2oddi) | initialize the device when the system boots |
intr(D2oddi) | handle interrupt from a block device | |
start(D2oddi) | access device-specific I/O ports | |
probe(D2oddi) | defines the device for the Device Query Interface |
For more information about writing SCO OpenServer 5 block device drivers,
see Chapters 7 and 8 of Peter Kettle and Steve Statler,
Writing Device Drivers for SCO UNIX.
Devices, especially storage devices, often offer support for both raw and block I/O. DDI 8 drivers use the biostart(D2) entry point routine for both raw and block I/O, but ODDI drivers and DDI drivers prior to version 8 must code a strategy(D2) entry point for block I/O and read(D2) and write(D2) entry points for raw I/O. The ODDI routines are strategy(D2oddi), read(D2oddi), and write(D2oddi).
When performing raw I/O, a user process can open and read/write directly to a device. All I/O transfers take place directly to the process's address space, without any intervening copying to the kernel address space. The process's virtual-to-physical address translation must be maintained at least for the duration of the transfer, or data could be copied to a totally unrelated physical memory location. In addition, because the I/O request from the user can be initiated as a vector and requests for reads and writes can be interspersed with lseeks, it is necessary to generate a mapping scheme to translate a user process's view of I/O to absolute locations on a device. The physiock(D3) function accomplishes this task for DDI drivers;. the physio(D3oddi) and physck(D3oddi) functions serve the same purpose for ODDI drivers. The functionality provided includes the following:
When programming a block device to support raw I/O, you must generate a set of kernel virtual addresses that the driver can use during the raw I/O operations where user virtual/physical addresses serve as the source or destination of transfer. When doing programmed I/O, the physical memory (corresponding to the user's virtual address) from which the I/O takes place should have a kernel virtual address for the drivers to use. When using DMA, you must ensure that the data is moved to and from the correct physical location. A process's virtual to physical address translation should be unchanged during an I/O data transfer.
See ``DMA'', ``Programmed I/O (PIO)'', ``Memory-mapped I/O'', and ``Memory allocation''.