static int parse_filter(int argc, char **argv, int i, struct pci_filter *filter) { char *c = argv[i++]; char *d; if (!c[1] || !strchr("sd", c[1])) parse_err("Invalid option -%c", c[1]); if (c[2]) d = (c[2] == '=') ? c+3 : c+2; else if (i < argc) d = argv[i++]; else parse_err("Option -%c requires an argument", c[1]); switch (c[1]) { case 's': if (d = pci_filter_parse_slot(filter, d)) parse_err("Unable to parse filter -s %s", d); break; case 'd': if (d = pci_filter_parse_id(filter, d)) parse_err("Unable to parse filter -d %s", d); break; default: parse_err("Unknown filter option -%c", c[1]); } return i; }
static struct pci_dev * create_pci_dev(struct pci_access * pci, char * slot) { struct pci_filter filter; pci_filter_init(pci, &filter); if (pci_filter_parse_slot(&filter, slot)) { fprintf(stderr, "Failed to parse device id %s\n", slot); goto pci_filter_parse_failed; } pci_init(pci); struct pci_dev * dev = pci_get_dev(pci, filter.domain, filter.bus, filter.slot, filter.func); if (! dev) { fprintf(stderr, "Failed to allocate dev\n"); goto pci_get_dev_failed; } pci_fill_info(dev, PCI_FILL_IDENT); return dev; pci_get_dev_failed: pci_filter_parse_failed: return NULL; }
/* 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; }
int main (int argc, char *argv[]) { struct pci_access *pacc; struct pci_dev *dev; struct pci_filter filter; char *msg; uint16_t command; int v1_1 = 0, i2c; if (argc != 2 && ((argc != 3) || (!(v1_1 = !strcmp(argv[2], "1.1")) && strcmp(argv[2], "1.0")))) { fprintf(stderr, "VT6307 OHCI mode config\n" "Version 0.9\n" "Copyright (C) 2007 Krzysztof Halasa <*****@*****.**>\n" "\n" "Usage: vt6307ohciver <pci_device> [ 1.0 | 1.1 ]\n"); exit(1); } if (iopl(3)) { fprintf(stderr, "iopl() failed (must be root)\n"); exit(1); } pacc = pci_alloc(); pci_filter_init(pacc, &filter); if ((msg = pci_filter_parse_slot(&filter, argv[1]))) { fprintf(stderr, "Invalid pci_device\n"); exit(1); } filter.vendor = VENDOR_ID; filter.device = DEVICE_ID; pci_init(pacc); pci_scan_bus(pacc); for (dev = pacc->devices; dev; dev = dev->next) if (pci_filter_match(&filter, dev)) break; if (!dev) { fprintf(stderr, "Device %s not found\n", argv[2]); exit(1); } pci_fill_info(dev, PCI_FILL_BASES | PCI_FILL_SIZES); if (dev->size[0] != MEM_SIZE || dev->size[1] != IO_SIZE) { fprintf(stderr, "Unexpected MEM/IO region size, is it" " VT6307 chip?\n"); exit(1); } command = pci_read_word(dev, PCI_COMMAND); if ((command & PCI_COMMAND_IO) == 0) { fprintf(stderr, "Device disabled, trying to enable it\n"); pci_write_word(dev, PCI_COMMAND, command | PCI_COMMAND_IO); } io_ports = dev->base_addr[1] & PCI_BASE_ADDRESS_IO_MASK; i2c = (inl(io_ports + 0x20) & 0x80) ? 0 : 1; fprintf(stderr, "I/O region #1 is at %04X\n", io_ports); fprintf(stderr, "It seems your VT6307 chip is connected to %s " "EEPROM\n", i2c ? "I^2C (24c01 or similar)" : "93c46"); if (argc == 3) { /* enable direct access to pins */ outl_p(inl(io_ports) | 0x80, io_ports); if (i2c) write_i2c(0x22, v1_1 ? 8 : 0); else write_4w(0x11, v1_1 ? 8 : 0); /* disable direct access to pins */ outl_p(0x20, io_ports + 0x20); fprintf(stderr, "Please reboot\n"); } else display(dev->base_addr[0] & PCI_BASE_ADDRESS_MEM_MASK); if ((command & PCI_COMMAND_IO) == 0) { fprintf(stderr, "Disabling device\n"); pci_write_word(dev, PCI_COMMAND, command); } exit(0); }