aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/3c515.c
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2008-01-13 09:17:35 -0500
committerJeff Garzik <jeff@garzik.org>2008-01-18 14:44:33 -0500
commitb665982409fd5e4d3f1b71591d2f6badf9d2ee99 (patch)
tree00f16223e91563bd99cb4a42178f62e693aa2030 /drivers/net/3c515.c
parentc15561f0e5615607e2b5524c4b3af64d20cd6e28 (diff)
3c574, 3c515 bitfields abuse
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>
Diffstat (limited to 'drivers/net/3c515.c')
-rw-r--r--drivers/net/3c515.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 275e7510eba..684bab78101 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -243,14 +243,16 @@ enum eeprom_offset {
243enum Window3 { /* Window 3: MAC/config bits. */ 243enum Window3 { /* Window 3: MAC/config bits. */
244 Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8, 244 Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
245}; 245};
246union wn3_config { 246enum wn3_config {
247 int i; 247 Ram_size = 7,
248 struct w3_config_fields { 248 Ram_width = 8,
249 unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2; 249 Ram_speed = 0x30,
250 int pad8:8; 250 Rom_size = 0xc0,
251 unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1; 251 Ram_split_shift = 16,
252 int pad24:7; 252 Ram_split = 3 << Ram_split_shift,
253 } u; 253 Xcvr_shift = 20,
254 Xcvr = 7 << Xcvr_shift,
255 Autoselect = 0x1000000,
254}; 256};
255 257
256enum Window4 { 258enum Window4 {
@@ -614,7 +616,7 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
614 /* Read the station address from the EEPROM. */ 616 /* Read the station address from the EEPROM. */
615 EL3WINDOW(0); 617 EL3WINDOW(0);
616 for (i = 0; i < 0x18; i++) { 618 for (i = 0; i < 0x18; i++) {
617 short *phys_addr = (short *) dev->dev_addr; 619 __be16 *phys_addr = (__be16 *) dev->dev_addr;
618 int timer; 620 int timer;
619 outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd); 621 outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
620 /* Pause for at least 162 us. for the read to take place. */ 622 /* 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,
646 648
647 { 649 {
648 char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" }; 650 char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
649 union wn3_config config; 651 __u32 config;
650 EL3WINDOW(3); 652 EL3WINDOW(3);
651 vp->available_media = inw(ioaddr + Wn3_Options); 653 vp->available_media = inw(ioaddr + Wn3_Options);
652 config.i = inl(ioaddr + Wn3_Config); 654 config = inl(ioaddr + Wn3_Config);
653 if (corkscrew_debug > 1) 655 if (corkscrew_debug > 1)
654 printk(KERN_INFO " Internal config register is %4.4x, transceivers %#x.\n", 656 printk(KERN_INFO " Internal config register is %4.4x, transceivers %#x.\n",
655 config.i, inw(ioaddr + Wn3_Options)); 657 config, inw(ioaddr + Wn3_Options));
656 printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", 658 printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
657 8 << config.u.ram_size, 659 8 << config & Ram_size,
658 config.u.ram_width ? "word" : "byte", 660 config & Ram_width ? "word" : "byte",
659 ram_split[config.u.ram_split], 661 ram_split[(config & Ram_split) >> Ram_split_shift],
660 config.u.autoselect ? "autoselect/" : "", 662 config & Autoselect ? "autoselect/" : "",
661 media_tbl[config.u.xcvr].name); 663 media_tbl[(config & Xcvr) >> Xcvr_shift].name);
662 dev->if_port = config.u.xcvr; 664 vp->default_media = (config & Xcvr) >> Xcvr_shift;
663 vp->default_media = config.u.xcvr; 665 vp->autoselect = config & Autoselect ? 1 : 0;
664 vp->autoselect = config.u.autoselect; 666 dev->if_port = vp->default_media;
665 } 667 }
666 if (vp->media_override != 7) { 668 if (vp->media_override != 7) {
667 printk(KERN_INFO " Media override to transceiver type %d (%s).\n", 669 printk(KERN_INFO " Media override to transceiver type %d (%s).\n",
@@ -694,14 +696,14 @@ static int corkscrew_open(struct net_device *dev)
694{ 696{
695 int ioaddr = dev->base_addr; 697 int ioaddr = dev->base_addr;
696 struct corkscrew_private *vp = netdev_priv(dev); 698 struct corkscrew_private *vp = netdev_priv(dev);
697 union wn3_config config; 699 __u32 config;
698 int i; 700 int i;
699 701
700 /* Before initializing select the active media port. */ 702 /* Before initializing select the active media port. */
701 EL3WINDOW(3); 703 EL3WINDOW(3);
702 if (vp->full_duplex) 704 if (vp->full_duplex)
703 outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */ 705 outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
704 config.i = inl(ioaddr + Wn3_Config); 706 config = inl(ioaddr + Wn3_Config);
705 707
706 if (vp->media_override != 7) { 708 if (vp->media_override != 7) {
707 if (corkscrew_debug > 1) 709 if (corkscrew_debug > 1)
@@ -727,12 +729,12 @@ static int corkscrew_open(struct net_device *dev)
727 } else 729 } else
728 dev->if_port = vp->default_media; 730 dev->if_port = vp->default_media;
729 731
730 config.u.xcvr = dev->if_port; 732 config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
731 outl(config.i, ioaddr + Wn3_Config); 733 outl(config, ioaddr + Wn3_Config);
732 734
733 if (corkscrew_debug > 1) { 735 if (corkscrew_debug > 1) {
734 printk("%s: corkscrew_open() InternalConfig %8.8x.\n", 736 printk("%s: corkscrew_open() InternalConfig %8.8x.\n",
735 dev->name, config.i); 737 dev->name, config);
736 } 738 }
737 739
738 outw(TxReset, ioaddr + EL3_CMD); 740 outw(TxReset, ioaddr + EL3_CMD);
@@ -901,7 +903,7 @@ static void corkscrew_timer(unsigned long data)
901 ok = 1; 903 ok = 1;
902 } 904 }
903 if (!ok) { 905 if (!ok) {
904 union wn3_config config; 906 __u32 config;
905 907
906 do { 908 do {
907 dev->if_port = 909 dev->if_port =
@@ -928,9 +930,9 @@ static void corkscrew_timer(unsigned long data)
928 ioaddr + Wn4_Media); 930 ioaddr + Wn4_Media);
929 931
930 EL3WINDOW(3); 932 EL3WINDOW(3);
931 config.i = inl(ioaddr + Wn3_Config); 933 config = inl(ioaddr + Wn3_Config);
932 config.u.xcvr = dev->if_port; 934 config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
933 outl(config.i, ioaddr + Wn3_Config); 935 outl(config, ioaddr + Wn3_Config);
934 936
935 outw(dev->if_port == 3 ? StartCoax : StopCoax, 937 outw(dev->if_port == 3 ? StartCoax : StopCoax,
936 ioaddr + EL3_CMD); 938 ioaddr + EL3_CMD);