summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorse <se@FreeBSD.org>1997-01-21 23:23:40 +0000
committerse <se@FreeBSD.org>1997-01-21 23:23:40 +0000
commit784b0949d6e2aa7e6a0c069ff892d2c3aeb4bf31 (patch)
tree1541b922e1ceb2ea7b909670526e8b7b791162a1 /sys/dev
parentfe537196d330ad8f0b38629a10633c0313ffd586 (diff)
downloadFreeBSD-src-784b0949d6e2aa7e6a0c069ff892d2c3aeb4bf31.zip
FreeBSD-src-784b0949d6e2aa7e6a0c069ff892d2c3aeb4bf31.tar.gz
Add PCI LKM support.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/pci.c679
1 files changed, 389 insertions, 290 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index c332094..08ad7d9 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -86,11 +86,8 @@ struct pcicb {
struct pcicb *pcicb_down;
pcici_t pcicb_bridge;
- u_long pcicb_seen;
u_char pcicb_bus;
u_char pcicb_subordinate;
- u_char pcicb_flags;
-#define PCICB_ISAMEM 0x01
u_int pcicb_mfrom;
u_int pcicb_mupto;
u_int pcicb_mamount;
@@ -108,19 +105,30 @@ struct pcicb {
u_long pcicb_p_memlimit;
};
+struct pci_lkm {
+ struct pci_device *dvp;
+ struct pci_lkm *next;
+};
+
static void
not_supported (pcici_t tag, u_long type);
static void
pci_bus_config (void);
+static void
+pci_rescan (void);
+
+static void pci_attach (int bus, int dev, int func,
+ struct pci_device *dvp, const char *name);
+
static int
pci_bridge_config (void);
static int
pci_mfdev (int bus, int device);
-static void pci_remember (int bus, int dev, int func);
+static void pci_remember (int bus, int dev, int func, struct pci_device *dvp);
/*========================================================
**
@@ -140,8 +148,6 @@ unsigned pciroots = 0; /* XXX pcisupport.c increments this
* for the Orion host to PCI bridge
* UGLY hack ... :( Will be changed :)
*/
-static struct pcibus* pcibus;
-
/*--------------------------------------------------------
**
** Local variables.
@@ -149,10 +155,18 @@ static struct pcibus* pcibus;
**--------------------------------------------------------
*/
+static struct pcibus *pcibus;
+
static int pci_conf_count;
static int pci_info_done;
static int pcibusmax;
-static struct pcicb *pcicb;
+static struct pcicb *pcicb;
+
+static struct pci_conf *pci_dev_list;
+static unsigned pci_dev_list_count;
+static unsigned pci_dev_list_size;
+
+static struct pci_lkm *pci_lkm_head;
/*-----------------------------------------------------------------
**
@@ -374,6 +388,264 @@ pci_bridge_config (void)
/*========================================================
**
+** pci_attach()
+**
+** Attach one device
+**
+**========================================================
+*/
+
+static void pci_attach (int bus, int dev, int func,
+ struct pci_device *dvp, const char *name)
+{
+ u_long data;
+ int unit;
+ u_char reg;
+ u_char pciint;
+ int irq;
+ pcici_t tag = pcibus->pb_tag (bus, dev, func);
+
+ /*
+ ** Get and increment the unit.
+ */
+
+ unit = (*dvp->pd_count)++;
+
+ /*
+ ** Announce this device
+ */
+
+ printf ("%s%d <%s> rev %d", dvp->pd_name, unit, name,
+ (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff);
+
+ /*
+ ** Get the int pin number (pci interrupt number a-d)
+ ** from the pci configuration space.
+ */
+
+ data = pci_conf_read (tag, PCI_INTERRUPT_REG);
+ pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
+
+ if (pciint) {
+
+ printf (" int %c irq ", 0x60+pciint);
+
+ irq = PCI_INTERRUPT_LINE_EXTRACT(data);
+
+ /*
+ ** If it's zero, the isa irq number is unknown,
+ ** and we cannot bind the pci interrupt.
+ */
+
+ if (irq && (irq != 0xff))
+ printf ("%d", irq);
+ else
+ printf ("??");
+ };
+
+ printf (" on pci%d:%d:%d\n", bus, dev, func);
+
+ /*
+ ** Read the current mapping,
+ ** and update the pcicb fields.
+ */
+
+ for (reg=PCI_MAP_REG_START;reg<PCI_MAP_REG_END;reg+=4) {
+ u_int map, addr, size;
+
+ data = pci_conf_read(tag, PCI_CLASS_REG);
+ switch (data & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
+ case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
+ continue;
+ };
+
+ map = pci_conf_read (tag, reg);
+ if (!(map & PCI_MAP_MEMORY_ADDRESS_MASK))
+ continue;
+
+ pci_conf_write (tag, reg, 0xffffffff);
+ data = pci_conf_read (tag, reg);
+ pci_conf_write (tag, reg, map);
+
+ switch (data & 7) {
+
+ default:
+ continue;
+ case 1:
+ case 5:
+ addr = map & PCI_MAP_IO_ADDRESS_MASK;
+ size = -(data & PCI_MAP_IO_ADDRESS_MASK);
+ size &= ~(addr ^ -addr);
+
+ pci_register_io (pcicb, addr, addr+size-1);
+ pcicb->pcicb_pamount += size;
+ break;
+
+ case 0:
+ case 2:
+ case 4:
+ size = -(data & PCI_MAP_MEMORY_ADDRESS_MASK);
+ addr = map & PCI_MAP_MEMORY_ADDRESS_MASK;
+ if (addr >= 0x100000) {
+ pci_register_memory (pcicb, addr, addr+size-1);
+ pcicb->pcicb_mamount += size;
+ };
+ break;
+ };
+ if (bootverbose)
+ printf ("\tmapreg[%02x] type=%d addr=%08x size=%04x.\n",
+ reg, map&7, addr, size);
+ };
+
+ /*
+ ** attach device
+ ** may produce additional log messages,
+ ** i.e. when installing subdevices.
+ */
+
+ (*dvp->pd_attach) (tag, unit);
+
+ /*
+ ** Special processing of certain classes
+ */
+
+ data = pci_conf_read(tag, PCI_CLASS_REG);
+
+ switch (data & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
+ struct pcicb *this, **link;
+ unsigned char primary, secondary, subordinate;
+ u_int command;
+
+ case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
+
+ /*
+ ** get current configuration of the bridge.
+ */
+ data = pci_conf_read (tag, PCI_PCI_BRIDGE_BUS_REG);
+ primary = PCI_PRIMARY_BUS_EXTRACT (data);
+ secondary = PCI_SECONDARY_BUS_EXTRACT(data);
+ subordinate = PCI_SUBORDINATE_BUS_EXTRACT(data);
+#ifndef PCI_QUIET
+ if (bootverbose) {
+ printf ("\tbridge from pci%d to pci%d through %d.\n",
+ primary, secondary, subordinate);
+ printf ("\tmapping regs: io:%08lx mem:%08lx pmem:%08lx\n",
+ pci_conf_read (tag, PCI_PCI_BRIDGE_IO_REG),
+ pci_conf_read (tag, PCI_PCI_BRIDGE_MEM_REG),
+ pci_conf_read (tag, PCI_PCI_BRIDGE_PMEM_REG));
+ }
+#endif
+ /*
+ ** check for uninitialized bridge.
+ */
+ if (!(primary < secondary
+ && secondary <= subordinate
+ && bus == primary)) {
+
+ printf ("\tINCORRECTLY or NEVER CONFIGURED.\n");
+ /*
+ ** disable this bridge
+ */
+ pci_conf_write (tag, PCI_COMMAND_STATUS_REG, 0xffff0000);
+ secondary = 0;
+ subordinate = 0;
+ };
+
+ /*
+ ** allocate bus descriptor for bus behind the bridge
+ */
+ link = &pcicb->pcicb_down;
+ while (*link && (*link)->pcicb_bus < secondary)
+ link = &(*link)->pcicb_next;
+
+ this = malloc (sizeof (*this), M_DEVBUF, M_WAITOK);
+
+ /*
+ ** Initialize this descriptor so far.
+ ** (the initialization is completed just before
+ ** scanning the bus behind the bridge.
+ */
+ bzero (this, sizeof(*this));
+ this->pcicb_next = *link;
+ this->pcicb_up = pcicb;
+ this->pcicb_bridge = tag;
+ this->pcicb_bus = secondary;
+ this->pcicb_subordinate = subordinate;
+
+ command = pci_conf_read(tag,PCI_COMMAND_STATUS_REG);
+
+ if (command & PCI_COMMAND_IO_ENABLE){
+ /*
+ ** Bridge was configured by the bios.
+ ** Read out the mapped io region.
+ */
+ unsigned reg;
+
+ reg = pci_conf_read (tag, PCI_PCI_BRIDGE_IO_REG);
+ this->pcicb_iobase = PCI_PPB_IOBASE_EXTRACT (reg);
+ this->pcicb_iolimit = PCI_PPB_IOLIMIT_EXTRACT(reg);
+
+ /*
+ ** Note the used io space.
+ */
+ pci_register_io (pcicb, this->pcicb_iobase,
+ this->pcicb_iolimit);
+
+ };
+
+ if (command & PCI_COMMAND_MEM_ENABLE) {
+ /*
+ ** Bridge was configured by the bios.
+ ** Read out the mapped memory regions.
+ */
+ unsigned reg;
+
+ /*
+ ** non prefetchable memory
+ */
+ reg = pci_conf_read (tag, PCI_PCI_BRIDGE_MEM_REG);
+ this->pcicb_membase = PCI_PPB_MEMBASE_EXTRACT (reg);
+ this->pcicb_memlimit = PCI_PPB_MEMLIMIT_EXTRACT(reg);
+
+ /*
+ ** Register used memory space.
+ */
+ pci_register_memory (pcicb,
+ this->pcicb_membase,
+ this->pcicb_memlimit);
+
+ /*
+ ** prefetchable memory
+ */
+ reg = pci_conf_read (tag, PCI_PCI_BRIDGE_PMEM_REG);
+ this->pcicb_p_membase = PCI_PPB_MEMBASE_EXTRACT (reg);
+ this->pcicb_p_memlimit = PCI_PPB_MEMLIMIT_EXTRACT(reg);
+
+ /*
+ ** Register used memory space.
+ */
+ pci_register_memory (pcicb,
+ this->pcicb_p_membase,
+ this->pcicb_p_memlimit);
+ }
+
+ /*
+ ** Link it in chain.
+ */
+ *link=this;
+
+ /*
+ ** Update mapping info of parent bus.
+ */
+ if (!pcicb->pcicb_bfrom||secondary< pcicb->pcicb_bfrom)
+ pcicb->pcicb_bfrom = secondary;
+ if (subordinate > pcicb->pcicb_bupto)
+ pcicb->pcicb_bupto = subordinate;
+ }
+}
+
+/*========================================================
+**
** pci_bus_config()
**
** Autoconfiguration of one pci bus.
@@ -429,10 +701,6 @@ pci_bus_config (void)
u_char reg;
pcici_t tag, mtag;
pcidi_t type;
- u_long data;
- int unit;
- u_char pciint;
- int irq;
struct pci_device *dvp;
@@ -454,9 +722,6 @@ pci_bus_config (void)
struct pci_device **dvpp;
int func, maxfunc = 0;
- if ((pcicb->pcicb_seen >> device) & 1)
- continue;
-
for (func=0; func <= maxfunc; func++) {
tag = pcibus->pb_tag (bus_no, device, func);
type = pci_conf_read (tag, PCI_ID_REG);
@@ -522,7 +787,7 @@ pci_bus_config (void)
maxfunc = 7;
}
- pci_remember(bus_no, device, func);
+ pci_remember(bus_no, device, func, dvp);
if (dvp==NULL) {
#ifndef PCI_QUIET
@@ -540,268 +805,8 @@ pci_bus_config (void)
continue;
};
- pcicb->pcicb_seen |= (1ul << device);
-
- /*
- ** Get and increment the unit.
- */
-
- unit = (*dvp->pd_count)++;
-
- /*
- ** ignore device ?
- */
-
- if (!*name) continue;
-
- /*
- ** Announce this device
- */
-
- printf ("%s%d <%s> rev %d", dvp->pd_name, unit, name,
- (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff);
-
- /*
- ** Get the int pin number (pci interrupt number a-d)
- ** from the pci configuration space.
- */
-
- data = pci_conf_read (tag, PCI_INTERRUPT_REG);
- pciint = PCI_INTERRUPT_PIN_EXTRACT(data);
-
- if (pciint) {
-
- printf (" int %c irq ", 0x60+pciint);
-
- irq = PCI_INTERRUPT_LINE_EXTRACT(data);
-
- /*
- ** If it's zero, the isa irq number is unknown,
- ** and we cannot bind the pci interrupt.
- */
-
- if (irq && (irq != 0xff))
- printf ("%d", irq);
- else
- printf ("??");
- };
-
- if (maxfunc == 0)
- printf (" on pci%d:%d\n", bus_no, device);
- else
- printf (" on pci%d:%d:%d\n", bus_no, device, func);
-
- /*
- ** Read the current mapping,
- ** and update the pcicb fields.
- */
-
- for (reg=PCI_MAP_REG_START;reg<PCI_MAP_REG_END;reg+=4) {
- u_int map, addr, size;
-
- data = pci_conf_read(tag, PCI_CLASS_REG);
- switch (data & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
- case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
- continue;
- };
-
- map = pci_conf_read (tag, reg);
- if (!(map & PCI_MAP_MEMORY_ADDRESS_MASK))
- continue;
-
- pci_conf_write (tag, reg, 0xffffffff);
- data = pci_conf_read (tag, reg);
- pci_conf_write (tag, reg, map);
-
- switch (data & 7) {
-
- default:
- continue;
- case 1:
- case 5:
- addr = map & PCI_MAP_IO_ADDRESS_MASK;
- size = -(data & PCI_MAP_IO_ADDRESS_MASK);
- size &= ~(addr ^ -addr);
-
- pci_register_io (pcicb, addr, addr+size-1);
- pcicb->pcicb_pamount += size;
- break;
-
- case 0:
- case 2:
- case 4:
- size = -(data & PCI_MAP_MEMORY_ADDRESS_MASK);
- addr = map & PCI_MAP_MEMORY_ADDRESS_MASK;
- if (addr >= 0x100000) {
- pci_register_memory
- (pcicb, addr, addr+size-1);
- pcicb->pcicb_mamount += size;
- } else {
- pcicb->pcicb_flags |= PCICB_ISAMEM;
- };
- break;
- };
- if (bootverbose)
- printf ("\tmapreg[%02x] type=%d addr=%08x size=%04x.\n",
- reg, map&7, addr, size);
- };
-
- /*
- ** attach device
- ** may produce additional log messages,
- ** i.e. when installing subdevices.
- */
-
- (*dvp->pd_attach) (tag, unit);
-
- /*
- ** Special processing of certain classes
- */
-
- data = pci_conf_read(tag, PCI_CLASS_REG);
-
- switch (data & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) {
- struct pcicb *this, **link;
- unsigned char primary, secondary, subordinate;
- u_int command;
-
- case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI:
-
- /*
- ** get current configuration of the bridge.
- */
- data = pci_conf_read (tag, PCI_PCI_BRIDGE_BUS_REG);
- primary = PCI_PRIMARY_BUS_EXTRACT (data);
- secondary = PCI_SECONDARY_BUS_EXTRACT(data);
- subordinate = PCI_SUBORDINATE_BUS_EXTRACT(data);
-#ifndef PCI_QUIET
- if (bootverbose) {
- printf ("\tbridge from pci%d to pci%d through %d.\n",
- primary, secondary, subordinate);
- printf ("\tmapping regs: io:%08lx mem:%08lx pmem:%08lx\n",
- pci_conf_read (tag, PCI_PCI_BRIDGE_IO_REG),
- pci_conf_read (tag, PCI_PCI_BRIDGE_MEM_REG),
- pci_conf_read (tag, PCI_PCI_BRIDGE_PMEM_REG));
- }
-#endif
- /*
- ** check for uninitialized bridge.
- */
- if (!(primary < secondary
- && secondary <= subordinate
- && bus_no == primary))
- {
- printf ("\tINCORRECTLY or NEVER CONFIGURED.\n");
- /*
- ** disable this bridge
- */
- pci_conf_write (tag, PCI_COMMAND_STATUS_REG,
- 0xffff0000);
- secondary = 0;
- subordinate = 0;
- };
-
- /*
- ** allocate bus descriptor for bus behind the bridge
- */
- link = &pcicb->pcicb_down;
- while (*link && (*link)->pcicb_bus < secondary)
- link = &(*link)->pcicb_next;
-
- this = malloc (sizeof (*this), M_DEVBUF, M_WAITOK);
-
- /*
- ** Initialize this descriptor so far.
- ** (the initialization is completed just before
- ** scanning the bus behind the bridge.
- */
- bzero (this, sizeof(*this));
- this->pcicb_next = *link;
- this->pcicb_up = pcicb;
- this->pcicb_bridge = tag;
- this->pcicb_bus = secondary;
- this->pcicb_subordinate = subordinate;
-
- command = pci_conf_read(tag,PCI_COMMAND_STATUS_REG);
-
- if (command & PCI_COMMAND_IO_ENABLE){
- /*
- ** Bridge was configured by the bios.
- ** Read out the mapped io region.
- */
- unsigned reg;
-
- reg = pci_conf_read (tag,
- PCI_PCI_BRIDGE_IO_REG);
- this->pcicb_iobase =
- PCI_PPB_IOBASE_EXTRACT (reg);
- this->pcicb_iolimit =
- PCI_PPB_IOLIMIT_EXTRACT(reg);
-
- /*
- ** Note the used io space.
- */
- pci_register_io (pcicb, this->pcicb_iobase,
- this->pcicb_iolimit);
-
- };
-
- if (command & PCI_COMMAND_MEM_ENABLE) {
- /*
- ** Bridge was configured by the bios.
- ** Read out the mapped memory regions.
- */
- unsigned reg;
-
- /*
- ** non prefetchable memory
- */
- reg = pci_conf_read (tag,
- PCI_PCI_BRIDGE_MEM_REG);
- this->pcicb_membase =
- PCI_PPB_MEMBASE_EXTRACT (reg);
- this->pcicb_memlimit =
- PCI_PPB_MEMLIMIT_EXTRACT(reg);
-
- /*
- ** Register used memory space.
- */
- pci_register_memory (pcicb,
- this->pcicb_membase,
- this->pcicb_memlimit);
-
- /*
- ** prefetchable memory
- */
- reg = pci_conf_read (tag,
- PCI_PCI_BRIDGE_PMEM_REG);
- this->pcicb_p_membase=
- PCI_PPB_MEMBASE_EXTRACT (reg);
- this->pcicb_p_memlimit=
- PCI_PPB_MEMLIMIT_EXTRACT(reg);
-
- /*
- ** Register used memory space.
- */
- pci_register_memory (pcicb,
- this->pcicb_p_membase,
- this->pcicb_p_memlimit);
- }
-
- /*
- ** Link it in chain.
- */
- *link=this;
-
- /*
- ** Update mapping info of parent bus.
- */
- if (!pcicb->pcicb_bfrom||secondary< pcicb->pcicb_bfrom)
- pcicb->pcicb_bfrom = secondary;
- if (subordinate > pcicb->pcicb_bupto)
- pcicb->pcicb_bupto = subordinate;
-
- break;
+ if (*name) {
+ pci_attach (bus_no, device, func, dvp, name);
}
}
}
@@ -832,9 +837,6 @@ pci_bus_config (void)
**
** Autoconfiguration of pci devices.
**
-** May be called more than once.
-** Any device is attached only once.
-**
** Has to take care of mirrored devices, which are
** entailed by incomplete decoding of pci address lines.
**
@@ -896,6 +898,81 @@ void pci_configure()
pci_conf_count++;
}
+/*========================================================
+**
+** pci_rescan ()
+**
+** try to find lkm driver for device
+**
+** May be called more than once.
+** Any device is attached only once.
+**
+**========================================================
+*/
+
+static void pci_rescan()
+{
+ int i;
+ for (i = 0; i < pci_dev_list_count; i++)
+ {
+ struct pci_lkm *lkm;
+ pcici_t tag;
+ struct pci_device *dvp;
+ pcidi_t type = pci_dev_list[i].pc_devid;
+ char *name = NULL;
+ int bus, dev, func;
+
+ if (pci_dev_list[i].pc_dvp)
+ continue;
+
+ bus = pci_dev_list[i].pc_sel.pc_bus;
+ dev = pci_dev_list[i].pc_sel.pc_dev;
+ func = pci_dev_list[i].pc_sel.pc_func;
+
+ tag = pcibus->pb_tag (bus, dev, func);
+
+ for (lkm = pci_lkm_head; lkm; lkm = lkm->next) {
+ dvp = lkm->dvp;
+ if (name=(*dvp->pd_probe)(tag, type))
+ break;
+ }
+ if (name && *name) {
+ pcicb = pci_dev_list[i].pc_cb;
+ pci_attach (bus, dev, func, dvp, name);
+ pci_dev_list[i].pc_dvp = dvp;
+ }
+ }
+}
+
+/*========================================================
+**
+** pci_register_lkm ()
+**
+** Add LKM PCI driver's struct pci_device to pci_lkm chain
+**
+**========================================================
+*/
+
+int pci_register_lkm (struct pci_device *dvp)
+{
+ struct pci_lkm *lkm;
+
+ if (!dvp || !dvp->pd_probe || !dvp->pd_attach) {
+ return -1;
+ }
+
+ lkm = malloc (sizeof (*lkm), M_DEVBUF, M_WAITOK);
+ if (!lkm) {
+ return -1;
+ }
+
+ lkm->dvp = dvp;
+ lkm->next = pci_lkm_head;
+ pci_lkm_head = lkm;
+ pci_rescan();
+ return 0;
+}
+
/*-----------------------------------------------------------------------
**
** Map device into port space.
@@ -923,12 +1000,6 @@ int pci_map_port (pcici_t tag, u_long reg, u_short* pa)
return (0);
};
- /*if (pcicb->pcicb_flags & PCICB_NOIOSET) {
- printf ("pci_map_port failed: pci%d has not been configured for I/O access\n",
- pcicb->pcicb_bus);
- return (0);
- }*/
-
/*
** get size and type of port
**
@@ -1709,12 +1780,10 @@ void not_supported (pcici_t tag, u_long type)
/*
* This is the user interface to the PCI configuration space.
*/
-static struct pci_conf *pci_dev_list;
-static unsigned pci_dev_list_count;
-static unsigned pci_dev_list_size;
+
static void
-pci_remember(int bus, int dev, int func)
+pci_remember(int bus, int dev, int func, struct pci_device *dvp)
{
struct pci_conf *p;
pcici_t tag;
@@ -1746,6 +1815,8 @@ pci_remember(int bus, int dev, int func)
p->pc_hdr = (pci_conf_read (tag, PCI_HEADER_MISC) >> 16) & 0xff;
tag = pcibus->pb_tag (bus, dev, func);
p->pc_devid = pci_conf_read(tag, PCI_ID_REG);
+ p->pc_dvp = dvp;
+ p->pc_cb = pcicb;
if ((p->pc_hdr & 0x7f) == 1) {
p->pc_subid = pci_conf_read(tag, PCI_SUBID_REG1);
} else {
@@ -1828,6 +1899,34 @@ pci_ioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
}
break;
+ case PCIOCATTACHED:
+ io = (struct pci_io *)data;
+ switch(io->pi_width) {
+ case 4:
+ {
+ int i = pci_dev_list_count;
+ struct pci_conf *p = pci_dev_list;
+ error = ENODEV;
+ while (i--) {
+ if (io->pi_sel.pc_bus == p->pc_sel.pc_bus &&
+ io->pi_sel.pc_dev == p->pc_sel.pc_dev &&
+ io->pi_sel.pc_func == p->pc_sel.pc_func) {
+ io->pi_data = (u_int32_t)p->pc_dvp;
+ error = 0;
+ break;
+ }
+ p++;
+ }
+ }
+ break;
+ case 2:
+ case 1:
+ default:
+ error = ENODEV;
+ break;
+ }
+ break;
+
default:
error = ENOTTY;
break;
OpenPOWER on IntegriCloud