This chapter describes when and why you would use the kernel interfaces developed for use with TURBOchannel device drivers. Included are brief examples on how to use these interfaces in device drivers. For complete descriptions of the definitions and arguments for these kernel interfaces, see Appendix A.
When writing device drivers for the TURBOchannel bus, you need to be familiar with kernel interfaces that:
Additionally, the I/O subsystems for the DEC 3000 series processors allow a TURBOchannel device driver to use a hardware scatter-gather map to transfer data to and from noncontiguous physical memory.
The tc_module_name interface returns the name of a specific TURBOchannel option module. You pass a pointer to a controller structure and a character array to be filled in by tc_module_name.
The following code fragment shows a call to the tc_module_name interface:
.
.
.
struct controller *ctlr; [1] char cp[TC_ROMNAMLEN + 1]; [2]
.
.
.
if (tc_module_name(ctlr, cp) == -1) { [3] printf("Module name conversion failed\n"); [4] } else { printf("Module name is %s\n", cp); [5]
.
.
.
In the tc_module_name interface, you pass a pointer to a controller structure to determine the TURBOchannel option's module name. However, the pointer to the controller structure is not valid in the driver's xxprobe interface. Therefore, if you need to determine the name of a device in the xxprobe interface, use the tc_addr_to_name interface. The tc_addr_to_name interface returns the TURBOchannel option's module name referred to by the base address of the device (the base address of the device is the I/O handle passed to the driver's xxprobe interface).
The following code fragment shows a call to tc_addr_to_name:
.
.
.
struct controller *ctlr; [1] char cp[10]; [2]
if (tc_addr_to_name(ctlr->addr, cp) == -1) { [3] printf("Address to Name lookup failed\n"); [4] } else { printf("Module name is %s\n", cp); [5]
.
.
.
The addr member stores the address of the device registers for the controller. [Return to example]
To obtain and log information about errors that occur on a direct memory access (DMA) operation, call the tc_isolate_memerr interface. Support for this interface is CPU specific. The call to tc_isolate_memerr returns -1 if the interface is not supported by the CPU. The tc_isolate_memerr interface takes a pointer to a structure that contains the following information:
Error types are returned to indicate if a parity (transient, hard, or soft) error occurred or if no error occurred.
The following code fragment for the /dev/xx device driver shows a call to the tc_isolate_memerr interface:
.
.
.
#include <io/dec/tc/tc.h>
.
.
.
struct tc_memerr_status *xx_memerr_status; [1] xx_memerr_status = &xx_memerr; [2]
xx_memerr_status->pa = err_addr; [3] xx_memerr_status->log = TC_LOG_MEMERR; [4]
tc_isolate_memerr(xx_memerr_status); [5]
.
.
.
TURBOchannel device drivers that operate on the ULTRIX operating system and MIPS CPUs call the wbflush interface to ensure that a write to I/O space has completed. Device drivers that operate on the Digital UNIX operating system and Alpha CPUs should call the mb interface. See Writing Device Drivers: Tutorial for discussions of how and when to use the mb interface.
Previous versions of this book discuss how TURBOchannel device drivers use the following TURBOchannel-specific interfaces associated with scatter-gather maps: tc_map_alloc, tc_loadmap, and tc_map_free. Digital UNIX now provides generic interfaces to perform DMA data transfer operations. Use of these generic interfaces makes device drivers more portable between DMA hardware-mapping implementations across different hardware platforms because it masks out any future changes in the kernel- and system-level DMA mapping data structures.
The following interfaces replace the TURBOchannel-specific interfaces associated with scatter-gather maps: