2 * Copyright 1999 Egbert Eich
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the authors not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The authors makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
28 #include <sys/types.h>
31 #if defined (__alpha__) || defined (__ia64__)
34 #include "AsmMacros.h"
39 * I'm rather simple mindend - therefore I do a poor man's
40 * pci scan without all the fancy stuff that is done in
41 * scanpci. However that's all we need.
44 PciStructPtr PciStruct = NULL;
45 PciBusPtr PciBuses = NULL;
46 PciStructPtr CurrentPci = NULL;
47 PciStructPtr PciList = NULL;
48 PciStructPtr BootBios = NULL;
51 static CARD32 PciCfg1Addr;
53 static void readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func,
55 static int checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func);
56 static int checkSlotCfg2(CARD32 bus, int dev);
57 static void readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg);
58 static CARD8 interpretConfigSpace(CARD32 *reg, int busidx,
59 CARD8 dev, CARD8 func);
60 static CARD32 findBIOSMap(PciStructPtr pciP, CARD32 *biosSize);
61 static void restoreMem(PciStructPtr pciP);
65 #define PCI_BUS_FROM_TAG(tag) (((tag) & 0x00ff0000) >> 16)
66 #define PCI_DFN_FROM_TAG(tag) (((tag) & 0x0000ff00) >> 8)
68 #include <asm/unistd.h>
71 axpPciCfgRead(CARD32 tag)
74 CARD32 val = 0xffffffff;
76 bus = PCI_BUS_FROM_TAG(tag);
77 dfn = PCI_DFN_FROM_TAG(tag);
79 syscall(__NR_pciconfig_read, bus, dfn, tag & 0xff, 4, &val);
84 axpPciCfgWrite(CARD32 tag, CARD32 val)
88 bus = PCI_BUS_FROM_TAG(tag);
89 dfn = PCI_DFN_FROM_TAG(tag);
91 syscall(__NR_pciconfig_write, bus, dfn, tag & 0xff, 4, &val);
94 static CARD32 (*readPci)(CARD32 reg) = axpPciCfgRead;
95 static void (*writePci)(CARD32 reg, CARD32 val) = axpPciCfgWrite;
97 static CARD32 readPciCfg1(CARD32 reg);
98 static void writePciCfg1(CARD32 reg, CARD32 val);
99 static CARD32 readPciCfg2(CARD32 reg);
100 static void writePciCfg2(CARD32 reg, CARD32 val);
102 static CARD32 (*readPci)(CARD32 reg) = readPciCfg1;
103 static void (*writePci)(CARD32 reg, CARD32 val) = writePciCfg1;
106 #if defined(__alpha__) || defined(__sparc__)
107 #define PCI_EN 0x00000000
109 #define PCI_EN 0x80000000
114 static int hostbridges = 1;
115 static unsigned long pciMinMemReg = ~0;
121 unsigned short configtype;
131 PciBusPtr pci_b1,pci_b2;
133 #if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__)
137 CARD32 tmp32_1, tmp32_2;
138 outb(PCI_MODE2_ENABLE_REG, 0x00);
139 outb(PCI_MODE2_FORWARD_REG, 0x00);
140 tmp1 = inb(PCI_MODE2_ENABLE_REG);
141 tmp2 = inb(PCI_MODE2_FORWARD_REG);
142 if ((tmp1 == 0x00) && (tmp2 == 0x00)) {
144 readPci = readPciCfg2;
145 writePci = writePciCfg2;
146 P_printf("PCI says configuration type 2\n");
148 tmp32_1 = inl(PCI_MODE1_ADDRESS_REG);
149 outl(PCI_MODE1_ADDRESS_REG, PCI_EN);
150 tmp32_2 = inl(PCI_MODE1_ADDRESS_REG);
151 outl(PCI_MODE1_ADDRESS_REG, tmp32_1);
152 if (tmp32_2 == PCI_EN) {
154 P_printf("PCI says configuration type 1\n");
156 P_printf("No PCI !\n");
162 if (configtype == 1) {
163 P_printf("PCI probing configuration type 1\n");
168 P_printf("\nProbing for devices on PCI bus %d:\n", busidx);
169 for (cardnum = 0; cardnum < MAX_DEV_PER_VENDOR_CFG1; cardnum++) {
172 /* loop over the different functions, if present */
173 if (!checkSlotCfg1(busidx,cardnum,func))
175 readConfigSpaceCfg1(busidx,cardnum,func,reg);
177 func = interpretConfigSpace(reg,busidx,
180 if (idx++ > MAX_PCI_DEVICES)
184 } while (++busidx < PCI_MAXBUS);
185 #if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__)
186 /* don't use outl() ;-) */
188 outl(PCI_MODE1_ADDRESS_REG, 0);
193 P_printf("PCI probing configuration type 2\n");
198 for (slot=0xc0; slot<0xd0; i++) {
199 if (!checkSlotCfg2(busidx,slot))
201 readConfigSpaceCfg2(busidx,slot,reg);
203 interpretConfigSpace(reg,busidx,
205 if (idx++ > MAX_PCI_DEVICES)
208 } while (++busidx < PCI_MAXBUS);
212 pciMaxBus = numbus - 1;
213 P_printf("Number of buses in system: %i\n",pciMaxBus + 1);
214 P_printf("Min PCI mem address: 0x%lx\n",pciMinMemReg);
222 if (pci_b1->primary == pci_b2->secondary)
223 pci_b1->pBus = pci_b2;
224 pci_b2 = pci_b2->next;
226 pci_b1 = pci_b1->next;
233 if (pci1->bus == pci_b2->secondary)
235 pci_b2 = pci_b2->next;
240 PciStructPtr tmp = PciStruct, tmp1;
244 tmp->next = PciStruct;
249 PciList = CurrentPci = PciStruct;
254 readPciCfg1(CARD32 reg)
258 outl(PCI_MODE1_ADDRESS_REG, reg);
259 val = inl(PCI_MODE1_DATA_REG);
260 outl(PCI_MODE1_ADDRESS_REG, 0);
261 P_printf("reading: 0x%x from 0x%x\n",val,reg);
266 writePciCfg1(CARD32 reg, CARD32 val)
268 P_printf("writing: 0x%x to 0x%x\n",val,reg);
269 outl(PCI_MODE1_ADDRESS_REG, reg);
270 outl(PCI_MODE1_DATA_REG,val);
271 outl(PCI_MODE1_ADDRESS_REG, 0);
275 readPciCfg2(CARD32 reg)
278 CARD8 bus = (reg >> 16) & 0xff;
279 CARD8 dev = (reg >> 11) & 0x1f;
280 CARD8 num = reg & 0xff;
282 outb(PCI_MODE2_ENABLE_REG, 0xF1);
283 outb(PCI_MODE2_FORWARD_REG, bus);
284 val = inl((dev << 8) + num);
285 outb(PCI_MODE2_ENABLE_REG, 0x00);
286 P_printf("reading: 0x%x from 0x%x\n",val,reg);
291 writePciCfg2(CARD32 reg, CARD32 val)
293 CARD8 bus = (reg >> 16) & 0xff;
294 CARD8 dev = (reg >> 11) & 0x1f;
295 CARD8 num = reg & 0xff;
297 P_printf("writing: 0x%x to 0x%x\n",val,reg);
298 outb(PCI_MODE2_ENABLE_REG, 0xF1);
299 outb(PCI_MODE2_FORWARD_REG, bus);
300 outl((dev << 8) + num,val);
301 outb(PCI_MODE2_ENABLE_REG, 0x00);
306 pciVideoDisable(void)
308 /* disable VGA routing on bridges */
309 PciBusPtr pbp = PciBuses;
310 PciStructPtr pcp = PciStruct;
313 writePci(pbp->Slot.l | 0x3c, pbp->bctl & ~(CARD32)(8<<16));
316 /* disable display devices */
318 writePci(pcp->Slot.l | 0x04, pcp->cmd_st & ~(CARD32)3);
319 writePci(pcp->Slot.l | 0x30, pcp->RomBase & ~(CARD32)1);
325 pciVideoRestore(void)
327 /* disable VGA routing on bridges */
328 PciBusPtr pbp = PciBuses;
329 PciStructPtr pcp = PciStruct;
332 writePci(pbp->Slot.l | 0x3c, pbp->bctl);
335 /* disable display devices */
337 writePci(pcp->Slot.l | 0x04, pcp->cmd_st);
338 writePci(pcp->Slot.l | 0x30, pcp->RomBase);
347 PciStructPtr pcp = CurrentPci;
352 while (pbp) { /* enable bridges */
353 writePci(pbp->Slot.l | 0x3c, pbp->bctl | (CARD32)(8<<16));
356 writePci(pcp->Slot.l | 0x04, pcp->cmd_st | (CARD32)3);
357 writePci(pcp->Slot.l | 0x30, pcp->RomBase | (CARD32)1);
361 PciRead8(int offset, CARD32 Slot)
363 int shift = offset & 0x3;
364 offset = offset & 0xFC;
365 return ((readPci(Slot | offset) >> (shift << 3)) & 0xff);
369 PciRead16(int offset, CARD32 Slot)
371 int shift = offset & 0x2;
372 offset = offset & 0xFC;
373 return ((readPci(Slot | offset) >> (shift << 3)) & 0xffff);
377 PciRead32(int offset, CARD32 Slot)
379 offset = offset & 0xFC;
380 return (readPci(Slot | offset));
384 PciWrite8(int offset, CARD8 byte, CARD32 Slot)
387 int shift = offset & 0x3;
388 offset = offset & 0xFC;
389 val = readPci(Slot | offset);
390 val &= ~(CARD32)(0xff << (shift << 3));
391 val |= byte << (shift << 3);
392 writePci(Slot | offset, val);
396 PciWrite16(int offset, CARD16 word, CARD32 Slot)
399 int shift = offset & 0x2;
400 offset = offset & 0xFC;
401 val = readPci(Slot | offset);
402 val &= ~(CARD32)(0xffff << (shift << 3));
403 val |= word << (shift << 3);
404 writePci(Slot | offset, val);
408 PciWrite32(int offset, CARD32 lg, CARD32 Slot)
410 offset = offset & 0xFC;
411 writePci(Slot | offset, lg);
415 mapPciRom(PciStructPtr pciP)
417 unsigned long RomBase = 0;
419 unsigned char *mem, *ptr;
420 unsigned char *scratch = NULL;
422 CARD32 biosSize = 0x1000000;
429 RomBase = findBIOSMap(pciP, &biosSize);
431 fprintf(stderr,"Cannot remap BIOS of %i:%i:%i "
432 "- trying preset address\n",pciP->bus,pciP->dev,
434 RomBase = pciP->RomBase & ~(CARD32)0xFF;
437 RomBase = pciP->RomBase & ~(CARD32)0xFF;
438 if (~RomBase + 1 < biosSize || !RomBase)
439 RomBase = findBIOSMap(pciP, &biosSize);
442 P_printf("RomBase: 0x%lx\n",RomBase);
444 if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
445 perror("opening memory");
450 PciWrite32(0x30,RomBase | 1,pciP->Slot.l);
453 mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
454 MAP_SHARED, mem_fd, RomBase | _bus_base());
456 mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
457 MAP_SHARED, mem_fd, RomBase);
459 if (pciP != CurrentPci) {
460 enablePci = PciRead32(0x4,pciP->Slot.l);
461 PciWrite32(0x4,enablePci | 0x2,pciP->Slot.l);
465 dprint((unsigned long)ptr,0x30);
467 while ( *ptr == 0x55 && *(ptr+1) == 0xAA) {
468 unsigned short data_off = *(ptr+0x18) | (*(ptr+0x19)<< 8);
469 unsigned char *data = ptr + data_off;
473 if (*data!='P' || *(data+1)!='C' || *(data+2)!='I' || *(data+3)!='R') {
476 type = *(data + 0x14);
477 P_printf("data segment in BIOS: 0x%x, type: 0x%x ",data_off,type);
479 if (type != 0) { /* not PC-AT image: find next one */
480 unsigned int image_length;
481 unsigned char indicator = *(data + 0x15);
482 if (indicator & 0x80) /* last image */
484 image_length = (*(data + 0x10)
485 | (*(data + 0x11) << 8)) << 9;
486 P_printf("data image length: 0x%x, ind: 0x%x\n",
487 image_length,indicator);
488 ptr = ptr + image_length;
491 /* OK, we have a PC Image */
492 length = (*(ptr + 2) << 9);
493 P_printf("BIOS length: 0x%x\n",length);
494 scratch = (unsigned char *)malloc(length);
495 /* don't use memcpy() here: Reading from bus! */
496 for (i=0;i<length;i++)
497 *(scratch + i)=*(ptr + i);
501 if (pciP != CurrentPci)
502 PciWrite32(0x4,enablePci,pciP->Slot.l);
504 /* unmap/close/disable PCI bios mem */
505 munmap(mem, biosSize);
507 /* disable and restore mapping */
508 writePci(pciP->Slot.l | 0x30, pciP->RomBase & ~(CARD32)1);
510 if (scratch && length) {
511 memcpy((unsigned char *)V_BIOS, scratch, length);
520 findPci(CARD16 slotBX)
522 CARD32 slot = slotBX << 8;
524 if (slot == (CurrentPci->Slot.l & ~PCI_EN))
525 return (CurrentPci->Slot.l | PCI_EN);
528 PciBusPtr pBus = CurrentPci->pBus;
530 /* fprintf(stderr,"slot: 0x%x bridge: 0x%x\n",slot, pBus->Slot.l); */
531 if (slot == (pBus->Slot.l & ~PCI_EN))
532 return pBus->Slot.l | PCI_EN;
536 PciStructPtr pPci = PciStruct;
538 /*fprintf(stderr,"slot: 0x%x bridge: 0x%x\n",slot, pPci->Slot.l); */
539 if (slot == (pPci->Slot.l & ~PCI_EN))
540 return pPci->Slot.l | PCI_EN;
549 pciSlotBX(PciStructPtr pPci)
551 return (CARD16)((pPci->Slot.l >> 8) & 0xFFFF);
555 findPciDevice(CARD16 vendorID, CARD16 deviceID, char n)
557 PciStructPtr pPci = CurrentPci;
561 if ((pPci->VendorID == vendorID) && (pPci->DeviceID == deviceID)) {
570 findPciClass(CARD8 intf, CARD8 subClass, CARD16 class, char n)
572 PciStructPtr pPci = CurrentPci;
576 if ((pPci->Interface == intf) && (pPci->SubClass == subClass)
577 && (pPci->BaseClass == class)) {
586 readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func, CARD32 *reg)
588 CARD32 config_cmd = PCI_EN | (bus<<16) |
589 (dev<<11) | (func<<8);
592 for (i = 0; i<64;i+=4) {
594 reg[i] = axpPciCfgRead(config_cmd | i);
596 outl(PCI_MODE1_ADDRESS_REG, config_cmd | i);
597 reg[i] = inl(PCI_MODE1_DATA_REG);
601 P_printf("0x%lx\n",reg[i]);
607 checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func)
609 CARD32 config_cmd = PCI_EN | (bus<<16) |
610 (dev<<11) | (func<<8);
613 reg = axpPciCfgRead(config_cmd);
615 outl(PCI_MODE1_ADDRESS_REG, config_cmd);
616 reg = inl(PCI_MODE1_DATA_REG);
618 if (reg != 0xFFFFFFFF)
625 checkSlotCfg2(CARD32 bus, int dev)
629 outb(PCI_MODE2_ENABLE_REG, 0xF1);
630 outb(PCI_MODE2_FORWARD_REG, bus);
632 outb(PCI_MODE2_FORWARD_REG, 0x00);
633 outb(PCI_MODE2_ENABLE_REG, 0x00);
634 if (val == 0xFFFFFFFF)
636 if (val == 0xF0F0F0F0)
642 readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg)
646 outb(PCI_MODE2_ENABLE_REG, 0xF1);
647 outb(PCI_MODE2_FORWARD_REG, bus);
648 for (i = 0; i<64;i+=4) {
649 reg[i] = inl((dev << 8) + i);
651 P_printf("0x%lx\n",reg[i]);
654 outb(PCI_MODE2_ENABLE_REG, 0x00);
658 interpretConfigSpace(CARD32 *reg, int busidx, CARD8 dev, CARD8 func)
661 CARD16 vendor, device;
662 CARD8 baseclass, subclass;
663 CARD8 primary, secondary;
664 CARD8 header, interface;
667 config_cmd = PCI_EN | busidx<<16 |
668 (dev<<11) | (func<<8);
670 for (i = 0x10; i < 0x28; i+=4) {
671 if (IS_MEM32(reg[i]))
672 if ((reg[i] & 0xFFFFFFF0) < pciMinMemReg)
673 pciMinMemReg = (reg[i] & 0xFFFFFFF0);
675 if (IS_MEM64(reg[i])) {
676 unsigned long addr = reg[i] |
677 (unsigned long)(reg[i+4]) << 32;
678 if ((addr & ~0xfL) < pciMinMemReg)
679 pciMinMemReg = (addr & ~0xfL);
684 vendor = reg[0] & 0xFFFF;
685 device = reg[0] >> 16;
686 P_printf("bus: %i card: %i func %i reg0: 0x%x ", busidx,dev,func,reg[0]);
687 baseclass = reg[8] >> 24;
688 subclass = (reg[8] >> 16) & 0xFF;
689 interface = (reg[8] >> 8) & 0xFF;
691 header = (reg[0x0c] >> 16) & 0xff;
692 P_printf("bc 0x%x, sub 0x%x, if 0x%x, hdr 0x%x\n",
693 baseclass,subclass,interface,header);
694 if (BRIDGE_CLASS(baseclass)) {
695 if (BRIDGE_PCI_CLASS(subclass)) {
696 PciBusPtr pbp = malloc(sizeof(PciBusRec));
697 P_printf("Pci-Pci Bridge found; ");
698 primary = reg[0x18] & 0xFF;
699 secondary = (reg[0x18] >> 8) & 0xFF;
700 P_printf("primary: 0x%x secondary: 0x%x\n",
702 pbp->bctl = reg[0x3c];
703 pbp->primary = primary;
704 pbp->secondary = secondary;
705 pbp->Slot.l = config_cmd;
706 pbp->next = PciBuses;
709 } else if (BRIDGE_HOST_CLASS(subclass)
710 && (hostbridges++ > 1)) {
713 } else if (VIDEO_CLASS(baseclass,subclass)) {
714 PciStructPtr pcp = malloc(sizeof(PciStructRec));
715 P_printf("Display adapter found\n");
716 pcp->RomBase = reg[0x30];
717 pcp->cmd_st = reg[4];
718 pcp->active = (reg[4] & 0x03) == 3 ? 1 : 0;
719 pcp->VendorID = vendor;
720 pcp->DeviceID = device;
721 pcp->Interface = interface;
722 pcp->BaseClass = baseclass;
723 pcp->SubClass = subclass;
724 pcp->Slot.l = config_cmd;
728 pcp->next = PciStruct;
732 && ((header & PCI_MULTIFUNC_DEV) == 0))
739 static CARD32 remapMEM_val;
740 static int remapMEM_num;
742 static int /* map it on some other video device */
743 remapMem(PciStructPtr pciP, int num, CARD32 size)
745 PciStructPtr pciPtr = PciStruct;
751 org = PciRead32(num + 0x10,pciP->Slot.l);
754 for (i = 0; i < 20; i=i+4) {
756 val = PciRead32(i + 0x10,pciPtr->Slot.l);
757 /* don't map it on itself */
758 if ((org & 0xfffffff0) == (val & 0xfffffff0))
760 if (val && !(val & 1))
761 PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l);
764 size_n = PciRead32(i + 0x10,pciPtr->Slot.l);
765 PciWrite32(i + 0x10,val,pciPtr->Slot.l);
766 size_n = ~(CARD32)(size_n & 0xfffffff0) + 1;
768 if (size_n >= size) {
769 PciWrite32(num + 0x10,val,pciP->Slot.l);
773 pciPtr = pciPtr->next;
775 /* last resort: try to go below lowest PCI mem address */
776 val = ((pciMinMemReg & ~(CARD32)(size - 1)) - size);
777 if (val > 0x7fffffff) {
778 PciWrite32(num + 0x10,val, pciP->Slot.l);
786 restoreMem(PciStructPtr pciP)
788 if (remapMEM_val == 0) return;
789 PciWrite32(remapMEM_num + 0x10,remapMEM_val,pciP->Slot.l);
794 findBIOSMap(PciStructPtr pciP, CARD32 *biosSize)
796 PciStructPtr pciPtr = PciStruct;
801 PciWrite32(0x30,0xffffffff,pciP->Slot.l);
802 *biosSize = PciRead32(0x30,pciP->Slot.l);
803 P_printf("bios size: 0x%x\n",*biosSize);
804 PciWrite32(0x30,pciP->RomBase,pciP->Slot.l);
805 *biosSize = ~(*biosSize & 0xFFFFFF00) + 1;
806 P_printf("bios size masked: 0x%x\n",*biosSize);
807 if (*biosSize > (1024 * 1024 * 16)) {
808 *biosSize = 1024 * 1024 * 16;
809 P_printf("fixing broken BIOS size: 0x%x\n",*biosSize);
812 if (pciPtr->bus != pciP->bus) {
813 pciPtr = pciPtr->next;
816 for (i = 0; i < 20; i=i+4) {
818 val = PciRead32(i + 0x10,pciPtr->Slot.l);
821 PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l);
824 size = PciRead32(i + 0x10,pciPtr->Slot.l);
825 PciWrite32(i + 0x10,val,pciPtr->Slot.l);
826 size = ~(CARD32)(size & 0xFFFFFFF0) + 1;
827 #ifdef V86_BIOS_DEBUG
828 P_printf("size: 0x%x\n",size);
830 if (size >= *biosSize) {
831 if (pciP == pciPtr) { /* if same device remap ram*/
832 if (!(remapMem(pciP,i,size)))
839 return val & 0xFFFFFF00;
842 pciPtr = pciPtr->next;
845 /* very last resort */
846 if (pciP->bus == 0 && (pciMinMemReg > *biosSize))
847 return (pciMinMemReg - size) & ~(size - 1);
853 cfg1out(CARD16 addr, CARD32 val)
858 } else if (addr == 0xCFC) {
859 writePci(PciCfg1Addr, val);
866 cfg1in(CARD16 addr, CARD32 *val)
871 } else if (addr == 0xCFC) {
872 *val = readPci(PciCfg1Addr);
881 PciStructPtr pci = PciList;
884 printf("[0x%x:0x%x:0x%x] vendor: 0x%4.4x dev: 0x%4.4x class: 0x%4.4x"
885 " subclass: 0x%4.4x\n",pci->bus,pci->dev,pci->func,
886 pci->VendorID,pci->DeviceID,pci->BaseClass,pci->SubClass);
892 findPciByIDs(int bus, int dev, int func)
894 PciStructPtr pciP = PciList;
897 if (pciP->bus == bus && pciP->dev == dev && pciP->func == func)