[Return to Library]  [TOC]  [PREV]  SECT--  [NEXT]  [INDEX] [Help]

3    Structure of a VMEbus Device Driver

The sections that make up a Digital UNIX device driver differ, depending on whether the driver is a block, character, or network driver. Figure 3-1 shows the sections that a character device driver can contain and the possible sections that a block device driver can contain. Device drivers are not required to use all of the sections and more complex drivers can have additional sections.

Both types of drivers contain:

The block device driver can also contain a strategy section, a psize section, and a dump section.


Note

Although the strategy interface applies to reading and writing of block data by block device drivers, character drivers can also contain a strategy interface that the character driver's read and write interfaces call. VMEbus device drivers are typically character drivers and their read and write interfaces use the physio interface. The physio interface performs the appropriate read or write operation (programmed I/O, VMEbus adapter hardware DMA, or device DMA). One of the parameters passed to the physio interface is the driver's strategy interface.


The character device driver contains the following sections not contained in a block device driver:

Writing Device Drivers: Tutorial discusses each of the driver sections. The remainder of this chapter describes the differences in the following driver sections as they relate to VMEbus device drivers:


Figure 3-1: Sections of a Character Device Driver and a Block Device Driver



[Return to Library]  [TOC]  [PREV]  SECT--  [NEXT]  [INDEX] [Help]

3.1    Include Files Section

Data structures and constant values are defined in header files that you include in the Include Files Section of the driver source code. The number and types of header files you specify in the Include Files Section vary, depending on such things as what structures, constants, and kernel interfaces your device driver references. You need to be familiar with:

Writing Device Drivers: Tutorial describes these files. VMEbus device drivers use the following header file for VMEbus definitions:

#include <io/dec/vme/vbareg.h>


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

3.2    Configure Section

The Configure Section of a device driver must define a bus-specific name constant. This constant represents the name of the bus on which your driver operates, and is passed to the configure_driver and unconfigure_driver interfaces.

For VMEbus device drivers, you must specify vba as the definition for the bus name constant. For example, for the dmaex example driver:

#define DMAEX_BUSNAME1 "vba"
You must also specify vba for the bus_name member of the controller_config data structure (described in Writing Device Drivers: Tutorial), which Configure Section register_configuration code sets up in preparation for a call to the create_controller_structure interface. In the created controller structure, the bus_name field is set to vba.

Specifying vba provides the means for the VMEbus autoconfiguration code to determine that a controller structure is associated with the VMEbus.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

3.3    Autoconfiguration Support Section

When Digital UNIX boots, the kernel determines what devices are connected to the computer. After finding a device, the kernel initializes it so that the device can be used at a later time. The probe interface determines if a particular device is present and the attach interface initializes the device. The slave interface, if one is implemented, checks that a device is valid for a specific controller.

The Autoconfiguration Support Section of a VMEbus device driver contains the code that implements these interfaces for both character and block device drivers. For drivers that are dynamically configured into the kernel, the Autoconfiguration Support Section also contains a controller unattach or a device unattach interface, which is called when the driver is unloaded. You define the entry point for each of these interfaces in the driver structure.

Writing Device Drivers: Tutorial describes each of these interfaces. In addition, the remainder of this chapter discusses each interface from a VMEbus device driver prespective:

For convenience in referring to the names of the driver interfaces, the chapter uses the prefix xx. For example, xxprobe refers to a probe interface for a VMEbus device XX.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

3.3.1    Setting Up a probe Interface

A device driver's xxprobe interface performs tasks necessary to determine if the device exists and is functional on a given system. At boot time, the kernel performs checks to determine if the device is present before calling the xxprobe interface for statically configured drivers. For dynamically configured drivers, the xxprobe interface is called indirectly during the driver loading process.

The driver's configure interface calls the configure_driver interface to merge the driver's connectivity information into the system (hardware) configuration tree, which consists of bus, controller, and device structures. The call to configure_driver results in the system calling xxprobe for each instance of the controller present on the VMEbus.

Some tasks performed by the xxprobe interface vary, depending on whether the device driver is configured as static or loadable:

The xxprobe interface returns a nonzero value if the probe operation is successful. It returns the value zero (0) to indicate that the driver did not complete the probe operation.

The arguments you pass to the probe interface differ according to the bus on which the driver operates. The following code fragment shows you how to set up a probe interface for a driver that operates on a VMEbus:

int xxprobe(iohandle_t addr1, [1]
            struct controller *ctlr) [2]
{
/* Variable and structure declarations */

.
.
.
/* Code to perform necessary checks */
.
.
.
/* Code to obtain the second I/O handle */ [3]
.
.
.
  1. --> Specifies an I/O handle that you can use to reference a device register located in the VMEbus address space. The VMEbus configuration code passes this I/O handle to the driver's xxprobe interface during device autoconfiguration. You can perform standard C mathematical operations (addition and subtraction only) on the I/O handle. For example, you can add an offset to or subtract an offset from the I/O handle.

    This I/O handle corresponds to the first CSR address that you specified in a VBA_Option entry in the /etc/sysconfigtab file or a sysconfigtab file fragment. (Section 4.3 describes the VBA_Option entry.) You use the Csr1 field of the VBA_Option entry to specify the CSR address for the VMEbus device, as follows:

    VBA_Option = ..., Csr1 - 0x8020, ...
    The bus configuration code converts the Csr1 address, combined with information in driver structure members addr1_size and addr1_atype, into an appropriate I/O handle and passes it to the driver's xxprobe interface.

    Device drivers pass the I/O handle to the following categories of interfaces, which are discussed in Writing Device Drivers: Tutorial. These interfaces can process the I/O handle to access the desired bus address space.

  2. --> Specifies a pointer to the controller structure associated with this device. The bus configuration code passes this pointer to the driver's xxprobe interface. The device driver can reference hardware resources and other information contained in the controller structure pointer. Section 4.1 describes those members of the controller structure that are specific to the VMEbus.

  3. --> In previous versions of the operating system, the xxprobe interface for VMEbus device drivers specified a third argument called addr2. For this version of Digital UNIX, the VMEbus configuration code passes information in the addr2 member of the controller structure pointer instead of a third argument.

    This member specifies an I/O handle that you can use to reference a device register located in the VMEbus onboard memory. You can perform standard C mathematical operations (addition and subtraction only) on the I/O handle. For example, you can add an offset to or subtract an offset from the I/O handle.

    This I/O handle corresponds to the second CSR address, if any, that you specified in a VBA_Option entry in the /etc/sysconfigtab file or a sysconfigtab file fragment. (Section 4.3 describes the VBA_Option entry.) You can use the Csr2 field of the VBA_Option entry to specify an optional VMEbus device register or memory address to map into CPU I/O space, as follows:

    VBA_Option = ..., Csr2 - 0x8040, ...
    The bus configuration code converts the Csr2 address, combined with information in driver structure members addr2_size and addr2_atype, into an appropriate I/O handle. It is not passed to the driver's xxprobe interface, but is available in the driver's controller structure.

Section 6.5 provides more details on how to write a probe interface for a driver that operates on the VMEbus.

In previous versions of the operating system, the xxprobe interface returned the size of the control/status register address space. For this version of Digital UNIX, the xxprobe interface returns a nonzero value on success and the value zero (0) on failure.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

3.3.2    Setting Up the slave Interface

A device driver's xxslave interface is called only for a controller that has slave devices connected to it. This interface is called once for each slave attached to the controller. The following code fragment shows you how to set up a slave interface for a driver that operates on a VMEbus:
int xxslave(struct device *device,   [1]
            iohandle_t addr1)   [2]
{
/* Variable and structure declarations */

.
.
.
/* Code to check that the device is valid */
.
.
.
/* Code to obtain the second I/O handle */ [3]
.
.
.

  1. --> Specifies a pointer to a device structure for this device. The VMEbus configuration code passes this pointer to the driver's xxslave interface. The interface can thus reference such information as the logical unit number of the device, whether the device is functional, and the controller number associated with the controller that this device is connected to.

  2. --> Specifies an I/O handle that you can use to reference a device register located in the VMEbus address space. This I/O handle is created, passed, and can be used in the same manner as the addr1 I/O handle passed to xxprobe; see Section 3.3.1.

  3. --> In previous versions of the operating system, the xxslave interface for VMEbus device drivers specified a third argument called addr2. For this version of Digital UNIX, the VMEbus configuration code passes information to the addr2 member of the controller structure pointer instead of a third argument.

    This member specifies an I/O handle that you can use to reference a device register located in the VMEbus onboard memory. This I/O handle is created, stored, and can be used in the same manner as the second I/O handle described for xxprobe; see Section 3.3.1.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

3.3.3    Setting Up a Controller attach Interface

A device driver's attach interface establishes communication with the device. There are two attach interfaces: a controller attach for controller-specific initialization (called once for each controller) and a device attach interface for device-specific initialization (called once for each slave device attached to a controller).

The following code shows the general form for setting up a controller attach interface:

int xxcattach (struct controller *ctlr)
{
 ...
 /* Interface calls to establish communication with the device */
 ...
}
A device attach is set up similarly, except it receives a pointer to a device structure instead of a controller structure, and performs device-specific initialization.

The example driver used in this manual has a very brief controller attach interface and no device attach interface; see Section 6.5.2 for the /dev/dmaex driver's implementation of the attach interface.


[Return to Library]  [TOC]  [PREV]  --SECT  SECT--  [NEXT]  [INDEX] [Help]

3.3.4    Setting Up a Controller unattach Interface

A device driver's unattach interface removes the specified controller or device structure from the list of controllers or devices it handles, unmaps any controller or device CSRs that were mapped, frees any controller or device resources that were allocated, and removes any handlers that were added per controller or device. There are two unattach interfaces: a controller unattach for controller structure removal and a device unattach for device structure removal.

The following code shows the general form for setting up a controller unattach interface:

int xx_ctlr_unattach (struct bus *bus,
                      struct controller *ctlr)
{
 ...
 /* Interface calls to remove structures, handlers, free resources */
 ...
}
In the case of VMEbus device drivers, actions might include calling the vba_unmap_csr interface to unmap CSRs mapped with vba_map_csr and issuing handler_disable and handler_delete calls for every handler associated with the controller.

A device unattach is set up similarly, except it receives a pointer to a device structure instead of a bus structure, and performs device-specific cleanup.

The example driver used in this manual has a controller unattach interface and no device unattach interface; see Section 6.5.3 for the /dev/dmaex driver's implementation of the unattach interface.