Commit 3bcaef6a authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (09/12) Probe2 -- arlan

Convert arlan driver to new probing.  This meant a rather large
rework of the probing code for this driver since it did a lot ofnon
standard things.
parent fd60992e
...@@ -59,7 +59,7 @@ extern int i82596_probe(struct net_device *); ...@@ -59,7 +59,7 @@ extern int i82596_probe(struct net_device *);
extern int ewrk3_probe(struct net_device *); extern int ewrk3_probe(struct net_device *);
extern int el1_probe(struct net_device *); extern int el1_probe(struct net_device *);
extern int wavelan_probe(struct net_device *); extern int wavelan_probe(struct net_device *);
extern int arlan_probe(struct net_device *); extern struct net_device *arlan_probe(int unit);
extern struct net_device *el16_probe(int unit); extern struct net_device *el16_probe(int unit);
extern int elmc_probe(struct net_device *); extern int elmc_probe(struct net_device *);
extern int skmca_probe(struct net_device *); extern int skmca_probe(struct net_device *);
...@@ -267,14 +267,14 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -267,14 +267,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_WAVELAN /* WaveLAN */ #ifdef CONFIG_WAVELAN /* WaveLAN */
{wavelan_probe, 0}, {wavelan_probe, 0},
#endif
#ifdef CONFIG_ARLAN /* Aironet */
{arlan_probe, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 isa_probes2[] __initdata = { static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_ARLAN /* Aironet */
{arlan_probe, 0},
#endif
#ifdef CONFIG_EL16 /* 3c507 */ #ifdef CONFIG_EL16 /* 3c507 */
{el16_probe, 0}, {el16_probe, 0},
#endif #endif
......
...@@ -19,9 +19,7 @@ struct net_device *arlan_device[MAX_ARLANS]; ...@@ -19,9 +19,7 @@ struct net_device *arlan_device[MAX_ARLANS];
static int SID = SIDUNKNOWN; static int SID = SIDUNKNOWN;
static int radioNodeId = radioNodeIdUNKNOWN; static int radioNodeId = radioNodeIdUNKNOWN;
static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
static int mem = memUNKNOWN;
int arlan_debug = debugUNKNOWN; int arlan_debug = debugUNKNOWN;
static int numDevices = numDevicesUNKNOWN;
static int spreadingCode = spreadingCodeUNKNOWN; static int spreadingCode = spreadingCodeUNKNOWN;
static int channelNumber = channelNumberUNKNOWN; static int channelNumber = channelNumberUNKNOWN;
static int channelSet = channelSetUNKNOWN; static int channelSet = channelSetUNKNOWN;
...@@ -45,9 +43,7 @@ static int mdebug; ...@@ -45,9 +43,7 @@ static int mdebug;
MODULE_PARM(irq, "i"); MODULE_PARM(irq, "i");
MODULE_PARM(mem, "i"); MODULE_PARM(mem, "i");
MODULE_PARM(probe, "i");
MODULE_PARM(arlan_debug, "i"); MODULE_PARM(arlan_debug, "i");
MODULE_PARM(numDevices, "i");
MODULE_PARM(testMemory, "i"); MODULE_PARM(testMemory, "i");
MODULE_PARM(spreadingCode, "i"); MODULE_PARM(spreadingCode, "i");
MODULE_PARM(channelNumber, "i"); MODULE_PARM(channelNumber, "i");
...@@ -69,9 +65,7 @@ MODULE_PARM(arlan_entry_and_exit_debug, "i"); ...@@ -69,9 +65,7 @@ MODULE_PARM(arlan_entry_and_exit_debug, "i");
MODULE_PARM(arlan_EEPROM_bad, "i"); MODULE_PARM(arlan_EEPROM_bad, "i");
MODULE_PARM_DESC(irq, "(unused)"); MODULE_PARM_DESC(irq, "(unused)");
MODULE_PARM_DESC(mem, "Arlan memory address for single device probing"); MODULE_PARM_DESC(mem, "Arlan memory address for single device probing");
MODULE_PARM_DESC(probe, "Arlan probe at initialization (0-1)");
MODULE_PARM_DESC(arlan_debug, "Arlan debug enable (0-1)"); MODULE_PARM_DESC(arlan_debug, "Arlan debug enable (0-1)");
MODULE_PARM_DESC(numDevices, "Number of Arlan devices; ignored if >1");
MODULE_PARM_DESC(testMemory, "(unused)"); MODULE_PARM_DESC(testMemory, "(unused)");
MODULE_PARM_DESC(mdebug, "Arlan multicast debugging (0-1)"); MODULE_PARM_DESC(mdebug, "Arlan multicast debugging (0-1)");
MODULE_PARM_DESC(retries, "Arlan maximum packet retransmisions"); MODULE_PARM_DESC(retries, "Arlan maximum packet retransmisions");
...@@ -88,7 +82,6 @@ MODULE_PARM_DESC(arlan_entry_and_exit_debug, "(ignored)"); ...@@ -88,7 +82,6 @@ MODULE_PARM_DESC(arlan_entry_and_exit_debug, "(ignored)");
struct arlan_conf_stru arlan_conf[MAX_ARLANS]; struct arlan_conf_stru arlan_conf[MAX_ARLANS];
static int arlans_found; static int arlans_found;
static int arlan_probe_here(struct net_device *dev, int ioaddr);
static int arlan_open(struct net_device *dev); static int arlan_open(struct net_device *dev);
static int arlan_tx(struct sk_buff *skb, struct net_device *dev); static int arlan_tx(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs);
...@@ -975,24 +968,27 @@ static int lastFoundAt = 0xbe000; ...@@ -975,24 +968,27 @@ static int lastFoundAt = 0xbe000;
* probes on the ISA bus. A good device probes avoids doing writes, and * probes on the ISA bus. A good device probes avoids doing writes, and
* verifies that the correct device exists and functions. * verifies that the correct device exists and functions.
*/ */
#define ARLAN_SHMEM_SIZE 0x2000
static int __init arlan_check_fingerprint(int memaddr) static int __init arlan_check_fingerprint(unsigned long memaddr)
{ {
static char probeText[] = "TELESYSTEM SLW INC. ARLAN \0"; static const char probeText[] = "TELESYSTEM SLW INC. ARLAN \0";
char tempBuf[49];
volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr; volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr;
unsigned long paddr = virt_to_phys((void *) memaddr);
char tempBuf[49];
ARLAN_DEBUG_ENTRY("arlan_check_fingerprint"); ARLAN_DEBUG_ENTRY("arlan_check_fingerprint");
if (check_mem_region(virt_to_phys((void *)memaddr),0x2000 )){
// printk(KERN_WARNING "arlan: memory region %lx excluded from probing \n",virt_to_phys((void*)memaddr)); if (!request_mem_region(paddr, ARLAN_SHMEM_SIZE, "arlan")) {
// printk(KERN_WARNING "arlan: memory region %lx excluded from probing \n",paddr);
return -ENODEV; return -ENODEV;
} }
memcpy_fromio(tempBuf, arlan->textRegion, 29); memcpy_fromio(tempBuf, arlan->textRegion, 29);
tempBuf[30] = 0; tempBuf[30] = 0;
/* check for card at this address */ /* check for card at this address */
if (0 != strncmp(tempBuf, probeText, 29)){ if (0 != strncmp(tempBuf, probeText, 29)){
// not release_mem_region(virt_to_phys((void*)memaddr),0x2000); release_mem_region(paddr, ARLAN_SHMEM_SIZE);
return -ENODEV; return -ENODEV;
} }
...@@ -1000,51 +996,8 @@ static int __init arlan_check_fingerprint(int memaddr) ...@@ -1000,51 +996,8 @@ static int __init arlan_check_fingerprint(int memaddr)
ARLAN_DEBUG_EXIT("arlan_check_fingerprint"); ARLAN_DEBUG_EXIT("arlan_check_fingerprint");
return 0; return 0;
} }
static int __init arlan_probe_everywhere(struct net_device *dev)
{
int m;
int probed = 0;
int found = 0;
SET_MODULE_OWNER(dev);
ARLAN_DEBUG_ENTRY("arlan_probe_everywhere");
if (mem != 0 && numDevices == 1) /* Check a single specified location. */
{
if (arlan_probe_here(dev, (int) phys_to_virt( mem) ) == 0)
return 0;
else
return -ENODEV;
}
for (m = (int)phys_to_virt(lastFoundAt) + 0x2000; m <= (int)phys_to_virt(0xDE000); m += 0x2000)
{
if (arlan_probe_here(dev, m) == 0)
{
found++;
lastFoundAt = (int)virt_to_phys((void*)m);
break;
}
probed++;
}
if (found == 0 && probed != 0)
{
if (lastFoundAt == 0xbe000)
printk(KERN_ERR "arlan: No Arlan devices found \n");
return -ENODEV;
}
else
return 0;
ARLAN_DEBUG_EXIT("arlan_probe_everywhere");
return -ENODEV;
}
static int arlan_change_mtu(struct net_device *dev, int new_mtu) static int arlan_change_mtu(struct net_device *dev, int new_mtu)
{ {
struct arlan_private *priv = dev->priv; struct arlan_private *priv = dev->priv;
...@@ -1085,47 +1038,14 @@ static int arlan_mac_addr(struct net_device *dev, void *p) ...@@ -1085,47 +1038,14 @@ static int arlan_mac_addr(struct net_device *dev, void *p)
static void __init arlan_setup_device(struct net_device *dev, int num)
static int __init
arlan_allocate_device(int num, struct net_device *devs)
{ {
struct arlan_private *ap = dev->priv;
struct net_device *dev; ARLAN_DEBUG_ENTRY("arlan_setup_device");
struct arlan_private *ap;
ARLAN_DEBUG_ENTRY("arlan_allocate_device"); ap->conf = (struct arlan_shmem *)(ap+1);
if (!devs) {
dev = init_etherdev(0, sizeof(struct arlan_private) + sizeof(struct arlan_shmem));
if (!dev) {
printk(KERN_ERR "ARLAN: init_etherdev failed\n");
return 0;
}
ap = dev->priv;
ap->conf = dev->priv + sizeof(struct arlan_private);
ap->init_etherdev_alloc = 1;
} else {
dev = devs;
dev->priv = kmalloc(sizeof(struct arlan_private) + sizeof(struct arlan_shmem), GFP_KERNEL);
if (!dev->priv) {
printk(KERN_ERR "ARLAN: kmalloc of dev->priv failed\n");
return 0;
}
ap = dev->priv;
ap->conf = dev->priv + sizeof(struct arlan_private);
memset(ap, 0, sizeof(*ap));
}
/* Fill in the 'dev' fields. */
dev->base_addr = 0;
dev->mem_start = 0;
dev->mem_end = 0;
dev->mtu = 1500;
dev->flags = 0; /* IFF_BROADCAST & IFF_MULTICAST & IFF_PROMISC; */
dev->irq = 0;
dev->dma = 0;
dev->tx_queue_len = tx_queue_len;
ether_setup(dev);
dev->tx_queue_len = tx_queue_len; dev->tx_queue_len = tx_queue_len;
dev->open = arlan_open; dev->open = arlan_open;
dev->stop = arlan_close; dev->stop = arlan_close;
...@@ -1145,34 +1065,29 @@ static int __init ...@@ -1145,34 +1065,29 @@ static int __init
ap->Conf->rx_tweak1 = 30; ap->Conf->rx_tweak1 = 30;
ap->Conf->rx_tweak2 = 0; ap->Conf->rx_tweak2 = 0;
ARLAN_DEBUG_EXIT("arlan_allocate_device"); ARLAN_DEBUG_EXIT("arlan_setup_device");
return (int) dev;
} }
static int __init arlan_probe_here(struct net_device *dev,
static int __init arlan_probe_here(struct net_device *dev, int memaddr) unsigned long memaddr)
{ {
volatile struct arlan_shmem *arlan; struct arlan_private *ap = dev->priv;
ARLAN_DEBUG_ENTRY("arlan_probe_here"); ARLAN_DEBUG_ENTRY("arlan_probe_here");
if (arlan_check_fingerprint(memaddr)) if (arlan_check_fingerprint(memaddr))
return -ENODEV; return -ENODEV;
printk(KERN_NOTICE "%s: Arlan found at %x, \n ", dev->name, (int) virt_to_phys((void*)memaddr)); printk(KERN_NOTICE "%s: Arlan found at %x, \n ", dev->name,
(int) virt_to_phys((void*)memaddr));
if (!arlan_allocate_device(arlans_found, dev))
return -1;
((struct arlan_private *) dev->priv)->card = (struct arlan_shmem *) memaddr;
arlan = (void *) memaddr;
ap->card = (void *) memaddr;
dev->mem_start = memaddr; dev->mem_start = memaddr;
dev->mem_end = memaddr + 0x1FFF; dev->mem_end = memaddr + ARLAN_SHMEM_SIZE-1;
if (dev->irq < 2) if (dev->irq < 2)
{ {
READSHM(dev->irq, arlan->irqLevel, u_char); READSHM(dev->irq, ap->card->irqLevel, u_char);
} else if (dev->irq == 2) } else if (dev->irq == 2)
dev->irq = 9; dev->irq = 9;
...@@ -1183,8 +1098,6 @@ static int __init arlan_probe_here(struct net_device *dev, int memaddr) ...@@ -1183,8 +1098,6 @@ static int __init arlan_probe_here(struct net_device *dev, int memaddr)
} }
static int arlan_open(struct net_device *dev) static int arlan_open(struct net_device *dev)
{ {
struct arlan_private *priv = dev->priv; struct arlan_private *priv = dev->priv;
...@@ -1193,12 +1106,6 @@ static int arlan_open(struct net_device *dev) ...@@ -1193,12 +1106,6 @@ static int arlan_open(struct net_device *dev)
ARLAN_DEBUG_ENTRY("arlan_open"); ARLAN_DEBUG_ENTRY("arlan_open");
if (dev->mem_start == 0)
ret = arlan_probe_everywhere(dev);
if (ret != 0)
return ret;
arlan = priv->card;
ret = request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev); ret = request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev);
if (ret) if (ret)
{ {
...@@ -1768,14 +1675,9 @@ static int arlan_close(struct net_device *dev) ...@@ -1768,14 +1675,9 @@ static int arlan_close(struct net_device *dev)
{ {
struct arlan_private *priv = dev->priv; struct arlan_private *priv = dev->priv;
if (!priv)
{
printk(KERN_CRIT "arlan: No Device priv \n");
return 0;
}
ARLAN_DEBUG_ENTRY("arlan_close"); ARLAN_DEBUG_ENTRY("arlan_close");
del_timer(&priv->timer); del_timer_sync(&priv->timer);
arlan_command(dev, ARLAN_COMMAND_POWERDOWN); arlan_command(dev, ARLAN_COMMAND_POWERDOWN);
...@@ -1867,39 +1769,68 @@ static void arlan_set_multicast(struct net_device *dev) ...@@ -1867,39 +1769,68 @@ static void arlan_set_multicast(struct net_device *dev)
} }
int __init arlan_probe(struct net_device *dev) struct net_device * __init arlan_probe(int unit)
{ {
printk("Arlan driver %s\n", arlan_version); struct net_device *dev;
int m;
if (arlan_probe_everywhere(dev)) ARLAN_DEBUG_ENTRY("arlan_probe");
return -ENODEV;
arlans_found++; if (arlans_found == MAX_ARLANS)
return 0; return ERR_PTR(-ENODEV);
}
#ifdef MODULE /*
* Reserve space for local data and a copy of the shared memory
* that is used by the /proc interface.
*/
dev = alloc_etherdev(sizeof(struct arlan_private)
+ sizeof(struct arlan_shmem));
if (!dev)
return ERR_PTR(-ENOMEM);
static int probe = probeUNKNOWN; SET_MODULE_OWNER(dev);
static int __init arlan_find_devices(void) if (unit >= 0) {
{ sprintf(dev->name, "eth%d", unit);
int m; netdev_boot_setup_check(dev);
int found = 0;
if (dev->mem_start) {
if (arlan_probe_here(dev, dev->mem_start) == 0)
goto found;
goto not_found;
}
}
ARLAN_DEBUG_ENTRY("arlan_find_devices");
if (mem != 0 && numDevices == 1) /* Check a single specified location. */ for (m = (int)phys_to_virt(lastFoundAt) + ARLAN_SHMEM_SIZE;
return 1; m <= (int)phys_to_virt(0xDE000);
for (m =(int) phys_to_virt(0xc0000); m <=(int) phys_to_virt(0xDE000); m += 0x2000) m += ARLAN_SHMEM_SIZE)
{ {
if (arlan_check_fingerprint(m) == 0) if (arlan_probe_here(dev, m) == 0)
found++; {
lastFoundAt = (int)virt_to_phys((void*)m);
goto found;
}
} }
ARLAN_DEBUG_EXIT("arlan_find_devices");
return found; if (lastFoundAt == 0xbe000)
printk(KERN_ERR "arlan: No Arlan devices found \n");
not_found:
free_netdev(dev);
return ERR_PTR(-ENODEV);
found:
arlan_setup_device(dev, arlans_found++);
if (arlans_found == 1) {
printk(KERN_INFO "Arlan driver %s\n", arlan_version);
}
return dev;
} }
#ifdef MODULE
int init_module(void) int init_module(void)
{ {
int i = 0; int i = 0;
...@@ -1909,21 +1840,11 @@ int init_module(void) ...@@ -1909,21 +1840,11 @@ int init_module(void)
if (channelSet != channelSetUNKNOWN || channelNumber != channelNumberUNKNOWN || systemId != systemIdUNKNOWN) if (channelSet != channelSetUNKNOWN || channelNumber != channelNumberUNKNOWN || systemId != systemIdUNKNOWN)
return -EINVAL; return -EINVAL;
numDevices = arlan_find_devices(); for (i = 0; i < MAX_ARLANS; i++) {
if (numDevices == 0) struct net_device *dev = arlan_probe(i);
return -ENODEV;
for (i = 0; i < numDevices && i < MAX_ARLANS; i++)
{
if (!arlan_allocate_device(i, NULL))
return -ENOMEM;
if (arlan_device[i] == NULL) if (IS_ERR(dev))
return -ENOMEM; return PTR_ERR(dev);
if (probe)
arlan_probe_everywhere(arlan_device[i]);
// arlan_command(arlan_device[i], ARLAN_COMMAND_POWERDOWN );
} }
init_arlan_proc(); init_arlan_proc();
printk(KERN_INFO "Arlan driver %s\n", arlan_version); printk(KERN_INFO "Arlan driver %s\n", arlan_version);
...@@ -1935,7 +1856,7 @@ int init_module(void) ...@@ -1935,7 +1856,7 @@ int init_module(void)
void cleanup_module(void) void cleanup_module(void)
{ {
int i = 0; int i = 0;
struct arlan_private *ap; struct net_device *dev;
ARLAN_DEBUG_ENTRY("cleanup_module"); ARLAN_DEBUG_ENTRY("cleanup_module");
...@@ -1946,22 +1867,18 @@ void cleanup_module(void) ...@@ -1946,22 +1867,18 @@ void cleanup_module(void)
for (i = 0; i < MAX_ARLANS; i++) for (i = 0; i < MAX_ARLANS; i++)
{ {
if (arlan_device[i]) dev = arlan_device[i];
{ if (dev) {
arlan_command(arlan_device[i], ARLAN_COMMAND_POWERDOWN ); arlan_command(dev, ARLAN_COMMAND_POWERDOWN );
// release_mem_region(virt_to_phys(arlan_device[i]->mem_start), 0x2000 ); unregister_netdev(dev);
unregister_netdev(arlan_device[i]); release_mem_region(virt_to_phys((void *) dev->mem_start),
ap = arlan_device[i]->priv; ARLAN_SHMEM_SIZE);
if (ap->init_etherdev_alloc) { free_netdev(dev);
free_netdev(arlan_device[i]); arlan_device[i] = NULL;
arlan_device[i] = NULL;
} else {
kfree(ap);
ap = NULL;
}
} }
} }
ARLAN_DEBUG_EXIT("cleanup_module"); ARLAN_DEBUG_EXIT("cleanup_module");
} }
......
...@@ -57,12 +57,8 @@ extern int arlan_command(struct net_device * dev, int command); ...@@ -57,12 +57,8 @@ extern int arlan_command(struct net_device * dev, int command);
#define SIDUNKNOWN -1 #define SIDUNKNOWN -1
#define radioNodeIdUNKNOWN -1 #define radioNodeIdUNKNOWN -1
#define encryptionKeyUNKNOWN '\0';
#define irqUNKNOWN 0 #define irqUNKNOWN 0
#define memUNKNOWN 0
#define debugUNKNOWN 0 #define debugUNKNOWN 0
#define probeUNKNOWN 1
#define numDevicesUNKNOWN 1
#define testMemoryUNKNOWN 1 #define testMemoryUNKNOWN 1
#define spreadingCodeUNKNOWN 0 #define spreadingCodeUNKNOWN 0
#define channelNumberUNKNOWN 0 #define channelNumberUNKNOWN 0
...@@ -82,6 +78,8 @@ extern int arlan_command(struct net_device * dev, int command); ...@@ -82,6 +78,8 @@ extern int arlan_command(struct net_device * dev, int command);
#define ARLAN_DEBUG(a,b) #define ARLAN_DEBUG(a,b)
#endif #endif
#define ARLAN_SHMEM_SIZE 0x2000
struct arlan_shmem struct arlan_shmem
{ {
/* Header Signature */ /* Header Signature */
......
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