vserver 1.9.3
[linux-2.6.git] / drivers / net / 3c59x.c
index ab2e61a..89faad1 100644 (file)
@@ -695,7 +695,7 @@ enum Window2 {                      /* Window 2. */
        Wn2_ResetOptions=12,
 };
 enum Window3 {                 /* Window 3: MAC/config bits. */
-       Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
+       Wn3_Config=0, Wn3_MaxPktSize=4, Wn3_MAC_Ctrl=6, Wn3_Options=8,
 };
 
 #define BFEXT(value, offset, bitcount)  \
@@ -723,7 +723,8 @@ enum Win4_Media_bits {
        Media_LnkBeat = 0x0800,
 };
 enum Window7 {                                 /* Window 7: Bus Master control. */
-       Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
+       Wn7_MasterAddr = 0, Wn7_VlanEtherType=4, Wn7_MasterLen = 6,
+       Wn7_MasterStatus = 12,
 };
 /* Boomerang bus master control registers. */
 enum MasterCtrl {
@@ -819,7 +820,8 @@ struct vortex_private {
                pm_state_valid:1,                               /* power_state[] has sane contents */
                open:1,
                medialock:1,
-               must_free_region:1;                             /* Flag: if zero, Cardbus owns the I/O region */
+               must_free_region:1,                             /* Flag: if zero, Cardbus owns the I/O region */
+               large_frames:1;                 /* accept large frames */
        int drv_flags;
        u16 status_enable;
        u16 intr_enable;
@@ -900,10 +902,14 @@ static void dump_tx_ring(struct net_device *dev);
 static void update_stats(long ioaddr, struct net_device *dev);
 static struct net_device_stats *vortex_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
+#ifdef CONFIG_PCI
 static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#endif
 static void vortex_tx_timeout(struct net_device *dev);
 static void acpi_set_WOL(struct net_device *dev);
 static struct ethtool_ops vortex_ethtool_ops;
+static void set_8021q_mode(struct net_device *dev, int enable);
+
 \f
 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
 /* Option count limit only -- unlimited interfaces are supported. */
@@ -1164,6 +1170,7 @@ static int __devinit vortex_probe1(struct device *gendev,
        dev->base_addr = ioaddr;
        dev->irq = irq;
        dev->mtu = mtu;
+       vp->large_frames = mtu > 1500;
        vp->drv_flags = vci->drv_flags;
        vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
        vp->io_size = vci->io_size;
@@ -1290,6 +1297,13 @@ static int __devinit vortex_probe1(struct device *gendev,
                for (i = 0; i < 6; i++)
                        printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
        }
+       /* Unfortunately an all zero eeprom passes the checksum and this
+          gets found in the wild in failure cases. Crypto is hard 8) */
+       if (!is_valid_ether_addr(dev->dev_addr)) {
+               retval = -EINVAL;
+               printk(KERN_ERR "*** EEPROM MAC address is invalid.\n");
+               goto free_ring; /* With every pack */
+       }
        EL3WINDOW(2);
        for (i = 0; i < 6; i++)
                outb(dev->dev_addr[i], ioaddr + i);
@@ -1468,7 +1482,9 @@ static int __devinit vortex_probe1(struct device *gendev,
 
        dev->stop = vortex_close;
        dev->get_stats = vortex_get_stats;
+#ifdef CONFIG_PCI
        dev->do_ioctl = vortex_ioctl;
+#endif
        dev->ethtool_ops = &vortex_ethtool_ops;
        dev->set_multicast_list = set_rx_mode;
        dev->tx_timeout = vortex_tx_timeout;
@@ -1616,7 +1632,7 @@ vortex_up(struct net_device *dev)
 
        /* Set the full-duplex bit. */
        outw(   ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
-                       (dev->mtu > 1500 ? 0x40 : 0) |
+                       (vp->large_frames ? 0x40 : 0) |
                        ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
                        ioaddr + Wn3_MAC_Ctrl);
 
@@ -1700,6 +1716,8 @@ vortex_up(struct net_device *dev)
        }
        /* Set receiver mode: presumably accept b-case and phys addr only. */
        set_rx_mode(dev);
+       /* enable 802.1q tagged frames */
+       set_8021q_mode(dev, 1);
        outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
 //     issue_and_wait(dev, SetTxStart|0x07ff);
@@ -1842,7 +1860,7 @@ vortex_timer(unsigned long data)
                                                /* Set the full-duplex bit. */
                                                EL3WINDOW(3);
                                                outw(   (vp->full_duplex ? 0x20 : 0) |
-                                                               (dev->mtu > 1500 ? 0x40 : 0) |
+                                                               (vp->large_frames ? 0x40 : 0) |
                                                                ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
                                                                ioaddr + Wn3_MAC_Ctrl);
                                                if (vortex_debug > 1)
@@ -2068,6 +2086,8 @@ vortex_error(struct net_device *dev, int status)
                        issue_and_wait(dev, RxReset|0x07);
                        /* Set the Rx filter to the current state. */
                        set_rx_mode(dev);
+                       /* enable 802.1q VLAN tagged frames */
+                       set_8021q_mode(dev, 1);
                        outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
                        outw(AckIntr | HostError, ioaddr + EL3_CMD);
                }
@@ -2672,6 +2692,9 @@ vortex_down(struct net_device *dev, int final_down)
        outw(RxDisable, ioaddr + EL3_CMD);
        outw(TxDisable, ioaddr + EL3_CMD);
 
+       /* Disable receiving 802.1q tagged frames */
+       set_8021q_mode(dev, 0);
+
        if (dev->if_port == XCVR_10base2)
                /* Turn off thinnet power.  Green! */
                outw(StopCoax, ioaddr + EL3_CMD);
@@ -2868,6 +2891,7 @@ static struct ethtool_ops vortex_ethtool_ops = {
        .get_drvinfo =          vortex_get_drvinfo,
 };
 
+#ifdef CONFIG_PCI
 static int vortex_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct vortex_private *vp = netdev_priv(dev);
@@ -2925,6 +2949,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        return err;
 }
+#endif
 
 
 /* Pre-Cyclone chips have no documented multicast filter, so the only
@@ -2947,6 +2972,61 @@ static void set_rx_mode(struct net_device *dev)
        outw(new_mode, ioaddr + EL3_CMD);
 }
 
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+/* Setup the card so that it can receive frames with an 802.1q VLAN tag.
+   Note that this must be done after each RxReset due to some backwards
+   compatibility logic in the Cyclone and Tornado ASICs */
+
+/* The Ethernet Type used for 802.1q tagged frames */
+#define VLAN_ETHER_TYPE 0x8100
+
+static void set_8021q_mode(struct net_device *dev, int enable)
+{
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       long ioaddr = dev->base_addr;
+       int old_window = inw(ioaddr + EL3_CMD);
+       int mac_ctrl;
+
+       if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) {
+               /* cyclone and tornado chipsets can recognize 802.1q
+                * tagged frames and treat them correctly */
+
+               int max_pkt_size = dev->mtu+14; /* MTU+Ethernet header */
+               if (enable)
+                       max_pkt_size += 4;      /* 802.1Q VLAN tag */
+
+               EL3WINDOW(3);
+               outw(max_pkt_size, ioaddr+Wn3_MaxPktSize);
+
+               /* set VlanEtherType to let the hardware checksumming
+                  treat tagged frames correctly */
+               EL3WINDOW(7);
+               outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
+       } else {
+               /* on older cards we have to enable large frames */
+
+               vp->large_frames = dev->mtu > 1500 || enable;
+
+               EL3WINDOW(3);
+               mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl);
+               if (vp->large_frames)
+                       mac_ctrl |= 0x40;
+               else
+                       mac_ctrl &= ~0x40;
+               outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
+       }
+
+       EL3WINDOW(old_window);
+}
+#else
+
+static void set_8021q_mode(struct net_device *dev, int enable)
+{
+}
+
+
+#endif
+
 /* MII transceiver control section.
    Read and write the MII registers using software-generated serial
    MDIO protocol.  See the MII specifications or DP83840A data sheet