int nicintel_init(void) { struct pci_dev *dev = NULL; uintptr_t addr; /* Needed only for PCI accesses on some platforms. * FIXME: Refactor that into get_mem_perms/rget_io_perms/get_pci_perms? */ if (rget_io_perms()) return 1; /* FIXME: BAR2 is not available if the device uses the CardBus function. */ dev = pcidev_init(nics_intel, PCI_BASE_ADDRESS_2); if (!dev) return 1; addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); if (!addr) return 1; nicintel_bar = rphysmap("Intel NIC flash", addr, NICINTEL_MEMMAP_SIZE); if (nicintel_bar == ERROR_PTR) return 1; addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); if (!addr) return 1; nicintel_control_bar = rphysmap("Intel NIC control/status reg", addr, NICINTEL_CONTROL_MEMMAP_SIZE); if (nicintel_control_bar == ERROR_PTR) return 1; /* FIXME: This register is pretty undocumented in all publicly available * documentation from Intel. Let me quote the complete info we have: * "Flash Control Register: The Flash Control register allows the CPU to * enable writes to an external Flash. The Flash Control Register is a * 32-bit field that allows access to an external Flash device." * Ah yes, we also know where it is, but we have absolutely _no_ idea * what we should do with it. Write 0x0001 because we have nothing * better to do with our time. */ pci_rmmio_writew(0x0001, nicintel_control_bar + CSR_FCR); max_rom_decode.parallel = NICINTEL_MEMMAP_SIZE; register_par_programmer(&par_programmer_nicintel, BUS_PARALLEL); return 0; }
int nicrealtek_init(void) { struct pci_dev *dev = NULL; if (rget_io_perms()) return 1; dev = pcidev_init(nics_realtek, PCI_BASE_ADDRESS_0); if (!dev) return 1; io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); /* Beware, this ignores the vendor ID! */ switch (dev->device_id) { case 0x8139: /* RTL8139 */ case 0x1211: /* SMC 1211TX */ default: bios_rom_addr = 0xD4; bios_rom_data = 0xD7; break; case 0x8169: /* RTL8169 */ bios_rom_addr = 0x30; bios_rom_data = 0x33; break; } if (register_shutdown(nicrealtek_shutdown, NULL)) return 1; register_par_programmer(&par_programmer_nicrealtek, BUS_PARALLEL); return 0; }
int atahpt_init(void) { struct pci_dev *dev = NULL; uint32_t reg32; if (rget_io_perms()) return 1; dev = pcidev_init(ata_hpt, PCI_BASE_ADDRESS_4); if (!dev) return 1; io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_4); if (!io_base_addr) return 1; /* Enable flash access. */ reg32 = pci_read_long(dev, REG_FLASH_ACCESS); reg32 |= (1 << 24); rpci_write_long(dev, REG_FLASH_ACCESS, reg32); register_par_master(&par_master_atahpt, BUS_PARALLEL); return 0; }
int nicnatsemi_init(void) { struct pci_dev *dev = NULL; if (rget_io_perms()) return 1; dev = pcidev_init(nics_natsemi, PCI_BASE_ADDRESS_0); if (!dev) return 1; io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); if (!io_base_addr) return 1; /* The datasheet shows address lines MA0-MA16 in one place and MA0-MA15 * in another. My NIC has MA16 connected to A16 on the boot ROM socket * so I'm assuming it is accessible. If not then next line wants to be * max_rom_decode.parallel = 65536; and the mask in the read/write * functions below wants to be 0x0000FFFF. */ max_rom_decode.parallel = 131072; register_par_programmer(&par_programmer_nicnatsemi, BUS_PARALLEL); return 0; }
int drkaiser_init(void) { struct pci_dev *dev = NULL; uint32_t addr; if (rget_io_perms()) return 1; dev = pcidev_init(drkaiser_pcidev, PCI_BASE_ADDRESS_2); if (!dev) return 1; addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); if (!addr) return 1; /* Write magic register to enable flash write. */ rpci_write_word(dev, PCI_MAGIC_DRKAISER_ADDR, PCI_MAGIC_DRKAISER_VALUE); /* Map 128kB flash memory window. */ drkaiser_bar = rphysmap("Dr. Kaiser PC-Waechter flash memory", addr, DRKAISER_MEMMAP_SIZE); if (drkaiser_bar == ERROR_PTR) return 1; max_rom_decode.parallel = 128 * 1024; register_par_master(&par_master_drkaiser, BUS_PARALLEL); return 0; }
int nicintel_init(void) { uintptr_t addr; /* Needed only for PCI accesses on some platforms. * FIXME: Refactor that into get_mem_perms/rget_io_perms/get_pci_perms? */ if (rget_io_perms()) return 1; /* No need to check for errors, pcidev_init() will not return in case * of errors. * FIXME: BAR2 is not available if the device uses the CardBus function. */ addr = pcidev_init(PCI_BASE_ADDRESS_2, nics_intel); nicintel_bar = physmap("Intel NIC flash", addr, NICINTEL_MEMMAP_SIZE); if (nicintel_bar == ERROR_PTR) goto error_out_unmap; /* FIXME: Using pcidev_dev _will_ cause pretty explosions in the future. */ addr = pcidev_readbar(pcidev_dev, PCI_BASE_ADDRESS_0); /* FIXME: This is not an aligned mapping. Use 4k? */ nicintel_control_bar = physmap("Intel NIC control/status reg", addr, NICINTEL_CONTROL_MEMMAP_SIZE); if (nicintel_control_bar == ERROR_PTR) goto error_out; if (register_shutdown(nicintel_shutdown, NULL)) return 1; /* FIXME: This register is pretty undocumented in all publicly available * documentation from Intel. Let me quote the complete info we have: * "Flash Control Register: The Flash Control register allows the CPU to * enable writes to an external Flash. The Flash Control Register is a * 32-bit field that allows access to an external Flash device." * Ah yes, we also know where it is, but we have absolutely _no_ idea * what we should do with it. Write 0x0001 because we have nothing * better to do with our time. */ pci_rmmio_writew(0x0001, nicintel_control_bar + CSR_FCR); max_rom_decode.parallel = NICINTEL_MEMMAP_SIZE; register_par_programmer(&par_programmer_nicintel, BUS_PARALLEL); return 0; error_out_unmap: physunmap(nicintel_bar, NICINTEL_MEMMAP_SIZE); error_out: pci_cleanup(pacc); return 1; }
int ogp_spi_init(void) { struct pci_dev *dev = NULL; char *type; type = extract_programmer_param("rom"); if (!type) { msg_perr("Please use flashrom -p ogp_spi:rom=... to specify " "which flashchip you want to access.\n"); return 1; } else if (!strcasecmp(type, "bprom") || !strcasecmp(type, "bios")) { ogp_reg_sel = OGA1_XP10_BPROM_REG_SEL; ogp_reg_siso = OGA1_XP10_BPROM_SI; ogp_reg__ce = OGA1_XP10_BPROM_CE_BAR; ogp_reg_sck = OGA1_XP10_BPROM_SCK; } else if (!strcasecmp(type, "cprom") || !strcasecmp(type, "s3")) { ogp_reg_sel = OGA1_XP10_CPROM_REG_SEL; ogp_reg_siso = OGA1_XP10_CPROM_SI; ogp_reg__ce = OGA1_XP10_CPROM_CE_BAR; ogp_reg_sck = OGA1_XP10_CPROM_SCK; } else { msg_perr("Invalid or missing rom= parameter.\n"); free(type); return 1; } free(type); if (rget_io_perms()) return 1; dev = pcidev_init(ogp_spi, PCI_BASE_ADDRESS_0); if (!dev) return 1; uint32_t io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); if (!io_base_addr) return 1; ogp_spibar = rphysmap("OGP registers", io_base_addr, 4096); if (ogp_spibar == ERROR_PTR) return 1; if (register_spi_bitbang_master(&bitbang_spi_master_ogp)) return 1; return 0; }
/* pcidev_init gets an array of allowed PCI device IDs and returns a pointer to struct pci_dev iff exactly one * match was found. If the "pci=bb:dd.f" programmer parameter was specified, a match is only considered if it * also matches the specified bus:device.function. * For convenience, this function also registers its own undo handlers. */ struct pci_dev *pcidev_init(const struct dev_entry *devs, int bar) { struct pci_dev *dev; struct pci_dev *found_dev = NULL; struct pci_filter filter; char *pcidev_bdf; char *msg = NULL; int found = 0; int i; uintptr_t addr = 0; if (pci_init_common() != 0) return NULL; pci_filter_init(pacc, &filter); /* Filter by bb:dd.f (if supplied by the user). */ pcidev_bdf = extract_programmer_param("pci"); if (pcidev_bdf != NULL) { if ((msg = pci_filter_parse_slot(&filter, pcidev_bdf))) { msg_perr("Error: %s\n", msg); return NULL; } } free(pcidev_bdf); for (dev = pacc->devices; dev; dev = dev->next) { if (pci_filter_match(&filter, dev)) { /* Check against list of supported devices. */ for (i = 0; devs[i].device_name != NULL; i++) if ((dev->vendor_id == devs[i].vendor_id) && (dev->device_id == devs[i].device_id)) break; /* Not supported, try the next one. */ if (devs[i].device_name == NULL) continue; msg_pdbg("Found \"%s %s\" (%04x:%04x, BDF %02x:%02x.%x).\n", devs[i].vendor_name, devs[i].device_name, dev->vendor_id, dev->device_id, dev->bus, dev->dev, dev->func); if (devs[i].status == NT) msg_pinfo("===\nThis PCI device is UNTESTED. Please report the 'flashrom -p " "xxxx' output \n" "to [email protected] if it works for you. Please add the name " "of your\n" "PCI device to the subject. Thank you for your help!\n===\n"); /* FIXME: We should count all matching devices, not * just those with a valid BAR. */ if ((addr = pcidev_readbar(dev, bar)) != 0) { found_dev = dev; found++; } } } /* Only continue if exactly one supported PCI dev has been found. */ if (found == 0) { msg_perr("Error: No supported PCI device found.\n"); return NULL; } else if (found > 1) { msg_perr("Error: Multiple supported PCI devices found. Use 'flashrom -p xxxx:pci=bb:dd.f' \n" "to explicitly select the card with the given BDF (PCI bus, device, function).\n"); return NULL; } return found_dev; }