Writing Device Drivers

Data Access Functions

Data access functions allow drivers to transfer data to and from devices without directly referencing the hardware registers. The driver can transfer data to the device or receive data from the device using the ddi_put8(9F) or the ddi_get8(9F) families of routines. The ddi_put8(9F) routines allow a driver to write data to the device in quantities of 8 bits (ddi_put8(9F)), 16 bits (ddi_put16(9F)), 32 bits (ddi_put32(9F)), and 64 bits (ddi_put64(9F)). The ddi_get8(9F) routines exist for reading from a device. Multiple values may be written or read by using the ddi_rep_put8(9F) or ddi_rep_get8(9F) family of routines respectively. See Appendix C, Summary of Solaris 7 DDI/DKI Services for more information on data access functions.


Note -

These routines may be applied to any address base returned from ddi_regs_map_setup(9F) regardless of the address space the register resides in (such as memory, I/O, or configuration space).


Example 3-1 illustrates the use of ddi_regs_map_setup(9F) and ddi_put8(9F) to access device registers.


Example 3-1 Accessing Device Registers

static ddi_device_acc_attr_t access_attr = {
	DDI_DEVICE_ATTR_V0, /*version number */
	DDI_STRUCTURE_BE_ACC, /* big endian */
	DDI_STRICTORDER_ACC /*strict ordering */
};

caddr_t reg_addr;
ddi_acc_handle_t data_access_handle;

ddi_regs_map_setup(..., &reg_addr, ..., &access_attr,
	&data_access_handle);

When ddi_regs_map_setup(9F) returns, reg_addr contains the address base and data_access_handle contains the opaque data handle to be used in subsequent data accesses. The driver may now access the mapped registers. The following example writes one byte to the first mapped location.

ddi_put8(data_access_handle, (uint8_t *)reg_addr, 0x10);

Similarly, the driver could have used ddi_get8(9F) to read data from the device registers.

Memory Space Access

In memory-mapped access, device registers appear in memory address space. The driver must call ddi_regs_map_setup(9F) to set up the mapping. The driver can then access the device registers using one of the ddi_put8(9F) or ddi_get8(9F) family of routines.

To access memory space, the driver can use the ddi_mem_put8(9F) and ddi_mem_get8(9F) family of routines. These functions may be more efficient on some platforms. Use of these routines, however, may limit the ability of the driver to remain portable across different bus versions of the device.

I/O Space Access

In I/O space access, the device registers appear in I/O space. Each addressable element of the I/O address is called an I/O port. Device registers are accessed through I/O port numbers. These port numbers can refer to 8, 16, or 32-bit registers. The driver must call ddi_regs_map_setup(9F) to set up the mapping, and it can then access the I/O port using one of the ddi_put8(9F) or ddi_get8(9F) family of routines.

The driver can also access I/O space using the ddi_io_put8(9F) and ddi_io_get8(9F) family of routines. These functions may be more efficient on some platforms. Use of these routines, however, may limit the ability of the driver to remain portable across different bus versions of the device.

Configuration Space Access

Configuration space is used primarily during device initialization. It determines the location and size of register sets and memory buffers located on the device. The driver can access configuration space using the ddi_regs_map_setup(9F) and the ddi_put(9F or ddi_get(9F) functions as described previously.


Note -

For PCI local bus devices, an alternative set of routines exists. To get access to the configuration address space, the driver can use pci_config_setup(9F) in place of ddi_regs_map_setup(9F). The pci_config_get8(9F) and pci_config_put8(9F) family of routines may be used in place of the generic routines ddi_get8(9F) and ddi_put8(9F). These functions provide equivalent configuration space access as defined in the PCI bus binding for the IEEE 1275 specifications for FCode drivers. However, use of these routines may limit the ability of the driver to remain portable across different bus versions of the device.