One goal of an open systems environment is to provide hardware and software platforms that promote the use of standards. Platforms that adhere to standard interfaces enable third-party application programmers to write applications that can run on a variety of operating systems and hardware. Digital UNIX supports this philosophy by providing kernel interfaces that device drivers operating on any bus can use. Writing Device Drivers: Tutorial provides examples of how to use many of these interfaces.
In some cases, the kernel interface has a specific use on a bus. One such interface is get_config. The get_config interface returns configuration data information assigned to the specified device. For device drivers operating on the EISA bus, you use get_config to find out what resources the EISA Configuration Utility (ECU) assigned to your device. For example, by calling get_config you can find out which interrupt channel characteristics, which DMA channel, and which memory region the ECU assigned to the device.
The get_config interface takes a pointer to a structure appropriate for storing the requested data. For device drivers operating on EISA/ISA buses, you store the data returned by get_config in the following data structures defined in /usr/sys/include/io/dec/eisa/eisa.h:
Describes EISA/ISA bus memory characteristics
Contains direct memory access (DMA) channel information
Contains I/O port information
Contains EISA/ISA bus interrupt channel characteristics
The get_config interface allows you to obtain multiple instances of a given resource by returning a handle to the next instance. The following code fragment shows how you call get_config for a device that allocates two memory blocks:
struct controller *ctlr_p;
.
.
.
struct bus_mem buf[2]; [1] int handle; [2] int i;
handle = 0; i = 0;
do handle = get_config (ctlr_p, RES_MEM, , &buf[i], handle); [3] while (handle > 0 && i < 2);
if (i >= 2 || handle < 0) /* Deal with possible error conditions */
.
.
.
The get_config interface takes five arguments:
The first argument specifies a pointer to the controller structure associated with the controller to be configured. The get_config interface obtains the device whose assigned configuration data you want through its controller's associated controller structure pointer.
In this call, you pass the controller structure pointer associated with this device.
The second argument specifies a pointer to the controller structure associated with the controller to be configured. The get_config interface obtains the device whose assigned configuration data you want through its controller's associated controller structure pointer.
In this call, you pass the constant RES_MEM to indicate that get_config should return bus memory characteristics.
The third argument specifies a bus-specific argument. For the EISA bus, this argument specifies the function type string that appears in the device's eisa_option structure. This argument has no meaning for the ISA bus because the ISA bus does not use the function string specified in the eisa_option structure.
In this call, you pass the null string.
The fourth argument specifies a pointer to a structure appropriate for storing the requested data.
In this call, you pass the address of the bus_mem structure array.
The fifth argument specifies a handle returned by get_config if there is more configuration data of the type requested in the config_item argument. You must pass the value zero (0) on the first call to get_config. On subsequent calls to get_config for this configuration data type, you pass the value returned in the previous call to get_config.
In this call, you pass the handle argument. The first time get_config is called, this argument is zero (0). The second time get_config is called, this argument contains a handle that points to the next element in the list.
You can also achieve the same results by assigning a unique TYPE string to each memory block request in the device configuration file and calling get_config. Assume that you assign one memory block request a TYPE string of Input buffer and the other memory block request a TYPE string of Output buffer. The call to get_config now looks as follows:
struct bus_mem in_buf, out_buf; int handle;
handle = get_config (ctlr_p, RES_MEM, "Input buffer", &in_buf, 0); if (handle != 0) /* Deal with possible error conditions */
handle = get_config (ctlr_p, RES_MEM, "Output buffer", &out_buf, 0); if (handle != 0) /* Deal with possible error conditions */