static void probe_function(uint8_t bus, uint8_t device, uint8_t function) { uint32_t class = pci_readconfig(bus, device, function, 0x08); uint8_t baseclass = class >> 24; uint8_t subclass = class >> 16; uint8_t prog_interface = class >> 8; //uint8_t revision = class; d_printf("Found PCI device! bus %x device %x function %x\n", bus, device, function); d_printf(" base class: %x subclass: %x prog_interface: %x\n", baseclass, subclass, prog_interface); // is this a PCI bridge? if(baseclass == 0x04 && subclass == 0x06) { uint32_t secondary_bus = pci_readconfig(bus, device, function, 0x18); secondary_bus >>= 8; secondary_bus &= 0xff; probe_bus(secondary_bus); }
static pciconf_bus_t * query_bus(pciconf_bus_t *parent, pciconf_dev_t *pd, int dev) { pciconf_bus_t *pb; pcireg_t busreg, io, pmem; pciconf_win_t *pi, *pm; pb = malloc (sizeof (pciconf_bus_t), M_DEVBUF, M_NOWAIT); if (!pb) panic("Unable to allocate memory for PCI configuration."); pb->cacheline_size = parent->cacheline_size; pb->parent_bus = parent; alloc_busno(parent, pb); if (pci_conf_debug) printf("PCI bus bridge covers busses %d-%d\n", pb->busno, pb->last_busno); busreg = parent->busno << PCI_BRIDGE_BUS_PRIMARY_SHIFT; busreg |= pb->busno << PCI_BRIDGE_BUS_SECONDARY_SHIFT; busreg |= pb->last_busno << PCI_BRIDGE_BUS_SUBORDINATE_SHIFT; pci_conf_write(parent->pc, pd->tag, PCI_BRIDGE_BUS_REG, busreg); pb->swiz = parent->swiz + dev; pb->ioext = NULL; pb->memext = NULL; pb->pmemext = NULL; pb->pc = parent->pc; pb->io_total = pb->mem_total = pb->pmem_total = 0; pb->io_32bit = 0; if (parent->io_32bit) { io = pci_conf_read(parent->pc, pd->tag, PCI_BRIDGE_STATIO_REG); if (PCI_BRIDGE_IO_32BITS(io)) { pb->io_32bit = 1; } } pb->pmem_64bit = 0; if (parent->pmem_64bit) { pmem = pci_conf_read(parent->pc, pd->tag, PCI_BRIDGE_PREFETCHMEM_REG); if (PCI_BRIDGE_PREFETCHMEM_64BITS(pmem)) { pb->pmem_64bit = 1; } } if (probe_bus(pb)) { printf("Failed to probe bus %d\n", pb->busno); goto err; } if (pb->io_total > 0) { if (parent->niowin >= MAX_CONF_IO) { printf("pciconf: too many I/O windows\n"); goto err; } pb->io_total |= 0xfff; /* Round up */ pi = get_io_desc(parent, pb->io_total); pi->dev = pd; pi->reg = 0; pi->size = pb->io_total; pi->align = 0x1000; /* 4K alignment */ pi->prefetch = 0; parent->niowin++; parent->io_total += pb->io_total; } if (pb->mem_total > 0) { if (parent->nmemwin >= MAX_CONF_MEM) { printf("pciconf: too many MEM windows\n"); goto err; } pb->mem_total |= 0xfffff; /* Round up */ pm = get_mem_desc(parent, pb->mem_total); pm->dev = pd; pm->reg = 0; pm->size = pb->mem_total; pm->align = 0x100000; /* 1M alignment */ pm->prefetch = 0; parent->nmemwin++; parent->mem_total += pb->mem_total; } if (pb->pmem_total > 0) { if (parent->nmemwin >= MAX_CONF_MEM) { printf("pciconf: too many MEM windows\n"); goto err; } pb->pmem_total |= 0xfffff; /* Round up */ pm = get_mem_desc(parent, pb->pmem_total); pm->dev = pd; pm->reg = 0; pm->size = pb->pmem_total; pm->align = 0x100000; /* 1M alignment */ pm->prefetch = 1; parent->nmemwin++; parent->pmem_total += pb->pmem_total; } return pb; err: free(pb, M_DEVBUF); return NULL; }