This appendix describes the following TURBOchannel-specific information:
Refer to Writing Device Drivers: Reference for reference information on header files, kernel interfaces, ioctls, global variables, data structures, and driver interfaces that are not bus specific.
The following sections describe the conventions used for:
The description of the header file associated with TURBOchannel device drivers can include the following sections.
This section lists the name of the header file along with a summary description of its contents.
This section presents the pathname for the header file. The pathname makes it easier for you to locate specific header files.
This section briefly describes the contents of the header file.
This section explains when to include a header file for block and character drivers.
This section lists specific structures, macros, constant values, and so forth that are of interest to device driver writers.
This section lists related kernel interfaces, structures, system calls, and so forth.
The descriptions of the kernel interfaces associated with TURBOchannel device drivers are presented as reference pages in alphabetical order. The descriptions can include the following sections.
This section lists the name of the kernel interface, along with a summary description of its purpose. In general, there is one interface described for each reference page. However, in some cases it makes sense to describe more than one interface on the same page if the interfaces are related. When this occurs, this section lists the names of all the interfaces it describes.
This section shows the kernel interface function definition. The style used is that of the function definition, not the function call. This book assumes that you understand how to interpret the function definition and how to write an appropriate call for a specific interface. The following example shows these conventions:
int copyin
(user_src,
kernel_dest,
bcount)
caddr_t
user_src;
caddr_t
kernel_dest;
u_int
bcount;
The kernel interface function definition gives you the following information:
The data type of the return value, if the kernel interface returns data. If the kernel interface does not return a value, the void data type is used.
The kernel interface name, for example, copyin. Some kernel interfaces are in uppercase.
The name of each kernel interface argument name. In the example, the argument names are user_src, kernel_dest, and bcount.
The types for each of the arguments. In the example, these types are caddr_t and u_int.
This book uses the word kernel ``interface'' instead of kernel ``routine'' or kernel ``macro.''
This section provides descriptions for the arguments associated with a given kernel interface. In most cases, argument descriptions begin with the word specifies to indicate that you pass the argument (with some specified value) to the kernel interface. If the type of the argument appears as a void *, the argument description states that you must define the type.
This section
contains explanations of the tasks performed by the kernel interface.
This section discusses information that falls into the following categories:
Some kernel interfaces behave differently depending on the architecture of the hardware.
Some kernel interfaces behave differently depending on the implementation of the operating system.
Some kernel interfaces require specific information important to the device driver writer.
This section provides information of particular importance when you use the kernel interface. In many cases, the text in this section alerts you to anything that might cause a panic.
This section provides the possible error constants a given kernel interface can return, along with a short description of the error.
This section describes special processing performed by the kernel interface. For example, the Side Effects section for the uiomove kernel interface describes the members of the uio structure that it can update.
This section describes the return values that a given kernel interface can return. In most cases, if the kernel interface returns an error value, this value is described in the Return Values section.
This section lists related kernel interfaces, structures, system calls, and so forth.
The description of the data structure associated with TURBOchannel device drivers is presented as a reference page. The description includes the following sections.
This section lists the name of the structure along with a summary description of its purpose.
This section lists the header file, including the path, where the structure is defined.
This section considers the following when describing structures:
This section provides a short description of each member of the structure.
This section gives more details about the purpose of the structure.
This section lists related kernel interfaces, structures, system calls, and so forth.
The descriptions of the device driver interfaces associated with TURBOchannel device drivers are presented as reference pages in alphabetical order. The descriptions can include the following sections.
This section lists the name of the driver interface along with a summary description of its purpose. In general, there is one interface described for each reference page. However, in some cases it makes sense to describe more than one interface on the same page if the interfaces are related. When this occurs, this section lists the names of all the interfaces it describes.
This section lists the structure or file where you specify the entry for the device driver interface.
This section shows the device driver interface function definition. The style used is that of the function definition, not the function call. This book assumes that you understand how to interpret the function definition and how to write an appropriate call for a specific interface. The presentation shown in the following example is of the function definition:
int xxprobe
(addr,
ctlr)
io_handle_t
addr;
struct controller
*ctlr;
The previous interface function definition gives you the following information:
Gives the data type of the return value, if the interface returns data. If the interface does not return a value, the function definition shows a void data type.
Gives the driver interface name.
In the example,
xxprobe is the name of the driver interface.
The prefix
xx
indicates that this part of the name is variable.
Replace it with the character prefix that represents the name of the device
for which the driver is being written.
Gives the name of each driver interface argument. In the example, the argument names are addr and ctlr.
Gives the types for each of the arguments. If you must define the type of the argument, a void * is used. In the example, these types are io_handle_t and struct controller *.
The term driver interface is used instead of driver routine to establish consistent terminology with that used for the kernel interfaces.
This section provides descriptions for the arguments associated with a given driver interface. In most cases, argument descriptions begin with the word specifies to indicate that the driver writer passes the argument (with some specified value) to the driver interface.
This section contains explanations of the tasks performed by the driver interface.
This section contains information about the driver interface pertinent to the device driver writer.
This section describes the values that a given driver interface can return.
This section lists related kernel interfaces, structures, system calls, and so forth.
The /usr/sys/include/io/dec/tc/tc.h file is the only header file used exclusively by TURBOchannel device drivers.
Contains definitions for TURBOchannel bus support
/usr/sys/include/io/dec/tc/tc.h
The tc.h file contains constants, bit values, and data structures related to the TURBOchannel bus.
You include this file in block and character device drivers that connect to the TURBOchannel bus.
Items of interest to device driver writers are:
tc_addr_to_name, tc_isolate_memerr, tc_module_name, tc_option_control
Table A-1 lists the kernel interfaces specific to TURBOchannel device drivers, along with short descriptions of their purpose.
Note
The following lists the header files that device drivers use most frequently:
#include <sys/types.h> #include <sys/errno.h> #include <io/common/devdriver.h> #include <sys/uio.h> #include <machine/cpu.h> #include <sys/conf.h> #include <sys/sysconfig.h>
Kernel Interface | Summary Description |
tc_addr_to_name | Returns the option module name. |
tc_isolate_memerr | Logs memory-related errors. |
tc_module_name | Determines the name of a specific option module. |
tc_option_control | Enables and disables various bus options. |
Returns the option module name
int tc_addr_to_name
(io_handle,
cp)
io_handle_t
io_handle;
char
*cp;
The tc_addr_to_name interface fills in the character array cp with the ASCII string of the TURBOchannel option's module name referred to by the base address addr. In the tc_module_name interface, you pass a pointer to a controller structure, which is not valid in the driver's xxprobe interface. Therefore, use tc_addr_to_name rather than tc_module_name in a driver's xxprobe interface.
This interface returns a value of -1 if it is unable to use the cp pointer you passed. The interface returns zero (0) on success.
Logs memory-related errors
int tc_isolate_memerr
(memerr_status)
struct tc_memerr_status
*memerr_status;
The tc_isolate_memerr interface logs memory-related errors associated with devices that operate on the TURBOchannel bus. The mechanism for logging these errors is the tc_memerr_status data structure.
The tc_isolate_memerr interface checks the virtual address of the error (the va member of the tc_memerr_status structure). If the address equals the value zero (0), the interface uses the physical address (the pa member of the tc_memerr_status structure) to form a virtual address.
The tc_isolate_memerr interface calls a system-specific interface, which determines the exact error based on the virtual address and the physical address. If the log member of the tc_memerr_status structure is set to TC_LOG_MEMERR, the system-specific interface logs the error in the same manner as a memory error is logged when it comes directly into the CPU.
See Section 5.3 for a code example of the tc_isolate_memerr interface.
The tc_isolate_memerr interface returns a value of -1 if the supplied physical address is invalid or if the system-specific interface does not exist.
Determines the name of a specific option module
int tc_module_name
(ctlr_p,
cp)
struct controller
*ctlr_p;
char
*cp;
The tc_module_name interface fills in the character array cp with the ASCII string of the TURBOchannel option's module name referred to by the pointer to the controller structure.
See Section 5.1 for a code example of the tc_module_name interface.
The tc_module_name interface returns a value of -1 if it was unable to use the cp pointer you passed.
Enables and disables various bus options
int tc_option_control
(ctlr_p,
flags)
struct controller
*ctlr_p;
int
flags;
Value | Meaning |
SLOT_PARITY | Enables or disables parity for the specified option. |
SLOT_BLOCKMODE | Enables or disables block mode transfers for the specified option. |
SLOT_MAPREGS | Enables or disables use of map registers for address translation for the specified module. |
SLOT_STATUS | Requests current state of preceding flags; do not change current settings. |
The tc_option_control interface enables or disables various slot-specific options. Use the SLOT_PARITY, SLOT_BLOCKMODE, and SLOT_MAPREGS flags to change option settings. A call to the tc_option_control interface returns the state of the option settings after execution. To find out what the option settings are without changing any of the settings, use the SLOT_STATUS flag.
The return value of this interface is the current state of flags after completion of the operations requested by the call to tc_option_control.
Table A-2 lists the data structure specific to TURBOchannel device drivers, along with a short description of its contents.
Structure Name | Meaning |
tc_memerr_status | Contains information on logging memory errors. |
Contains information on logging memory errors
/usr/sys/include/io/dec/tc/tc.h
Member Name | Data Type |
pa | caddr_t |
va | caddr_t |
log | int |
blocksize | int |
errtype | u_int |
Value | Meaning |
TC_NOLOG_MEMERR | Do not log the error. |
TC_LOG_MEMERR | Log the error. |
Value | Meaning |
TC_MEMERR_NOERROR | No error occurred. |
TC_MEMERR_TRANS | A transient parity error occurred. |
TC_MEMERR_SOFT | A soft parity error occurred. |
TC_MEMERR_HARD | A hard parity error occurred. |
The tc_isolate_memerr interface uses the tc_memerr_status data structure to obtain error information associated with devices that operate on the TURBOchannel bus.
Table A-3 lists the device driver interfaces specific to TURBOchannel device drivers, along with short descriptions of their contents.
Driver Interface | Summary Description |
xxprobe | Determines whether the device exists. |
xxslave | Checks that the device is valid for this controller. |
Determines whether the device exists
The driver structure
int xxprobe
(bus_io_handle,
ctlr)
io_handle_t
bus_io_handle;
struct controller
*ctlr;
A TURBOchannel bus device driver's xxprobe interface performs tasks necessary to determine if the device exists and is functional on a given system. The xxprobe interface typically registers a driver's interrupt handlers by using the ihandler_t and handler_intr_info structures and by calling the handler_add and handler_enable interfaces.
Other tasks that the xxprobe interface performs vary as follows, depending on whether the device driver is statically or dynamically configured into the kernel:
The xxprobe interface typically checks some device control status register (CSR) to determine whether the physical device is present. If the device is not present, the device is not initialized and not available for use. The kernel calls the xxprobe interface for each device that you defined in calls to the create_device_struct interface.
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 bus.
When device drivers are dynamically loaded, the bus configuration code checks for the existence of the device before calling xxprobe.
The arguments you pass to the probe interface differ according to the bus on which the driver operates. The Synopsis section shows the arguments associated with a probe interface for a TURBOchannel bus.
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.
The CSR I/O access interfaces are read_io_port and write_io_port. These are generic interfaces that allow device drivers to read from and write to device registers. Using these interfaces to read data from and write data to a device register makes the device driver more portable across different bus architectures, different CPU architectures, and different CPU types within the same CPU architecture.
The I/O copy interfaces are io_copyin, io_copyio, io_copyout, and io_zero. These are generic interfaces that allow device drivers to perform I/O copy operations. Using these interfaces to perform the copy operation makes the device driver more portable across different CPU architectures and different CPU types within the same architecture.
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.
Writing Device Drivers: Reference: controller structure
Checks that the device is valid for this controller
The driver structure
int xxslave
(device,
bus_io_handle)
struct device
*device;
io_handle_t
bus_io_handle;
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 arguments you pass to the slave interface differ according to the bus on which the driver operates. The Synopsis section shows the arguments associated with a slave interface for a TURBOchannel bus.
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.
The CSR I/O access interfaces are read_io_port and write_io_port. These are generic interfaces that allow device drivers to read from and write to device registers. Using these interfaces to read data from and write data to a device register makes the device driver more portable across different bus architectures, different CPU architectures, and different CPU types within the same CPU architecture.
The I/O copy interfaces are io_copyin, io_copyio, io_copyout, and io_zero. These are generic interfaces that allow device drivers to perform I/O copy operations. Using these interfaces to perform the copy operation makes the device driver more portable across different CPU architectures and different CPU types within the same architecture.
The xxslave interface returns a nonzero value if the device is present.
Writing Device Drivers: Reference: device structure