Commit 63d5381e authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/spare/repo/netdev-2.6/misc

into redhat.com:/spare/repo/net-drivers-2.6
parents fc3b6177 2210dfec
...@@ -384,6 +384,8 @@ static void tc574_detach(dev_link_t *link) ...@@ -384,6 +384,8 @@ static void tc574_detach(dev_link_t *link)
#define CS_CHECK(fn, ret) \ #define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
static void tc574_config(dev_link_t *link) static void tc574_config(dev_link_t *link)
{ {
client_handle_t handle = link->handle; client_handle_t handle = link->handle;
...@@ -396,6 +398,7 @@ static void tc574_config(dev_link_t *link) ...@@ -396,6 +398,7 @@ static void tc574_config(dev_link_t *link)
ioaddr_t ioaddr; ioaddr_t ioaddr;
u16 *phys_addr; u16 *phys_addr;
char *cardname; char *cardname;
union wn3_config config;
phys_addr = (u16 *)dev->dev_addr; phys_addr = (u16 *)dev->dev_addr;
...@@ -431,15 +434,7 @@ static void tc574_config(dev_link_t *link) ...@@ -431,15 +434,7 @@ static void tc574_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ; dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1; dev->base_addr = link->io.BasePort1;
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
goto failed;
}
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
/* The 3c574 normally uses an EEPROM for configuration info, including /* The 3c574 normally uses an EEPROM for configuration info, including
the hardware address. The future products may include a modem chip the hardware address. The future products may include a modem chip
...@@ -467,24 +462,14 @@ static void tc574_config(dev_link_t *link) ...@@ -467,24 +462,14 @@ static void tc574_config(dev_link_t *link)
} else } else
cardname = "3Com 3c574"; cardname = "3Com 3c574";
printk(KERN_INFO "%s: %s at io %#3lx, irq %d, hw_addr ",
dev->name, cardname, dev->base_addr, dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : ".\n"));
{ {
u_char mcr, *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; u_char mcr;
union wn3_config config;
outw(2<<11, ioaddr + RunnerRdCtrl); outw(2<<11, ioaddr + RunnerRdCtrl);
mcr = inb(ioaddr + 2); mcr = inb(ioaddr + 2);
outw(0<<11, ioaddr + RunnerRdCtrl); outw(0<<11, ioaddr + RunnerRdCtrl);
printk(KERN_INFO " ASIC rev %d,", mcr>>3); printk(KERN_INFO " ASIC rev %d,", mcr>>3);
EL3WINDOW(3); EL3WINDOW(3);
config.i = inl(ioaddr + Wn3_Config); config.i = inl(ioaddr + Wn3_Config);
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 " : "");
lp->default_media = config.u.xcvr; lp->default_media = config.u.xcvr;
lp->autoselect = config.u.autoselect; lp->autoselect = config.u.autoselect;
} }
...@@ -531,6 +516,25 @@ static void tc574_config(dev_link_t *link) ...@@ -531,6 +516,25 @@ static void tc574_config(dev_link_t *link)
} }
} }
link->state &= ~DEV_CONFIG_PENDING;
link->dev = &lp->node;
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
link->dev = NULL;
goto failed;
}
strcpy(lp->node.dev_name, dev->name);
printk(KERN_INFO "%s: %s at io %#3lx, irq %d, hw_addr ",
dev->name, cardname, dev->base_addr, dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : ".\n"));
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 " : "");
return; return;
cs_failed: cs_failed:
......
...@@ -308,7 +308,7 @@ static void tc589_config(dev_link_t *link) ...@@ -308,7 +308,7 @@ static void tc589_config(dev_link_t *link)
tuple_t tuple; tuple_t tuple;
cisparse_t parse; cisparse_t parse;
u16 buf[32], *phys_addr; u16 buf[32], *phys_addr;
int last_fn, last_ret, i, j, multi = 0; int last_fn, last_ret, i, j, multi = 0, fifo;
ioaddr_t ioaddr; ioaddr_t ioaddr;
char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
...@@ -357,11 +357,6 @@ static void tc589_config(dev_link_t *link) ...@@ -357,11 +357,6 @@ static void tc589_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ; dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1; dev->base_addr = link->io.BasePort1;
if (register_netdev(dev) != 0) {
printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
goto failed;
}
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
EL3WINDOW(0); EL3WINDOW(0);
...@@ -382,13 +377,10 @@ static void tc589_config(dev_link_t *link) ...@@ -382,13 +377,10 @@ static void tc589_config(dev_link_t *link)
} }
} }
strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
/* The address and resource configuration register aren't loaded from /* The address and resource configuration register aren't loaded from
the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */ the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
outw(0x3f00, ioaddr + 8); outw(0x3f00, ioaddr + 8);
fifo = inl(ioaddr);
/* The if_port symbol can be set when the module is loaded */ /* The if_port symbol can be set when the module is loaded */
if ((if_port >= 0) && (if_port <= 3)) if ((if_port >= 0) && (if_port <= 3))
...@@ -396,14 +388,24 @@ static void tc589_config(dev_link_t *link) ...@@ -396,14 +388,24 @@ static void tc589_config(dev_link_t *link)
else else
printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); printk(KERN_ERR "3c589_cs: invalid if_port requested\n");
link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
if (register_netdev(dev) != 0) {
printk(KERN_ERR "3c589_cs: register_netdev() failed\n");
link->dev = NULL;
goto failed;
}
strcpy(lp->node.dev_name, dev->name);
printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr ", printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr ",
dev->name, (multi ? "562" : "589"), dev->base_addr, dev->name, (multi ? "562" : "589"), dev->base_addr,
dev->irq); dev->irq);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
i = inl(ioaddr);
printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n",
(i & 7) ? 32 : 8, ram_split[(i >> 16) & 3], (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
if_names[dev->if_port]); if_names[dev->if_port]);
return; return;
......
...@@ -430,19 +430,11 @@ static void axnet_config(dev_link_t *link) ...@@ -430,19 +430,11 @@ static void axnet_config(dev_link_t *link)
ei_status.block_input = &block_input; ei_status.block_input = &block_input;
ei_status.block_output = &block_output; ei_status.block_output = &block_output;
strcpy(info->node.dev_name, dev->name);
if (inb(dev->base_addr + AXNET_TEST) != 0) if (inb(dev->base_addr + AXNET_TEST) != 0)
info->flags |= IS_AX88790; info->flags |= IS_AX88790;
else else
info->flags |= IS_AX88190; info->flags |= IS_AX88190;
printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, hw_addr ",
dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
dev->base_addr, dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
if (info->flags & IS_AX88790) if (info->flags & IS_AX88790)
outb(0x10, dev->base_addr + AXNET_GPIO); /* select Internal PHY */ outb(0x10, dev->base_addr + AXNET_GPIO); /* select Internal PHY */
...@@ -463,19 +455,27 @@ static void axnet_config(dev_link_t *link) ...@@ -463,19 +455,27 @@ static void axnet_config(dev_link_t *link)
} }
info->phy_id = (i < 32) ? i : -1; info->phy_id = (i < 32) ? i : -1;
if (i < 32) { link->dev = &info->node;
DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j); link->state &= ~DEV_CONFIG_PENDING;
} else {
printk(KERN_NOTICE " No MII transceivers found!\n");
}
if (register_netdev(dev) != 0) { if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n");
link->dev = NULL;
goto failed; goto failed;
} }
link->dev = &info->node; strcpy(info->node.dev_name, dev->name);
link->state &= ~DEV_CONFIG_PENDING;
printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, hw_addr ",
dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
dev->base_addr, dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
if (info->phy_id != -1) {
DEBUG(0, " MII transceiver at index %d, status %x.\n", info->phy_id, j);
} else {
printk(KERN_NOTICE " No MII transceivers found!\n");
}
return; return;
cs_failed: cs_failed:
......
...@@ -141,7 +141,6 @@ static dev_link_t *dev_list; ...@@ -141,7 +141,6 @@ static dev_link_t *dev_list;
typedef struct com20020_dev_t { typedef struct com20020_dev_t {
struct net_device *dev; struct net_device *dev;
int dev_configured;
dev_node_t node; dev_node_t node;
} com20020_dev_t; } com20020_dev_t;
...@@ -277,13 +276,10 @@ static void com20020_detach(dev_link_t *link) ...@@ -277,13 +276,10 @@ static void com20020_detach(dev_link_t *link)
dev = info->dev; dev = info->dev;
if (dev) if (dev)
{ {
if (info->dev_configured) if (link->dev)
{ {
DEBUG(1,"unregister...\n"); DEBUG(1,"unregister...\n");
if (netif_running(dev))
dev->stop(dev);
unregister_netdev(dev); unregister_netdev(dev);
/* /*
...@@ -398,17 +394,18 @@ static void com20020_config(dev_link_t *link) ...@@ -398,17 +394,18 @@ static void com20020_config(dev_link_t *link)
lp->card_name = "PCMCIA COM20020"; lp->card_name = "PCMCIA COM20020";
lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
i = com20020_found(dev, 0); /* calls register_netdev */ i = com20020_found(dev, 0); /* calls register_netdev */
if (i != 0) { if (i != 0) {
DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n");
link->dev = NULL;
goto failed; goto failed;
} }
info->dev_configured = 1;
strcpy(info->node.dev_name, dev->name); strcpy(info->node.dev_name, dev->name);
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n",
dev->name, dev->base_addr, dev->irq); dev->name, dev->base_addr, dev->irq);
......
...@@ -510,10 +510,6 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -510,10 +510,6 @@ static void fmvj18x_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
dev->irq = link->irq.AssignedIRQ; dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1; dev->base_addr = link->io.BasePort1;
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
goto failed;
}
if (link->io.BasePort2 != 0) if (link->io.BasePort2 != 0)
fmvj18x_setup_mfc(link); fmvj18x_setup_mfc(link);
...@@ -575,7 +571,6 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -575,7 +571,6 @@ static void fmvj18x_config(dev_link_t *link)
/* Read MACID from Buggy CIS */ /* Read MACID from Buggy CIS */
if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) { if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) {
printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n"); printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n");
unregister_netdev(dev);
goto failed; goto failed;
} }
for (i = 0 ; i < 6; i++) { for (i = 0 ; i < 6; i++) {
...@@ -592,10 +587,18 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -592,10 +587,18 @@ static void fmvj18x_config(dev_link_t *link)
break; break;
} }
strcpy(lp->node.dev_name, dev->name); lp->cardtype = cardtype;
link->dev = &lp->node; link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING;
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
link->dev = NULL;
goto failed;
}
strcpy(lp->node.dev_name, dev->name);
lp->cardtype = cardtype;
/* print current configuration */ /* print current configuration */
printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ", printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ",
dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
...@@ -603,7 +606,6 @@ static void fmvj18x_config(dev_link_t *link) ...@@ -603,7 +606,6 @@ static void fmvj18x_config(dev_link_t *link)
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
link->state &= ~DEV_CONFIG_PENDING;
return; return;
cs_failed: cs_failed:
......
...@@ -317,13 +317,10 @@ static void ibmtr_config(dev_link_t *link) ...@@ -317,13 +317,10 @@ static void ibmtr_config(dev_link_t *link)
/* Try PRIMARY card at 0xA20-0xA23 */ /* Try PRIMARY card at 0xA20-0xA23 */
link->io.BasePort1 = 0xA20; link->io.BasePort1 = 0xA20;
i = pcmcia_request_io(link->handle, &link->io); i = pcmcia_request_io(link->handle, &link->io);
if (i == CS_SUCCESS) { if (i != CS_SUCCESS) {
memcpy(info->node.dev_name, "tr0\0", 4);
} else {
/* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */
link->io.BasePort1 = 0xA24; link->io.BasePort1 = 0xA24;
CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
memcpy(info->node.dev_name, "tr1\0", 4);
} }
dev->base_addr = link->io.BasePort1; dev->base_addr = link->io.BasePort1;
...@@ -367,15 +364,17 @@ static void ibmtr_config(dev_link_t *link) ...@@ -367,15 +364,17 @@ static void ibmtr_config(dev_link_t *link)
Adapters Technical Reference" SC30-3585 for this info. */ Adapters Technical Reference" SC30-3585 for this info. */
ibmtr_hw_setup(dev, mmiobase); ibmtr_hw_setup(dev, mmiobase);
link->dev = &info->node;
link->state &= ~DEV_CONFIG_PENDING;
i = ibmtr_probe_card(dev); i = ibmtr_probe_card(dev);
if (i != 0) { if (i != 0) {
printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n"); printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
link->dev = NULL;
goto failed; goto failed;
} }
link->dev = &info->node; strcpy(info->node.dev_name, dev->name);
link->state &= ~DEV_CONFIG_PENDING;
printk(KERN_INFO "%s: port %#3lx, irq %d,", printk(KERN_INFO "%s: port %#3lx, irq %d,",
dev->name, dev->base_addr, dev->irq); dev->name, dev->base_addr, dev->irq);
......
...@@ -734,11 +734,6 @@ static void nmclan_config(dev_link_t *link) ...@@ -734,11 +734,6 @@ static void nmclan_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
dev->irq = link->irq.AssignedIRQ; dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1; dev->base_addr = link->io.BasePort1;
i = register_netdev(dev);
if (i != 0) {
printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
goto failed;
}
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
...@@ -777,10 +772,18 @@ static void nmclan_config(dev_link_t *link) ...@@ -777,10 +772,18 @@ static void nmclan_config(dev_link_t *link)
else else
printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n"); printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
strcpy(lp->node.dev_name, dev->name);
link->dev = &lp->node; link->dev = &lp->node;
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
i = register_netdev(dev);
if (i != 0) {
printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
link->dev = NULL;
goto failed;
}
strcpy(lp->node.dev_name, dev->name);
printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port, hw_addr ", printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port, hw_addr ",
dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]); dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
......
...@@ -901,6 +901,7 @@ static void smc91c92_config(dev_link_t *link) ...@@ -901,6 +901,7 @@ static void smc91c92_config(dev_link_t *link)
char *name; char *name;
int i, j, rev; int i, j, rev;
ioaddr_t ioaddr; ioaddr_t ioaddr;
u_long mir;
DEBUG(0, "smc91c92_config(0x%p)\n", link); DEBUG(0, "smc91c92_config(0x%p)\n", link);
...@@ -952,11 +953,6 @@ static void smc91c92_config(dev_link_t *link) ...@@ -952,11 +953,6 @@ static void smc91c92_config(dev_link_t *link)
else else
printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n"); printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
goto config_undo;
}
switch (smc->manfid) { switch (smc->manfid) {
case MANFID_OSITECH: case MANFID_OSITECH:
case MANFID_PSION: case MANFID_PSION:
...@@ -977,8 +973,6 @@ static void smc91c92_config(dev_link_t *link) ...@@ -977,8 +973,6 @@ static void smc91c92_config(dev_link_t *link)
goto config_undo; goto config_undo;
} }
strcpy(smc->node.dev_name, dev->name);
link->dev = &smc->node;
smc->duplex = 0; smc->duplex = 0;
smc->rx_ovrn = 0; smc->rx_ovrn = 0;
...@@ -993,25 +987,16 @@ static void smc91c92_config(dev_link_t *link) ...@@ -993,25 +987,16 @@ static void smc91c92_config(dev_link_t *link)
case 8: name = "100-FD"; break; case 8: name = "100-FD"; break;
case 9: name = "110"; break; case 9: name = "110"; break;
} }
printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
"hw_addr ", dev->name, name, (rev & 0x0f), dev->base_addr,
dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
if (rev > 0) { if (rev > 0) {
u_long mir, mcr; u_long mcr;
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
mir = inw(ioaddr + MEMINFO) & 0xff; mir = inw(ioaddr + MEMINFO) & 0xff;
if (mir == 0xff) mir++; if (mir == 0xff) mir++;
/* Get scale factor for memory size */ /* Get scale factor for memory size */
mcr = ((rev >> 4) > 3) ? inw(ioaddr + MEMCFG) : 0x0200; mcr = ((rev >> 4) > 3) ? inw(ioaddr + MEMCFG) : 0x0200;
mir *= 128 * (1<<((mcr >> 9) & 7)); mir *= 128 * (1<<((mcr >> 9) & 7));
if (mir & 0x3ff)
printk(KERN_INFO " %lu byte", mir);
else
printk(KERN_INFO " %lu kb", mir>>10);
SMC_SELECT_BANK(1); SMC_SELECT_BANK(1);
smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT; smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;
smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC; smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC;
...@@ -1019,9 +1004,8 @@ static void smc91c92_config(dev_link_t *link) ...@@ -1019,9 +1004,8 @@ static void smc91c92_config(dev_link_t *link)
smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0; smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0;
if ((rev >> 4) >= 7) if ((rev >> 4) >= 7)
smc->cfg |= CFG_MII_SELECT; smc->cfg |= CFG_MII_SELECT;
printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ? } else
"MII" : if_names[dev->if_port]); mir = 0;
}
if (smc->cfg & CFG_MII_SELECT) { if (smc->cfg & CFG_MII_SELECT) {
SMC_SELECT_BANK(3); SMC_SELECT_BANK(3);
...@@ -1031,16 +1015,45 @@ static void smc91c92_config(dev_link_t *link) ...@@ -1031,16 +1015,45 @@ static void smc91c92_config(dev_link_t *link)
if ((j != 0) && (j != 0xffff)) break; if ((j != 0) && (j != 0xffff)) break;
} }
smc->mii_if.phy_id = (i < 32) ? i : -1; smc->mii_if.phy_id = (i < 32) ? i : -1;
if (i < 32) {
DEBUG(0, " MII transceiver at index %d, status %x.\n", i, j);
} else {
printk(KERN_NOTICE " No MII transceivers found!\n");
}
SMC_SELECT_BANK(0); SMC_SELECT_BANK(0);
} }
link->dev = &smc->node;
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
link->dev = NULL;
goto config_undo;
}
strcpy(smc->node.dev_name, dev->name);
printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
"hw_addr ", dev->name, name, (rev & 0x0f), dev->base_addr,
dev->irq);
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
if (rev > 0) {
if (mir & 0x3ff)
printk(KERN_INFO " %lu byte", mir);
else
printk(KERN_INFO " %lu kb", mir>>10);
printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?
"MII" : if_names[dev->if_port]);
}
if (smc->cfg & CFG_MII_SELECT) {
if (smc->mii_if.phy_id != -1) {
DEBUG(0, " MII transceiver at index %d, status %x.\n",
smc->mii_if.phy_id, j);
} else {
printk(KERN_NOTICE " No MII transceivers found!\n");
}
}
return; return;
config_undo: config_undo:
......
...@@ -1114,17 +1114,20 @@ xirc2ps_config(dev_link_t * link) ...@@ -1114,17 +1114,20 @@ xirc2ps_config(dev_link_t * link)
/* we can now register the device with the net subsystem */ /* we can now register the device with the net subsystem */
dev->irq = link->irq.AssignedIRQ; dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1; dev->base_addr = link->io.BasePort1;
if (local->dingo)
do_reset(dev, 1); /* a kludge to make the cem56 work */
link->dev = &local->node;
link->state &= ~DEV_CONFIG_PENDING;
if ((err=register_netdev(dev))) { if ((err=register_netdev(dev))) {
printk(KNOT_XIRC "register_netdev() failed\n"); printk(KNOT_XIRC "register_netdev() failed\n");
link->dev = NULL;
goto config_error; goto config_error;
} }
strcpy(local->node.dev_name, dev->name); strcpy(local->node.dev_name, dev->name);
link->dev = &local->node;
link->state &= ~DEV_CONFIG_PENDING;
if (local->dingo)
do_reset(dev, 1); /* a kludge to make the cem56 work */
/* give some infos about the hardware */ /* give some infos about the hardware */
printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr", printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr",
......
...@@ -1761,11 +1761,11 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev) ...@@ -1761,11 +1761,11 @@ static void __devexit tulip_remove_one (struct pci_dev *pdev)
return; return;
tp = netdev_priv(dev); tp = netdev_priv(dev);
unregister_netdev(dev);
pci_free_consistent (pdev, pci_free_consistent (pdev,
sizeof (struct tulip_rx_desc) * RX_RING_SIZE + sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
sizeof (struct tulip_tx_desc) * TX_RING_SIZE, sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
tp->rx_ring, tp->rx_ring_dma); tp->rx_ring, tp->rx_ring_dma);
unregister_netdev (dev);
if (tp->mtable) if (tp->mtable)
kfree (tp->mtable); kfree (tp->mtable);
#ifndef USE_IO_OPS #ifndef USE_IO_OPS
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Driver for Atmel at76c502 at76c504 and at76c506 wireless cards. Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
Copyright 2000-2001 ATMEL Corporation. Copyright 2000-2001 ATMEL Corporation.
Copyright 2003 Simon Kelley. Copyright 2003-2004 Simon Kelley.
This code was developed from version 2.1.1 of the Atmel drivers, This code was developed from version 2.1.1 of the Atmel drivers,
released by Atmel corp. under the GPL in December 2002. It also released by Atmel corp. under the GPL in December 2002. It also
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ctype.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -70,7 +71,7 @@ ...@@ -70,7 +71,7 @@
#include "ieee802_11.h" #include "ieee802_11.h"
#define DRIVER_MAJOR 0 #define DRIVER_MAJOR 0
#define DRIVER_MINOR 91 #define DRIVER_MINOR 96
MODULE_AUTHOR("Simon Kelley"); MODULE_AUTHOR("Simon Kelley");
MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards."); MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
...@@ -519,7 +520,6 @@ struct atmel_private { ...@@ -519,7 +520,6 @@ struct atmel_private {
} host_info; } host_info;
enum { enum {
STATION_STATE_INITIALIZING,
STATION_STATE_SCANNING, STATION_STATE_SCANNING,
STATION_STATE_JOINNING, STATION_STATE_JOINNING,
STATION_STATE_AUTHENTICATING, STATION_STATE_AUTHENTICATING,
...@@ -527,15 +527,14 @@ struct atmel_private { ...@@ -527,15 +527,14 @@ struct atmel_private {
STATION_STATE_READY, STATION_STATE_READY,
STATION_STATE_REASSOCIATING, STATION_STATE_REASSOCIATING,
STATION_STATE_DOWN, STATION_STATE_DOWN,
STATION_STATE_NO_CARD, STATION_STATE_MGMT_ERROR
STATION_STATE_MGMT_ERROR
} station_state; } station_state;
int operating_mode, power_mode; int operating_mode, power_mode;
time_t last_qual; time_t last_qual;
int beacons_this_sec; int beacons_this_sec;
int channel; int channel;
int reg_domain; int reg_domain, config_reg_domain;
int tx_rate; int tx_rate;
int auto_tx_rate; int auto_tx_rate;
int rts_threshold; int rts_threshold;
...@@ -578,6 +577,19 @@ struct atmel_private { ...@@ -578,6 +577,19 @@ struct atmel_private {
static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16}; static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
static const struct {
int reg_domain;
int min, max;
char *name;
} channel_table[] = { { REG_DOMAIN_FCC, 1, 11, "USA" },
{ REG_DOMAIN_DOC, 1, 11, "Canada" },
{ REG_DOMAIN_ETSI, 1, 13, "Europe" },
{ REG_DOMAIN_SPAIN, 10, 11, "Spain" },
{ REG_DOMAIN_FRANCE, 10, 13, "France" },
{ REG_DOMAIN_MKK, 14, 14, "MKK" },
{ REG_DOMAIN_MKK1, 1, 14, "MKK1" },
{ REG_DOMAIN_ISRAEL, 3, 9, "Israel"} };
static void build_wpa_mib(struct atmel_private *priv); static void build_wpa_mib(struct atmel_private *priv);
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len); static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len);
...@@ -606,8 +618,9 @@ static void atmel_join_bss(struct atmel_private *priv, int bss_index); ...@@ -606,8 +618,9 @@ static void atmel_join_bss(struct atmel_private *priv, int bss_index);
static void atmel_smooth_qual(struct atmel_private *priv); static void atmel_smooth_qual(struct atmel_private *priv);
static void atmel_writeAR(struct net_device *dev, u16 data); static void atmel_writeAR(struct net_device *dev, u16 data);
static int probe_atmel_card(struct net_device *dev); static int probe_atmel_card(struct net_device *dev);
int reset_atmel_card(struct net_device *dev ); static int reset_atmel_card(struct net_device *dev );
static void atmel_enter_state(struct atmel_private *priv, int new_state); static void atmel_enter_state(struct atmel_private *priv, int new_state);
int atmel_open (struct net_device *dev);
static inline u16 atmel_hi(struct atmel_private *priv, u16 offset) static inline u16 atmel_hi(struct atmel_private *priv, u16 offset)
{ {
...@@ -649,7 +662,6 @@ static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data) ...@@ -649,7 +662,6 @@ static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
outw(data, dev->base_addr + offset); outw(data, dev->base_addr + offset);
} }
static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos) static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
{ {
atmel_writeAR(priv->dev, pos); atmel_writeAR(priv->dev, pos);
...@@ -802,14 +814,14 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -802,14 +814,14 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
if (priv->station_state != STATION_STATE_READY) { if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) {
priv->stats.tx_errors++; priv->stats.tx_errors++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
} }
if (priv->card && priv->present_callback && if (priv->station_state != STATION_STATE_READY) {
!(*priv->present_callback)(priv->card)) {
priv->stats.tx_errors++; priv->stats.tx_errors++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
...@@ -872,8 +884,8 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev) ...@@ -872,8 +884,8 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
} }
static void atmel_transmit_management_frame(struct atmel_private *priv, static void atmel_transmit_management_frame(struct atmel_private *priv,
struct ieee802_11_hdr *header, struct ieee802_11_hdr *header,
u8 *body, int body_len) u8 *body, int body_len)
{ {
u16 buff; u16 buff;
int len = MGMT_FRAME_BODY_OFFSET + body_len; int len = MGMT_FRAME_BODY_OFFSET + body_len;
...@@ -1153,82 +1165,112 @@ static void rx_done_irq(struct atmel_private *priv) ...@@ -1153,82 +1165,112 @@ static void rx_done_irq(struct atmel_private *priv)
} }
} }
static void reset_irq_status(struct atmel_private *priv, u8 mask)
{
u8 isr;
atmel_lock_mac(priv);
isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
isr ^= mask;
atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
}
static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = (struct net_device *) dev_id; struct net_device *dev = (struct net_device *) dev_id;
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
u8 isr; u8 isr;
int i = -1;
static u8 irq_order[] = {
ISR_OUT_OF_RANGE,
ISR_RxCOMPLETE,
ISR_TxCOMPLETE,
ISR_RxFRAMELOST,
ISR_FATAL_ERROR,
ISR_COMMAND_COMPLETE,
ISR_IBSS_MERGE,
ISR_GENERIC_IRQ
};
if (priv->card && priv->present_callback && if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) !(*priv->present_callback)(priv->card))
return IRQ_HANDLED; return IRQ_HANDLED;
/* In this state upper-level code assumes it can mess with
the card unhampered by interrupts which may change register state.
Note that even though the card shouldn't generate interrupts
the inturrupt line may be shared. This allows card setup
to go on without disabling interrupts for a long time. */
if (priv->station_state == STATION_STATE_DOWN)
return IRQ_NONE;
atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */ atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
while (1) { while (1) {
if (!atmel_lock_mac(priv)) { if (!atmel_lock_mac(priv)) {
printk(KERN_ALERT "%s: MAC gone away in ISR.\n", dev->name); /* failed to contact card */
/* bad things - don't re-enable interrupts */ printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET)); isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0); atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
if (isr)
atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */ if (!isr) {
else atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
break; /* no pending irqs */ return i == -1 ? IRQ_NONE : IRQ_HANDLED;
}
if (isr & ISR_OUT_OF_RANGE) {
reset_irq_status(priv, ISR_OUT_OF_RANGE); atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
if(priv->operating_mode == IW_MODE_INFRA &&
priv->station_state == STATION_STATE_READY) { for (i = 0; i < sizeof(irq_order)/sizeof(u8); i++)
if (isr & irq_order[i])
break;
if (!atmel_lock_mac(priv)) {
/* failed to contact card */
printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
return IRQ_HANDLED;
}
isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
isr ^= irq_order[i];
atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
switch (irq_order[i]) {
case ISR_OUT_OF_RANGE:
if (priv->operating_mode == IW_MODE_INFRA &&
priv->station_state == STATION_STATE_READY) {
priv->station_is_associated = 0; priv->station_is_associated = 0;
atmel_scan(priv, 1); atmel_scan(priv, 1);
} }
} else if (isr & ISR_RxCOMPLETE) { break;
reset_irq_status(priv, ISR_RxCOMPLETE);
case ISR_RxFRAMELOST:
priv->wstats.discard.misc++;
/* fall through */
case ISR_RxCOMPLETE:
rx_done_irq(priv); rx_done_irq(priv);
} else if (isr & ISR_TxCOMPLETE) { break;
reset_irq_status(priv, ISR_TxCOMPLETE);
case ISR_TxCOMPLETE:
tx_done_irq(priv); tx_done_irq(priv);
} else if (isr & ISR_RxFRAMELOST) { break;
reset_irq_status(priv, ISR_RxFRAMELOST);
priv->wstats.discard.misc++; case ISR_FATAL_ERROR:
rx_done_irq(priv);
} else if (isr & ISR_FATAL_ERROR) {
reset_irq_status(priv, ISR_FATAL_ERROR);
printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name); printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
} else if (isr & ISR_COMMAND_COMPLETE) { break;
reset_irq_status(priv, ISR_COMMAND_COMPLETE);
atmel_command_irq(priv); case ISR_COMMAND_COMPLETE:
} else if (isr & ISR_IBSS_MERGE) { atmel_command_irq(priv);
reset_irq_status(priv, ISR_IBSS_MERGE); break;
case ISR_IBSS_MERGE:
atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS, atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
priv->CurrentBSSID, 6); priv->CurrentBSSID, 6);
/* The WPA stuff cares about the current AP address */ /* The WPA stuff cares about the current AP address */
if (priv->use_wpa) if (priv->use_wpa)
build_wpa_mib(priv); build_wpa_mib(priv);
} else if (isr & ISR_GENERIC_IRQ) { break;
reset_irq_status(priv, ISR_GENERIC_IRQ); case ISR_GENERIC_IRQ:
printk(KERN_INFO "%s: Generic_irq recieved.\n", dev->name); printk(KERN_INFO "%s: Generic_irq recieved.\n", dev->name);
break;
} }
} }
atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
return IRQ_HANDLED;
} }
...@@ -1256,8 +1298,8 @@ static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev) ...@@ -1256,8 +1298,8 @@ static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
priv->wstats.qual.noise = 0; priv->wstats.qual.noise = 0;
priv->wstats.qual.updated = 7; priv->wstats.qual.updated = 7;
} else { } else {
// Quality levels cannot be determined in ad-hoc mode, /* Quality levels cannot be determined in ad-hoc mode,
// because we can 'hear' more that one remote station. because we can 'hear' more that one remote station. */
priv->wstats.qual.qual = 0; priv->wstats.qual.qual = 0;
priv->wstats.qual.level = 0; priv->wstats.qual.level = 0;
priv->wstats.qual.noise = 0; priv->wstats.qual.noise = 0;
...@@ -1281,18 +1323,62 @@ static int atmel_set_mac_address(struct net_device *dev, void *p) ...@@ -1281,18 +1323,62 @@ static int atmel_set_mac_address(struct net_device *dev, void *p)
struct sockaddr *addr = p; struct sockaddr *addr = p;
memcpy (dev->dev_addr, addr->sa_data, dev->addr_len); memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
reset_atmel_card(dev); return atmel_open(dev);
return 0;
} }
static int atmel_open (struct net_device *dev) EXPORT_SYMBOL(atmel_open);
int atmel_open (struct net_device *dev)
{ {
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
priv->station_state = STATION_STATE_INITIALIZING; int i, channel;
if (!reset_atmel_card(dev)) {
priv->station_state = STATION_STATE_DOWN; /* any scheduled timer is no longer needed and might screw things up.. */
del_timer_sync(&priv->management_timer);
/* Interrupts will not touch the card once in this state... */
priv->station_state = STATION_STATE_DOWN;
if (priv->new_SSID_size) {
memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size);
priv->SSID_size = priv->new_SSID_size;
priv->new_SSID_size = 0;
}
priv->BSS_list_entries = 0;
priv->AuthenticationRequestRetryCnt = 0;
priv->AssociationRequestRetryCnt = 0;
priv->ReAssociationRequestRetryCnt = 0;
priv->CurrentAuthentTransactionSeqNum = 0x0001;
priv->ExpectedAuthentTransactionSeqNum = 0x0002;
priv->site_survey_state = SITE_SURVEY_IDLE;
priv->station_is_associated = 0;
if (!reset_atmel_card(dev))
return -EAGAIN; return -EAGAIN;
if (priv->config_reg_domain) {
priv->reg_domain = priv->config_reg_domain;
atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS, priv->reg_domain);
} else {
priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
if (priv->reg_domain == channel_table[i].reg_domain)
break;
if (i == sizeof(channel_table)/sizeof(channel_table[0])) {
priv->reg_domain = REG_DOMAIN_MKK1;
printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
}
} }
if ((channel = atmel_validate_channel(priv, priv->channel)))
priv->channel = channel;
/* this moves station_state on.... */
atmel_scan(priv, 1);
atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
return 0; return 0;
} }
...@@ -1300,19 +1386,34 @@ static int atmel_close (struct net_device *dev) ...@@ -1300,19 +1386,34 @@ static int atmel_close (struct net_device *dev)
{ {
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
netif_carrier_off(dev); atmel_enter_state(priv, STATION_STATE_DOWN);
if (netif_running(dev))
netif_stop_queue(dev);
priv->station_state = STATION_STATE_DOWN;
if (priv->bus_type == BUS_TYPE_PCCARD) if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060); atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040); atmel_write16(dev, GCR, 0x0040);
return 0; return 0;
} }
static int atmel_validate_channel(struct atmel_private *priv, int channel)
{
/* check that channel is OK, if so return zero,
else return suitable default channel */
int i;
for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
if (priv->reg_domain == channel_table[i].reg_domain) {
if (channel >= channel_table[i].min &&
channel <= channel_table[i].max)
return 0;
else
return channel_table[i].min;
}
return 0;
}
static int atmel_proc_output (char *buf, struct atmel_private *priv) static int atmel_proc_output (char *buf, struct atmel_private *priv)
{ {
int i;
char *p = buf; char *p = buf;
char *s, *r, *c; char *s, *r, *c;
...@@ -1338,17 +1439,12 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) ...@@ -1338,17 +1439,12 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
default: c = "<unknown>"; default: c = "<unknown>";
} }
switch (priv->reg_domain) {
case REG_DOMAIN_FCC: r = "USA"; break; r = "<unknown>";
case REG_DOMAIN_DOC: r = "Canada"; break; for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
case REG_DOMAIN_ETSI: r = "Europe"; break; if (priv->reg_domain == channel_table[i].reg_domain)
case REG_DOMAIN_SPAIN: r = "Spain"; break; r = channel_table[i].name;
case REG_DOMAIN_FRANCE: r = "France"; break;
case REG_DOMAIN_MKK: r = "Japan (MKK)"; break;
case REG_DOMAIN_MKK1: r = "Japan (MKK1)"; break;
case REG_DOMAIN_ISRAEL: r = "Israel"; break;
default: r = "<unknown>";
}
p += sprintf(p, "MAC memory type:\t%s\n", c); p += sprintf(p, "MAC memory type:\t%s\n", c);
p += sprintf(p, "Regulatory domain:\t%s\n", r); p += sprintf(p, "Regulatory domain:\t%s\n", r);
p += sprintf(p, "Host CRC checking:\t%s\n", p += sprintf(p, "Host CRC checking:\t%s\n",
...@@ -1358,14 +1454,12 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) ...@@ -1358,14 +1454,12 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
} }
switch(priv->station_state) { switch(priv->station_state) {
case STATION_STATE_INITIALIZING: s = "Initialising"; break;
case STATION_STATE_SCANNING: s = "Scanning"; break; case STATION_STATE_SCANNING: s = "Scanning"; break;
case STATION_STATE_JOINNING: s = "Joining"; break; case STATION_STATE_JOINNING: s = "Joining"; break;
case STATION_STATE_AUTHENTICATING: s = "Authenticating"; break; case STATION_STATE_AUTHENTICATING: s = "Authenticating"; break;
case STATION_STATE_ASSOCIATING: s = "Associating"; break; case STATION_STATE_ASSOCIATING: s = "Associating"; break;
case STATION_STATE_READY: s = "Ready"; break; case STATION_STATE_READY: s = "Ready"; break;
case STATION_STATE_REASSOCIATING: s = "Reassociating"; break; case STATION_STATE_REASSOCIATING: s = "Reassociating"; break;
case STATION_STATE_NO_CARD: s = "No card"; break;
case STATION_STATE_MGMT_ERROR: s = "Management error"; break; case STATION_STATE_MGMT_ERROR: s = "Management error"; break;
case STATION_STATE_DOWN: s = "Down"; break; case STATION_STATE_DOWN: s = "Down"; break;
default: s = "<unknown>"; default: s = "<unknown>";
...@@ -1441,6 +1535,8 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware ...@@ -1441,6 +1535,8 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware
priv->preamble = LONG_PREAMBLE; priv->preamble = LONG_PREAMBLE;
priv->operating_mode = IW_MODE_INFRA; priv->operating_mode = IW_MODE_INFRA;
priv->connect_to_any_BSS = 0; priv->connect_to_any_BSS = 0;
priv->config_reg_domain = 0;
priv->reg_domain = 0;
priv->tx_rate = 3; priv->tx_rate = 3;
priv->auto_tx_rate = 1; priv->auto_tx_rate = 1;
priv->channel = 4; priv->channel = 4;
...@@ -1547,36 +1643,6 @@ void stop_atmel_card(struct net_device *dev, int freeres) ...@@ -1547,36 +1643,6 @@ void stop_atmel_card(struct net_device *dev, int freeres)
EXPORT_SYMBOL(stop_atmel_card); EXPORT_SYMBOL(stop_atmel_card);
static const struct {
int reg_domain;
int min, max;
} channel_table[] = { { REG_DOMAIN_FCC, 1, 11},
{ REG_DOMAIN_DOC, 1, 11},
{ REG_DOMAIN_ETSI, 1, 13},
{ REG_DOMAIN_SPAIN, 10, 11},
{ REG_DOMAIN_FRANCE, 10, 13},
{ REG_DOMAIN_MKK, 14, 14},
{ REG_DOMAIN_MKK1, 1, 14},
{ REG_DOMAIN_ISRAEL, 9} };
static int atmel_validate_channel(struct atmel_private *priv, int channel)
{
/* check that channel is OK, if so return zero,
else return suitable default channel */
int i;
for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
if (priv->reg_domain == channel_table[i].reg_domain) {
if (channel >= channel_table[i].min &&
channel <= channel_table[i].max)
return 0;
else
return channel_table[i].min;
}
return 1;
}
static int atmel_set_essid(struct net_device *dev, static int atmel_set_essid(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,
struct iw_point *dwrq, struct iw_point *dwrq,
...@@ -1613,7 +1679,7 @@ static int atmel_get_essid(struct net_device *dev, ...@@ -1613,7 +1679,7 @@ static int atmel_get_essid(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
/* Get the current SSID */ /* Get the current SSID */
if (priv->SSID_size == 0) { if (priv->new_SSID_size != 0) {
memcpy(extra, priv->new_SSID, priv->new_SSID_size); memcpy(extra, priv->new_SSID, priv->new_SSID_size);
extra[priv->new_SSID_size] = '\0'; extra[priv->new_SSID_size] = '\0';
dwrq->length = priv->new_SSID_size + 1; dwrq->length = priv->new_SSID_size + 1;
...@@ -2037,6 +2103,7 @@ static int atmel_set_scan(struct net_device *dev, ...@@ -2037,6 +2103,7 @@ static int atmel_set_scan(struct net_device *dev,
char *extra) char *extra)
{ {
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
unsigned long flags;
/* Note : you may have realised that, as this is a SET operation, /* Note : you may have realised that, as this is a SET operation,
* this is privileged and therefore a normal user can't * this is privileged and therefore a normal user can't
...@@ -2045,8 +2112,7 @@ static int atmel_set_scan(struct net_device *dev, ...@@ -2045,8 +2112,7 @@ static int atmel_set_scan(struct net_device *dev,
* traffic doesn't flow, so it's a perfect DoS... * traffic doesn't flow, so it's a perfect DoS...
* Jean II */ * Jean II */
if (priv->station_state == STATION_STATE_DOWN || if (priv->station_state == STATION_STATE_DOWN)
priv->station_state == STATION_STATE_NO_CARD)
return -EAGAIN; return -EAGAIN;
/* Timeout old surveys. */ /* Timeout old surveys. */
...@@ -2057,14 +2123,14 @@ static int atmel_set_scan(struct net_device *dev, ...@@ -2057,14 +2123,14 @@ static int atmel_set_scan(struct net_device *dev,
/* Initiate a scan command */ /* Initiate a scan command */
if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS) if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
return -EBUSY; return -EBUSY;
del_timer_sync(&priv->management_timer);
spin_lock_irqsave(&priv->irqlock, flags);
priv->site_survey_state = SITE_SURVEY_IN_PROGRESS; priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
del_timer_sync(&priv->management_timer);
priv->fast_scan = 0; priv->fast_scan = 0;
atmel_scan(priv, 0); atmel_scan(priv, 0);
atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */ spin_unlock_irqrestore(&priv->irqlock, flags);
return 0; return 0;
} }
...@@ -2116,7 +2182,7 @@ static int atmel_get_scan(struct net_device *dev, ...@@ -2116,7 +2182,7 @@ static int atmel_get_scan(struct net_device *dev,
/* Length of data */ /* Length of data */
dwrq->length = (current_ev - extra); dwrq->length = (current_ev - extra);
dwrq->flags = 0; /* todo */ dwrq->flags = 0;
return 0; return 0;
} }
...@@ -2196,15 +2262,16 @@ static int atmel_set_wap(struct net_device *dev, ...@@ -2196,15 +2262,16 @@ static int atmel_set_wap(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
int i; int i;
static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 }; static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 };
unsigned long flags;
if (awrq->sa_family != ARPHRD_ETHER) if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL; return -EINVAL;
if (memcmp(bcast, awrq->sa_data, 6) == 0) { if (memcmp(bcast, awrq->sa_data, 6) == 0) {
atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
del_timer_sync(&priv->management_timer); del_timer_sync(&priv->management_timer);
spin_lock_irqsave(&priv->irqlock, flags);
atmel_scan(priv, 1); atmel_scan(priv, 1);
atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */ spin_unlock_irqrestore(&priv->irqlock, flags);
return 0; return 0;
} }
...@@ -2214,9 +2281,13 @@ static int atmel_set_wap(struct net_device *dev, ...@@ -2214,9 +2281,13 @@ static int atmel_set_wap(struct net_device *dev,
return -EINVAL; return -EINVAL;
} else if (priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) { } else if (priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) {
return -EINVAL; return -EINVAL;
} else } else {
atmel_join_bss(priv, i); del_timer_sync(&priv->management_timer);
return 0; spin_lock_irqsave(&priv->irqlock, flags);
atmel_join_bss(priv, i);
spin_unlock_irqrestore(&priv->irqlock, flags);
return 0;
}
} }
} }
...@@ -2228,8 +2299,7 @@ static int atmel_config_commit(struct net_device *dev, ...@@ -2228,8 +2299,7 @@ static int atmel_config_commit(struct net_device *dev,
void *zwrq, /* NULL */ void *zwrq, /* NULL */
char *extra) /* NULL */ char *extra) /* NULL */
{ {
reset_atmel_card(dev); return atmel_open(dev);
return 0;
} }
static const iw_handler atmel_handler[] = static const iw_handler atmel_handler[] =
...@@ -2297,12 +2367,15 @@ typedef struct atmel_priv_ioctl { ...@@ -2297,12 +2367,15 @@ typedef struct atmel_priv_ioctl {
#define ATMELFWL SIOCIWFIRSTPRIV #define ATMELFWL SIOCIWFIRSTPRIV
#define ATMELIDIFC ATMELFWL + 1 #define ATMELIDIFC ATMELFWL + 1
#define ATMELRD ATMELFWL + 2
#define ATMELMAGIC 0x51807 #define ATMELMAGIC 0x51807
#define REGDOMAINSZ 20
static const struct iw_priv_args atmel_private_args[] = { static const struct iw_priv_args atmel_private_args[] = {
/*{ cmd, set_args, get_args, name } */ /*{ cmd, set_args, get_args, name } */
{ ATMELFWL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (atmel_priv_ioctl), IW_PRIV_TYPE_NONE, "atmelfwl" }, { ATMELFWL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (atmel_priv_ioctl), IW_PRIV_TYPE_NONE, "atmelfwl" },
{ ATMELIDIFC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "atmelidifc" }, { ATMELIDIFC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "atmelidifc" },
{ ATMELRD, IW_PRIV_TYPE_CHAR | REGDOMAINSZ, IW_PRIV_TYPE_NONE, "regdomain" },
}; };
static const struct iw_handler_def atmel_handler_def = static const struct iw_handler_def atmel_handler_def =
...@@ -2317,11 +2390,12 @@ static const struct iw_handler_def atmel_handler_def = ...@@ -2317,11 +2390,12 @@ static const struct iw_handler_def atmel_handler_def =
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ {
int rc = 0; int i, rc = 0;
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
atmel_priv_ioctl com; atmel_priv_ioctl com;
struct iwreq *wrq = (struct iwreq *) rq; struct iwreq *wrq = (struct iwreq *) rq;
unsigned char *new_firmware; unsigned char *new_firmware;
char domain[REGDOMAINSZ+1];
switch (cmd) { switch (cmd) {
case SIOCGIWPRIV: case SIOCGIWPRIV:
...@@ -2371,6 +2445,39 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2371,6 +2445,39 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
priv->firmware_id[31] = '\0'; priv->firmware_id[31] = '\0';
break; break;
case ATMELRD:
if (copy_from_user(domain, rq->ifr_data, REGDOMAINSZ)) {
rc = -EFAULT;
break;
}
if (!capable(CAP_NET_ADMIN)) {
rc = -EPERM;
break;
}
domain[REGDOMAINSZ] = 0;
rc = -EINVAL;
for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++) {
/* strcasecmp doesn't exist in the library */
char *a = channel_table[i].name;
char *b = domain;
while (*a) {
char c1 = *a++;
char c2 = *b++;
if (tolower(c1) != tolower(c2))
break;
}
if (!*a && !*b) {
priv->config_reg_domain = channel_table[i].reg_domain;
rc = 0;
}
}
if (rc == 0 && priv->station_state != STATION_STATE_DOWN)
rc = atmel_open(dev);
break;
default: default:
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
...@@ -2390,10 +2497,12 @@ struct auth_body { ...@@ -2390,10 +2497,12 @@ struct auth_body {
static void atmel_enter_state(struct atmel_private *priv, int new_state) static void atmel_enter_state(struct atmel_private *priv, int new_state)
{ {
int old_state = priv->station_state; int old_state = priv->station_state;
if (new_state == old_state) if (new_state == old_state)
return; return;
priv->station_state = new_state;
if (new_state == STATION_STATE_READY) { if (new_state == STATION_STATE_READY) {
netif_start_queue(priv->dev); netif_start_queue(priv->dev);
netif_carrier_on(priv->dev); netif_carrier_on(priv->dev);
...@@ -2401,12 +2510,10 @@ static void atmel_enter_state(struct atmel_private *priv, int new_state) ...@@ -2401,12 +2510,10 @@ static void atmel_enter_state(struct atmel_private *priv, int new_state)
if (old_state == STATION_STATE_READY) { if (old_state == STATION_STATE_READY) {
netif_carrier_off(priv->dev); netif_carrier_off(priv->dev);
netif_stop_queue(priv->dev); if (netif_running(priv->dev))
netif_stop_queue(priv->dev);
priv->last_beacon_timestamp = 0; priv->last_beacon_timestamp = 0;
} }
priv->station_state = new_state;
} }
static void atmel_scan(struct atmel_private *priv, int specific_ssid) static void atmel_scan(struct atmel_private *priv, int specific_ssid)
...@@ -2423,8 +2530,6 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid) ...@@ -2423,8 +2530,6 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
u8 SSID_size; u8 SSID_size;
} cmd; } cmd;
atmel_enter_state(priv, STATION_STATE_SCANNING);
memset(cmd.BSSID, 0xff, 6); memset(cmd.BSSID, 0xff, 6);
if (priv->fast_scan) { if (priv->fast_scan) {
...@@ -2450,6 +2555,10 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid) ...@@ -2450,6 +2555,10 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE); BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd)); atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
/* This must come after all hardware access to avoid being messed up
by stuff happening in interrupt context after we leave STATE_DOWN */
atmel_enter_state(priv, STATION_STATE_SCANNING);
} }
static void join(struct atmel_private *priv, int type) static void join(struct atmel_private *priv, int type)
...@@ -3060,16 +3169,12 @@ static void atmel_management_timer(u_long a) ...@@ -3060,16 +3169,12 @@ static void atmel_management_timer(u_long a)
if (priv->card && priv->present_callback && if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) !(*priv->present_callback)(priv->card))
return; return;
if (priv->station_state == STATION_STATE_NO_CARD)
return;
spin_lock_irqsave(&priv->irqlock, flags); spin_lock_irqsave(&priv->irqlock, flags);
switch (priv->station_state) { switch (priv->station_state) {
case STATION_STATE_AUTHENTICATING: case STATION_STATE_AUTHENTICATING:
if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) { if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0; priv->station_is_associated = 0;
...@@ -3085,7 +3190,6 @@ static void atmel_management_timer(u_long a) ...@@ -3085,7 +3190,6 @@ static void atmel_management_timer(u_long a)
break; break;
case STATION_STATE_ASSOCIATING: case STATION_STATE_ASSOCIATING:
if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) { if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0; priv->station_is_associated = 0;
...@@ -3100,7 +3204,6 @@ static void atmel_management_timer(u_long a) ...@@ -3100,7 +3204,6 @@ static void atmel_management_timer(u_long a)
break; break;
case STATION_STATE_REASSOCIATING: case STATION_STATE_REASSOCIATING:
if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) { if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0; priv->station_is_associated = 0;
...@@ -3113,7 +3216,7 @@ static void atmel_management_timer(u_long a) ...@@ -3113,7 +3216,7 @@ static void atmel_management_timer(u_long a)
} }
break; break;
default: default:
break; break;
} }
...@@ -3203,7 +3306,7 @@ static int atmel_wakeup_firmware(struct atmel_private *priv) ...@@ -3203,7 +3306,7 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
struct host_info_struct *iface = &priv->host_info; struct host_info_struct *iface = &priv->host_info;
u16 mr1, mr3; u16 mr1, mr3;
int i; int i;
if (priv->card_type == CARD_TYPE_SPI_FLASH) if (priv->card_type == CARD_TYPE_SPI_FLASH)
atmel_set_gcr(priv->dev, GCR_REMAP); atmel_set_gcr(priv->dev, GCR_REMAP);
...@@ -3233,7 +3336,6 @@ static int atmel_wakeup_firmware(struct atmel_private *priv) ...@@ -3233,7 +3336,6 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) { if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
printk(KERN_ALERT "%s: card missing.\n", priv->dev->name); printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
priv->station_state = STATION_STATE_NO_CARD;
return 0; return 0;
} }
...@@ -3271,10 +3373,10 @@ static int atmel_wakeup_firmware(struct atmel_private *priv) ...@@ -3271,10 +3373,10 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name); printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name);
return 0; return 0;
} }
atmel_copy_to_host(priv->dev, (unsigned char *)iface, atmel_copy_to_host(priv->dev, (unsigned char *)iface,
priv->host_info_base, sizeof(*iface)); priv->host_info_base, sizeof(*iface));
iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos); iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size); iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos); iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
...@@ -3323,7 +3425,6 @@ static int probe_atmel_card(struct net_device *dev) ...@@ -3323,7 +3425,6 @@ static int probe_atmel_card(struct net_device *dev)
printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name); printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name);
} else { } else {
atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6); atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
/* got address, now squash it again until the network /* got address, now squash it again until the network
interface is opened */ interface is opened */
if (priv->bus_type == BUS_TYPE_PCCARD) if (priv->bus_type == BUS_TYPE_PCCARD)
...@@ -3469,7 +3570,7 @@ static void build_wpa_mib(struct atmel_private *priv) ...@@ -3469,7 +3570,7 @@ static void build_wpa_mib(struct atmel_private *priv)
atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib)); atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
} }
int reset_atmel_card(struct net_device *dev) static int reset_atmel_card(struct net_device *dev)
{ {
/* do everything necessary to wake up the hardware, including /* do everything necessary to wake up the hardware, including
waiting for the lightning strike and throwing the knife switch.... waiting for the lightning strike and throwing the knife switch....
...@@ -3485,7 +3586,6 @@ int reset_atmel_card(struct net_device *dev) ...@@ -3485,7 +3586,6 @@ int reset_atmel_card(struct net_device *dev)
including a copy of the firmware's hostinfo stucture including a copy of the firmware's hostinfo stucture
which is the route into the rest of the firmare datastructures. */ which is the route into the rest of the firmare datastructures. */
int channel;
struct atmel_private *priv = netdev_priv(dev); struct atmel_private *priv = netdev_priv(dev);
u8 configuration; u8 configuration;
...@@ -3497,37 +3597,14 @@ int reset_atmel_card(struct net_device *dev) ...@@ -3497,37 +3597,14 @@ int reset_atmel_card(struct net_device *dev)
"", "",
NULL NULL
}; };
if (priv->station_state == STATION_STATE_NO_CARD ||
priv->station_state == STATION_STATE_DOWN)
return 0;
/* reset pccard */ /* reset pccard */
if (priv->bus_type == BUS_TYPE_PCCARD) if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(priv->dev, GCR, 0x0060); atmel_write16(priv->dev, GCR, 0x0060);
/* stop card , disable interrupts */ /* stop card , disable interrupts */
atmel_write16(priv->dev, GCR, 0x0040); atmel_write16(priv->dev, GCR, 0x0040);
/* any scheduled timer is no longer needed and might screw things up.. */
del_timer_sync(&priv->management_timer);
if (priv->new_SSID_size) {
memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size);
priv->SSID_size = priv->new_SSID_size;
priv->new_SSID_size = 0;
}
priv->BSS_list_entries = 0;
priv->AuthenticationRequestRetryCnt = 0;
priv->AssociationRequestRetryCnt = 0;
priv->ReAssociationRequestRetryCnt = 0;
priv->CurrentAuthentTransactionSeqNum = 0x0001;
priv->ExpectedAuthentTransactionSeqNum = 0x0002;
priv->station_state = STATION_STATE_INITIALIZING;
priv->site_survey_state = SITE_SURVEY_IDLE;
priv->station_is_associated = 0;
if (priv->card_type == CARD_TYPE_EEPROM) { if (priv->card_type == CARD_TYPE_EEPROM) {
/* copy in firmware if needed */ /* copy in firmware if needed */
const struct firmware *fw_entry = NULL; const struct firmware *fw_entry = NULL;
...@@ -3573,7 +3650,7 @@ int reset_atmel_card(struct net_device *dev) ...@@ -3573,7 +3650,7 @@ int reset_atmel_card(struct net_device *dev)
len = fw_entry->size; len = fw_entry->size;
} }
if (len <= 0x6000) { if (len <= 0x6000) {
atmel_write16(priv->dev, BSR, BSS_IRAM); atmel_write16(priv->dev, BSR, BSS_IRAM);
atmel_copy_to_card(priv->dev, 0, fw, len); atmel_copy_to_card(priv->dev, 0, fw, len);
atmel_set_gcr(priv->dev, GCR_REMAP); atmel_set_gcr(priv->dev, GCR_REMAP);
...@@ -3628,29 +3705,14 @@ int reset_atmel_card(struct net_device *dev) ...@@ -3628,29 +3705,14 @@ int reset_atmel_card(struct net_device *dev)
configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET)); configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
configuration | FUNC_CTRL_RxENABLE); configuration | FUNC_CTRL_RxENABLE);
priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
if (priv->reg_domain != REG_DOMAIN_FCC &&
priv->reg_domain != REG_DOMAIN_DOC &&
priv->reg_domain != REG_DOMAIN_ETSI &&
priv->reg_domain != REG_DOMAIN_SPAIN &&
priv->reg_domain != REG_DOMAIN_FRANCE &&
priv->reg_domain != REG_DOMAIN_MKK &&
priv->reg_domain != REG_DOMAIN_MKK1 &&
priv->reg_domain != REG_DOMAIN_ISRAEL) {
priv->reg_domain = REG_DOMAIN_MKK1;
printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
}
if ((channel = atmel_validate_channel(priv, priv->channel)))
priv->channel = channel;
if (!priv->radio_on_broken) { if (!priv->radio_on_broken) {
if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) == if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
CMD_STATUS_REJECTED_RADIO_OFF) { CMD_STATUS_REJECTED_RADIO_OFF) {
printk(KERN_INFO printk(KERN_INFO
"%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n", "%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n",
dev->name); dev->name);
return 0; return 0;
} }
} }
...@@ -3674,15 +3736,9 @@ int reset_atmel_card(struct net_device *dev) ...@@ -3674,15 +3736,9 @@ int reset_atmel_card(struct net_device *dev)
else else
build_wep_mib(priv); build_wep_mib(priv);
atmel_scan(priv, 1);
atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
return 1; return 1;
} }
EXPORT_SYMBOL(reset_atmel_card);
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size) static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size)
{ {
if (cmd) if (cmd)
...@@ -3698,16 +3754,17 @@ static int atmel_send_command_wait(struct atmel_private *priv, int command, void ...@@ -3698,16 +3754,17 @@ static int atmel_send_command_wait(struct atmel_private *priv, int command, void
int i, status; int i, status;
atmel_send_command(priv, command, cmd, cmd_size); atmel_send_command(priv, command, cmd, cmd_size);
for (i = LOOP_RETRY_LIMIT; i; i--) { for (i = 5000; i; i--) {
status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET)); status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
if (status != CMD_STATUS_IDLE && if (status != CMD_STATUS_IDLE &&
status != CMD_STATUS_IN_PROGRESS) status != CMD_STATUS_IN_PROGRESS)
break; break;
udelay(20);
} }
if (i == 0) { if (i == 0) {
printk(KERN_ALERT "%s: command %d failed to complete.\n", priv->dev->name, command); printk(KERN_ALERT "%s: failed to contact MAC.\n", priv->dev->name);
status = CMD_STATUS_HOST_ERROR; status = CMD_STATUS_HOST_ERROR;
} else { } else {
if (command != CMD_EnableRadio) if (command != CMD_EnableRadio)
...@@ -3835,9 +3892,13 @@ static void atmel_clear_gcr(struct net_device *dev, u16 mask) ...@@ -3835,9 +3892,13 @@ static void atmel_clear_gcr(struct net_device *dev, u16 mask)
static int atmel_lock_mac(struct atmel_private *priv) static int atmel_lock_mac(struct atmel_private *priv)
{ {
int i, j = 100; int i, j = 20;
retry: retry:
for (i = LOOP_RETRY_LIMIT ; atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET)) && i ; i--); for (i = 5000; i; i--) {
if (!atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET)))
break;
udelay(20);
}
if (!i) return 0; /* timed out */ if (!i) return 0; /* timed out */
......
...@@ -54,7 +54,6 @@ ...@@ -54,7 +54,6 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <linux/wireless.h> #include <linux/wireless.h>
#include <linux/802_11.h>
/* /*
...@@ -104,7 +103,7 @@ MODULE_PARM(irq_list, "1-4i"); ...@@ -104,7 +103,7 @@ MODULE_PARM(irq_list, "1-4i");
struct net_device *init_atmel_card(int, int, char *, struct device *, struct net_device *init_atmel_card(int, int, char *, struct device *,
int (*present_func)(void *), void * ); int (*present_func)(void *), void * );
void stop_atmel_card( struct net_device *, int ); void stop_atmel_card( struct net_device *, int );
int reset_atmel_card( struct net_device * ); int atmel_open( struct net_device * );
static void atmel_config(dev_link_t *link); static void atmel_config(dev_link_t *link);
static void atmel_release(dev_link_t *link); static void atmel_release(dev_link_t *link);
...@@ -335,7 +334,7 @@ static struct { ...@@ -335,7 +334,7 @@ static struct {
{ 0, 0, "ATMEL/AT76C504A", "atmel_at76c504a_2958%s.bin", "NoName-504a-2958" }, { 0, 0, "ATMEL/AT76C504A", "atmel_at76c504a_2958%s.bin", "NoName-504a-2958" },
{ 0, 0, "ATMEL/AT76C504_R", "atmel_at76c504_2958%s.bin", "NoName-504-2958" }, { 0, 0, "ATMEL/AT76C504_R", "atmel_at76c504_2958%s.bin", "NoName-504-2958" },
{ MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRWE62092B" }, { MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRWE62092B" },
{ MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRSHPW_96" }, { MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRSHPW196" },
{ 0, 0, "SMC/2632W-V2", "atmel_at76c502%s.bin", "SMC 2632W-V2" }, { 0, 0, "SMC/2632W-V2", "atmel_at76c502%s.bin", "SMC 2632W-V2" },
{ 0, 0, "SMC/2632W", "atmel_at76c502d%s.bin", "SMC 2632W-V3" }, { 0, 0, "SMC/2632W", "atmel_at76c502d%s.bin", "SMC 2632W-V3" },
{ 0xd601, 0x0007, NULL, "atmel_at76c502%s.bin", "Sitecom WLAN-011" }, { 0xd601, 0x0007, NULL, "atmel_at76c502%s.bin", "Sitecom WLAN-011" },
...@@ -661,7 +660,7 @@ static int atmel_event(event_t event, int priority, ...@@ -661,7 +660,7 @@ static int atmel_event(event_t event, int priority,
case CS_EVENT_CARD_RESET: case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
reset_atmel_card(local->eth_dev); atmel_open(local->eth_dev);
netif_device_attach(local->eth_dev); netif_device_attach(local->eth_dev);
} }
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment