SCO OpenServer


Sharegister -- dynamically register a SCSI host adapter driver


   #include <sys/devreg.h>

static SHAREG_EX shareg_ex; Sharegister (*shareg_ex);

static SHAREG shareg; Sharegister (*shareg);


The Sharegister(D3osdi) function is called by all SCSI host adapter drivers to register themselves to the kernel.


pointer to an shareg_ex(D4osdi) structure.

Return values



There are two forms of the Sharegister( ) function, differentiated by the type of structure that is passed to the function (either SHAREG or SHAREG_EX):

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)

Context and synchronization

Initialization context.

Hardware applicability


Version applicability

osdi: 2, 3, 4, 5 host adapter drivers



``Multithreaded drivers'' in HDK Technical Reference

``OSDI SCSI driver interface version for SCO OpenServer 5'' in HDK Technical Reference


The following example assumes that the driver is capable of controlling both PCI and non-PCI devices. If this is not true, then only code relevant to the supported bus architecture needs to be included.
   #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; }

... }

           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)

/* * 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]); }

... }

19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 5 HDK - June 2005