This chapter discusses how you port device drivers from the ULTRIX operating system to the Digital UNIX operating system. The chapter also summarizes the issues you need to consider before you decide to update existing Digital UNIX device drivers to the current version of Digital UNIX.
This section discusses the tasks you need to perform when porting device drivers from the ULTRIX operating system (running on Digital hardware) to the Digital UNIX operating system (also running on Digital hardware). The section does not discuss how to port drivers running on other UNIX operating systems, such as System V, or running on other hardware platforms, such as Sun Microsystems. Specifically, you need to:
These tasks are discussed in the following sections.
Porting a device driver requires that you understand the hardware device and the associated driver you want to port. One way to learn about the hardware device and its associated driver is to run a test suite, if it exists, on the machine and the operating system you are porting from (the source machine and the source operating system). If the test suite does not exist, you need to write a full test suite for that device on the source machine and the source operating system. For example, if you port a device driver written for a Digital CPU running the ULTRIX operating system, write the full test suite on that Digital CPU.
Write the test suite so that only minimal changes are necessary when you move it to the Digital CPU running the Digital UNIX operating system you are porting to (the target machine and the target operating system). The test suite represents a cross section of your users, and they should not have to modify their applications to work with the ported driver. You need to have both the source machine and source operating system and the target machine and target operating system on a network or make them accessible through a common interface, such as the Small Computer System Interface (SCSI).
After writing the test suite on the source machine, move the driver and the test suite to the target machine. Move only the .c and the .h files that were created for the driver. Do not copy any header or binary executable files because these files on the source machine will probably not be compatible on the target machine.
Check the header files in the driver you want to port with those in the Digital UNIX device drivers. Section 5.1 provides information on the header files that Digital UNIX uses. Writing Device Drivers: Reference provides reference page descriptions of the header files that Digital UNIX device drivers use most frequently.
The following example summarizes the differences in the way header files are included in device drivers on Digital UNIX and ULTRIX systems:
/* Header Files Included in Digital UNIX */ [1] #include <sys/types.h>/* Header Files Included in ULTRIX */ [1] #include "../h/types.h"
Digital UNIX supports static and dynamic configuration of device drivers into the kernel. The steps and tools that driver writers use to configure drivers into the kernel are different than those used on ULTRIX systems. The chapters in Part 4 of this book describe device driver configuration on Digital UNIX.
You need to compare the driver interfaces that ULTRIX device drivers use with those that Digital UNIX device drivers use. Writing Device Drivers: Reference provides reference page descriptions of the driver interfaces that Digital UNIX device drivers use. Use this information to compare the interface's behavior, number and type of arguments, return values, and so forth with its associated ULTRIX driver interface.
You need to compare the kernel interfaces that ULTRIX device drivers use with those that Digital UNIX device drivers use. Writing Device Drivers: Reference provides reference page descriptions of the kernel interfaces that Digital UNIX device drivers use. Use this information to compare the interface's behavior, number and type of arguments, return values, and so forth with its associated ULTRIX kernel interface. Table 4-1 lists some of these differences.
Kernel Interface | Remarks |
BADADDR | You can use BADADDR in device drivers that are statically configured into the kernel on Digital UNIX. However, you cannot use BADADDR if the driver is dynamically configured into the kernel. If you implement the driver to be both statically and dynamically configured, you can declare a variable and use it to control the call to BADADDR. For an example of how noneprobe uses such a variable (called none_is_dynamic), see Section 7.1.8. |
bufflush | ULTRIX BSD device drivers written for platforms based on MIPS use the bufflush interface. This interface is not used for Alpha platforms. Therefore, delete this interface from your device driver. |
KM_ALLOC | A previous version of the operating system instructed you to replace calls to KM_ALLOC with calls to kalloc. Digital UNIX supports a new memory allocator. Thus, replace calls to KM_ALLOC with calls to MALLOC. |
KM_FREE | A previous version of the operating system instructed you to replace calls to KM_FREE with calls to kfree. Digital UNIX supports a new memory allocator. Thus, replace calls to KM_FREE with calls to FREE. |
printf interfaces | ULTRIX device drivers can call cprintf, mprintf, printf, and uprintf. Digital UNIX device drivers can call printf and uprintf. |
selwakeup | The selwakeup interface is not used in Digital UNIX. Replace calls to selwakeup with calls to select_wakeup. Note that the formal parameters for the two interfaces are different. |
vslock | The vslock interface is obsolete on Digital UNIX. Therefore, replace calls to vslock with calls to vm_map_pageable. |
vsunlock | The vsunlock interface is obsolete on Digital UNIX. Therefore, replace calls to vsunlock with calls to vm_map_pageable. |
useracc |
The
useracc
interface is obsolete on Digital UNIX.
If you called
useracc
with
vslock,
replace both interfaces with a call to
vm_map_pageable.
Typically, the
useracc
interface was called by the driver's
strategy
interface.
In most cases, the driver's
strategy
interface would be called indirectly from the
physio
interface (in response to
read
and
write
system calls or file-system access).
In Digital UNIX, the physio interface verifies access permissions to the user buffer and locks down the memory. For this reason, in existing drivers that may have historically called useracc, it is no longer necessary to perform such a check and subsequent locking of memory with vslock. The general rule is that any interface called from the physio interface (that is, the driver's strategy interface) should not call useracc or its replacement vm_map_pageable because the physio interface performs those functions. If you called useracc prior to accessing user data, replace it with calls to copyin and copyout to access user space. Calling useracc simply verifies access permissions to the specified memory at the time the useracc interface is called. It is possible that immediately after the useracc interface has returned back to the driver that the corresponding memory could be invalid. The memory could be invalid if it was swapped out or otherwise remapped by the virtual memory management portion of the kernel. Therefore, a driver should not assume that the memory region whose access permissions are verified through a call to useracc is persistent. In Digital UNIX, calls to useracc are either unnecessary (as previously explained) or should be replaced by direct calls to vm_map_pageable. This interface performs functions for both verifying access permissions and for locking down the memory so that it cannot be invalidated until it is unlocked by subsequent calls to vm_map_pageable for this memory region. |
You need to compare the data structures that ULTRIX device drivers use with those that Digital UNIX device drivers use. Writing Device Drivers: Reference provides reference page descriptions of the data structures that Digital UNIX device drivers use. Use this information to compare the data structure's members with its associated ULTRIX data structure. Table 4-2 lists some of these differences.
Data Structure | Remarks |
uba_ctlr | Replace references to the uba_ctlr structure and its associated members with references to the controller structure and its associated members. |
uba_device | Replace references to the uba_device structure and its associated members with references to the device structure and its associated members. Make sure that the reference is to a slave, for example, a disk or tape drive. If the reference is to a controller, reference the controller structure, not the device structure. |
uba_driver | Replace references to the uba_driver structure and its associated members with references to the driver structure and its associated members. |
This section is for driver writers who have already written device drivers for previous versions of the operating system.
The following list summarizes the issues you need to consider when deciding whether to update device drivers written on previous versions of the operating system to the current version of Digital UNIX. Although existing device drivers are binary compatible with the current version of Digital UNIX, you might want to make these changes to take advantage of the single binary module technology.
The following sections provide details on each of these issues. Section 4.2.14 lists the interfaces that will be retired in a future release of Digital UNIX and the replacement interface, if applicable. Section 4.2.15 lists the data structures that will be retired in a future release of Digital UNIX and the replacement structure, if applicable. Section 4.2.16 lists the fields used in the sysconfigtab file fragment (formerly, the stanza.static and stanza.loadable file fragments) that will be retired in a future release of Digital UNIX.
In previous versions of the operating system, you could do the following:
For statically configured drivers operating on the EISA bus, ISA bus, TURBOchannel bus, and VMEbus, you could specify the associated interrupt handlers in the config.file file fragment or target (system) configuration file.
For statically or dynamically configured drivers operating on the PCI bus and for dynamically configured drivers operating on the EISA bus, ISA bus, and TURBOchannel bus you had to use the handler interfaces to register the associated interrupt handlers.
Digital recommends that you register interrupt handlers for statically and dynamically configured drivers operating on any Digital-supported bus (EISA, ISA, PCI, and TURBOchannel) by using the ihandler_t and handler_intr_info structures and by calling the handler interfaces. Section 7.1.6 shows how to accomplish this task. You typically register interrupt handlers in the driver's probe interface.
For the VMEbus, you call the handler interfaces, but instead of using the handler_intr_info structure, you use the vme_handler_info structure. One of the members of the vme_handler_info structure is a handler_intr_info structure.
Because the method for registering interrupt handlers is through the handler interfaces, device drivers should no longer be calling the enable_option and disable_option interfaces. The enable_option and disable_option interfaces will be retired in a future release of Digital UNIX.
In previous versions of the operating system, you could do the following:
For the third-party device driver configuration model, you specified the entry points for the I/O services interfaces (and other information) for block and character device drivers in the stanza.static file fragment. For the traditional model, you edited the bdevsw and/or cdevsw tables in the conf.c file with the entry points for the I/O services interfaces (and other information) for block and character drivers.
For block device drivers, you added the entry points for the I/O services interfaces (and other information) to the bdevsw table by calling the bdevsw_add interface in the driver's configure interface.
For character device drivers, you added the entry points I/O services interfaces (and other information) to the cdevsw table by calling the cdevsw_add interface in the driver's configure interface.
For block and character device drivers, you added the entry points for the I/O services interfaces (and other information) to the bdevsw and cdevsw tables by calling the dualdevsw_add interface in the driver's configure interface.
If you implemented the driver to be statically or dynamically configured, you perform the tasks listed in the previous items.
To register character and block driver entry points for statically or dynamically configured drivers, you call the devsw_add interface. You no longer specify a static driver's interfaces in the stanza.static file fragment. Section 6.6.5.2 discusses how to register character and block driver interfaces by calling the devsw_add interface. (The stanza.static file fragment is replaced by the sysconfigtab file fragment.)
The call to the devsw_add interface also reserves a major number (both block and character). A device driver is responsible for determining if an open or close call is to the block or character device by examining the format argument.
In previous versions of the operating system, the buses implemented on Alpha CPUs have an associated bus-specific option data structure defined in the bus-specific header file. The following list identifies the option structures for the EISA, ISA, PCI, and TURBOchannel buses that were supported in a previous version of Digital UNIX:
In a previous version of Digital UNIX, to write portable device drivers (that were statically configured) across multiple bus architectures you needed to add device entries to the bus-specific option structure arrays. When using the traditional model, you used a text editor to directly edit these arrays. When using the third-party model, you did not directly edit the arrays. Instead, you provided the bus-specific option array information in the following files for use with the mkdata utility: eisa_data (for the EISA/ISA bus option structure array), pci_data (for the PCI bus option structure array), and tc_data (for the TURBOchannel bus option structure array). To write portable drivers (that were dynamically configured) across multiple bus architectures in a previous version of Digital UNIX, you needed to declare and initialize bus-specific option structure snippets.
For this version of Digital UNIX, you no longer add entries to the bus-specific option structure arrays (for statically configured drivers) or declare and initialize a bus-specific option structure snippet (for dynamically configured drivers) or add entries to the eisa_data, pci_data, and tc_data files (for the traditional model). You now use the EISA_Option (for EISA buses), ISA_Option (for ISA buses), PCI_Option (for PCI buses), TC_Option (for TURBOchannel buses), and VBA_Option (for the VMEbus) attribute fields to populate a driver's sysconfigtab file fragment. See the bus-specific book for descriptions of the EISA_Option, ISA_Option, PCI_Option, TC_Option, and VBA_Option attribute fields.
In previous versions of the operating system, third-party driver writers supplied to their customers:
In this version of Digital UNIX it is not necessary to ship files with .o extensions. The reason is that Digital UNIX supports a single binary module (for drivers that are statically or dynamically configured into the kernel). Thus, third-party driver writers supply to their customers a single binary module, which has a .mod extension. Note that the .mod file in this version of Digital UNIX is not the same as the .mod file in previous versions of the operating system. Part 4 contains chapters that describe how to statically and dynamically configure third-party device drivers into the kernel.
In previous versions of the operating system, you could specify the following in the stanza.static file fragment:
For this version of Digital UNIX, the stanza.static file fragment is replaced by the sysconfigtab file fragment. You must not specify the I/O services interfaces (and other information) for block and character drivers in the sysconfigtab file fragment. Section 6.6.5.2 discusses how to register character and block driver interfaces by calling the devsw_add interface.
You specify device special file information, bus option, and other information in the sysconfigtab file fragment. Section 14.1.5 describes in detail how to create a driver's sysconfigtab file fragment and what items to place in it.
In previous versions of the operating system, you could specify the following in the stanza.loadable file fragment:
Module_Config1 = controller none0 at tc?
For this version of Digital UNIX, the stanza.loadable file fragment is replaced by the sysconfigtab file fragment. You must not specify device connectivity information in the sysconfigtab file fragment. Section 6.6.6 shows how to specify device connectivity information by calling the create_controller_struct and create_device_struct interfaces.
You specify device special file, bus option, and other information in the sysconfigtab file fragment. Section 14.1.5 describes in detail how to create a driver's sysconfigtab file fragment and what items to place in it.
The syntax you use to specify information in the files file fragment has changed. The reason for the changes is to accommodate the single binary module. Section 14.1.3 discusses the syntax associated with a files file fragment. Note that the if_dynamic and optional keywords will be retired in a future release of the Digital UNIX operating system.
In previous versions of the operating system, you could specify the following in the config.file file fragment:
For this version of Digital UNIX, the config.file file fragment is no longer used. Section 6.6.6 shows how to specify device connectivity information by calling the create_controller_struct and create_device_struct interfaces.
In previous versions of the operating system, you typically called the following kernel support interfaces:
Configures the specified controller
Merges the configuration data
Unconfigures the specified controller
Digital recommends that you replace these interfaces as follows:
In previous versions of the operating system, you identified bus, controller, and device information as follows:
For drivers that are statically configured, you identify bus, controller, and device information by specifying an appropriate syntax in the config.file file fragment. For this version of Digital UNIX, the config.file file fragment is no longer used.
For drivers that are dynamically configured, you identify bus, controller, and device information by specifying an appropriate syntax in the stanza.loadable file fragment. For this version of Digital UNIX, the stanza.loadable file fragment is replaced by the sysconfigtab file fragment. You do not identify bus, controller, and device information in the sysconfigtab file fragment.
Digital UNIX provides the create_controller_struct and create_device_struct interfaces. These interfaces create the controller and device structures associated with your device driver. Section 6.6.4.3 shows you how to use these interfaces.
As a result of these changes, you no longer need to supply bus, controller, and device specification information in the sysconfigtab file fragment. (This means that the Module_Config stanza field will not be supported in a future release of Digital UNIX.)
Digital no longer recommends that you use name_data.c files to size the data structures and data structure arrays for drivers that are statically configured into the kernel. All references to name_data.c files have been deleted. Section 2.6.2 describes how to dynamically allocate data structures.
In previous versions of the operating system, you specified device special file information in the stanza.static file fragment for statically configured drivers and in the stanza.loadable file fragment for dynamically configured drivers. You specified device special file informtion by using the device special file-related attribute fields.
For this version of Digital UNIX, the stanza.static and stanza.loadable file fragments are replaced by the sysconfigtab file fragment. You use the device special file-related attribute fields in the sysconfigtab file fragment to identify device special files. Section 13.4 describes the sysconfigtab file fragment and Section 14.1.5 describes the syntax for the attribute fields associated with the sysconfigtab file fragment.
The device driver header file contains #define statements for as many devices as are configured into the system. This file is generated by the config program during static configuration of the device driver. The config program creates a compile-time variable, which defines how many devices exist on the system. Many existing ULTRIX-based drivers use this compile-time variable in device driver code to refer to the number of this type of device on the system. This usage most frequently occurs in structure array declarations and in condition (for example, if and while) statements. In previous versions of Digital UNIX device drivers could use this device driver header file.
For this version of Digital UNIX, the device driver header file is no longer used.
Table 4-3 lists the interfaces that will be retired in a future release of Digital UNIX. The table also identifies a replacement for the retired interface (if applicable).
Retired Interface | Replacement |
bdevsw_add | devsw_add |
bdevsw_del | devsw_del |
cdevsw_add | devsw_add |
cdevsw_del | devsw_del |
disable_option | Not applicable |
dualdevsw_add | devsw_add |
dualdevsw_del | devsw_del |
enable_option | Not applicable |
kalloc | MALLOC |
kfree | FREE |
kget | Not applicable |
ldbl_ctlr_configure | configure_driver |
ldbl_ctlr_unconfigure | unconfigure_driver |
ldbl_stanza_resolver | Not applicable |
zalloc | MALLOC |
zchange | Not applicable |
zfree | FREE |
zget | Not applicable |
zinit | Not applicable |
Table 4-4 lists the data structures that will be retired in a future release of Digital UNIX. The table also identifies a replacement for the retired structure.
Retired Structure | Replacement |
bdevsw | dsent |
cdevsw | dsent |
zone | Not applicable |
The following list identifies stanza fields that will be retired in a future release of Digital UNIX: