eth_ntoa fixups
[people/xl0/gpxe.git] / src / drivers / net / 3c90x.c
index 1c8b7e4..0859443 100644 (file)
 
 #include "etherboot.h"
 #include "nic.h"
-#include "pci.h"
+#include <gpxe/pci.h>
+#include <gpxe/ethernet.h>
 #include "timer.h"
 
+static struct nic_operations a3c90x_operations;
+
 #define        XCVR_MAGIC      (0x5A00)
 /** any single transmission fails after 16 collisions or other errors
  ** this is the number of times to retry the transmission -- this should
@@ -239,6 +242,7 @@ typedef struct
 /*** Global variables ***/
 static struct
     {
+    unsigned int       is3c556;
     unsigned char      isBrev;
     unsigned char      CurrentWindow;
     unsigned int       IOAddr;
@@ -302,7 +306,15 @@ a3c90x_internal_ReadEeprom(int ioaddr, int address)
        while((1<<15) & inw(ioaddr + regEepromCommand_0_w));
 
        /** Read the value. **/
-       outw(address + ((0x02)<<6), ioaddr + regEepromCommand_0_w);
+       if (INF_3C90X.is3c556)
+        {
+            outw(address + (0x230), ioaddr + regEepromCommand_0_w);
+        }
+       else
+        {
+            outw(address + ((0x02)<<6), ioaddr + regEepromCommand_0_w);
+        }
        while((1<<15) & inw(ioaddr + regEepromCommand_0_w));
        val = inw(ioaddr + regEepromData_0_w);
 
@@ -663,9 +675,7 @@ a3c90x_poll(struct nic *nic, int retrieve)
  *** [Ken]
  ***/
 static void
-a3c90x_disable(struct dev *dev __unused)
-{
-       /* reset and disable merge */
+a3c90x_disable ( struct nic *nic __unused ) {
        a3c90x_reset();
        /* Disable the receiver and transmitter. */
        outw(cmdRxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w);
@@ -688,9 +698,8 @@ static void a3c90x_irq(struct nic *nic __unused, irq_action_t action __unused)
  *** initialization.  If this routine is called, the pci functions did find the
  *** card.  We just have to init it here.
  ***/
-static int a3c90x_probe(struct dev *dev, struct pci_device *pci)
-{
-    struct nic *nic = (struct nic *)dev;
+static int a3c90x_probe ( struct nic *nic, struct pci_device *pci ) {
+
     int i, c;
     unsigned short eeprom[0x21];
     unsigned int cfg;
@@ -698,15 +707,18 @@ static int a3c90x_probe(struct dev *dev, struct pci_device *pci)
     unsigned int mstat;
     unsigned short linktype;
 #define        HWADDR_OFFSET   10
-
+    
     if (pci->ioaddr == 0)
           return 0;
 
     adjust_pci_device(pci);
 
-    nic->ioaddr = pci->ioaddr & ~3;
+    pci_fill_nic ( nic, pci );
+
+    nic->ioaddr = pci->ioaddr;
     nic->irqno = 0;
 
+    INF_3C90X.is3c556 = (pci->device == 0x6055);
     INF_3C90X.IOAddr = pci->ioaddr & ~3;
     INF_3C90X.CurrentWindow = 255;
     switch (a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, 0x03))
@@ -790,7 +802,17 @@ static int a3c90x_probe(struct dev *dev, struct pci_device *pci)
     INF_3C90X.HWAddr[3] = eeprom[HWADDR_OFFSET + 1]&0xFF;
     INF_3C90X.HWAddr[4] = eeprom[HWADDR_OFFSET + 2]>>8;
     INF_3C90X.HWAddr[5] = eeprom[HWADDR_OFFSET + 2]&0xFF;
-    printf("MAC Address = %!\n", INF_3C90X.HWAddr);
+
+    DBG ( "MAC Address = %s\n", eth_ntoa ( INF_3C90X.HWAddr ) );
+
+    /** 3C556: Invert MII power **/
+    if (INF_3C90X.is3c556) {
+       unsigned int tmp;
+       a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winAddressing2);
+       tmp = inw(INF_3C90X.IOAddr + regResetOptions_2_w);
+       tmp |= 0x4000;
+       outw(tmp, INF_3C90X.IOAddr + regResetOptions_2_w);
+    }
 
     /* Test if the link is good, if not continue */
     a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winDiagnostics4);
@@ -950,17 +972,21 @@ static int a3c90x_probe(struct dev *dev, struct pci_device *pci)
                                  cmdAcknowledgeInterrupt, 0x661);
 
     /** Set our exported functions **/
-    dev->disable  = a3c90x_disable;
-    nic->poll     = a3c90x_poll;
-    nic->transmit = a3c90x_transmit;
-    nic->irq      = a3c90x_irq;
-
+    nic->nic_op        = &a3c90x_operations;
     return 1;
 }
 
+static struct nic_operations a3c90x_operations = {
+       .connect        = dummy_connect,
+       .poll           = a3c90x_poll,
+       .transmit       = a3c90x_transmit,
+       .irq            = a3c90x_irq,
 
-static struct pci_id a3c90x_nics[] = {
+};
+
+static struct pci_device_id a3c90x_nics[] = {
 /* Original 90x revisions: */
+PCI_ROM(0x10b7, 0x6055, "3c556",        "3C556"),              /* Huricane */
 PCI_ROM(0x10b7, 0x9000, "3c905-tpo",     "3Com900-TPO"),       /* 10 Base TPO */
 PCI_ROM(0x10b7, 0x9001, "3c905-t4",      "3Com900-Combo"),     /* 10/100 T4 */
 PCI_ROM(0x10b7, 0x9050, "3c905-tpo100",  "3Com905-TX"),                /* 100 Base TX / 10/100 TPO */
@@ -986,11 +1012,7 @@ PCI_ROM(0x10b7, 0x1201, "3c982a",        "3Com982A"),
 PCI_ROM(0x10b7, 0x1202, "3c982b",        "3Com982B"),
 };
 
-static struct pci_driver a3c90x_driver __pci_driver = {
-       .type     = NIC_DRIVER,
-       .name     = "3C90X",
-       .probe    = a3c90x_probe,
-       .ids      = a3c90x_nics,
-       .id_count = sizeof(a3c90x_nics)/sizeof(a3c90x_nics[0]),
-       .class    = 0,
-};
+PCI_DRIVER ( a3c90x_driver, a3c90x_nics, PCI_NO_CLASS );
+
+DRIVER ( "3C90X", nic_driver, pci_driver, a3c90x_driver,
+        a3c90x_probe, a3c90x_disable );