Previous versions of the operating system provided VMEbus device driver writers with numerous VMEbus-specific interfaces. To promote the portability of device drivers across different bus and CPU architectures, this version of Digital UNIX eliminates some of the VMEbus-specific interfaces and replaces them with more generic interfaces.
This appendix describes the following VMEbus-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 VMEbus 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 VMEbus device drivers are presented in alphabetical order and in reference (man) page style. 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 descriptions of the data structures associated with VMEbus device drivers are presented in alphabetical order and in reference (man) page style. The descriptions can include 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 occurs when you need to understand or initialize all of the members of a structure.
This occurs when you need to understand or reference some of the members of a particular structure.
This occurs when the structure is opaque. This means the members of the structure are manipulated by the Digital UNIX operating system. You do not manipulate or reference any of the members.
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 VMEbus device drivers are presented in alphabetical order and in reference (man) page style. 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
(ctlr,
addr1,
addr2)
struct controller
*ctlr;
caddr_t
addr1;
caddr_t
addr2;
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 ctlr, addr1, and addr2.
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 struct controller * and caddr_t. 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.
Table A-1 lists the header file related to VMEbus device drivers and a short description of its contents. Device drivers should include header files that use the relative pathname instead of the explicit pathname. For example, although buf.h resides in /usr/sys/include/sys/buf.h, device drivers should include it as:
<sys/buf.h>
Header File | Contents |
vbareg.h | Contains definitions for VMEbus support. |
Contains definitions for VMEbus support
/usr/sys/include/io/dec/vme/vbareg.h
The vbareg.h file defines bit constants that the dma_map_alloc, dma_map_load, vba_map_csr, and busphys_to_iohandle kernel interfaces use. The file also defines bit constants that device drivers use for the addr1_atype and addr2_atype members of the driver structure.
VMEbus block and character device drivers include this file in order to use the VMEbus bit constants.
Items of interest to device driver writers are the bit constants that the flags argument of dma_map_alloc and dma_map_load use.
Table A-2 lists the kernel interfaces specific to VMEbus device drivers, along with short descriptions of their purpose.
Note
The following lists the header files most frequently used by device drivers:
#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 |
vba_clear_irq | Removes a posted interrupt request. |
vba_display_addr_type | Prints the address type. |
vba_dma | Performs Master Block Transfers with local DMA. |
vba_get_dma_addr | Returns the VMEbus address and DMA flags. |
vba_get_vmeaddr | Obtains a VMEbus address. |
vba_get_vmeaddr_am | Obtains the VMEbus address modifiers. |
vba_map_csr | Maps a VMEbus address CSR area. |
vba_post_irq | Asserts an interrupt. |
vba_set_dma_addr | Specifies a specific VMEbus address and DMA flags. |
vba_unmap_csr | Unmaps a VMEbus address CSR area. |
Removes a posted interrupt request
boolean_t vba_clear_irq
(ctlr,
irq,
status_ID)
struct controller
*ctlr;
unsigned int
irq;
unsigned int
status_ID;
The
vba_clear_irq
interface removes an interrupt request that was posted on a previous
call to
vba_post_irq.
If you pass a
status_ID,
it must match the value you passed to
vba_post_irq.
Otherwise,
vba_clear_irq
returns an error.
If you pass the value zero (0) to
status_ID,
then
vba_clear_irq
removes any interrupt request on the specified interrupt request line.
The vba_clear_irq interface returns one of the following values:
Value | Meaning |
TRUE |
The
vba_clear_irq
interface clears the posted interrupt on the specified interrupt request
line.
This VMEbus adapter provides no support for a vba_clear_irq interface. |
FALSE |
The
vba_clear_irq
interface failed to clear the posted interrupt on the specified interrupt
request line.
The status_ID you specified does not match the posted interrupt on the specified interrupt request line. |
Prints the address type
void vba_display_addr_type
(atype)
vme_atype_t
atype;
The vba_display_addr_type interface prints on the console terminal the value of the address space and access mode of the CSR area during device autoconfiguration.
None
Performs Master Block Transfers with local DMA
#include <io/dec/vme/vbareg.h>
u_long vba_dma
(ctlr_p,
dma_handle)
struct controller
*ctlr_p;
dma_handle_t
dma_handle;
If the VMEbus adapter provides a master block transfer local DMA engine, the vba_dma interface performs the transfer through DMA. If the hardware does not support a local DMA engine, vba_dma either performs the transfer through programmed I/O or returns an error indication.
The VME adapter support code may segment the transfer depending on the block-mode DMA hardware limitations. Further segmentation may occur depending on the amount of physically contiguous memory pages found in the virtual buffer supplied to dma_map_load.
You must invoke the following interfaces with the appropriate specification of flags:
Specify the VMEbus and DMA flags along with the VMEbus address. You must uniquely specify the flags DMA_IN (read from VMEbus to memory) or DMA_OUT (write from memory to VMEbus). These flag bits indicate to dma_map_alloc and dma_map_load that a local DMA engine will be utilized.
Allocates resources for DMA data transfers
Loads and sets allocated DMA resources and sets up a DMA data path for DMA data transfers
Performs the actual DMA or I/O copy transfer
Unloads the system DMA resources
Releases and deallocates the DMA resources previously allocated for DMA data transfers
See Section D.3 for a code example of the use of vba_dma.
Upon successful completion, vba_dma returns the number of bytes transferred. This value should agree with the byte count value specified in the call to dma_map_load. If it does not, then an error occurred during the transfer.
If you specify DMA_SLEEP in the flags argument of either dma_map_alloc or dma_map_load, then vba_dma waits for the DMA resource if currently active. Access to the DMA hardware is single threaded at this point. If you do not specify DMA_SLEEP and vba_dma is active, a -1UL is returned to indicate that vba_dma is active. A -1UL is also returned if the VMEbus adapter does not supply support code for this function.
controller, vba_set_dma_addr Writing Device Drivers: Reference: dma_map_alloc, dma_map_dealloc, dma_map_load, dma_map_unload
Returns the VMEbus address and DMA flags
void vba_get_dma_addr
(ctlr,
param_flags,
flags,
vme_address)
struct controller
*ctlr;
unsigned int
param_flags;
unsigned int
*flags;
vme_addr_t
*vme_address;
The vba_get_dma_addr interface returns the direct memory access (DMA) flags and VMEbus address specified in a previous call to vba_set_dma_addr. The interface recombines the VMEbus-related flags' bits with the DMA-related bits and stores them in the address passed to the flags argument.
Bus adapter driver writers typically call vba_get_dma_addr to obtain the VMEbus address and DMA-related flags.
The vba_get_dma_addr interface returns data explicitly to the pointers passed to the flags and vme_address arguments.
Obtains a VMEbus address
vme_addr_t vba_get_vmeaddr
(ctlr,
csr_addr_handle)
struct controller
*ctlr;
io_handle_t
csr_addr_handle;
The vba_get_vmeaddr interface returns the VMEbus address associated with the specified I/O handle.
The use of the io_handle_t data type for the address is new. Previous versions of this interface used a data type of u_long.
You can call the vba_get_vmeaddr_am interface to obtain the following information associated with the returned address: the VMEbus address space, access type, data transfer size, and swap mode.
Upon successful completion, the vba_get_vmeaddr interface returns the vme_addr_t address corresponding to the I/O handle passed to the csr_addr_handle argument.
Obtains the VMEbus address modifiers
vme_atype_t vba_get_vmeaddr_am
(ctlr,
csr_addr_handle)
struct controller
*ctlr;
io_handle_t
csr_addr_handle;
The vba_get_vmeaddr_am interface obtains the VMEbus address modifiers for the VMEbus address associated with the I/O handle you pass to the csr_addr_handle argument. You obtained this handle in a previous call to vba_map_csr. These VMEbus address modifiers are associated with the valid bits passed to the atype argument of the vba_map_csr interface.
Upon successful completion, vba_get_vmeaddr_am returns a value of type vme_atype_t. This return has the same definition as the atype argument in the vba_map_csr interface.
Maps a VMEbus address CSR area
io_handle_t vba_map_csr
(ctlr,
vme_address,
bcnt,
atype)
struct controller
*ctlr;
vme_addr_t
vme_address;
unsigned int
bcnt;
vme_atype_t
atype;
The vba_map_csr interface maps the specified VMEbus address space to an I/O handle (an io_handle_t data type). If you specify the VME_DENSE bit in the atype argument, vba_map_csr maps the CSR area such that there are no read-ahead side effects. This dense access maps large memory buffers (for example, graphics frame buffers) present in the A32 address space.
As the description for the atype argument stated, you can specify atype as the bitwise inclusive OR of the valid bits in the following table:
Bit Category | Value | Meaning |
Swap mode bits | VME_BS_NOSWAP | Specifies no byte swapping. |
VME_BS_BYTE | Specifies byte swapping in bytes. | |
VME_BS_WORD | Specifies byte swapping in words. | |
VME_BS_LWORD | Specifies byte swapping in longwords. | |
VME_BS_QUAD | Specifies byte swapping in quadwords. | |
Address space bits | VME_A16 | Specifies a request for the 16-bit address space. |
VME_A24 | Specifies a request for the 24-bit address space. | |
VME_A32 | Specifies a request for the 32-bit address space. | |
VME_A64 | Specifies a request for the 64-bit address space. | |
Transfer size bits | VME_D08 | Specifies a request for the 8-bit data size. |
VME_D16 | Specifies a request for the 16-bit data size. | |
VME_D32 | Specifies a request for the 32-bit data size. | |
Access mode bits | VME_UDATA | Specifies user data. |
VME_UPROG | Specifies a user program. | |
VME_SDATA | Specifies supervisory data. | |
VME_SPROG | Specifies a supervisory program. | |
CPU allocation space bits | The default CPU allocation space is sparse space. To specify dense space, you use the VME_DENSE bit. |
The following code fragment shows how vba_map_csr references the values for the addr, size, and atype arguments during device autoconfiguration:
.
.
.
struct controller *ctlr; struct driver *drp;
.
.
.
ctlr->physaddr = ctlr->addr; ctlr->physaddr2 = ctlr->addr2; drp = ctlr->driver;
.
.
.
/* * we need to connect the ctlr to the bus * before we map csr addresses because it will use * the map_csr routine found via the bus structure. */ ctlr->bus_hd = bus; /* Map csr space(s) */ /* Map csr1 address space if present */ if(ctlr->addr) { if ( (ctlr->addr = (caddr_t) vba_map_csr(ctlr, (vme_addr_t)ctlr->physaddr, drp->addr1_size, (vme_atype_t)drp->addr1_atype)) == 0){ printf(" %s%d not configured.\n", ctlr->ctlr_name, ctlr->ctlr_num); ctlr->addr = ctlr->physaddr; continue; }
.
.
.
Upon successful completion, vba_map_csr returns an I/O handle that the driver can use as an argument to the interfaces called to read and write CSRs and copy buffers between system memory and I/O space. For example, you can pass this returned I/O handle in calls to read_io_port and write_io_port.
If unsuccessful, vba_map_csr returns an I/O handle of zero (0).
Asserts an interrupt
unsigned int vba_post_irq
(ctlr,
irq,
status_ID,
iack_isr)
struct controller
*ctlr;
unsigned int
irq;
unsigned int
status_ID;
int
(*iack_isr) ();
The vba_post_irq interface asserts an interrupt on the interrupt request line specified in irq. There is a maximum of one posted, unacknowledged interrupt per interrupt request line. If you attempt to post an interrupt on an interrupt request line on which there is a pending interrupt request, vba_post_irq returns an error.
When the interrupt is acknowledged and an interrupt callback service interface is provided through the iack_isr argument, the specified interrupt callback interface is invoked from the VMEbus adapter's common interrupt acknowledge handler. The user-specified interrupt callback interface is passed two arguments. The first argument is struct controller * ctlr, the controller structure pointer. The second argument is unsigned int irq, the interrupt request (IRQ) corresponding to the IRQ being acknowledged. The user-specified interrupt callback interface executes as an interrupt service interface with the same constraints on execution.
After the interrupt request has been acknowledged and the user-specified callback service interface (if provided) is invoked, the interrupt request line is made available for another call to the vba_post_irq interface.
Upon successful completion, vba_post_irq returns the value 1. Otherwise, it returns the value zero (0). If the bus adapter is not capable of posting interrupts, vba_post_irq returns a -1.
Specifies a specific VMEbus address and DMA flags
unsigned int vba_set_dma_addr
(ctlr,
flags,
vme_address)
struct controller
*ctlr;
vme_atype_t
flags;
vme_addr_t
vme_address;
The vba_set_dma_addr interface allows VMEbus device drivers to pass a specific VMEbus address and direct memory access (DMA) flags to the dma_map_alloc and dma_map_load interfaces.
The vba_set_dma_addr interface provides a mechanism to select the VME adapter's DMA engine to perform master block transfers. (See Section D.3 for a description and examples.) This is the recommended use of the vba_set_dma_addr interface. See the Notes section for a more detailed discussion on the use of vba_set_dma_addr.
The vba_set_dma_addr interface also provides a mechinism to map to a specific VMEbus address versus the dynamic allocation normally performed by dma_map_alloc or dma_map_load. The interface mimics the functionality that was available in the obsolete interfaces vballoc and vbasetup. Digital recommends that you not use the vba_set_dma_addr interface in this way unless you understand all of the issues related to the way the obsolete interfaces worked. See the Notes section for a discussion about the issues for this type of mapping.
The vba_set_dma_addr interface searches an internal data structure for a free resource and then does the following:
The caller passes this return value to the flags argument of dma_map_alloc or dma_map_load.
When the VME adapter's DMA allocation interface detects the special value, it calls vba_get_dma_addr to retrieve the DMA flags and VMEbus address.
As the description for the flags argument states, you can specify atype as the bitwise inclusive OR of the valid bits in the following table. The /usr/sys/include/io/dec/vme/vbareg.h file defines these and other bits.
Bit Category | Value | Meaning |
Swap mode bits | VME_BS_NOSWAP | Specifies no byte swapping. |
VME_BS_BYTE | Specifies byte swapping in bytes. | |
VME_BS_WORD | Specifies byte swapping in words. | |
VME_BS_LWORD | Specifies byte swapping in longwords. | |
VME_BS_QUAD | Specifies byte swapping in quadwords. | |
Address space bits | VME_A16 | Specifies a request for the 16-bit address space. |
VME_A24 | Specifies a request for the 24-bit address space. | |
VME_A32 | Specifies a request for the 32-bit address space. | |
VME_A64 | Specifies a request for the 64-bit address space. | |
Transfer size bits | VME_D08 | Specifies a request for the 8-bit data size. |
VME_D16 | Specifies a request for the 16-bit data size. | |
VME_D32 | Specifies a request for the 32-bit data size. | |
Access mode bits | VME_UDATA | Specifies user data. |
VME_UPROG | Specifies a user program. | |
VME_SDATA | Specifies supervisory data. | |
VME_SPROG | Specifies a supervisory program. | |
CPU allocation space bits | The default CPU allocation space is sparse space. To specify dense space, you use the VME_DENSE bit. |
Note
The VME adapter's master block transfer DMA engine may not support all data transport sizes. See Section D.3 or the documentation that comes with your adapter for block mode restrictions.
You can pass the bitwise inclusive OR of the following special condition bits defined in /usr/sys/include/io/common/devdriver.h:
Value | Meaning |
DMA_GUARD_UPPER | Allocates additional resources so that contiguous data overruns are captured by the system map error functions. This bit is probably most useful during device driver development and debugging. |
DMA_GUARD_LOWER | Allocates additional resources so that contiguous data underruns are captured by the system map error functions. This bit is probably most useful during device driver development and debugging. |
DMA_SLEEP | Puts the process to sleep if the system cannot allocate the necessary resources to perform a data transfer of size byte_count at the time the driver calls the interface. |
DMA_IN | Selects the VME adapter's DMA engine to perform master block transfers to DMA data from the specified VMEbus address into system memory. |
DMA_OUT | Selects the VME adapter's DMA engine to perform master block transfers to DMA data from the system memory to specified VMEbus address. |
DMA_ALL | Returns a nonzero value, only if the system can satisfy a DMA transfer of size byte_count. |
To select the VMEbus adapter's master block transfer DMA engine for DMA transfer, specify either DMA_IN or DMA_OUT in the flags argument in the call to the vba_set_dma_addr interface. In addition, specify the bitwise inclusive OR of the VMEbus flag bits from the first table listed in the Description section. You also specify the starting VMEbus address of the transfer in the vme_address argument. You must then pass the return value from vba_set_dma_addr to either dma_map_alloc or dma_map_load. If you call both these interfaces, then you must pass the return value to both.
To perform the actual master block mode DMA transfer, call the vba_dma interface. When the transfer has completed, the VMEbus device driver can call vba_dma again to transfer the same buffer again. If the device driver needs to provide a different buffer, call dma_map_load and vba_dma to transfer the next buffer. This reloading of the buffer works providing the size of the buffer does not exceed the byte count passed to dma_map_alloc or to dma_map_load. When the master block transfer with local DMA engine is no longer needed, call dma_map_unload and dma_map_dealloc to return master block transfer DMA page map register resources back to the VMEbus adapter.
You can also use the vba_set_dma_addr interface to pass a specific VMEbus address to dma_map_alloc or dma_map_load. The purpose of doing this is to request the VMEbus adapter's allocation interface to map its system memory at a specific VMEbus address rather than the dynamic allocation that normally occurs when you call dma_map_alloc or dma_map_load. You must not specify the DMA_IN or DMA_OUT flags to the dma_map_alloc or dma_map_load interfaces to cause this desired mapping. You pass the return value from the vba_set_dma_addr interface to dma_map_alloc or dma_map_load. If the VMEbus adapter's allocation interface has not already allocated the VMEbus address space to another VMEbus device driver, and if there are enough page map registers available to handle the requested mapping size specified by the byte_count argument of dma_map_alloc or dma_map_load, the VMEbus adapter's DMA allocation interface will reserve the resources and return successfully. If you were to call dma_map_load, the system memory would be mapped to the VMEbus upon successful allocation. If the DMA resources were previously allocated, then dma_map_alloc or dma_map_load would return an error condition.
Upon successful completion of dma_map_load, the VMEbus device driver should call dma_get_curr_sgentry to obtain the actual address mapped to the VMEbus. The address returned by the call to dma_get_curr_sgentry may not be the specified address requested by vba_set_dma_addr. However, the address will be within the VMEbus window associated with the page map register representing the VMEbus address. The reason is that the VMEbus address consists of two parts. The first part is a VMEbus address that corresponds to a particular resource (page map register). This part of the address is a multiple of the bus window that the page map register represents (typically an alpha page size). The second part of the VMEbus address is the page offset of the system memory buffer from the start of an alpha page. You pass the system memory buffer to the virt_addr argument of the dma_map_load interface.
It is possible that the requested VMEbus address will not be mapped to memory or only partially mapped. This can occur in three cases:
To guard against the previously described problems, ensure that the specified system memory buffer and VMEbus address are aligned to an alpha page boundary. The memory buffer allocated should be large enough to encompass the page offset of the required VMEbus address. You should pass the byte count of the memory buffer to the byte_count argument of the dma_map_alloc or dma_map_load interface. To get to the desired VMEbus address, add the correct page offset to the system memory buffer and to the VMEbus address returned in the call to dma_get_curr_sgentry.
The vba_set_dma_addr can return one of the following values:
Value | Meaning |
The value zero (0) | The system could not allocate internal resources. |
A nonzero value | The system could allocate internal resources and fill in the internal data structure with DMA flags and the VMEbus address. Pass this return value to the flags argument of dma_map_alloc or dma_map_load. |
Section D.3: Master Block Transfers with Local DMA
Unmaps a VMEbus address CSR area
void vba_unmap_csr
(ctlr,
csr_addr_handle)
struct controller
*ctlr;
io_handle_t
csr_addr_handle;
The vba_unmap_csr interface unmaps the VMEbus address specified in the csr_addr_handle argument. This frees up the resources (for example, one or more outbound mapping registers) that were mapped in a previous call to vba_map_csr.
The following code fragment shows how vba_unmap_csr releases resources obtained in a previous call to vba_map_csr:
.
.
.
vba_unmap_csr(ctlr, (io_handle_t)ctlr->addr);
.
.
.
None
Table A-3 lists the data structures specific to VMEbus device drivers, along with short descriptions of their contents.
Structure Name | Meaning |
controller | Represents an instance of a controller entity. |
driver | Defines driver entry points and other driver-specific information. |
vme_handler_info | Contains interrupt handler information for device controllers connected to the VMEbus. |
Contains members that store information about hardware resources and store data for communication between the kernel and the device driver
/usr/sys/include/io/common/devdriver.h
Member Name | Data Type |
bus_priority | int |
ivnum | int |
priority | int |
The controller structure represents an instance of a controller entity, one that connects logically to a bus. A controller can control devices that are directly connected or can perform some other controlling operation, such as a network interface or terminal controller operation.
driver, The controller structure discussed in Writing Device Drivers: Reference
Defines driver entry points and other driver-specific information
/usr/sys/include/io/common/devdriver.h
Member Name | Data Type |
addr1_size | int |
addr1_atype | int |
addr2_size | int |
addr2_atype | int |
The driver structure defines driver entry points and other driver-specific information. You declare and initialize an instance of this structure in the declarations section of the device driver. The bus configuration code uses the entry points defined in this structure during device autoconfiguration. The bus configuration code fills in the dev_list and ctlr_list arrays. The driver interfaces use these arrays (members of the device and controller structures) to get the structures for specific devices or controllers.
You can set the addr1_atype and addr2_atype members to the bitwise inclusive OR of the valid bits described in the following table:
Bit Category | Value | Meaning |
Swap mode bits | VME_BS_NOSWAP | Specifies no byte swapping. |
VME_BS_BYTE | Specifies byte swapping in bytes. | |
VME_BS_WORD | Specifies byte swapping in words. | |
VME_BS_LWORD | Specifies byte swapping in longwords. | |
VME_BS_QUAD | Specifies byte swapping in quadwords. | |
Address space bits | VME_A16 | Specifies a request for the 16-bit address space. |
VME_A24 | Specifies a request for the 24-bit address space. | |
VME_A32 | Specifies a request for the 32-bit address space. | |
VME_A64 | Specifies a request for the 64-bit address space. | |
Transfer size bits | VME_D08 | Specifies a request for the 8-bit data size. |
VME_D16 | Specifies a request for the 16-bit data size. | |
VME_D32 | Specifies a request for the 32-bit data size. | |
Access mode bits | VME_UDATA | Specifies user data. |
VME_UPROG | Specifies a user program. | |
VME_SDATA | Specifies supervisory data. | |
VME_SPROG | Specifies a supervisory program. | |
CPU allocation space bits | The default CPU allocation space is sparse space. To specify dense space, you use the VME_DENSE bit. |
controller, The driver structure discussed in Writing Device Drivers: Reference
Contains interrupt handler information for device controllers connected to the VMEbus
/usr/sys/include/io/dec/vme/vbareg.h
Member Name | Data Type |
gen_intr_info | struct handler_intr_info |
unsigned int | vec |
irq | int |
The vme_handler_info structure contains interrupt handler information for device controllers connected to a VMEbus. This structure uses the generic handler_intr_info structure that contains all of the necessary information to add an interrupt handler for any bus. It also contains some VMEbus-specific members.
The handler_intr_info structure discussed in Writing Device Drivers: Reference
Table A-4 lists the device driver interfaces specific to VMEbus device drivers, along with short descriptions of their contents. See the Writing Device Drivers: Reference for reference (man) page-style descriptions of the other driver interfaces.
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
(addr1,
ctlr)
io_handle_t
addr1;
struct controller
*ctlr;
This I/O handle corresponds to the first CSR address that you specified in the system configuration file. You precede the control status register (CSR) address for the VMEbus device in the system configuration file with the csr keyword, as follows:
csr 0x8020
The bus configuration code converts this address into an appropriate I/O handle and passes it to the driver's xxprobe interface.
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 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. The VMEbus configuration code passes this I/O handle to the driver's xxprobe interface through the controller structure pointer 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 second CSR address, if present, that you specified in the system configuration file or the stanza.static file fragment. If you did not specify a second CSR address, the value of this argument is zero (0). You precede the second CSR address for the VMEbus device in the system configuration file with the csr2 keyword, as follows:
csr2 0x8040
The bus configuration code converts this address into an appropriate I/O handle and passes it to the driver's xxprobe 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. The kernel calls the xxprobe interface for each device that is defined in the system configuration file or config.file file fragment for static drivers. In addition, the kernel calls the xxprobe interface for each stanza entry that is defined in the stanza.loadable file fragment for loadable 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 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.
In previous versions of the operating system, you defined the device interrupt handlers for static device drivers in the system configuration file or the stanza.static file fragment. At system configuration time, the config program registered the defined device interrupt handlers. For this version of Digital UNIX, Digital requires that you register the device interrupt handlers for static device drivers in the same way that you register them for loadable device drivers: by calling the handler_add and handler_enable interfaces.
When device drivers are dynamically loaded, the bus configuration code checks for the existence of the device before calling xxprobe.
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 Synopsis section shows the arguments associated with a probe interface for a VMEbus.
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.
Checks that the device is valid for this controller
The driver structure
int xxslave
(device,
addr1)
struct device
*device;
io_handle_t
addr1;
This I/O handle corresponds to the first CSR address that you specified in the system configuration file. You precede the control status register (CSR) address for the VMEbus device in the system configuration file with the csr keyword, as follows:
csr 0x8020
The bus configuration code converts this address into an appropriate I/O handle and passes it to the driver's xxslave interface.
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. The VMEbus configuration code passes this I/O handle to the driver's xxprobe interface through the controller structure pointer 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 second CSR address, if present, that you specified in the system configuration file or the stanza.static file fragment. If you did not specify a second CSR address, the value of this argument is zero (0). You precede the second CSR address for the VMEbus device in the system configuration file with the csr2 keyword, as follows:
csr2 0x8040
The bus configuration code converts this address into an appropriate I/O handle and passes it to the driver's xxslave 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. You (or the system manager) specify the attachments of these slave devices for static device drivers in the system configuration file or stanza.static file fragment.
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 VMEbus.
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.