xf86_pci.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,218 行 · 第 1/3 页
C
1,218 行
((CARD32)func << 8); } break; case 2: if (cardnum < PCI_CONFIG2_MAXDEV) { tag.cfg2.port = 0xc000 | ((CARD16)cardnum << 8); tag.cfg2.enable = 0xf0 | (func << 1); tag.cfg2.forward = bus; } break; } return tag;}static pciTagRecpcibusFTag(pciTagRec tag, CARD8 func){ if (func > 7) { return tag; } switch (pciConfigType) { case 1: tag.cfg1 &= ~0x700UL; tag.cfg1 |= ((CARD32)func << 8); break; case 2: tag.cfg2.enable = 0xf0 | (func << 1); break; } return tag;}CARD32pcibusRead(pciTagRec tag, CARD32 reg){ CARD32 addr, data = 0; if (!tag.cfg1) { return 0xffffffff; }#if !defined(__alpha__) switch (pciConfigType) { case 1: addr = tag.cfg1 | (reg & 0xfc); outl(PCI_MODE1_ADDRESS_REG, addr); data = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, 0); break; case 2: addr = tag.cfg2.port | (reg & 0xfc); outb(PCI_MODE2_ENABLE_REG, tag.cfg2.enable); outb(PCI_MODE2_FORWARD_REG, tag.cfg2.forward); data = inl((CARD16)addr); outb(PCI_MODE2_ENABLE_REG, 0); outb(PCI_MODE2_FORWARD_REG, 0); break; }#else /* !__alpha__ */ pciconfig_read(BUS(tag.cfg1), DFN(tag.cfg1), reg, 4, &data);#endif /* !__alpha__ */ return data;}CARD16pciReadWord(pciTagRec tag, CARD32 reg){ CARD32 addr; CARD16 data = 0; if (!tag.cfg1) { return 0xff; }#if !defined(__alpha__) switch (pciConfigType) { case 1: addr = tag.cfg1 | (reg & 0xfc); outl(PCI_MODE1_ADDRESS_REG, addr); data = inw(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, 0); break; case 2: addr = tag.cfg2.port | (reg & 0xfc); outb(PCI_MODE2_ENABLE_REG, tag.cfg2.enable); outb(PCI_MODE2_FORWARD_REG, tag.cfg2.forward); data = inw((CARD16)addr); outb(PCI_MODE2_ENABLE_REG, 0); outb(PCI_MODE2_FORWARD_REG, 0); break; }#else /* !__alpha__ */ pciconfig_read(BUS(tag.cfg1), DFN(tag.cfg1), reg, 2, &data);#endif /* !__alpha__ */ return data;}CARD8pciReadByte(pciTagRec tag, CARD32 reg){ CARD32 addr; CARD8 data = 0; if (!tag.cfg1) { return 0xff; }#if !defined(__alpha__) switch (pciConfigType) { case 1: addr = tag.cfg1 | (reg & 0xfc); outl(PCI_MODE1_ADDRESS_REG, addr); data = inb(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, 0); break; case 2: addr = tag.cfg2.port | (reg & 0xfc); outb(PCI_MODE2_ENABLE_REG, tag.cfg2.enable); outb(PCI_MODE2_FORWARD_REG, tag.cfg2.forward); data = inb((CARD16)addr); outb(PCI_MODE2_ENABLE_REG, 0); outb(PCI_MODE2_FORWARD_REG, 0); break; }#else /* !__alpha__ */ pciconfig_read(BUS(tag.cfg1), DFN(tag.cfg1), reg, 1, &data);#endif /* !__alpha__ */ return data;}voidpcibusWrite(pciTagRec tag, CARD32 reg, CARD32 data){ CARD32 addr; if (!tag.cfg1) { return; }#if !defined(__alpha__) switch (pciConfigType) { case 1: addr = tag.cfg1 | (reg & 0xfc); outl(PCI_MODE1_ADDRESS_REG, addr); outl(PCI_MODE1_DATA_REG, data); outl(PCI_MODE1_ADDRESS_REG, 0); break; case 2: addr = tag.cfg2.port | (reg & 0xfc); outb(PCI_MODE2_ENABLE_REG, tag.cfg2.enable); outb(PCI_MODE2_FORWARD_REG, tag.cfg2.forward); outl((CARD16)addr, data); outb(PCI_MODE2_ENABLE_REG, 0); outb(PCI_MODE2_FORWARD_REG, 0); break; }#else /* !__alpha__ */ addr = data; pciconfig_write(BUS(tag.cfg1), DFN(tag.cfg1), reg, 4, &addr);#endif /* !__alpha__ */}voidpciWriteWord(pciTagRec tag, CARD32 reg, CARD16 data){ CARD32 addr; if (!tag.cfg1) { return; }#if !defined(__alpha__) switch (pciConfigType) { case 1: addr = tag.cfg1 | (reg & 0xfc); outl(PCI_MODE1_ADDRESS_REG, addr); outw(PCI_MODE1_DATA_REG, data); outl(PCI_MODE1_ADDRESS_REG, 0); break; case 2: addr = tag.cfg2.port | (reg & 0xfc); outb(PCI_MODE2_ENABLE_REG, tag.cfg2.enable); outb(PCI_MODE2_FORWARD_REG, tag.cfg2.forward); outw((CARD16)addr, data); outb(PCI_MODE2_ENABLE_REG, 0); outb(PCI_MODE2_FORWARD_REG, 0); break; }#else /* !__alpha__ */ addr = data; pciconfig_write(BUS(tag.cfg1), DFN(tag.cfg1), reg, 2, &addr);#endif /* !__alpha__ */}voidpciWriteByte(pciTagRec tag, CARD32 reg, CARD8 data){ CARD32 addr; if (!tag.cfg1) { return; }#if !defined(__alpha__) switch (pciConfigType) { case 1: addr = tag.cfg1 | (reg & 0xfc); outl(PCI_MODE1_ADDRESS_REG, addr); outb(PCI_MODE1_DATA_REG, data); outl(PCI_MODE1_ADDRESS_REG, 0); break; case 2: addr = tag.cfg2.port | (reg & 0xfc); outb(PCI_MODE2_ENABLE_REG, tag.cfg2.enable); outb(PCI_MODE2_FORWARD_REG, tag.cfg2.forward); outb((CARD16)addr, data); outb(PCI_MODE2_ENABLE_REG, 0); outb(PCI_MODE2_FORWARD_REG, 0); break; }#else /* !__alpha__ */ addr = data; pciconfig_write(BUS(tag.cfg1), DFN(tag.cfg1), reg, 1, &addr);#endif /* !__alpha__ */}static voidpciEnableIO(int scrnIndex){ /* This is enough to ensure that full I/O is enabled */ unsigned pciIOPorts[] = { PCI_MODE1_ADDRESS_REG }; int numPciIOPorts = sizeof(pciIOPorts) / sizeof(pciIOPorts[0]); xf86ClearIOPortList(scrnIndex); xf86AddIOPorts(scrnIndex, numPciIOPorts, pciIOPorts); xf86EnableIOPorts(scrnIndex);}static voidpciDisableIO(int scrnIndex){ xf86DisableIOPorts(scrnIndex); xf86ClearIOPortList(scrnIndex);}static BoolpciMfDev(CARD8 bus, CARD8 cardnum){ pciTagRec tag0, tag1; CARD32 id0, id1; /* Detect a multi-function device that complies to the PCI 2.0 spec */ tag0 = pcibusTag(bus, cardnum, 0); if (pcibusRead(tag0, PCI_HEADER_MISC) & PCI_HEADER_MULTIFUNCTION) return TRUE; /* * Now, to find non-compliant devices... * If there is a valid ID for function 1 and the ID for func 0 and 1 * are different, or the base0 values of func 0 and 1 are differend, * then assume there is a multi-function device. */ tag1 = pcibusTag(bus, cardnum, 1); id1 = pcibusRead(tag1, PCI_ID_REG); if (id1 != 0xffffffff) { id0 = pcibusRead(tag0, PCI_ID_REG); if (id0 != id1) return TRUE; if (pcibusRead(tag0, PCI_MAP_REG_START) != pcibusRead(tag1, PCI_MAP_REG_START)) return TRUE; } return FALSE;}pciConfigPtr *xf86scanpci(int scrnIndex){ pciConfigRec pcr; int pcibusidx, pcinumbus, pcibuses[16]; int idx = 0; if (pci_devp[0]) return pci_devp; pciEnableIO(scrnIndex); /* Check for a PCI bus, and find the config type */ pcibusSetup(); if (pciConfigType == 0) return (pciConfigPtr *)NULL; pcibusidx = 0; pcibuses[0] = 0; pcinumbus = 1; do { for (pcr._cardnum = 0; pcr._cardnum < pciMaxDevice; pcr._cardnum++) { int maxfunc = 0; pciTagRec tag; pcr._bus = pcibuses[pcibusidx]; if (pciMfDev(pcr._bus, pcr._cardnum)) maxfunc = 7; tag = pcibusTag(pcr._bus, pcr._cardnum, 0); for (pcr._func = 0; pcr._func <= maxfunc; pcr._func++) { tag = pcibusFTag(tag, pcr._func); pcr._device_vendor = pcibusRead(tag, PCI_ID_REG); if (pcr._device_vendor == 0xffffffff) /* nothing there */ continue; pcr._status_command = pcibusRead(tag, PCI_CMD_STAT_REG); pcr._class_revision = pcibusRead(tag, PCI_CLASS_REG); pcr._bist_header_latency_cache = pcibusRead(tag, PCI_HEADER_MISC); pcr._base0 = pcibusRead(tag, PCI_MAP_REG_START); pcr._base1 = pcibusRead(tag, PCI_MAP_REG_START + 0x04); pcr._base2 = pcibusRead(tag, PCI_MAP_REG_START + 0x08); pcr._base3 = pcibusRead(tag, PCI_MAP_REG_START + 0x0c); pcr._base4 = pcibusRead(tag, PCI_MAP_REG_START + 0x10); pcr._base5 = pcibusRead(tag, PCI_MAP_REG_START + 0x14); pcr.rsvd1 = pcibusRead(tag, PCI_MAP_REG_START + 0x18); pcr.rsvd2 = pcibusRead(tag, PCI_MAP_REG_START + 0x1C); pcr._baserom = pcibusRead(tag, PCI_MAP_ROM_REG); pcr._max_min_ipin_iline = pcibusRead(tag, PCI_INTERRUPT_REG); pcr._user_config = pcibusRead(tag, PCI_REG_USERCONFIG); /* Check for PCI-PCI bridges */ if (pcr._base_class == PCI_CLASS_BRIDGE && pcr._sub_class == PCI_SUBCLASS_BRIDGE_PCI) { if (pcr._secondary_bus_number > 0) { pcibuses[pcinumbus++] = pcr._secondary_bus_number; } } if (idx >= MAX_PCI_DEVICES) continue; if ((pci_devp[idx] = (pciConfigPtr)xalloc(sizeof(pciConfigRec))) == (pciConfigPtr)NULL) { pciDisableIO(scrnIndex); return (pciConfigPtr *)NULL; } memcpy(pci_devp[idx++], &pcr, sizeof(pciConfigRec)); pci_devp[idx] = (pciConfigPtr)NULL; if (xf86Verbose > 1) { ErrorF("PCI: Bus 0x%x Card 0x%02x Func 0x%x ID 0x%04x," "0x%04x Rev 0x%02x Class 0x%02x,0x%02x\n", pcr._bus, pcr._cardnum, pcr._func, pcr._vendor, pcr._device, pcr._rev_id, pcr._base_class, pcr._sub_class); } } } } while (++pcibusidx < pcinumbus); pciDisableIO(scrnIndex); return pci_devp;}voidxf86writepci(int scrnIndex, int bus, int cardnum, int func, int reg, CARD32 mask, CARD32 value){ pciTagRec tag; CARD32 data; pciEnableIO(scrnIndex); /* Check for a PCI bus, and find the config type */ pcibusSetup(); if (pciConfigType == 0) return; tag = pcibusTag(bus, cardnum, func); data = pcibusRead(tag, reg) & ~mask | (value & mask); pcibusWrite(tag, reg, data); if (xf86Verbose > 2) { ErrorF("PCI: xf86writepci: Bus=0x%x Card=0x%x Func=0x%x Reg=0x%02x " "Mask=0x%08x Val=0x%08x\n", bus, cardnum, func, reg, mask, value); } pciDisableIO(scrnIndex);}voidxf86cleanpci(){ int idx = 0; while (pci_devp[idx]) xfree((pointer)pci_devp[idx++]); pci_devp[0] = (pciConfigPtr)NULL;}#endif /* USE_OLD_PCI_CODE */ /* } */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?