3c574, 3c515 bitfields abuse
authorAl Viro <viro@ftp.linux.org.uk>
Sun, 13 Jan 2008 14:17:35 +0000 (14:17 +0000)
committerJeff Garzik <jeff@garzik.org>
Fri, 18 Jan 2008 19:44:33 +0000 (14:44 -0500)
wn3_config is shared by these cards; the way we deal with it is both bad C
(union abuse) and broken on big-endian.  For 3c515 it's less serious (ISA
cards are quite rare outside of little-endian boxen), but 3c574 is a pcmcia
one and that'd better be endian-independent...  Fix is the same in both
cases.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/3c515.c
drivers/net/pcmcia/3c574_cs.c

index 275e7510ebaf64a67e2835f1adbdfc978cadc1a5..684bab7810156998f3fd366b27ac1b645d5169e7 100644 (file)
@@ -243,14 +243,16 @@ enum eeprom_offset {
 enum Window3 {                 /* Window 3: MAC/config bits. */
        Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
 };
-union wn3_config {
-       int i;
-       struct w3_config_fields {
-               unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
-               int pad8:8;
-               unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1;
-               int pad24:7;
-       } u;
+enum wn3_config {
+       Ram_size = 7,
+       Ram_width = 8,
+       Ram_speed = 0x30,
+       Rom_size = 0xc0,
+       Ram_split_shift = 16,
+       Ram_split = 3 << Ram_split_shift,
+       Xcvr_shift = 20,
+       Xcvr = 7 << Xcvr_shift,
+       Autoselect = 0x1000000,
 };
 
 enum Window4 {
@@ -614,7 +616,7 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
        /* Read the station address from the EEPROM. */
        EL3WINDOW(0);
        for (i = 0; i < 0x18; i++) {
-               short *phys_addr = (short *) dev->dev_addr;
+               __be16 *phys_addr = (__be16 *) dev->dev_addr;
                int timer;
                outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
                /* Pause for at least 162 us. for the read to take place. */
@@ -646,22 +648,22 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
 
        {
                char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
-               union wn3_config config;
+               __u32 config;
                EL3WINDOW(3);
                vp->available_media = inw(ioaddr + Wn3_Options);
-               config.i = inl(ioaddr + Wn3_Config);
+               config = inl(ioaddr + Wn3_Config);
                if (corkscrew_debug > 1)
                        printk(KERN_INFO "  Internal config register is %4.4x, transceivers %#x.\n",
-                               config.i, inw(ioaddr + Wn3_Options));
+                               config, inw(ioaddr + Wn3_Options));
                printk(KERN_INFO "  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
-                       8 << config.u.ram_size,
-                       config.u.ram_width ? "word" : "byte",
-                       ram_split[config.u.ram_split],
-                       config.u.autoselect ? "autoselect/" : "",
-                       media_tbl[config.u.xcvr].name);
-               dev->if_port = config.u.xcvr;
-               vp->default_media = config.u.xcvr;
-               vp->autoselect = config.u.autoselect;
+                       8 << config & Ram_size,
+                       config & Ram_width ? "word" : "byte",
+                       ram_split[(config & Ram_split) >> Ram_split_shift],
+                       config & Autoselect ? "autoselect/" : "",
+                       media_tbl[(config & Xcvr) >> Xcvr_shift].name);
+               vp->default_media = (config & Xcvr) >> Xcvr_shift;
+               vp->autoselect = config & Autoselect ? 1 : 0;
+               dev->if_port = vp->default_media;
        }
        if (vp->media_override != 7) {
                printk(KERN_INFO "  Media override to transceiver type %d (%s).\n",
@@ -694,14 +696,14 @@ static int corkscrew_open(struct net_device *dev)
 {
        int ioaddr = dev->base_addr;
        struct corkscrew_private *vp = netdev_priv(dev);
-       union wn3_config config;
+       __u32 config;
        int i;
 
        /* Before initializing select the active media port. */
        EL3WINDOW(3);
        if (vp->full_duplex)
                outb(0x20, ioaddr + Wn3_MAC_Ctrl);      /* Set the full-duplex bit. */
-       config.i = inl(ioaddr + Wn3_Config);
+       config = inl(ioaddr + Wn3_Config);
 
        if (vp->media_override != 7) {
                if (corkscrew_debug > 1)
@@ -727,12 +729,12 @@ static int corkscrew_open(struct net_device *dev)
        } else
                dev->if_port = vp->default_media;
 
-       config.u.xcvr = dev->if_port;
-       outl(config.i, ioaddr + Wn3_Config);
+       config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
+       outl(config, ioaddr + Wn3_Config);
 
        if (corkscrew_debug > 1) {
                printk("%s: corkscrew_open() InternalConfig %8.8x.\n",
-                      dev->name, config.i);
+                      dev->name, config);
        }
 
        outw(TxReset, ioaddr + EL3_CMD);
@@ -901,7 +903,7 @@ static void corkscrew_timer(unsigned long data)
                        ok = 1;
                }
                if (!ok) {
-                       union wn3_config config;
+                       __u32 config;
 
                        do {
                                dev->if_port =
@@ -928,9 +930,9 @@ static void corkscrew_timer(unsigned long data)
                             ioaddr + Wn4_Media);
 
                        EL3WINDOW(3);
-                       config.i = inl(ioaddr + Wn3_Config);
-                       config.u.xcvr = dev->if_port;
-                       outl(config.i, ioaddr + Wn3_Config);
+                       config = inl(ioaddr + Wn3_Config);
+                       config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
+                       outl(config, ioaddr + Wn3_Config);
 
                        outw(dev->if_port == 3 ? StartCoax : StopCoax,
                             ioaddr + EL3_CMD);
index 288177716a49f90e0c61dc7273960eeef7ddb1ae..36a7ba3134ce7468b643138f3d57ea95334b95bc 100644 (file)
@@ -187,14 +187,16 @@ enum Window1 {
 enum Window3 {                 /* Window 3: MAC/config bits. */
        Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
 };
-union wn3_config {
-       int i;
-       struct w3_config_fields {
-               unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
-               int pad8:8;
-               unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1;
-               int pad24:7;
-       } u;
+enum wn3_config {
+       Ram_size = 7,
+       Ram_width = 8,
+       Ram_speed = 0x30,
+       Rom_size = 0xc0,
+       Ram_split_shift = 16,
+       Ram_split = 3 << Ram_split_shift,
+       Xcvr_shift = 20,
+       Xcvr = 7 << Xcvr_shift,
+       Autoselect = 0x1000000,
 };
 
 enum Window4 {         /* Window 4: Xcvr/media bits. */
@@ -342,7 +344,7 @@ static int tc574_config(struct pcmcia_device *link)
        kio_addr_t ioaddr;
        __be16 *phys_addr;
        char *cardname;
-       union wn3_config config;
+       __u32 config;
        DECLARE_MAC_BUF(mac);
 
        phys_addr = (__be16 *)dev->dev_addr;
@@ -401,9 +403,9 @@ static int tc574_config(struct pcmcia_device *link)
                outw(0<<11, ioaddr + RunnerRdCtrl);
                printk(KERN_INFO "  ASIC rev %d,", mcr>>3);
                EL3WINDOW(3);
-               config.i = inl(ioaddr + Wn3_Config);
-               lp->default_media = config.u.xcvr;
-               lp->autoselect = config.u.autoselect;
+               config = inl(ioaddr + Wn3_Config);
+               lp->default_media = (config & Xcvr) >> Xcvr_shift;
+               lp->autoselect = config & Autoselect ? 1 : 0;
        }
 
        init_timer(&lp->media);
@@ -464,8 +466,9 @@ static int tc574_config(struct pcmcia_device *link)
               dev->name, cardname, dev->base_addr, dev->irq,
               print_mac(mac, dev->dev_addr));
        printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n",
-                  8 << config.u.ram_size, ram_split[config.u.ram_split],
-                  config.u.autoselect ? "autoselect " : "");
+                  8 << config & Ram_size,
+                  ram_split[(config & Ram_split) >> Ram_split_shift],
+                  config & Autoselect ? "autoselect " : "");
 
        return 0;