📄 pci.c
字号:
pcibus[busind].pb_rreg16= pcii_rreg16; pcibus[busind].pb_rreg32= pcii_rreg32; pcibus[busind].pb_wreg16= pcii_wreg16; pcibus[busind].pb_wreg32= pcii_wreg32; pcibus[busind].pb_rsts= pcii_rsts; pcibus[busind].pb_wsts= pcii_wsts; dstr= pci_dev_name(vid, did); if (!dstr) dstr= "unknown device"; if (debug) { printf("pci_intel_init: %s (%04X/%04X)\n", dstr, vid, did); } probe_bus(busind); r= do_isabridge(busind); if (r != OK) { /* Disable all devices for this bus */ for (i= 0; i<nr_pcidev; i++) { if (pcidev[i].pd_busind != busind) continue; pcidev[i].pd_inuse= 1; } return; } /* Look for PCI bridges (for AGP) */ do_pcibridge(busind);}/*===========================================================================* * probe_bus * *===========================================================================*/PRIVATE void probe_bus(busind)int busind;{ u32_t dev, func; u16_t vid, did, sts; u8_t headt; u8_t baseclass, subclass, infclass; int devind; char *s, *dstr;#if DEBUGprintf("probe_bus(%d)\n", busind);#endif if (nr_pcidev >= NR_PCIDEV) panic("PCI","too many PCI devices", nr_pcidev); devind= nr_pcidev; for (dev= 0; dev<32; dev++) { for (func= 0; func < 8; func++) { pcidev[devind].pd_busind= busind; pcidev[devind].pd_dev= dev; pcidev[devind].pd_func= func; pci_attr_wsts(devind, PSR_SSE|PSR_RMAS|PSR_RTAS); vid= pci_attr_r16(devind, PCI_VID); did= pci_attr_r16(devind, PCI_DID); headt= pci_attr_r8(devind, PCI_HEADT); sts= pci_attr_rsts(devind); if (vid == NO_VID) break; /* Nothing here */ if (sts & (PSR_SSE|PSR_RMAS|PSR_RTAS)) { if (qemu_pci) { printf( "pci: ignoring bad value 0x%x in sts for QEMU\n", sts & (PSR_SSE|PSR_RMAS|PSR_RTAS)); } else break; } dstr= pci_dev_name(vid, did); if (debug) { if (dstr) { printf("%d.%lu.%lu: %s (%04X/%04X)\n", busind, (unsigned long)dev, (unsigned long)func, dstr, vid, did); } else { printf( "%d.%lu.%lu: Unknown device, vendor %04X (%s), device %04X\n", busind, (unsigned long)dev, (unsigned long)func, vid, pci_vid_name(vid), did); } } baseclass= pci_attr_r8(devind, PCI_BCR); subclass= pci_attr_r8(devind, PCI_SCR); infclass= pci_attr_r8(devind, PCI_PIFR); s= pci_subclass_name(baseclass, subclass, infclass); if (!s) s= pci_baseclass_name(baseclass); { if (!s) s= "(unknown class)"; } if (debug) { printf("\tclass %s (%X/%X/%X)\n", s, baseclass, subclass, infclass); } devind= nr_pcidev; nr_pcidev++; pcidev[devind].pd_baseclass= baseclass; pcidev[devind].pd_subclass= subclass; pcidev[devind].pd_infclass= infclass; pcidev[devind].pd_vid= vid; pcidev[devind].pd_did= did; pcidev[devind].pd_inuse= 0; if (nr_pcidev >= NR_PCIDEV) panic("PCI","too many PCI devices", nr_pcidev); devind= nr_pcidev; if (func == 0 && !(headt & PHT_MULTIFUNC)) break; } }}/*===========================================================================* * do_isabridge * *===========================================================================*/PRIVATE int do_isabridge(busind)int busind;{ int unknown_bridge= -1; int bridge_dev= -1; int i, j, r, type; u16_t vid, did; char *dstr; j= 0; /* lint */ vid= did= 0; /* lint */ for (i= 0; i< nr_pcidev; i++) { if (pcidev[i].pd_busind != busind) continue; if (pcidev[i].pd_baseclass == 0x06 && pcidev[i].pd_subclass == 0x01 && pcidev[i].pd_infclass == 0x00) { /* ISA bridge. Report if no supported bridge is * found. */ unknown_bridge= i; } vid= pcidev[i].pd_vid; did= pcidev[i].pd_did; for (j= 0; pci_isabridge[j].vid != 0; j++) { if (pci_isabridge[j].vid != vid) continue; if (pci_isabridge[j].did != did) continue; if (pci_isabridge[j].checkclass && unknown_bridge != i) { /* This part of multifunction device is * not the bridge. */ continue; } break; } if (pci_isabridge[j].vid) { bridge_dev= i; break; } } if (bridge_dev != -1) { dstr= pci_dev_name(vid, did); if (!dstr) dstr= "unknown device"; if (debug) { printf("found ISA bridge (%04X/%04X) %s\n", vid, did, dstr); } pcibus[busind].pb_isabridge_dev= bridge_dev; type= pci_isabridge[j].type; pcibus[busind].pb_isabridge_type= type; switch(type) { case PCI_IB_PIIX: r= do_piix(bridge_dev); break; case PCI_IB_VIA: r= do_via_isabr(bridge_dev); break; case PCI_IB_AMD: r= do_amd_isabr(bridge_dev); break; case PCI_IB_SIS: r= do_sis_isabr(bridge_dev); break; default: panic("PCI","unknown ISA bridge type", type); } return r; } if (unknown_bridge == -1) { printf("(warning) no ISA bridge found on bus %d", busind); return 0; } printf("(warning) unsupported ISA bridge %04X/%04X for bus %d\n", pcidev[unknown_bridge].pd_vid, pcidev[unknown_bridge].pd_did, busind); return 0;}/*===========================================================================* * do_pcibridge * *===========================================================================*/PRIVATE void do_pcibridge(busind)int busind;{ int devind, i; int ind, type; u16_t vid, did; u8_t sbusn, baseclass, subclass, infclass; u32_t t3; vid= did= 0; /* lint */ for (devind= 0; devind< nr_pcidev; devind++) { if (pcidev[devind].pd_busind != busind) continue; vid= pcidev[devind].pd_vid; did= pcidev[devind].pd_did; for (i= 0; pci_pcibridge[i].vid != 0; i++) { if (pci_pcibridge[i].vid != vid) continue; if (pci_pcibridge[i].did != did) continue; break; } if (pci_pcibridge[i].vid == 0) { if (debug) { /* Report unsupported bridges */ baseclass= pci_attr_r8(devind, PCI_BCR); subclass= pci_attr_r8(devind, PCI_SCR); infclass= pci_attr_r8(devind, PCI_PIFR); t3= ((baseclass << 16) | (subclass << 8) | infclass); if (t3 != PCI_T3_PCI2PCI && t3 != PCI_T3_PCI2PCI_SUBTR) { /* No a PCI-to-PCI bridge */ continue; } printf( "Ignoring unknown PCI-to-PCI bridge: %04X/%04X\n", vid, did); } continue; } type= pci_pcibridge[i].type; if (debug) printf("PCI-to-PCI bridge: %04X/%04X\n", vid, did); /* Assume that the BIOS initialized the secondary bus * number. */ sbusn= pci_attr_r8(devind, PPB_SBUSN);#if DEBUG printf("sbusn = %d\n", sbusn);#endif if (nr_pcibus >= NR_PCIBUS) panic("PCI","too many PCI busses", nr_pcibus); ind= nr_pcibus; nr_pcibus++; pcibus[ind].pb_type= PBT_PCIBRIDGE; pcibus[ind].pb_isabridge_dev= -1; pcibus[ind].pb_isabridge_type= 0; pcibus[ind].pb_devind= devind; pcibus[ind].pb_bus= sbusn; pcibus[ind].pb_rreg8= pcibus[busind].pb_rreg8; pcibus[ind].pb_rreg16= pcibus[busind].pb_rreg16; pcibus[ind].pb_rreg32= pcibus[busind].pb_rreg32; pcibus[ind].pb_wreg16= pcibus[busind].pb_wreg16; pcibus[ind].pb_wreg32= pcibus[busind].pb_wreg32; switch(type) { case PCI_PCIB_INTEL: case PCI_AGPB_INTEL: pcibus[ind].pb_rsts= pcibr_intel_rsts; pcibus[ind].pb_wsts= pcibr_intel_wsts; break; case PCI_AGPB_VIA: pcibus[ind].pb_rsts= pcibr_via_rsts; pcibus[ind].pb_wsts= pcibr_via_wsts; break; default: panic("PCI","unknown PCI-PCI bridge type", type); } probe_bus(ind); }}/*===========================================================================* * do_piix * *===========================================================================*/PRIVATE int do_piix(devind)int devind;{ int i, s, dev, func, irqrc, irq; u16_t elcr1, elcr2, elcr;#if DEBUG printf("in piix\n");#endif dev= pcidev[devind].pd_dev; func= pcidev[devind].pd_func;#if USER_SPACE if (OK != (s=sys_inb(PIIX_ELCR1, &elcr1))) printf("Warning, sys_inb failed: %d\n", s); if (OK != (s=sys_inb(PIIX_ELCR2, &elcr2))) printf("Warning, sys_inb failed: %d\n", s);#else elcr1= inb(PIIX_ELCR1); elcr2= inb(PIIX_ELCR2);#endif elcr= elcr1 | (elcr2 << 8); for (i= 0; i<4; i++) { irqrc= pci_attr_r8(devind, PIIX_PIRQRCA+i); if (irqrc & PIIX_IRQ_DI) { if (debug) printf("INT%c: disabled\n", 'A'+i); } else { irq= irqrc & PIIX_IRQ_MASK; if (debug) printf("INT%c: %d\n", 'A'+i, irq); if (!(elcr & (1 << irq))) { if (debug) { printf( "(warning) IRQ %d is not level triggered\n", irq); } } irq_mode_pci(irq); } } return 0;}/*===========================================================================* * do_amd_isabr * *===========================================================================*/PRIVATE int do_amd_isabr(devind)int devind;{ int i, bus, dev, func, xdevind, irq, edge; u8_t levmask; u16_t pciirq; /* Find required function */ func= AMD_ISABR_FUNC; bus= pcidev[devind].pd_busind; dev= pcidev[devind].pd_dev; /* Fake a device with the required function */ if (nr_pcidev >= NR_PCIDEV) panic("PCI","too many PCI devices", nr_pcidev); xdevind= nr_pcidev; pcidev[xdevind].pd_busind= bus; pcidev[xdevind].pd_dev= dev; pcidev[xdevind].pd_func= func; pcidev[xdevind].pd_inuse= 1; nr_pcidev++; levmask= pci_attr_r8(xdevind, AMD_ISABR_PCIIRQ_LEV); pciirq= pci_attr_r16(xdevind, AMD_ISABR_PCIIRQ_ROUTE); for (i= 0; i<4; i++) { edge= (levmask >> i) & 1; irq= (pciirq >> (4*i)) & 0xf; if (!irq) { if (debug) printf("INT%c: disabled\n", 'A'+i); } else { if (debug) printf("INT%c: %d\n", 'A'+i, irq); if (edge && debug) { printf( "(warning) IRQ %d is not level triggered\n", irq); } irq_mode_pci(irq); } } nr_pcidev--; return 0;}/*===========================================================================* * do_sis_isabr * *===========================================================================*/PRIVATE int do_sis_isabr(devind)int devind;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -