|
|
#include <sys/devreg.h> #include <sys/ci/ciintr.h>void idistributed(driver_info dip);
``Interrupt handlers, attaching and registering'' in HDK Technical Reference,
``Multithreaded drivers'' in HDK Technical Reference,
``Linking and testing SCO OpenServer 5 drivers'' in Developing SCO OpenServer 5 kernel drivers
#include "sys/devreg.h" #include "sys/ci/ciintr.h" #include "sys/pci.h"#define PCI_DEVICE 1 #define NONPCI_DEVICE 2
extern struct xx_adapter_info xx_adapter_info[]; extern xx_processor, xx_weight, xx_ipl;
xxopen() { 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, IDIST_PCI_IRQ(ptr->device, ptr->function));
} first_time = 0; }
... }
xxinit() { int y, bus, device, function; struct pci_businfo businfo; struct pci_devinfo devinfo; driver_info di; ... /* * 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. */ 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;
di.name = "xx"; di.weight = xx_weight; di.ipl = xx_ipl; di.route = IROUTE_GLOBAL; di.mode = IMODE_SHARED_CDRIVERIPL;
/* * 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 * processor_mask should be set to 1 (this will restrict * interrupts to the base cpu only). */di.processor_mask = remap_driver_cpu(xx_processor, ICPU_EXANY);
if (xx_adapter_info[y].type == PCI_DEVICE) { di.version = DRV_INFO_VERS_2; di.irq = IDIST_PCI_IRQ(xx_adapter_info[y].device, xx_adapter_info[y].function); di.bus = xx_adapter_info[y].bus; } else { di.version = DRV_INFO_VERS_1; di.irq = xx_adapter_info[y].irq; }
idistributed(&di); /* note - argument can be local */ }
... }
Providing separate ISRs for each supported device improves performance and scalability for drivers that run on configurations that support distributed interrupts, since multiple interrupt contexts can run concurrently and independently on separate processors. This practice also provides the flexibility to, for example, allow the processing that is specific to a particular network to be bound to a particular processor.
1 extern int XX_irq[]; 2 extern void (*XX_intrs[]) (); 3 extern int XX_processor[];4 extern dev_t XXdevice[]; 5 void XXintr0(int lev) 6 { 7 XX_common_intr(lev, XXdevice); 8 } 9 void XXintr1(int lev) 10 { 11 XX_common_intr(lev, XXdevice + 1); 12 } 13 void XXintr2(int lev) 14 { 15 XX_common_intr(lev, XXdevice + 2); 16 } 17 void XXintr3(int lev) 18 { 19 XX_common_intr(lev, XXdevice + 3); 20 } 21 void (*XX_intrs[])() = {XXintr0, XXintr1, XXintr2, XXintr3 };
22 int XX_Processor[] = { 23 DRIVER_CPU_DEFAULT, 24 DRIVER_CPU_DEFAULT, 25 DRIVER_CPU_DEFAULT, 26 DRIVER_CPU_DEFAULT 27 };
28 for (board_index = 0; board_index < NUMDEVICES; board_index++) { 29 driver_info di;
30 di.version = DRV_INFO_VERS_1; 31 di.name = "XX"; 32 di.irq = XX_irq[board_index]; 33 di.iosaddr = 0; 34 di.ioeaddr = 0; 35 di.weight = SPL5; 36 di.intr = (int (*)())XX_intrs[board_index]; 37 di.ipl = SPL5; 38 di.route = IROUTE_GLOBAL; 39 di.mode = IMODE_SHARED_CDRIVERIPL;
40 di.processor_mask = remap_driver_cpu(XX_Processor[board_index], ICPU_EXANY);
41 idistributed(&di); 42 }