Check vendor_id for PCI based external programmers

Restructure PCI device detection code.
Rename pcidev_validate to pcidev_readbar.

Note: Slight changes in behaviour are possible, especially on dual/quad
chip NICs which appear as more than one PCI device. Found devices are no
longer printed at _pinfo level, but rather at _pdbg level.

Corresponding to flashrom svn r1548.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
diff --git a/nicintel.c b/nicintel.c
index 0415f46..49bdec2 100644
--- a/nicintel.c
+++ b/nicintel.c
@@ -87,7 +87,7 @@
 		goto error_out_unmap;
 
 	/* FIXME: Using pcidev_dev _will_ cause pretty explosions in the future. */
-	addr = pcidev_validate(pcidev_dev, PCI_BASE_ADDRESS_0, nics_intel);
+	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);
diff --git a/pcidev.c b/pcidev.c
index e8b4dc1..f490a68 100644
--- a/pcidev.c
+++ b/pcidev.c
@@ -35,157 +35,122 @@
 	TYPE_UNKNOWN
 };
 
-uintptr_t pcidev_validate(struct pci_dev *dev, int bar,
-			 const struct pcidev_status *devs)
+uintptr_t pcidev_readbar(struct pci_dev *dev, int bar)
 {
-	int i;
 	uint64_t addr;
 	uint32_t upperaddr;
 	uint8_t headertype;
 	uint16_t supported_cycles;
 	enum pci_bartype bartype = TYPE_UNKNOWN;
 
-	for (i = 0; devs[i].device_name != NULL; i++) {
-		if (dev->device_id != devs[i].device_id)
-			continue;
 
-		msg_pinfo("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);
+	headertype = pci_read_byte(dev, PCI_HEADER_TYPE) & 0x7f;
+	msg_pspew("PCI header type 0x%02x\n", headertype);
 
-		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);
 
-		/*
-		 * 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;
-			}
+	/* 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_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);
+		case PCI_ROM_ADDRESS:
+			bartype = TYPE_ROMBAR;
 			break;
 		}
-
-		supported_cycles = pci_read_word(dev, PCI_COMMAND);
-
-		msg_pdbg("Requested BAR is ");
-		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 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 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;
+		case PCI_ROM_ADDRESS1:
+			bartype = TYPE_ROMBAR;
 			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 "
-				 "flashrom@flashrom.org\n");
 		}
-		
-		if (devs[i].status == NT) {
-			msg_pinfo("===\nThis PCI device is UNTESTED. Please "
-				  "report the 'flashrom -p xxxx' output \n"
-				  "to flashrom@flashrom.org if it works "
-				  "for you. Please add the name of your\n"
-				  "PCI device to the subject. Thank you for "
-				  "your help!\n===\n");
-		}
-
-		return (uintptr_t)addr;
+		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;
 	}
 
-	return 0;
+	supported_cycles = pci_read_word(dev, PCI_COMMAND);
+
+	msg_pdbg("Requested BAR is ");
+	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 flashrom@flashrom.org\n");
+	}
+
+	return (uintptr_t)addr;
 }
 
 uintptr_t pcidev_init(int bar, const struct pcidev_status *devs)
@@ -195,6 +160,7 @@
 	char *pcidev_bdf;
 	char *msg = NULL;
 	int found = 0;
+	int i;
 	uintptr_t addr = 0, curaddr = 0;
 
 	pacc = pci_alloc();     /* Get the pci_access structure */
@@ -214,10 +180,29 @@
 
 	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 flashrom@flashrom.org 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_validate(dev, bar, devs)) != 0) {
+			if ((addr = pcidev_readbar(dev, bar)) != 0) {
 				curaddr = addr;
 				pcidev_dev = dev;
 				found++;
@@ -230,10 +215,8 @@
 		msg_perr("Error: No supported PCI device found.\n");
 		exit(1);
 	} 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");
+		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");
 		exit(1);
 	}
 
diff --git a/programmer.h b/programmer.h
index d60fc5d..51d04fd 100644
--- a/programmer.h
+++ b/programmer.h
@@ -227,7 +227,7 @@
 	const char *vendor_name;
 	const char *device_name;
 };
-uintptr_t pcidev_validate(struct pci_dev *dev, int bar, const struct pcidev_status *devs);
+uintptr_t pcidev_readbar(struct pci_dev *dev, int bar);
 uintptr_t pcidev_init(int bar, const struct pcidev_status *devs);
 /* rpci_write_* are reversible writes. The original PCI config space register
  * contents will be restored on shutdown.