The TURBOchannel bus is a synchronous, asymmetrical I/O channel that some Alpha CPUs support. You do not need an intimate understanding of the TURBOchannel hardware to write TURBOchannel device drivers. Therefore, this chapter discusses only the following aspects of the software architecture for a TURBOchannel device driver:
Whenever a TURBOchannel device driver writes to a hardware device register, the write may be delayed by the system write buffer used to synchronize the CPU on the TURBOchannel bus. A subsequent read of that register is not guaranteed to wait for the write to be completed. To ensure that a write to I/O space has completed prior to a subsequent read operation, the driver calls the mb interface. To ensure that multiple writes to the same hardware device register result in the device receiving the correct number of write requests in the proper order, you must insert calls to mb between each write. Otherwise, write requests may be merged in the write buffer with the result that the device receives fewer write requests than you intend or receives them in the wrong order.
ULTRIX on MIPS CPUs uses the wbflush interface to ensure that a write to I/O space has completed prior to a subsequent read operation. Although wbflush is aliased to mb on Alpha CPUs, Digital recommends that you call mb in all new device drivers.
Previous versions of this book discuss several TURBOchannel-specific interfaces associated with direct memory access (DMA) transfers. The tc_map_alloc, tc_loadmap, and tc_map_free interfaces let you allocate, load, and free (return to the free pool) entries for scatter-gather list maps. The tc_isolate_memerr interface lets you isolate and log errors that occur on a DMA transfer.
There is a drawback to using the TURBOchannel-specific interfaces: DMA operations can differ markedly from one device driver to another because of the DMA hardware support features for buses on Alpha systems and because of the diversity of the buses themselves. If you use the TURBOchannel-specific interfaces for performing DMA, you probably will not be able to write one device driver that operates on more than one CPU architecture or more than one CPU type within the same architecture.
To provide portability with regard to DMA operations, Digital UNIX provides generic kernel interfaces to the system-level interfaces required by device drivers to perform a DMA operation. These generic interfaces are typically called ``mapping interfaces.'' This is because their historical background is to acquire the hardware and software resources needed to map contiguous I/O bus addresses and accesses into discontiguous system memory addresses and accesses. Because these interfaces are designed to be CPU hardware independent, their use makes the driver more portable across different CPU architectures and more than one CPU type within the same architecture.
Table 2-1 summarizes the interfaces all new TURBOchannel device drivers should use to perform DMA data transfer operations. You do not need to change existing TURBOchannel device drivers to the new interfaces because they will still work with the previously listed TURBOchannel-specific interfaces.
See Writing Device Drivers: Tutorial for examples of how to use the generic DMA-related interfaces. See Writing Device Drivers: Reference for reference page descriptions of these generic DMA-related interfaces.
Kernel Interface | Summary Description |
dma_get_curr_sgentry | Returns a pointer to the current sg_entry. |
dma_get_next_sgentry | Returns a pointer to the next sg_entry. |
dma_get_private | Gets a data element from the DMA private storage space. |
dma_kmap_buffer | Returns a kernel segment (kseg) address of a DMA buffer. |
dma_map_alloc | Allocates resources for DMA data transfers. |
dma_map_dealloc | Releases and deallocates the DMA resources previously allocated for DMA data transfers. |
dma_map_load | Loads and sets allocated DMA resources and sets up a DMA data path for DMA data transfers. |
dma_map_unload | Unloads the system DMA resources. |
dma_min_boundary | Returns system-level information. |
dma_put_curr_sgentry | Puts a new bus address/byte count pair in the linked list of sg_entry structures. |
dma_put_prev_sgentry | Updates an internal pointer index to the linked list of sg_entry structures. |
dma_put_private | Stores a data element in the DMA private storage space. |