static int enable_flash_rdc_r8610(struct pci_dev *dev, const char *name) { uint8_t tmp; /* enable ROMCS for writes */ tmp = pci_read_byte(dev, 0x43); tmp |= 0x80; pci_write_byte(dev, 0x43, tmp); /* read the bootstrapping register */ tmp = pci_read_byte(dev, 0x40) & 0x3; switch (tmp) { case 3: internal_buses_supported = BUS_FWH; break; case 2: internal_buses_supported = BUS_LPC; break; default: internal_buses_supported = BUS_PARALLEL; break; } return 0; }
static uint8_t pci_find_cap_offset(struct pci_dev *pci_dev, uint8_t cap) { int id; int max_cap = 48; int pos = PCI_CAPABILITY_LIST; int status; status = pci_read_byte(pci_dev, PCI_STATUS); if ((status & PCI_STATUS_CAP_LIST) == 0) return 0; while (max_cap--) { pos = pci_read_byte(pci_dev, pos); if (pos < 0x40) break; pos &= ~3; id = pci_read_byte(pci_dev, pos + PCI_CAP_LIST_ID); if (id == 0xff) break; if (id == cap) return pos; pos += PCI_CAP_LIST_NEXT; } return 0; }
int try_ich(struct pci_access *pci, uint16_t reg_gpiobase, uint16_t reg_gc, const char *desc, int *fatal) { MSG("Checking for a %s system", desc); struct pci_dev *d31f0 = pci_find_dev(pci, 0, 31, 0); uint32_t gpiobase = pci_read_long(d31f0, reg_gpiobase); uint8_t gc = pci_read_byte(d31f0, reg_gc); MSG("GPIOBASE=%08x, GC=%02x", gpiobase, gc); if(gpiobase == 0xffffffff) { *fatal = 1; ERR("Cannot read GPIOBASE, are you running me as root?"); } else if(gpiobase == 0) { ERR("GPIOBASE not implemented at %04x", reg_gpiobase); } else if(!(gpiobase & 1)) { *fatal = 1; ERR("GPIOBASE is not an I/O BAR"); } if(!(gpiobase & 0xfffc)) { const uint32_t DEFAULT_GPIOBASE = 0x0480; MSG("GPIOBASE is not configured, setting to %08x and hoping this works", DEFAULT_GPIOBASE); pci_write_long(d31f0, reg_gpiobase, DEFAULT_GPIOBASE); gpiobase = pci_read_long(d31f0, reg_gpiobase); if((gpiobase & 0xfffc) != DEFAULT_GPIOBASE) { ERR("Cannot set GPIOBASE"); } } MSG("GPIO decoding is %s", (gc & REG_ICHx_GC_EN) ? "enabled" : "disabled"); MSG("GPIO lockdown is %s", (gc & REG_ICHx_GC_GLE) ? "enabled" : "disabled"); if(!(gc & REG_ICHx_GC_EN)) { MSG("Enabling GPIO decoding"); pci_write_byte(d31f0, reg_gc, gc | REG_ICHx_GC_EN); gc = pci_read_byte(d31f0, reg_gc); if(!(gc & REG_ICHx_GC_EN)) { ERR("Cannot enable GPIO decoding"); } } gpiobase &= 0xfffc; if(ioperm(gpiobase, 128, 1) == -1) { ERR("Cannot access I/O ports %04x:%04x", gpiobase, gpiobase + 128); } for(int n = 1; n < 3; n++) { MSG("USE_SEL%d=%08x", n, inl(gpiobase + ichx_regs[GPIO_USE_SEL][n])); MSG("IO_SEL%d=%08x", n, inl(gpiobase + ichx_regs[GPIO_IO_SEL][n])); MSG("LVL%d=%08x", n, inl(gpiobase + ichx_regs[GPIO_LVL][n])); } return 0; }
void pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus) { int dev, multi, ht; struct pci_dev *t; a->debug("Scanning bus %02x for devices...\n", bus); if (busmap[bus]) { a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus); return; } busmap[bus] = 1; t = pci_alloc_dev(a); t->bus = bus; for (dev=0; dev<32; dev++) { t->dev = dev; multi = 0; for (t->func=0; !t->func || multi && t->func<8; t->func++) { u32 vd = pci_read_long(t, PCI_VENDOR_ID); struct pci_dev *d; if (!vd || vd == 0xffffffff) continue; ht = pci_read_byte(t, PCI_HEADER_TYPE); if (!t->func) multi = ht & 0x80; ht &= 0x7f; d = pci_alloc_dev(a); d->bus = t->bus; d->dev = t->dev; d->func = t->func; d->vendor_id = vd & 0xffff; d->device_id = vd >> 16U; d->known_fields = PCI_FILL_IDENT; d->hdrtype = ht; pci_link_dev(a, d); switch (ht) { case PCI_HEADER_TYPE_NORMAL: break; case PCI_HEADER_TYPE_BRIDGE: case PCI_HEADER_TYPE_CARDBUS: pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS)); break; default: a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht); } } } pci_free_dev(t); }
int print_ambs(struct pci_dev *dev, struct pci_access *pacc) { struct pci_dev *dev16; int branch, channel, amb; int max_branch, max_channel, max_amb; volatile void *ambconfig; uint64_t ambconfig_phys; printf("\n============= AMBs ============\n\n"); switch (dev->device_id) { case PCI_DEVICE_ID_INTEL_I5000P: case PCI_DEVICE_ID_INTEL_I5000X: case PCI_DEVICE_ID_INTEL_I5000Z: max_branch = 2; if (!(dev16 = pci_get_dev(pacc, 0, 0, 0x10, 0))) { perror("Error: no device 0:16.0\n"); return 1; } ambconfig_phys = ((uint64_t)pci_read_long(dev16, 0x4c) << 32) | pci_read_long(dev16, 0x48); max_channel = pci_read_byte(dev16, 0x56)/max_branch; max_amb = pci_read_byte(dev16, 0x57); pci_free_dev(dev16); break; default: fprintf(stderr, "Error: Dumping AMBs on this MCH is not (yet) supported.\n"); return 1; } if (!(ambconfig = map_physical(ambconfig_phys, AMB_CONFIG_SPACE_SIZE))) { fprintf(stderr, "Error mapping AMB config space\n"); return 1; } for(branch = 0; branch < max_branch; branch++) { for(channel = 0; channel < max_channel; channel++) { for(amb = 0; amb < max_amb; amb++) { dump_amb(ambconfig, branch, channel, amb); } } } unmap_physical((void *)ambconfig, AMB_CONFIG_SPACE_SIZE); return 0; }
static void exec_op(struct op *op, struct pci_dev *dev) { char *mm[] = { NULL, "%02x", "%04x", NULL, "%08x" }; char *m = mm[op->width]; unsigned int x; int i, addr; if (verbose) printf("%02x:%02x.%x:%02x", dev->bus, dev->dev, dev->func, op->addr); addr = op->addr; if (op->num_values >= 0) for(i=0; i<op->num_values; i++) { if (verbose) { putchar(' '); printf(m, op->values[i]); } if (demo_mode) continue; switch (op->width) { case 1: pci_write_byte(dev, addr, op->values[i]); break; case 2: pci_write_word(dev, addr, op->values[i]); break; default: pci_write_long(dev, addr, op->values[i]); break; } addr += op->width; } else { if (verbose) printf(" = "); if (!demo_mode) { switch (op->width) { case 1: x = pci_read_byte(dev, addr); break; case 2: x = pci_read_word(dev, addr); break; default: x = pci_read_long(dev, addr); break; } printf(m, x); } else putchar('?'); } putchar('\n'); }
static int board_via_epia_m(const char *name) { struct pci_dev *dev; unsigned int base; uint8_t val; dev = pci_dev_find(0x1106, 0x3177); /* VT8235 ISA bridge */ if (!dev) { fprintf(stderr, "\nERROR: VT8235 ISA Bridge not found.\n"); return -1; } /* GPIO12-15 -> output */ val = pci_read_byte(dev, 0xE4); val |= 0x10; pci_write_byte(dev, 0xE4, val); /* Get Power Management IO address. */ base = pci_read_word(dev, 0x88) & 0xFF80; /* enable GPIO15 which is connected to write protect. */ val = inb(base + 0x4D); val |= 0x80; outb(val, base + 0x4D); return 0; }
static int board_asus_a7v8x_mx(const char *name) { struct pci_dev *dev; uint8_t val; dev = pci_dev_find(0x1106, 0x3177); /* VT8235 ISA bridge */ if (!dev) dev = pci_dev_find(0x1106, 0x3227); /* VT8237 ISA bridge */ if (!dev) { fprintf(stderr, "\nERROR: VT823x ISA bridge not found.\n"); return -1; } /* This bit is marked reserved actually */ val = pci_read_byte(dev, 0x59); val &= 0x7F; pci_write_byte(dev, 0x59, val); /* Raise ROM MEMW# line on Winbond w83697 SuperIO */ w836xx_ext_enter(); if (!(wbsio_read(0x24) & 0x02)) /* flash rom enabled? */ wbsio_mask(0x24, 0x08, 0x08); /* enable MEMW# */ w836xx_ext_leave(); return 0; }
static int enable_flash_sis85c496(struct pci_dev *dev, const char *name) { uint8_t tmp; tmp = pci_read_byte(dev, 0xd0); tmp |= 0xf8; rpci_write_byte(dev, 0xd0, tmp); return 0; }
static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name) { uint8_t tmp; /* * ROM Write enable, 0xFFFC0000-0xFFFDFFFF and * 0xFFFE0000-0xFFFFFFFF ROM select enable. */ tmp = pci_read_byte(dev, 0x47); tmp |= 0x46; rpci_write_byte(dev, 0x47, tmp); return 0; }
bool pci_device_get_next(struct pci_address* addr, int16_t class_id, int16_t sub_class, pci_device* result) { uint32_t* res_device_ptr = (uint32_t*)(result); for(; addr->bus < MAX_PCI_BUS_NR; addr->bus++) { for(; addr->device < MAX_PCI_BUS_DEV_NR; addr->device++) { for(; addr->func < MAX_FUNC_PER_PCI_BUS_DEV; addr->func++) { if(pci_read_word(addr, PCI_VENDOR_ID_REG_OFFSET) == PCI_VENDOR_ID_NO_DEVICE) continue; if(class_id != -1 && pci_read_byte(addr, PCI_DEV_CLASS_REG_OFFSET) != class_id) continue; if(sub_class != -1 && pci_read_byte(addr, PCI_DEV_SUB_CLASS_REG_OFFSET) != sub_class) continue; // Device found, read in the entire configuration space for (uint8_t i = 0; i < 64; i++) res_device_ptr[i] = pci_read_dword(addr, (i << 2)); return true; } // Ensure we scan all functions on the next device addr->func = 0; } // Ensure we scan all devices on the next bus addr->device = 0; } return false; // No more devices }
static void pci_scan_trad_caps(struct pci_dev *d) { word status = pci_read_word(d, PCI_STATUS); byte been_there[256]; int where; if (!(status & PCI_STATUS_CAP_LIST)) return; memset(been_there, 0, 256); where = pci_read_byte(d, PCI_CAPABILITY_LIST) & ~3; while (where) { byte id = pci_read_byte(d, where + PCI_CAP_LIST_ID); byte next = pci_read_byte(d, where + PCI_CAP_LIST_NEXT) & ~3; if (been_there[where]++) break; if (id == 0xff) break; pci_add_cap(d, where, id, PCI_CAP_NORMAL); where = next; } }
static void process_uhci(struct pci_address* addr, pci_device* dev) { uint8_t revision = pci_read_byte(addr, 0x60); if(revision != UHCI_REV_1_0) { // This host controller indicates that it supports a version // of the USB specification that is *not* 1.0. Ignore it KWARN("Detected UHCI with unsupported revision, ignoring..."); return; } // Bit 0 indicates whether it's memory mapped or port I/O bool memory_mapped = (dev->base_addr4 & 0x1) == 1; // Beore we initialize the card, make sure the cards I/O is disabled uint16_t cmd = pci_read_word(addr, PCI_COMMAND_REG_OFFSET); cmd = (cmd & ~0x1); pci_write_word(addr, PCI_COMMAND_REG_OFFSET, cmd); // THe USB book I'm reading is telling me to null out the // capabilities register as well as the two registers marked as "reserved" // Not sure why, TODO: Investigate! :-S pci_write_dword(addr, PCI_CAPS_OFF_REG_OFFSET, 0x00000000); pci_write_dword(addr, 0x38, 0x00000000); // Set the IRQ pci_write_byte(addr, PCI_IRQ_REG_OFFSET, UHCI_IRQ); // Now try to get the size of the address space //uint32_t size = pci_device_get_memory_size(addr, PCI_BASE_ADDR4_REG_OFFSET); // Enable bus mastering and I/O access pci_write_word(addr, 0x04, memory_mapped ? 0x06 : 0x05); // Disable legacy support and clear current status pci_write_word(addr, PCI_LEG_SUP_REG_OFFSET, PCI_LEGACY_PTS | // Clear Sequence ended bit PCI_LEGACY_TBY64W | PCI_LEGACY_TBY64R | PCI_LEGACY_TBY60W | PCI_LEGACY_TBY60R); // Clear status // The device is now ready for the UHCI driver to take over uhci_init(dev->base_addr4, dev, addr, UHCI_IRQ); }
uint16_t detect_ec(void) { uint16_t ec_port; struct pci_dev *dev; dev = pci_dev_find(0x1002, 0x439d); if (!dev) { return 0; } /* is EC disabled ? */ if (!(pci_read_byte(dev, 0x40) & (1 << 7))) return 0; ec_port = pci_read_word(dev, 0xa4); if (!(ec_port & 0x1)) return 0; ec_port &= ~0x1; return ec_port; }
int print_bioscntl(struct pci_dev *sb) { int i, size = 0; unsigned char bios_cntl = 0xff; const io_register_t *bios_cntl_register = NULL; printf("\n============= SPI / BIOS CNTL =============\n\n"); switch (sb->device_id) { case PCI_DEVICE_ID_INTEL_ICH6: bios_cntl = pci_read_byte(sb, 0xdc); bios_cntl_register = ich6_bios_cntl_registers; size = ARRAY_SIZE(ich6_bios_cntl_registers); break; case PCI_DEVICE_ID_INTEL_ICH7: case PCI_DEVICE_ID_INTEL_ICH7M: case PCI_DEVICE_ID_INTEL_ICH7DH: case PCI_DEVICE_ID_INTEL_ICH7MDH: case PCI_DEVICE_ID_INTEL_ICH8: case PCI_DEVICE_ID_INTEL_ICH8M: case PCI_DEVICE_ID_INTEL_ICH8ME: case PCI_DEVICE_ID_INTEL_ICH9DH: case PCI_DEVICE_ID_INTEL_ICH9DO: case PCI_DEVICE_ID_INTEL_ICH9R: case PCI_DEVICE_ID_INTEL_ICH9: case PCI_DEVICE_ID_INTEL_ICH9M: case PCI_DEVICE_ID_INTEL_ICH9ME: case PCI_DEVICE_ID_INTEL_ICH10: case PCI_DEVICE_ID_INTEL_ICH10R: case PCI_DEVICE_ID_INTEL_NM10: bios_cntl = pci_read_byte(sb, 0xdc); bios_cntl_register = ich7_bios_cntl_registers; size = ARRAY_SIZE(ich7_bios_cntl_registers); break; case PCI_DEVICE_ID_INTEL_3400: case PCI_DEVICE_ID_INTEL_3420: case PCI_DEVICE_ID_INTEL_3450: case PCI_DEVICE_ID_INTEL_3400_DESKTOP: case PCI_DEVICE_ID_INTEL_B55_A: case PCI_DEVICE_ID_INTEL_B55_B: case PCI_DEVICE_ID_INTEL_H55: case PCI_DEVICE_ID_INTEL_H57: case PCI_DEVICE_ID_INTEL_P55: case PCI_DEVICE_ID_INTEL_Q57: case PCI_DEVICE_ID_INTEL_3400_MOBILE: case PCI_DEVICE_ID_INTEL_3400_MOBILE_SFF: case PCI_DEVICE_ID_INTEL_HM55: case PCI_DEVICE_ID_INTEL_HM57: case PCI_DEVICE_ID_INTEL_PM55: case PCI_DEVICE_ID_INTEL_QM57: case PCI_DEVICE_ID_INTEL_QS57: case PCI_DEVICE_ID_INTEL_Z68: case PCI_DEVICE_ID_INTEL_P67: case PCI_DEVICE_ID_INTEL_UM67: case PCI_DEVICE_ID_INTEL_HM65: case PCI_DEVICE_ID_INTEL_H67: case PCI_DEVICE_ID_INTEL_HM67: case PCI_DEVICE_ID_INTEL_Q65: case PCI_DEVICE_ID_INTEL_QS67: case PCI_DEVICE_ID_INTEL_Q67: case PCI_DEVICE_ID_INTEL_QM67: case PCI_DEVICE_ID_INTEL_B65: case PCI_DEVICE_ID_INTEL_C202: case PCI_DEVICE_ID_INTEL_C204: case PCI_DEVICE_ID_INTEL_C206: case PCI_DEVICE_ID_INTEL_H61: case PCI_DEVICE_ID_INTEL_Z77: case PCI_DEVICE_ID_INTEL_Z75: case PCI_DEVICE_ID_INTEL_Q77: case PCI_DEVICE_ID_INTEL_Q75: case PCI_DEVICE_ID_INTEL_B75: case PCI_DEVICE_ID_INTEL_H77: case PCI_DEVICE_ID_INTEL_C216: case PCI_DEVICE_ID_INTEL_QM77: case PCI_DEVICE_ID_INTEL_QS77: case PCI_DEVICE_ID_INTEL_HM77: case PCI_DEVICE_ID_INTEL_UM77: case PCI_DEVICE_ID_INTEL_HM76: case PCI_DEVICE_ID_INTEL_HM75: case PCI_DEVICE_ID_INTEL_HM70: case PCI_DEVICE_ID_INTEL_NM70: case PCI_DEVICE_ID_INTEL_C8_MOBILE: case PCI_DEVICE_ID_INTEL_C8_DESKTOP: case PCI_DEVICE_ID_INTEL_Z87: case PCI_DEVICE_ID_INTEL_Z85: case PCI_DEVICE_ID_INTEL_HM86: case PCI_DEVICE_ID_INTEL_H87: case PCI_DEVICE_ID_INTEL_HM87: case PCI_DEVICE_ID_INTEL_Q85: case PCI_DEVICE_ID_INTEL_Q87: case PCI_DEVICE_ID_INTEL_QM87: case PCI_DEVICE_ID_INTEL_B85: case PCI_DEVICE_ID_INTEL_C222: case PCI_DEVICE_ID_INTEL_C224: case PCI_DEVICE_ID_INTEL_C226: case PCI_DEVICE_ID_INTEL_H81: bios_cntl = pci_read_byte(sb, 0xdc); bios_cntl_register = pch_bios_cntl_registers; size = ARRAY_SIZE(pch_bios_cntl_registers); break; default: printf("Error: Dumping SPI on this southbridge is not (yet) supported.\n"); return 1; } printf("BIOS_CNTL = 0x%04x (IO)\n\n", bios_cntl); if (bios_cntl_register) { for (i = 0; i < size; i++) { unsigned int val = bios_cntl >> bios_cntl_register[i].addr; val &= ((1 << bios_cntl_register[i].size) -1); printf("0x%04x = %s\n", val, bios_cntl_register[i].name); } } return 0; }
uint8_t pci_config_read_byte(struct pci_device *pdev, uint32_t offset) { return pci_read_byte(pdev->bus, pdev->slot, pdev->func, offset); }
uintptr_t pcidev_readbar(struct pci_dev *dev, int bar) { uint64_t addr; uint32_t upperaddr; uint8_t headertype; uint16_t supported_cycles; enum pci_bartype bartype = TYPE_UNKNOWN; headertype = pci_read_byte(dev, PCI_HEADER_TYPE) & 0x7f; msg_pspew("PCI header type 0x%02x\n", headertype); /* Don't use dev->base_addr[x] (as value for 'bar'), won't work on older libpci. */ addr = pci_read_long(dev, bar); /* Sanity checks. */ switch (headertype) { case PCI_HEADER_TYPE_NORMAL: switch (bar) { case PCI_BASE_ADDRESS_0: case PCI_BASE_ADDRESS_1: case PCI_BASE_ADDRESS_2: case PCI_BASE_ADDRESS_3: case PCI_BASE_ADDRESS_4: case PCI_BASE_ADDRESS_5: if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) bartype = TYPE_IOBAR; else bartype = TYPE_MEMBAR; break; case PCI_ROM_ADDRESS: bartype = TYPE_ROMBAR; break; } break; case PCI_HEADER_TYPE_BRIDGE: switch (bar) { case PCI_BASE_ADDRESS_0: case PCI_BASE_ADDRESS_1: if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) bartype = TYPE_IOBAR; else bartype = TYPE_MEMBAR; break; case PCI_ROM_ADDRESS1: bartype = TYPE_ROMBAR; break; } break; case PCI_HEADER_TYPE_CARDBUS: break; default: msg_perr("Unknown PCI header type 0x%02x, BAR type cannot be determined reliably.\n", headertype); break; } supported_cycles = pci_read_word(dev, PCI_COMMAND); msg_pdbg("Requested BAR is of type "); switch (bartype) { case TYPE_MEMBAR: msg_pdbg("MEM"); if (!(supported_cycles & PCI_COMMAND_MEMORY)) { msg_perr("MEM BAR access requested, but device has MEM space accesses disabled.\n"); /* TODO: Abort here? */ } msg_pdbg(", %sbit, %sprefetchable\n", ((addr & 0x6) == 0x0) ? "32" : (((addr & 0x6) == 0x4) ? "64" : "reserved"), (addr & 0x8) ? "" : "not "); if ((addr & 0x6) == 0x4) { /* The spec says that a 64-bit register consumes * two subsequent dword locations. */ upperaddr = pci_read_long(dev, bar + 4); if (upperaddr != 0x00000000) { /* Fun! A real 64-bit resource. */ if (sizeof(uintptr_t) != sizeof(uint64_t)) { msg_perr("BAR unreachable!"); /* TODO: Really abort here? If multiple PCI devices match, * we might never tell the user about the other devices. */ return 0; } addr |= (uint64_t)upperaddr << 32; } } addr &= PCI_BASE_ADDRESS_MEM_MASK; break; case TYPE_IOBAR: msg_pdbg("I/O\n"); #if __FLASHROM_HAVE_OUTB__ if (!(supported_cycles & PCI_COMMAND_IO)) { msg_perr("I/O BAR access requested, but device has I/O space accesses disabled.\n"); /* TODO: Abort here? */ } #else msg_perr("I/O BAR access requested, but flashrom does not support I/O BAR access on this " "platform (yet).\n"); #endif addr &= PCI_BASE_ADDRESS_IO_MASK; break; case TYPE_ROMBAR: msg_pdbg("ROM\n"); /* Not sure if this check is needed. */ if (!(supported_cycles & PCI_COMMAND_MEMORY)) { msg_perr("MEM BAR access requested, but device has MEM space accesses disabled.\n"); /* TODO: Abort here? */ } addr &= PCI_ROM_ADDRESS_MASK; break; case TYPE_UNKNOWN: msg_perr("BAR type unknown, please report a bug at [email protected]\n"); } return (uintptr_t)addr; }
static void determine_generation(struct pci_dev *dev) { amd_gen = CHIPSET_AMD_UNKNOWN; msg_pdbg2("Trying to determine the generation of the SPI interface... "); if (dev->device_id == 0x438d) { amd_gen = CHIPSET_SB6XX; msg_pdbg("SB6xx detected.\n"); } else if (dev->device_id == 0x439d) { struct pci_dev *smbus_dev = pci_dev_find(0x1002, 0x4385); if (smbus_dev == NULL) return; uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID); if (rev >= 0x39 && rev <= 0x3D) { amd_gen = CHIPSET_SB7XX; msg_pdbg("SB7xx/SP5100 detected.\n"); } else if (rev >= 0x40 && rev <= 0x42) { amd_gen = CHIPSET_SB89XX; msg_pdbg("SB8xx/SB9xx/Hudson-1 detected.\n"); } else { msg_pwarn("SB device found but SMBus revision 0x%02x does not match known values.\n" "Assuming SB8xx/SB9xx/Hudson-1. Please send a log to [email protected]\n", rev); amd_gen = CHIPSET_SB89XX; } } else if (dev->device_id == 0x780e) { /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash) * although they use different SPI interfaces. */ #ifdef USE_YANGTZE_HEURISTICS /* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on * Yangtze (and newer, compatible chipsets). */ int i; msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... "); for (i = 0x20; i <= 0x4f; i++) { if (mmio_readb(sb600_spibar + i) != 0xff) { amd_gen = CHIPSET_YANGTZE; msg_pdbg("found.\n"); return; } } msg_pdbg("not found. Assuming Hudson.\n"); amd_gen = CHIPSET_HUDSON234; #else struct pci_dev *smbus_dev = pci_dev_find(0x1022, 0x780B); if (smbus_dev == NULL) { msg_pdbg("No SMBus device with ID 1022:780B found.\n"); return; } uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID); if (rev >= 0x11 && rev <= 0x15) { amd_gen = CHIPSET_HUDSON234; msg_pdbg("Hudson-2/3/4 detected.\n"); } else if (rev >= 0x39 && rev <= 0x3A) { amd_gen = CHIPSET_YANGTZE; msg_pdbg("Yangtze detected.\n"); } else { msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n" "Please report this to [email protected] and include this log and\n" "the output of lspci -nnvx, thanks!.\n", rev); } #endif } else msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n" "Please report this to [email protected] and include this log and\n" "the output of lspci -nnvx, thanks!\n", __func__, dev->vendor_id, dev->device_id); }
int pci_generic_fill_info(struct pci_dev *d, int flags) { struct pci_access *a = d->access; if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0) d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f; if (flags & PCI_FILL_IDENT) { d->vendor_id = pci_read_word(d, PCI_VENDOR_ID); d->device_id = pci_read_word(d, PCI_DEVICE_ID); } if (flags & PCI_FILL_CLASS) d->device_class = pci_read_word(d, PCI_CLASS_DEVICE); if (flags & PCI_FILL_IRQ) d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE); if (flags & PCI_FILL_BASES) { int cnt = 0, i; memset(d->base_addr, 0, sizeof(d->base_addr)); switch (d->hdrtype) { case PCI_HEADER_TYPE_NORMAL: cnt = 6; break; case PCI_HEADER_TYPE_BRIDGE: cnt = 2; break; case PCI_HEADER_TYPE_CARDBUS: cnt = 1; break; } if (cnt) { for (i=0; i<cnt; i++) { u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4); if (!x || x == (u32) ~0) continue; if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) d->base_addr[i] = x; else { if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64) d->base_addr[i] = x; else if (i >= cnt-1) a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.", d->domain, d->bus, d->dev, d->func, i); else { u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4); #ifdef PCI_HAVE_64BIT_ADDRESS d->base_addr[i-1] = x | (((pciaddr_t) y) << 32); #else if (y) a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func); else d->base_addr[i-1] = x; #endif } } } } } if (flags & PCI_FILL_ROM_BASE) { int reg = 0; d->rom_base_addr = 0; switch (d->hdrtype) { case PCI_HEADER_TYPE_NORMAL: reg = PCI_ROM_ADDRESS; break; case PCI_HEADER_TYPE_BRIDGE: reg = PCI_ROM_ADDRESS1; break; } if (reg) { u32 u = pci_read_long(d, reg); if (u != 0xffffffff) d->rom_base_addr = u; } } if (flags & (PCI_FILL_CAPS | PCI_FILL_EXT_CAPS)) flags |= pci_scan_caps(d, flags); return flags & ~PCI_FILL_SIZES; }
static void exec_op(struct op *op, struct pci_dev *dev) { const char * const formats[] = { NULL, " %02x", " %04x", NULL, " %08x" }; const char * const mask_formats[] = { NULL, " %02x->(%02x:%02x)->%02x", " %04x->(%04x:%04x)->%04x", NULL, " %08x->(%08x:%08x)->%08x" }; unsigned int i, x, y; int addr = 0; int width = op->width; char slot[16]; sprintf(slot, "%04x:%02x:%02x.%x", dev->domain, dev->bus, dev->dev, dev->func); trace("%s ", slot); if (op->cap_type) { struct pci_cap *cap; cap = pci_find_cap(dev, op->cap_id, op->cap_type); if (cap) addr = cap->addr; else die("%s: %s %04x not found", slot, ((op->cap_type == PCI_CAP_NORMAL) ? "Capability" : "Extended capability"), op->cap_id); trace(((op->cap_type == PCI_CAP_NORMAL) ? "(cap %02x @%02x) " : "(ecap %04x @%03x) "), op->cap_id, addr); } addr += op->addr; trace("@%02x", addr); /* We have already checked it when parsing, but addressing relative to capabilities can change the address. */ if (addr & (width-1)) die("%s: Unaligned access of width %d to register %04x", slot, width, addr); if (addr + width > 0x1000) die("%s: Access of width %d to register %04x out of range", slot, width, addr); if (op->num_values) { for (i=0; i<op->num_values; i++) { if ((op->values[i].mask & max_values[width]) == max_values[width]) { x = op->values[i].value; trace(formats[width], op->values[i].value); } else { switch (width) { case 1: y = pci_read_byte(dev, addr); break; case 2: y = pci_read_word(dev, addr); break; default: y = pci_read_long(dev, addr); break; } x = (y & ~op->values[i].mask) | op->values[i].value; trace(mask_formats[width], y, op->values[i].value, op->values[i].mask, x); } if (!demo_mode) { switch (width) { case 1: pci_write_byte(dev, addr, x); break; case 2: pci_write_word(dev, addr, x); break; default: pci_write_long(dev, addr, x); break; } } addr += width; } trace("\n"); } else { trace(" = "); switch (width) { case 1: x = pci_read_byte(dev, addr); break; case 2: x = pci_read_word(dev, addr); break; default: x = pci_read_long(dev, addr); break; } printf(formats[width]+1, x); putchar('\n'); } }
int pci_generic_fill_info(struct pci_dev *d, int flags) { struct pci_access *a = d->access; if (flags & PCI_FILL_IDENT) { d->vendor_id = pci_read_word(d, PCI_VENDOR_ID); d->device_id = pci_read_word(d, PCI_DEVICE_ID); } if (flags & PCI_FILL_IRQ) d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE); if (flags & PCI_FILL_BASES) { int cnt = 0, i; //bzero(d->base_addr, sizeof(d->base_addr)); memset(d->base_addr,0, sizeof(d->base_addr)); switch (d->hdrtype) { case PCI_HEADER_TYPE_NORMAL: cnt = 6; break; case PCI_HEADER_TYPE_BRIDGE: cnt = 2; break; case PCI_HEADER_TYPE_CARDBUS: cnt = 1; break; } if (cnt) { u16 cmd = pci_read_word(d, PCI_COMMAND); for(i=0; i<cnt; i++) { u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4); if (!x || x == (u32) ~0) continue; d->base_addr[i] = x; if (x & PCI_BASE_ADDRESS_SPACE_IO) { if (!a->buscentric && !(cmd & PCI_COMMAND_IO)) d->base_addr[i] = 0; } else if (a->buscentric || (cmd & PCI_COMMAND_MEMORY)) { if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) { if (i >= cnt-1) a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func); else { u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4); #ifdef HAVE_64BIT_ADDRESS d->base_addr[i-1] |= ((pciaddr_t) y) << 32; #else if (y) { a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func); d->base_addr[i-1] = 0; } #endif } } } else d->base_addr[i] = 0; } } } if (flags & PCI_FILL_ROM_BASE) { int reg = 0; d->rom_base_addr = 0; switch (d->hdrtype) { case PCI_HEADER_TYPE_NORMAL: reg = PCI_ROM_ADDRESS; break; case PCI_HEADER_TYPE_BRIDGE: reg = PCI_ROM_ADDRESS1; break; } if (reg) { u32 a = pci_read_long(d, reg); if (a & PCI_ROM_ADDRESS_ENABLE) d->rom_base_addr = a; } } return flags & ~PCI_FILL_SIZES; }
void pci::probe(void) { pci_scan_bus(_pacc); uint8_t buf[CONFIG_SPACE_SIZE] = {0}; char classbuf[128] = {0}, vendorbuf[128] {0}, devbuf[128] = {0}; for (struct pci_dev *dev = _pacc->devices; dev && _entries.size() < MAX_DEVICES; dev = dev->next) { _entries.push_back(pciEntry()); pciEntry &e = _entries.back(); memset(buf, 0, sizeof(buf)); memset(classbuf, 0, sizeof(classbuf)); memset(vendorbuf, 0, sizeof(vendorbuf)); memset(devbuf, 0, sizeof(devbuf)); pci_setup_cache(dev, buf, CONFIG_SPACE_SIZE); pci_read_block(dev, 0, buf, CONFIG_SPACE_SIZE); pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_CAPS); pci_lookup_name(_pacc, vendorbuf, sizeof(vendorbuf), PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id); pci_lookup_name(_pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); e.text.append(vendorbuf).append("|").append(devbuf); e.class_type += classbuf; e.vendor = dev->vendor_id; e.device = dev->device_id; e.pci_domain = dev->domain; e.bus = dev->bus; e.pciusb_device = dev->dev; e.pci_function = dev->func; e.class_id = dev->device_class; e.subvendor = pci_read_word(dev, PCI_SUBSYSTEM_VENDOR_ID); e.subdevice = pci_read_word(dev, PCI_SUBSYSTEM_ID); e.pci_revision = pci_read_byte(dev, PCI_REVISION_ID); if ((e.subvendor == 0 && e.subdevice == 0) || (e.subvendor == e.vendor && e.subdevice == e.device)) { e.subvendor = 0xffff; e.subdevice = 0xffff; } if (pci_find_cap(dev,PCI_CAP_ID_EXP, PCI_CAP_NORMAL)) e.is_pciexpress = true; /* special case for realtek 8139 that has two drivers */ if (e.vendor == 0x10ec && e.device == 0x8139) { if (e.pci_revision < 0x20) e.module = "8139too"; else e.module = "8139cp"; } } // fake two PCI controllers for xen struct stat sb; if (!stat("/sys/bus/xen", &sb)) { // FIXME: use C++ streams.. FILE *f; if ((f = fopen("/sys/hypervisor/uuid", "r"))) { char buf[38]; fgets(buf, sizeof(buf) - 1, f); fclose(f); if (strncmp(buf, "00000000-0000-0000-0000-000000000000", sizeof(buf))) { // We're now sure to be in a Xen guest: { _entries.push_back(pciEntry()); pciEntry &e = _entries.back(); e.text.append("XenSource, Inc.|Block Frontend"); e.class_id = 0x0106; // STORAGE_SATA e.vendor = 0x1a71; // XenSource e.device = 0xfffa; // fake e.subvendor = 0; e.subdevice = 0; e.class_id = 0x0106; e.module = "xen_blkfront"; } { _entries.push_back(pciEntry()); pciEntry &e = _entries.back(); e.text.append("XenSource, Inc.|Network Frontend"); e.class_id = 0x0200; // NETWORK_ETHERNET e.vendor = 0x1a71; // XenSource e.device = 0xfffb; // fake e.subvendor = 0; e.subdevice = 0; e.class_id = 0x0200; e.module = "xen_netfront"; } } } } findModules("pcitable", false); }