Commit 515ab3de authored by Uwe Hermann's avatar Uwe Hermann
Browse files

Refactor parts of the 3COM NIC code


Move the reusable PCI specific parts into pcidev.c, they'll be usable
for other NIC code (Realtek, VIA, ...) and also for SATA/IDE controller
cards as external programmers (for every PCI device which can program
EEPROMs basically).

Also add print_supported_pcidevs() to show the supported PCI devices
(currently only NICs, soon more) in the 'flashrom -L' output.

Corresponding to flashrom svn r515.
Signed-off-by: default avatarUwe Hermann <uwe@hermann-uwe.de>
Acked-by: default avatarCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
parent 1e637844
......@@ -33,7 +33,7 @@ OBJS = chipset_enable.o board_enable.o udelay.o jedec.o stm50flw0x0x.o \
sst49lfxxxc.o sst_fwhub.o layout.o cbtable.o flashchips.o physmap.o \
flashrom.o w39v080fa.o sharplhf00l04.o w29ee011.o spi.o it87spi.o \
ichspi.o w39v040c.o sb600spi.o wbsio_spi.o m29f002.o internal.o \
dummyflasher.o nic3com.o
dummyflasher.o pcidev.o nic3com.o
all: pciutils dep $(PROGRAM)
......
......@@ -551,6 +551,23 @@ struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device);
struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
uint16_t card_vendor, uint16_t card_device);
/* pcidev.c */
#define PCI_OK 0
#define PCI_NT 1 /* Not tested */
extern uint32_t io_base_addr;
extern struct pci_access *pacc;
extern struct pci_filter filter;
struct pcidev_status {
uint16_t vendor_id;
uint16_t device_id;
int status;
const char *vendor_name;
const char *device_name;
};
uint32_t pcidev_validate(struct pci_dev *dev, struct pcidev_status *devs);
uint32_t pcidev_init(uint16_t vendor_id, struct pcidev_status *devs);
void print_supported_pcidevs(struct pcidev_status *devs);
/* board_enable.c */
void w836xx_ext_enter(uint16_t port);
void w836xx_ext_leave(uint16_t port);
......@@ -623,13 +640,14 @@ void nic3com_chip_writel(uint32_t val, volatile void *addr);
uint8_t nic3com_chip_readb(const volatile void *addr);
uint16_t nic3com_chip_readw(const volatile void *addr);
uint32_t nic3com_chip_readl(const volatile void *addr);
extern struct pcidev_status nics_3com[];
/* flashrom.c */
extern int verbose;
#define printf_debug(x...) { if (verbose) printf(x); }
void map_flash_registers(struct flashchip *flash);
int read_memmapped(struct flashchip *flash, uint8_t *buf);
extern char *nic_pcidev;
extern char *pcidev_bdf;
/* layout.c */
int show_id(uint8_t *bios, int size, int force);
......
......@@ -35,7 +35,6 @@ char *chip_to_probe = NULL;
int exclude_start_page, exclude_end_page;
int verbose = 0;
int programmer = PROGRAMMER_INTERNAL;
char *nic_pcidev = NULL;
const struct programmer_entry programmer_table[] = {
{
......@@ -446,6 +445,9 @@ int main(int argc, char *argv[])
print_supported_chips();
print_supported_chipsets();
print_supported_boards();
printf("\nSupported PCI devices flashrom can use "
"as programmer:\n\n");
print_supported_pcidevs(nics_3com);
exit(0);
break;
case 'p':
......@@ -456,7 +458,7 @@ int main(int argc, char *argv[])
} else if (strncmp(optarg, "nic3com", 7) == 0) {
programmer = PROGRAMMER_NIC3COM;
if (optarg[7] == '=')
nic_pcidev = strdup(optarg + 8);
pcidev_bdf = strdup(optarg + 8);
} else {
printf("Error: Unknown programmer.\n");
exit(1);
......
......@@ -31,108 +31,32 @@
#define INT_STATUS 0x0e
#define SELECT_REG_WINDOW 0x800
#define PCI_IO_BASE_ADDRESS 0x10
#define PCI_VENDOR_ID_3COM 0x10b7
uint32_t io_base_addr;
struct pci_access *pacc;
struct pci_filter filter;
#define OK 0
#define NT 1 /* Not tested */
static struct nic_status {
uint16_t device_id;
int status;
const char *device_name;
} nics[] = {
struct pcidev_status nics_3com[] = {
/* 3C90xB */
{0x9055, NT, "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX"},
{0x9001, NT, "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-T4" },
{0x9004, NT, "3C90xB: PCI 10BASE-T (TPO)" },
{0x9005, NT, "3C90xB: PCI 10BASE-T/10BASE2/AUI (COMBO)" },
{0x9006, NT, "3C90xB: PCI 10BASE-T/10BASE2 (TPC)" },
{0x900a, NT, "3C90xB: PCI 10BASE-FL" },
{0x905a, NT, "3C90xB: PCI 10BASE-FX" },
{0x10b7, 0x9055, PCI_NT, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX"},
{0x10b7, 0x9001, PCI_NT, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-T4" },
{0x10b7, 0x9004, PCI_NT, "3COM", "3C90xB: PCI 10BASE-T (TPO)" },
{0x10b7, 0x9005, PCI_NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2/AUI (COMBO)" },
{0x10b7, 0x9006, PCI_NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2 (TPC)" },
{0x10b7, 0x900a, PCI_NT, "3COM", "3C90xB: PCI 10BASE-FL" },
{0x10b7, 0x905a, PCI_NT, "3COM", "3C90xB: PCI 10BASE-FX" },
/* 3C905C */
{0x9200, OK, "3C905C: EtherLink 10/100 PCI (TX)" },
{0x10b7, 0x9200, PCI_OK, "3COM", "3C905C: EtherLink 10/100 PCI (TX)" },
/* 3C980C */
{0x9805, NT, "3C980C: EtherLink Server 10/100 PCI (TX)" },
{0x10b7, 0x9805, PCI_NT, "3COM", "3C980C: EtherLink Server 10/100 PCI (TX)" },
{},
};
uint32_t nic3com_validate(struct pci_dev *dev)
{
int i;
uint32_t addr;
for (i = 0; nics[i].device_name != NULL; i++) {
if (dev->device_id != nics[i].device_id)
continue;
addr = (uint32_t)(dev->base_addr[0] & ~0x03);
printf("Found NIC \"3COM %s\" (%04x:%04x, BDF %02x:%02x.%x)\n",
nics[i].device_name, dev->vendor_id,
dev->device_id, dev->bus, dev->dev, dev->func);
if (nics[i].status == NT) {
printf("===\nThis NIC is UNTESTED. Please email a "
"report including the 'flashrom -p nic3com'\n"
"output to flashrom@coreboot.org if it works "
"for you. Thank you for your help!\n===\n");
}
return addr;
}
return 0;
}
int nic3com_init(void)
{
struct pci_dev *dev;
char *msg = NULL;
int found = 0;
get_io_perms();
pacc = pci_alloc(); /* Get the pci_access structure */
pci_init(pacc); /* Initialize the PCI library */
pci_scan_bus(pacc); /* We want to get the list of devices */
pci_filter_init(pacc, &filter);
/* Filter by vendor and also bb:dd.f (if supplied by the user). */
filter.vendor = PCI_VENDOR_ID_3COM;
if (nic_pcidev != NULL) {
if ((msg = pci_filter_parse_slot(&filter, nic_pcidev))) {
fprintf(stderr, "Error: %s\n", msg);
exit(1);
}
}
for (dev = pacc->devices; dev; dev = dev->next) {
if (pci_filter_match(&filter, dev)) {
if ((io_base_addr = nic3com_validate(dev)) != 0)
found++;
}
}
/* Only continue if exactly one supported NIC has been found. */
if (found == 0) {
fprintf(stderr, "Error: No supported 3COM NIC found.\n");
exit(1);
} else if (found > 1) {
fprintf(stderr, "Error: Multiple supported NICs found. "
"Please use 'flashrom -p nic3com=bb:dd.f' \n"
"to explicitly select the card with the given BDF "
"(PCI bus, device, function).\n");
exit(1);
}
io_base_addr = pcidev_init(PCI_VENDOR_ID_3COM, nics_3com);
/*
* The lowest 16 bytes of the I/O mapped register space of (most) 3COM
......@@ -146,7 +70,7 @@ int nic3com_init(void)
int nic3com_shutdown(void)
{
free(nic_pcidev);
free(pcidev_bdf);
pci_cleanup(pacc);
#if defined(__FreeBSD__) || defined(__DragonFly__)
close(io_fd);
......
/*
* This file is part of the flashrom project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "flash.h"
uint32_t io_base_addr;
struct pci_access *pacc;
struct pci_filter filter;
char *pcidev_bdf = NULL;
uint32_t pcidev_validate(struct pci_dev *dev, struct pcidev_status *devs)
{
int i;
uint32_t addr;
for (i = 0; devs[i].device_name != NULL; i++) {
if (dev->device_id != devs[i].device_id)
continue;
addr = (uint32_t)(dev->base_addr[0] & ~0x03);
printf("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 == PCI_NT) {
printf("===\nThis PCI device is UNTESTED. Please email "
"a report including the 'flashrom -p xxxxxx'\n"
"output to flashrom@coreboot.org if it works "
"for you. Thank you for your help!\n===\n");
}
return addr;
}
return 0;
}
uint32_t pcidev_init(uint16_t vendor_id, struct pcidev_status *devs)
{
struct pci_dev *dev;
char *msg = NULL;
int found = 0;
uint32_t addr = 0;
pacc = pci_alloc(); /* Get the pci_access structure */
pci_init(pacc); /* Initialize the PCI library */
pci_scan_bus(pacc); /* We want to get the list of devices */
pci_filter_init(pacc, &filter);
/* Filter by vendor and also bb:dd.f (if supplied by the user). */
filter.vendor = vendor_id;
if (pcidev_bdf != NULL) {
if ((msg = pci_filter_parse_slot(&filter, pcidev_bdf))) {
fprintf(stderr, "Error: %s\n", msg);
exit(1);
}
}
for (dev = pacc->devices; dev; dev = dev->next) {
if (pci_filter_match(&filter, dev)) {
if ((addr = pcidev_validate(dev, devs)) != 0)
found++;
}
}
/* Only continue if exactly one supported PCI dev has been found. */
if (found == 0) {
fprintf(stderr, "Error: No supported PCI device found.\n");
exit(1);
} else if (found > 1) {
fprintf(stderr, "Error: Multiple supported PCI devices found. "
"Please use 'flashrom -p xxxxxx=bb:dd.f' \n"
"to explicitly select the card with the given BDF "
"(PCI bus, device, function).\n");
exit(1);
}
return addr;
}
void print_supported_pcidevs(struct pcidev_status *devs)
{
int i;
for (i = 0; devs[i].vendor_name != NULL; i++) {
printf("%s %s [%02x:%02x]%s\n", devs[i].vendor_name,
devs[i].device_name, devs[i].vendor_id,
devs[i].device_id,
(devs[i].status == PCI_NT) ? " (untested)" : "");
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment