|
|
#include <sys/devreg.h>static SHAREG_EX shareg_ex; Sharegister (*shareg_ex);
static SHAREG shareg; Sharegister (*shareg);
This form of the Sharegister( ) function also allows an adpater driver to use an interrupt vector other than the one that was configured for use by the driver when the kernel was linked. This is useful for adapters that provide the capability for the driver to determine the actual interrupt vector that is set on the hardware.
Sharegister( ) should be called once for each host adapter found by the driver. Each call should pass in a pointer to a unique static SHAREG_EX structure; in other words, do not reuse the same structure for successive board registration, and do not use an auto variable.
If no information is found about the adapter previously registered, the system will panic and display a diagnostic message on the console. If the device has already been registered, Sharegister( ) returns without performing any action.
Host adapters are registered at the back of a queue of shareg_ex structures so they do not preempt previously registered adapters. In this way, they are less likely to be used by code that guesses a boot device. On an Install kernel, the last HBA to register is the one that is assigned to peripheral drivers by default.
Sdevregister(D3osdi), scsi_distributed(D3osdi)
``Multithreaded drivers'' in HDK Technical Reference
``OSDI SCSI driver interface version for SCO OpenServer 5'' in HDK Technical Reference
#include "sys/pci.h" #include "sys/devreg.h"extern SHAREG_EX xx_reg[]; extern struct xx_adapter_info xx_adapter_info[]; extern xx_processor, xx_weight;
#define PCI_DEVICE 1 #define NONPCI_DEVICE 2
xx_entry(req_ptr) REQ_IO *req_ptr; { static int first_time = 1; struct xx_adapter_info *ptr; int y;
...
if (first_time) {
/* * Determine the (32-bit) argument passed to the interrupt * routine for all PCI devices controlled by this driver. * Note that this can also be done at interrupt time but NOT * at init time. */
for (y = 0; y < NADAPTERS; y++) { ptr = &xx_adapter_info[y]; if (ptr->type != PCI_DEVICE) continue;
ptr->intr_arg = get_intr_arg(ptr->bus, SHAREG_PCI_INTVEC(ptr->device, ptr->function));
} first_time = 0; }
... }
xxinit() { int y, bus, device, function; struct pci_businfo businfo; struct pci_devinfo devinfo;...
/* * Find all adapters that can be controlled by this driver. * Note that we must search the PCI buses first because it is * possible that a device on a PCI bus may have an IO base address * in the EISA/ISA range. */
if (pci_buspresent(&businfo)) {
for (y = 0; y < NADAPTERS, y++) {
/* * Note that any or all of xx_vendorID, xx_deviceID, * xx_baseclass, or xx_subclass may be wildcards. * See the pci* man pages in Section D3oddi for full details. */
if (pci_search(xx_vendorID, xx_deviceID, xx_baseclass, xx_subclass, y, &devinfo)) { xx_adapter_info[y].found = 1; xx_adapter_info[y].type = PCI_DEVICE; xx_adapter_info[y].bus = devinfo.busnum; xx_adapter_info[y].device = devinfo.slotnum; xx_adapter_info[y].function = devinfo.funcnum; } else { xx_adapter_info[y].found = 0; break; } } } /* * Now search for all non-PCI adapters. * Note that this will be adapter specific code. */
for ( ; y < NADAPTERS; y++) { if (xx_adapter_found()) { xx_adapter_info[y].found = 1; xx_adapter_info[y].type = NONPCI_DEVICE; } else { xx_adapter_info[y].found = 0; break; } }
for (y = 0; y < NADAPTERS; y++) { if (!xx_adapter_info[y].found) continue;/* * Call Sharegister for each un-registered adapter. */
xx_reg[y].forw = 0; xx_reg[y].back = 0; xx_reg[y].route = IROUTE_GLOBAL; xx_reg[y].weight = xx_weight; xx_reg[y].mode = IMODE_SHARED_CDRIVERIPL; xx_reg[y].entry = xx_entry; xx_reg[y].intr = xxintr; xx_reg[y].root_id = 0; xx_reg[y].in_use = 1;
/* * It is assumed that this driver is second level * multithreaded and is able to field interrupts on all * available processors. If this is not true then the * processor_mask field should be set to 1 (this will * restrict interrupts to the base cpu). */
xx_reg[y].processor_mask = remap_driver_cpu(xx_processor, ICPU_EXANY);
if (xx_adapter_info[y].type == PCI_DEVICE) { xx_reg[y].version = SHAREG_VERSION2; xx_reg[y].bus = xx_adapter_info[y].bus xx_reg[y].int_vec = SHAREG_PCI_INTVEC(xx_adapter_info[y].device, xx_adapter_info[y].function); } else { xx_reg[y].version = SHAREG_VERSION; xx_reg[y].int_vec = xx_adapter_info[y].int_vec; }
/* * Note - the argument passed to Sharegister() must * be global (or static) and unique for each call. */
Sharegister(&xx_reg[y]); }
... }