summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--flash.h3
-rw-r--r--flashchips.c14
-rw-r--r--nic3com.c26
-rw-r--r--pcidev.c10
4 files changed, 49 insertions, 4 deletions
diff --git a/flash.h b/flash.h
index b980cba..2a9b9bb 100644
--- a/flash.h
+++ b/flash.h
@@ -193,6 +193,7 @@ struct flashchip {
#define TEST_OK_ERASE (1<<2)
#define TEST_OK_WRITE (1<<3)
#define TEST_OK_PR (TEST_OK_PROBE|TEST_OK_READ)
+#define TEST_OK_PRE (TEST_OK_PROBE|TEST_OK_READ|TEST_OK_ERASE)
#define TEST_OK_PREW (TEST_OK_PROBE|TEST_OK_READ|TEST_OK_ERASE|TEST_OK_WRITE)
#define TEST_OK_MASK 0x0f
@@ -258,6 +259,7 @@ extern struct flashchip flashchips[];
#define AT_26DF321 0x4700 /* also 25DF321 */
#define AT_26F004 0x0400
#define AT_29C040A 0xA4
+#define AT_29C010A 0xD5
#define AT_29C020 0xDA
#define AT_45BR3214B /* No ID available */
#define AT_45CS1282 0x2920
@@ -559,6 +561,7 @@ struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
extern uint32_t io_base_addr;
extern struct pci_access *pacc;
extern struct pci_filter filter;
+extern struct pci_dev *pcidev_dev;
struct pcidev_status {
uint16_t vendor_id;
uint16_t device_id;
diff --git a/flashchips.c b/flashchips.c
index eb241a9..36307c1 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -376,6 +376,20 @@ struct flashchip flashchips[] = {
{
.vendor = "Atmel",
+ .name = "AT29C010A",
+ .manufacture_id = ATMEL_ID,
+ .model_id = AT_29C010A,
+ .total_size = 128,
+ .page_size = 128,
+ .tested = TEST_OK_PRE,
+ .probe = probe_jedec,
+ .erase = erase_chip_jedec,
+ .write = write_jedec, /* FIXME */
+ .read = read_memmapped,
+ },
+
+ {
+ .vendor = "Atmel",
.name = "AT29C020",
.manufacture_id = ATMEL_ID,
.model_id = AT_29C020,
diff --git a/nic3com.c b/nic3com.c
index f5d0aa1..4e3e475 100644
--- a/nic3com.c
+++ b/nic3com.c
@@ -29,13 +29,17 @@
#define BIOS_ROM_ADDR 0x04
#define BIOS_ROM_DATA 0x08
#define INT_STATUS 0x0e
+#define INTERNAL_CONFIG 0x00
#define SELECT_REG_WINDOW 0x800
#define PCI_VENDOR_ID_3COM 0x10b7
+uint32_t internal_conf;
+uint16_t id;
+
struct pcidev_status nics_3com[] = {
/* 3C90xB */
- {0x10b7, 0x9055, PCI_NT, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX"},
+ {0x10b7, 0x9055, PCI_OK, "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)" },
@@ -57,6 +61,18 @@ int nic3com_init(void)
get_io_perms();
io_base_addr = pcidev_init(PCI_VENDOR_ID_3COM, nics_3com);
+ id = pcidev_dev->device_id;
+
+ /* 3COM 3C90xB cards need a special fixup. */
+ if (id == 0x9055 || id == 0x9001 || id == 0x9004 || id == 0x9005
+ || id == 0x9006 || id == 0x900a || id == 0x905a) {
+ /* Select register window 3 and save the receiver status. */
+ OUTW(SELECT_REG_WINDOW + 3, io_base_addr + INT_STATUS);
+ internal_conf = INL(io_base_addr + INTERNAL_CONFIG);
+
+ /* Set receiver type to MII for full BIOS ROM access. */
+ OUTL((internal_conf & 0xf00fffff) | 0x00600000, io_base_addr);
+ }
/*
* The lowest 16 bytes of the I/O mapped register space of (most) 3COM
@@ -70,6 +86,14 @@ int nic3com_init(void)
int nic3com_shutdown(void)
{
+ /* 3COM 3C90xB cards need a special fixup. */
+ if (id == 0x9055 || id == 0x9001 || id == 0x9004 || id == 0x9005
+ || id == 0x9006 || id == 0x900a || id == 0x905a) {
+ /* Select register window 3 and restore the receiver status. */
+ OUTW(SELECT_REG_WINDOW + 3, io_base_addr + INT_STATUS);
+ OUTL(internal_conf, io_base_addr + INTERNAL_CONFIG);
+ }
+
free(pcidev_bdf);
pci_cleanup(pacc);
#if defined(__FreeBSD__) || defined(__DragonFly__)
diff --git a/pcidev.c b/pcidev.c
index f07fe80..41b5f25 100644
--- a/pcidev.c
+++ b/pcidev.c
@@ -32,6 +32,7 @@ uint32_t io_base_addr;
struct pci_access *pacc;
struct pci_filter filter;
char *pcidev_bdf = NULL;
+struct pci_dev *pcidev_dev = NULL;
uint32_t pcidev_validate(struct pci_dev *dev, struct pcidev_status *devs)
{
@@ -67,7 +68,7 @@ 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;
+ uint32_t addr = 0, curaddr = 0;
pacc = pci_alloc(); /* Get the pci_access structure */
pci_init(pacc); /* Initialize the PCI library */
@@ -85,8 +86,11 @@ uint32_t pcidev_init(uint16_t vendor_id, struct pcidev_status *devs)
for (dev = pacc->devices; dev; dev = dev->next) {
if (pci_filter_match(&filter, dev)) {
- if ((addr = pcidev_validate(dev, devs)) != 0)
+ if ((addr = pcidev_validate(dev, devs)) != 0) {
+ curaddr = addr;
+ pcidev_dev = dev;
found++;
+ }
}
}
@@ -102,7 +106,7 @@ uint32_t pcidev_init(uint16_t vendor_id, struct pcidev_status *devs)
exit(1);
}
- return addr;
+ return curaddr;
}
void print_supported_pcidevs(struct pcidev_status *devs)
OpenPOWER on IntegriCloud