Author: uwe Date: 2009-05-16 23:39:19 +0200 (Sat, 16 May 2009) New Revision: 520
Modified: trunk/flash.h trunk/flashchips.c trunk/nic3com.c trunk/pcidev.c Log: Add proper workaround for 3COM 3C90xB cards, which need special fixups (the 3C90xC ones don't). This is tested on hardware.
Also, add initial support for the Atmel AT29C010A chip (which I inserted in a 3COM 3C90xB card for testing). It can be detected, read works, erase works, but write will need some additional code (will post in another patch later).
Signed-off-by: Uwe Hermann uwe@hermann-uwe.de Acked-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Modified: trunk/flash.h =================================================================== --- trunk/flash.h 2009-05-16 21:22:56 UTC (rev 519) +++ trunk/flash.h 2009-05-16 21:39:19 UTC (rev 520) @@ -193,6 +193,7 @@ #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 @@ #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 @@ 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;
Modified: trunk/flashchips.c =================================================================== --- trunk/flashchips.c 2009-05-16 21:22:56 UTC (rev 519) +++ trunk/flashchips.c 2009-05-16 21:39:19 UTC (rev 520) @@ -376,6 +376,20 @@
{ .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,
Modified: trunk/nic3com.c =================================================================== --- trunk/nic3com.c 2009-05-16 21:22:56 UTC (rev 519) +++ trunk/nic3com.c 2009-05-16 21:39:19 UTC (rev 520) @@ -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,7 +61,19 @@ 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 * cards form a 'register window' into one of multiple (usually 8) @@ -70,6 +86,14 @@
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__)
Modified: trunk/pcidev.c =================================================================== --- trunk/pcidev.c 2009-05-16 21:22:56 UTC (rev 519) +++ trunk/pcidev.c 2009-05-16 21:39:19 UTC (rev 520) @@ -32,6 +32,7 @@ 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 @@ 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 @@
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 @@ exit(1); }
- return addr; + return curaddr; }
void print_supported_pcidevs(struct pcidev_status *devs)