📄 pciconf.c
字号:
}static void_pci_device_insert(parent, device) struct pci_device *parent; struct pci_device *device;{ struct pci_device *pd = parent->bridge.child; if(pd == NULL) { parent->bridge.child = device; } else { for(; pd->next != NULL; pd = pd->next) ;; pd->next = device; }}static void_pci_query_dev (struct pci_device *dev, int bus, int device, int initialise){ pcitag_t tag; pcireg_t id; pcireg_t misc; tag = _pci_make_tag(bus, device, 0); if (!_pci_canscan (tag)) return; if (_pciverbose >= 2) _pci_bdfprintf (bus, device, -1, "probe..."); id = _pci_conf_read(tag, PCI_ID_REG); if (_pciverbose >= 2) { PRINTF ("completed\n"); } if (id == 0 || id == 0xffffffff) { return; } misc = _pci_conf_read(tag, PCI_BHLC_REG); if (PCI_HDRTYPE_MULTIFN(misc)) { int function; for (function = 0; function < 8; function++) { tag = _pci_make_tag(bus, device, function); id = _pci_conf_read(tag, PCI_ID_REG); if (id == 0 || id == 0xffffffff) { return; } _pci_query_dev_func (dev, tag, initialise); } } else { _pci_query_dev_func (dev, tag, initialise); }}static pcireg_t_pci_allocate_mem(dev, size) struct pci_device *dev; vm_size_t size;{ pcireg_t address;#ifndef PCI_ALLOC_UPWARDS /* allocate downwards, then round to size boundary */ address = (dev->bridge.secbus->nextpcimemaddr - size) & ~(size - 1); if (address > dev->bridge.secbus->nextpcimemaddr || address < dev->bridge.secbus->minpcimemaddr) { return(-1); } dev->bridge.secbus->nextpcimemaddr = address;#else /* allocate upwards, then round to size boundary */ address = (dev->bridge.secbus->minpcimemaddr + size) & ~(size - 1); if (address > dev->bridge.secbus->nextpcimemaddr || address < dev->bridge.secbus->minpcimemaddr) { return(-1); } dev->bridge.secbus->minpcimemaddr = address;#endif return(address);}static pcireg_t_pci_allocate_io(dev, size) struct pci_device *dev; vm_size_t size;{ pcireg_t address;#ifndef PCI_ALLOC_UPWARDS /* allocate downwards, then round to size boundary */ address = (dev->bridge.secbus->nextpciioaddr - size) & ~(size - 1); if (address > dev->bridge.secbus->nextpciioaddr || address < dev->bridge.secbus->minpciioaddr) { return -1; } dev->bridge.secbus->nextpciioaddr = address;#else /* allocate downwards, then round to size boundary */ address = (dev->bridge.secbus->minpciioaddr + size) & ~(size - 1); if (address > dev->bridge.secbus->nextpciioaddr || address < dev->bridge.secbus->minpciioaddr) { return -1; } dev->bridge.secbus->minpciioaddr = address;#endif return(address);}static void_insertsort_window(pm_list, pm) struct pci_win **pm_list; struct pci_win *pm;{ struct pci_win *pm1, *pm2; pm1 = (struct pci_win *)pm_list; while((pm2 = pm1->next)) { if(pm->size >= pm2->size) { break; } pm1 = pm2; } pm1->next = pm; pm->next = pm2;}static void_pci_setup_windows (struct pci_device *dev){ struct pci_win *pm; struct pci_win *next; struct pci_device *pd; for(pm = dev->bridge.memspace; pm != NULL; pm = next) { pd = pm->device; next = pm->next; pm->address = _pci_allocate_mem (dev, pm->size); if (pm->address == -1) { _pci_tagprintf (pd->pa.pa_tag, "not enough PCI mem space (%d requested)\n", pm->size); continue; } if (_pciverbose >= 2) _pci_tagprintf (pd->pa.pa_tag, "mem @%p, %d bytes\n", pm->address, pm->size); if (PCI_ISCLASS(pd->pa.pa_class, PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_PCI) && (pm->reg == PCI_MEMBASE_1)) { pcireg_t memory; pd->bridge.secbus->minpcimemaddr = pm->address; pd->bridge.secbus->nextpcimemaddr = pm->address + pm->size; memory = (((pm->address+pm->size) >> 16) << 16) | (pm->address >> 16); _pci_conf_write(pd->pa.pa_tag, pm->reg, memory); } else if (pm->reg != PCI_MAPREG_ROM) { /* normal memory - expansion rom done below */ pcireg_t base = _pci_conf_read(pd->pa.pa_tag, pm->reg); base = pm->address | (base & ~PCI_MAPREG_MEM_ADDR_MASK); _pci_conf_write(pd->pa.pa_tag, pm->reg, base); } } /* Program expansion rom address base after normal memory base, to keep DEC ethernet chip happy */ for (pm = dev->bridge.memspace; pm != NULL; pm = next) { pd = pm->device; if (PCI_ISCLASS(pd->pa.pa_class, PCI_CLASS_DISPLAY, PCI_SUBCLASS_DISPLAY_VGA)) vga_dev = pd;#if 0 /* * If this is the first VGA card we find, set the BIOS rom * at address c0000 if PCI base address is 0x00000000. */ if (pm->reg == PCI_MAPREG_ROM && !have_vga && dev->bridge.secbus->minpcimemaddr == 0 && (PCI_ISCLASS(pd->pa.pa_class, PCI_CLASS_PREHISTORIC, PCI_SUBCLASS_PREHISTORIC_VGA) || PCI_ISCLASS(pd->pa.pa_class, PCI_CLASS_DISPLAY, PCI_SUBCLASS_DISPLAY_VGA))) { have_vga = pd->pa.pa_tag; pm->address = 0x000c0000; /* XXX PCI MEM @ 0x000!!! */ }#endif if (pm->reg == PCI_MAPREG_ROM) { /* expansion rom */ if (_pciverbose >= 2) _pci_tagprintf (pd->pa.pa_tag, "exp @%p, %d bytes\n", pm->address, pm->size); _pci_conf_write(pd->pa.pa_tag, pm->reg, pm->address | PCI_MAPREG_TYPE_ROM); } next = pm->next; dev->bridge.memspace = next; pfree(pm); } for(pm = dev->bridge.iospace; pm != NULL; pm = next) { pd = pm->device; next = pm->next; pm->address = _pci_allocate_io (dev, pm->size); if (pm->address == -1) { _pci_tagprintf (pd->pa.pa_tag, "not enough PCI io space (%d requested)\n", pm->size); pfree(pm); continue; } if (_pciverbose >= 2) _pci_tagprintf (pd->pa.pa_tag, "i/o @%p, %d bytes\n", pm->address, pm->size); if (PCI_ISCLASS(pd->pa.pa_class, PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_PCI) && (pm->reg == PCI_IOBASEL_1)) { pcireg_t tmp; pd->bridge.secbus->minpciioaddr = pm->address; pd->bridge.secbus->nextpciioaddr = pm->address + pm->size; tmp = _pci_conf_read(pd->pa.pa_tag,PCI_IOBASEL_1); tmp &= 0xffff0000; tmp |= (pm->address >> 8) & 0xf0; tmp |= ((pm->address + pm->size) & 0xf000); _pci_conf_write(pd->pa.pa_tag,PCI_IOBASEL_1, tmp); tmp = (pm->address >> 16) & 0xffff; tmp |= ((pm->address + pm->size) & 0xffff0000); _pci_conf_write(pd->pa.pa_tag,PCI_IOBASEH_1, tmp); } else { _pci_conf_write(pd->pa.pa_tag, pm->reg, pm->address | PCI_MAPREG_TYPE_IO); } dev->bridge.iospace = next; pfree(pm); } /* Recursive allocate memory for secondary buses */ for(pd = dev->bridge.child; pd != NULL; pd = pd->next) { if (PCI_ISCLASS(pd->pa.pa_class, PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_PCI)) { _pci_setup_windows(pd); } }}/* * Calculate interrupt routing for a device */static int_pci_getIntRouting(struct pci_device *dev){ return(dev->intr_routing[PCI_INTLINE_A]);}static int_pci_setupIntRouting(struct pci_device *dev){ int error = -1; struct pci_intline_routing *pi; for(pi = _pci_inthead; pi != NULL; pi = pi->next) { if(dev->parent->pa.pa_tag == _pci_make_tag(pi->bus, pi->device, pi->function)) { dev->intr_routing[PCI_INTLINE_A] = pi->intline[dev->pa.pa_device][PCI_INTLINE_A]; dev->intr_routing[PCI_INTLINE_B] = pi->intline[dev->pa.pa_device][PCI_INTLINE_B]; dev->intr_routing[PCI_INTLINE_C] = pi->intline[dev->pa.pa_device][PCI_INTLINE_C]; dev->intr_routing[PCI_INTLINE_D] = pi->intline[dev->pa.pa_device][PCI_INTLINE_D]; error = 0; break; } } /* * If there where no predefines routing calculate it. */ if(error == -1) { switch(dev->pa.pa_device % 4) { case 0: dev->intr_routing[PCI_INTLINE_A] = dev->parent->intr_routing[PCI_INTLINE_A]; dev->intr_routing[PCI_INTLINE_B] = dev->parent->intr_routing[PCI_INTLINE_B]; dev->intr_routing[PCI_INTLINE_C] = dev->parent->intr_routing[PCI_INTLINE_C]; dev->intr_routing[PCI_INTLINE_D] = dev->parent->intr_routing[PCI_INTLINE_D]; error = 0; break; case 1: dev->intr_routing[PCI_INTLINE_A] = dev->parent->intr_routing[PCI_INTLINE_B]; dev->intr_routing[PCI_INTLINE_B] = dev->parent->intr_routing[PCI_INTLINE_C]; dev->intr_routing[PCI_INTLINE_C] = dev->parent->intr_routing[PCI_INTLINE_D]; dev->intr_routing[PCI_INTLINE_D] = dev->parent->intr_routing[PCI_INTLINE_A]; error = 0; break; case 2: dev->intr_routing[PCI_INTLINE_A] = dev->parent->intr_routing[PCI_INTLINE_C]; dev->intr_routing[PCI_INTLINE_B] = dev->parent->intr_routing[PCI_INTLINE_D]; dev->intr_routing[PCI_INTLINE_C] = dev->parent->intr_routing[PCI_INTLINE_A]; dev->intr_routing[PCI_INTLINE_D] = dev->parent->intr_routing[PCI_INTLINE_B]; error = 0; break; case 3: dev->intr_routing[PCI_INTLINE_A] = dev->parent->intr_routing[PCI_INTLINE_D]; dev->intr_routing[PCI_INTLINE_B] = dev->parent->intr_routing[PCI_INTLINE_A]; dev->intr_routing[PCI_INTLINE_C] = dev->parent->intr_routing[PCI_INTLINE_B]; dev->intr_routing[PCI_INTLINE_D] = dev->parent->intr_routing[PCI_INTLINE_C]; error = 0; break; default: break; } } return(error);}static void_pci_setup_devices (struct pci_device *parent, int initialise){ struct pci_device *pd; for (pd = parent->bridge.child; pd ; pd = pd->next) { /* set device parameters */ struct pci_bus *pb = pd->pcibus; pcitag_t tag = pd->pa.pa_tag; pcireg_t cmd, misc, class; unsigned int ltim; cmd = _pci_conf_read(tag, PCI_COMMAND_STATUS_REG); if (initialise) { class = _pci_conf_read(tag, PCI_CLASS_REG); cmd |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_SERR_ENABLE | PCI_COMMAND_PARITY_ENABLE; /* always enable i/o & memory space, in case this card is just snarfing space from the fixed ISA block and doesn't declare separate PCI space. Exception from this is if it is a bridge chip which we will initialize later */ cmd |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE; if (pb->fast_b2b) cmd |= PCI_COMMAND_BACKTOBACK_ENABLE; _pci_conf_write(tag, PCI_COMMAND_STATUS_REG, cmd); ltim = pd->min_gnt * 33 / 4; ltim = MIN (MAX (pb->def_ltim, ltim), pb->max_ltim); misc = _pci_conf_read (tag, PCI_BHLC_REG); misc = (misc & ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT)) | ((ltim & 0xff) << PCI_LATTIMER_SHIFT); misc = (misc & ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT)) | ((PCI_CACHE_LINE_SIZE & 0xff) << PCI_CACHELINE_SHIFT); _pci_conf_write (tag, PCI_BHLC_REG, misc); if(PCI_CLASS(class) == PCI_CLASS_BRIDGE || PCI_SUBCLASS(class) == PCI_SUBCLASS_BRIDGE_PCI || pd->bridge.child != NULL) { _pci_setup_devices (pd, initialise); } } }}void_pci_businit (int init){ char *v; tgt_putchar('P'); v = getenv("pciverbose"); if (v) { _pciverbose = atol(v); } /* intialise the PCI bridge */ if (/*init*/ 1) { SBD_DISPLAY ("PCIH", CHKPNT_PCIH); init = _pci_hwinit (init, &def_bus_iot, &def_bus_memt); pci_roots = init; if (init < 1) return; } if(monarch_mode) { int i; struct pci_device *pb; if (_pciverbose) { printf("setting up %d bus\n", init); } for(i = 0, pb = _pci_head; i < pci_roots; i++, pb = pb->next) { _pci_scan_dev(pb, i, 0, init); } _setup_pcibuses(init); }}static void_pci_scan_dev(struct pci_device *dev, int bus, int device, int initialise){ for(; device < 32; device++) { _pci_query_dev (dev, bus, device, initialise); }}static void_setup_pcibuses(int initialise){ struct pci_bus *pb; struct pci_device *pd; unsigned int def_ltim, max_ltim; int i; SBD_DISPLAY ("PCIS", CHKPNT_PCIS); for(pb = _pci_bushead; pb != NULL; pb = pb->next) { if (pb->ndev == 0) return; if (initialise) { /* convert largest minimum grant time to cycle count *//*XXX 66/33 Mhz */ max_ltim = pb->min_gnt * 33 / 4; /* now see how much bandwidth is left to distribute */ if (pb->bandwidth <= 0) { if (_pciverbose) { _pci_bdfprintf (pb->bus, -1, -1, "WARN: total bandwidth exceeded\n"); } def_ltim = 1; } else { /* calculate a fair share for each device */ def_ltim = pb->bandwidth / pb->ndev; if (def_ltim > pb->max_lat) { /* would exceed critical time for some device */ def_ltim = pb->max_lat; } /* convert to cycle count */ def_ltim = def_ltim * 33 / 4; } /* most devices don't implement bottom three bits */ def_ltim = (def_ltim + 7) & ~7; max_ltim = (max_ltim + 7) & ~7; pb->def_ltim = MIN (def_ltim, 255); pb->max_ltim = MIN (MAX (max_ltim, def_ltim), 255); } } SBD_DISPLAY ("PCIR", CHKPNT_PCIR); _pci_hwreinit (); /* setup the individual device windows */ SBD_DISPLAY ("PCIW", CHKPNT_PCIW); for(i = 0, pd = _pci_head; i < pci_roots; i++, pd = pd->next) { _pci_setup_windows (pd); }}/* * Scan list of configured devices, probe and attach. */void_pci_devinit (int initialise){ SBD_DISPLAY ("PCID", CHKPNT_PCID); if(monarch_mode) { int i; struct pci_device *pd; for(i = 0, pd = _pci_head; i < pci_roots; i++, pd = pd->next) { _pci_setup_devices (pd, initialise); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -