Commit 65e9e2db authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (05/12) Probe2 -- ni5010

from viro NE16-ni5010
	* switched ni5010 to dynamic allocation
	* ni5010: embedded ->priv
	* ni5010: fixed clobbering ->irq
	* ni5010: fixed IO before request_region()
Additional:
	* add free_netdev
parent a56fc3a9
...@@ -68,7 +68,7 @@ extern int ac3200_probe(struct net_device *); ...@@ -68,7 +68,7 @@ extern int ac3200_probe(struct net_device *);
extern int es_probe(struct net_device *); extern int es_probe(struct net_device *);
extern int lne390_probe(struct net_device *); extern int lne390_probe(struct net_device *);
extern int e2100_probe(struct net_device *); extern int e2100_probe(struct net_device *);
extern int ni5010_probe(struct net_device *); extern struct net_device *ni5010_probe(int unit);
extern struct net_device *ni52_probe(int unit); extern struct net_device *ni52_probe(int unit);
extern struct net_device *ni65_probe(int unit); extern struct net_device *ni65_probe(int unit);
extern int sonic_probe(struct net_device *); extern int sonic_probe(struct net_device *);
...@@ -279,14 +279,14 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -279,14 +279,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_SK_G16 #ifdef CONFIG_SK_G16
{SK_init, 0}, {SK_init, 0},
#endif
#ifdef CONFIG_NI5010
{ni5010_probe, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 isa_probes2[] __initdata = { static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_NI5010
{ni5010_probe, 0},
#endif
#ifdef CONFIG_NI52 #ifdef CONFIG_NI52
{ni52_probe, 0}, {ni52_probe, 0},
#endif #endif
......
...@@ -82,7 +82,7 @@ static unsigned int bufsize_rcv; ...@@ -82,7 +82,7 @@ static unsigned int bufsize_rcv;
#ifndef FULL_IODETECT #ifndef FULL_IODETECT
/* A zero-terminated list of I/O addresses to be probed. */ /* A zero-terminated list of I/O addresses to be probed. */
static unsigned int ni5010_portlist[] __initdata = static unsigned int ports[] __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0 }; { 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0 };
#endif #endif
...@@ -95,13 +95,11 @@ static unsigned int ni5010_portlist[] __initdata = ...@@ -95,13 +95,11 @@ static unsigned int ni5010_portlist[] __initdata =
struct ni5010_local { struct ni5010_local {
struct net_device_stats stats; struct net_device_stats stats;
int o_pkt_size; int o_pkt_size;
int i_pkt_size;
spinlock_t lock; spinlock_t lock;
}; };
/* Index to functions, as function prototypes. */ /* Index to functions, as function prototypes. */
extern int ni5010_probe(struct net_device *dev);
static int ni5010_probe1(struct net_device *dev, int ioaddr); static int ni5010_probe1(struct net_device *dev, int ioaddr);
static int ni5010_open(struct net_device *dev); static int ni5010_open(struct net_device *dev);
static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev); static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev);
...@@ -120,38 +118,58 @@ static void chipset_init(struct net_device *dev, int startp); ...@@ -120,38 +118,58 @@ static void chipset_init(struct net_device *dev, int startp);
static void dump_packet(void *buf, int len); static void dump_packet(void *buf, int len);
static void ni5010_show_registers(struct net_device *dev); static void ni5010_show_registers(struct net_device *dev);
static int io;
static int irq;
int __init ni5010_probe(struct net_device *dev) struct net_device * __init ni5010_probe(int unit)
{ {
struct net_device *dev = alloc_etherdev(sizeof(struct ni5010_local));
int *port; int *port;
int base_addr = dev->base_addr; int err = 0;
PRINTK2((KERN_DEBUG "%s: Entering ni5010_probe\n", dev->name)); if (!dev)
return ERR_PTR(-ENOMEM);
SET_MODULE_OWNER(dev); if (unit >= 0) {
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
io = dev->base_addr;
irq = dev->irq;
}
if (base_addr > 0x1ff) /* Check a single specified location. */ PRINTK2((KERN_DEBUG "%s: Entering ni5010_probe\n", dev->name));
return ni5010_probe1(dev, base_addr);
else if (base_addr != 0) /* Don't probe at all. */
return -ENXIO;
SET_MODULE_OWNER(dev);
if (io > 0x1ff) { /* Check a single specified location. */
err = ni5010_probe1(dev, io);
} else if (io != 0) { /* Don't probe at all. */
err = -ENXIO;
} else {
#ifdef FULL_IODETECT #ifdef FULL_IODETECT
for (int ioaddr=0x200; ioaddr<0x400; ioaddr+=0x20) { for (io=0x200; io<0x400 && ni5010_probe1(dev, io) ; io+=0x20)
if (check_region(ioaddr, NI5010_IO_EXTENT)) ;
continue; if (io == 0x400)
if (ni5010_probe1(dev, ioaddr) == 0) err = -ENODEV;
return 0;
}
#else #else
for (port = ni5010_portlist; *port; port++) { for (port = ports; *port && ni5010_probe1(dev, *port); port++)
int ioaddr = *port; ;
if (check_region(ioaddr, NI5010_IO_EXTENT)) if (!*port)
continue; err = -ENODEV;
if (ni5010_probe1(dev, ioaddr) == 0)
return 0;
}
#endif /* FULL_IODETECT */ #endif /* FULL_IODETECT */
return -ENODEV; }
if (err)
goto out;
err = register_netdev(dev);
if (err)
goto out1;
return dev;
out1:
release_region(dev->base_addr, NI5010_IO_EXTENT);
out:
free_netdev(dev);
return ERR_PTR(err);
} }
static inline int rd_port(int ioaddr) static inline int rd_port(int ioaddr)
...@@ -188,9 +206,17 @@ static void __init trigger_irq(int ioaddr) ...@@ -188,9 +206,17 @@ static void __init trigger_irq(int ioaddr)
static int __init ni5010_probe1(struct net_device *dev, int ioaddr) static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
{ {
static unsigned version_printed; static unsigned version_printed;
struct ni5010_local *lp;
int i; int i;
unsigned int data = 0; unsigned int data = 0;
int boguscount = 40; int boguscount = 40;
int err = -ENODEV;
dev->base_addr = ioaddr;
dev->irq = irq;
if (!request_region(ioaddr, NI5010_IO_EXTENT, boardname))
return -EBUSY;
/* /*
* This is no "official" probe method, I've rather tested which * This is no "official" probe method, I've rather tested which
...@@ -205,36 +231,40 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) ...@@ -205,36 +231,40 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
* *
* - Andreas * - Andreas
*/ */
PRINTK2((KERN_DEBUG "%s: entering ni5010_probe1(%#3x)\n", PRINTK2((KERN_DEBUG "%s: entering ni5010_probe1(%#3x)\n",
dev->name, ioaddr)); dev->name, ioaddr));
if (inb(ioaddr+0) == 0xff) return -ENODEV; if (inb(ioaddr+0) == 0xff)
goto out;
while ( (rd_port(ioaddr) & rd_port(ioaddr) & rd_port(ioaddr) & while ( (rd_port(ioaddr) & rd_port(ioaddr) & rd_port(ioaddr) &
rd_port(ioaddr) & rd_port(ioaddr) & rd_port(ioaddr)) != 0xff) rd_port(ioaddr) & rd_port(ioaddr) & rd_port(ioaddr)) != 0xff)
{ {
if (boguscount-- == 0) return -ENODEV; if (boguscount-- == 0)
goto out;
} }
PRINTK2((KERN_DEBUG "%s: I/O #1 passed!\n", dev->name)); PRINTK2((KERN_DEBUG "%s: I/O #1 passed!\n", dev->name));
for (i=0; i<32; i++) for (i=0; i<32; i++)
if ( (data = rd_port(ioaddr)) != 0xff) break; if ( (data = rd_port(ioaddr)) != 0xff) break;
if (data==0xff) return -ENODEV; if (data==0xff)
goto out;
PRINTK2((KERN_DEBUG "%s: I/O #2 passed!\n", dev->name)); PRINTK2((KERN_DEBUG "%s: I/O #2 passed!\n", dev->name));
if ( (data == SA_ADDR0) && if ((data != SA_ADDR0) || (rd_port(ioaddr) != SA_ADDR1) ||
(rd_port(ioaddr) == SA_ADDR1) && (rd_port(ioaddr) != SA_ADDR2))
(rd_port(ioaddr) == SA_ADDR2) ) { goto out;
for (i=0; i<4; i++) rd_port(ioaddr);
if ( (rd_port(ioaddr) != NI5010_MAGICVAL1) || for (i=0; i<4; i++)
(rd_port(ioaddr) != NI5010_MAGICVAL2) ) { rd_port(ioaddr);
return -ENODEV;
} if ( (rd_port(ioaddr) != NI5010_MAGICVAL1) ||
} else return -ENODEV; (rd_port(ioaddr) != NI5010_MAGICVAL2) )
goto out;
PRINTK2((KERN_DEBUG "%s: I/O #3 passed!\n", dev->name)); PRINTK2((KERN_DEBUG "%s: I/O #3 passed!\n", dev->name));
if (NI5010_DEBUG && version_printed++ == 0) if (NI5010_DEBUG && version_printed++ == 0)
...@@ -267,8 +297,9 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) ...@@ -267,8 +297,9 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
PRINTK2((KERN_DEBUG "%s: I/O #6 passed!\n", dev->name)); PRINTK2((KERN_DEBUG "%s: I/O #6 passed!\n", dev->name));
if (dev->irq == 0) { if (dev->irq == 0) {
err = -EAGAIN;
printk(KERN_WARNING "%s: no IRQ found!\n", dev->name); printk(KERN_WARNING "%s: no IRQ found!\n", dev->name);
return -EAGAIN; goto out;
} }
PRINTK2((KERN_DEBUG "%s: I/O #7 passed!\n", dev->name)); PRINTK2((KERN_DEBUG "%s: I/O #7 passed!\n", dev->name));
} else if (dev->irq == 2) { } else if (dev->irq == 2) {
...@@ -278,19 +309,9 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) ...@@ -278,19 +309,9 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
PRINTK2((KERN_DEBUG "%s: I/O #9 passed!\n", dev->name)); PRINTK2((KERN_DEBUG "%s: I/O #9 passed!\n", dev->name));
/* DMA is not supported (yet?), so no use detecting it */ /* DMA is not supported (yet?), so no use detecting it */
lp = (struct ni5010_local*)dev->priv;
if (dev->priv == NULL) { spin_lock_init(&lp->lock);
struct ni5010_local* lp;
dev->priv = kmalloc(sizeof(struct ni5010_local), GFP_KERNEL|GFP_DMA);
if (dev->priv == NULL) {
printk(KERN_WARNING "%s: Failed to allocate private memory\n", dev->name);
return -ENOMEM;
}
lp = (struct ni5010_local*)dev->priv;
spin_lock_init(&lp->lock);
}
PRINTK2((KERN_DEBUG "%s: I/O #10 passed!\n", dev->name)); PRINTK2((KERN_DEBUG "%s: I/O #10 passed!\n", dev->name));
...@@ -315,9 +336,6 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) ...@@ -315,9 +336,6 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
} }
printk("// bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE); printk("// bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
memset(dev->priv, 0, sizeof(struct ni5010_local)); memset(dev->priv, 0, sizeof(struct ni5010_local));
/* Grab the region so we can find another board if autoIRQ fails. */
request_region(ioaddr, NI5010_IO_EXTENT, boardname);
dev->open = ni5010_open; dev->open = ni5010_open;
dev->stop = ni5010_close; dev->stop = ni5010_close;
...@@ -327,9 +345,6 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) ...@@ -327,9 +345,6 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
dev->tx_timeout = ni5010_timeout; dev->tx_timeout = ni5010_timeout;
dev->watchdog_timeo = HZ/20; dev->watchdog_timeo = HZ/20;
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */ dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */
/* Shut up the ni5010 */ /* Shut up the ni5010 */
...@@ -345,6 +360,9 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) ...@@ -345,6 +360,9 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
printk(KERN_INFO "Join the NI5010 driver development team!\n"); printk(KERN_INFO "Join the NI5010 driver development team!\n");
printk(KERN_INFO "Mail to a.mohr@mailto.de or jvbest@wi.leidenuniv.nl\n"); printk(KERN_INFO "Mail to a.mohr@mailto.de or jvbest@wi.leidenuniv.nl\n");
return 0; return 0;
out:
release_region(dev->base_addr, NI5010_IO_EXTENT);
return err;
} }
/* /*
...@@ -513,6 +531,7 @@ static void ni5010_rx(struct net_device *dev) ...@@ -513,6 +531,7 @@ static void ni5010_rx(struct net_device *dev)
int ioaddr = dev->base_addr; int ioaddr = dev->base_addr;
unsigned char rcv_stat; unsigned char rcv_stat;
struct sk_buff *skb; struct sk_buff *skb;
int i_pkt_size;
PRINTK2((KERN_DEBUG "%s: entering ni5010_rx()\n", dev->name)); PRINTK2((KERN_DEBUG "%s: entering ni5010_rx()\n", dev->name));
...@@ -532,17 +551,17 @@ static void ni5010_rx(struct net_device *dev) ...@@ -532,17 +551,17 @@ static void ni5010_rx(struct net_device *dev)
outb(0xff, EDLC_RCLR); /* Clear the interrupt */ outb(0xff, EDLC_RCLR); /* Clear the interrupt */
lp->i_pkt_size = inw(IE_RCNT); i_pkt_size = inw(IE_RCNT);
if (lp->i_pkt_size > ETH_FRAME_LEN || lp->i_pkt_size < 10 ) { if (i_pkt_size > ETH_FRAME_LEN || i_pkt_size < 10 ) {
PRINTK((KERN_DEBUG "%s: Packet size error, packet size = %#4.4x\n", PRINTK((KERN_DEBUG "%s: Packet size error, packet size = %#4.4x\n",
dev->name, lp->i_pkt_size)); dev->name, i_pkt_size));
lp->stats.rx_errors++; lp->stats.rx_errors++;
lp->stats.rx_length_errors++; lp->stats.rx_length_errors++;
return; return;
} }
/* Malloc up new buffer. */ /* Malloc up new buffer. */
skb = dev_alloc_skb(lp->i_pkt_size + 3); skb = dev_alloc_skb(i_pkt_size + 3);
if (skb == NULL) { if (skb == NULL) {
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++; lp->stats.rx_dropped++;
...@@ -555,7 +574,7 @@ static void ni5010_rx(struct net_device *dev) ...@@ -555,7 +574,7 @@ static void ni5010_rx(struct net_device *dev)
/* Read packet into buffer */ /* Read packet into buffer */
outb(MM_MUX, IE_MMODE); /* Rcv buffer to system bus */ outb(MM_MUX, IE_MMODE); /* Rcv buffer to system bus */
outw(0, IE_GP); /* Seek to beginning of packet */ outw(0, IE_GP); /* Seek to beginning of packet */
insb(IE_RBUF, skb_put(skb, lp->i_pkt_size), lp->i_pkt_size); insb(IE_RBUF, skb_put(skb, i_pkt_size), i_pkt_size);
if (NI5010_DEBUG >= 4) if (NI5010_DEBUG >= 4)
dump_packet(skb->data, skb->len); dump_packet(skb->data, skb->len);
...@@ -564,10 +583,10 @@ static void ni5010_rx(struct net_device *dev) ...@@ -564,10 +583,10 @@ static void ni5010_rx(struct net_device *dev)
netif_rx(skb); netif_rx(skb);
dev->last_rx = jiffies; dev->last_rx = jiffies;
lp->stats.rx_packets++; lp->stats.rx_packets++;
lp->stats.rx_bytes += lp->i_pkt_size; lp->stats.rx_bytes += i_pkt_size;
PRINTK2((KERN_DEBUG "%s: Received packet, size=%#4.4x\n", PRINTK2((KERN_DEBUG "%s: Received packet, size=%#4.4x\n",
dev->name, lp->i_pkt_size)); dev->name, i_pkt_size));
} }
...@@ -697,10 +716,10 @@ static void hardware_send_packet(struct net_device *dev, char *buf, int length, ...@@ -697,10 +716,10 @@ static void hardware_send_packet(struct net_device *dev, char *buf, int length,
if (NI5010_DEBUG > 3) dump_packet(buf, length); if (NI5010_DEBUG > 3) dump_packet(buf, length);
buf_offs = NI5010_BUFSIZE - length - pad; buf_offs = NI5010_BUFSIZE - length - pad;
lp->o_pkt_size = length + pad;
spin_lock_irqsave(&lp->lock, flags); spin_lock_irqsave(&lp->lock, flags);
lp->o_pkt_size = length + pad;
outb(0, EDLC_RMASK); /* Mask all receive interrupts */ outb(0, EDLC_RMASK); /* Mask all receive interrupts */
outb(0, IE_MMODE); /* Put Xmit buffer on system bus */ outb(0, IE_MMODE); /* Put Xmit buffer on system bus */
...@@ -745,9 +764,7 @@ static void ni5010_show_registers(struct net_device *dev) ...@@ -745,9 +764,7 @@ static void ni5010_show_registers(struct net_device *dev)
} }
#ifdef MODULE #ifdef MODULE
static struct net_device dev_ni5010; static struct net_device *dev_ni5010;
static int io;
static int irq;
MODULE_PARM(io, "i"); MODULE_PARM(io, "i");
MODULE_PARM(irq, "i"); MODULE_PARM(irq, "i");
...@@ -756,8 +773,6 @@ MODULE_PARM_DESC(irq, "ni5010 IRQ number"); ...@@ -756,8 +773,6 @@ MODULE_PARM_DESC(irq, "ni5010 IRQ number");
int init_module(void) int init_module(void)
{ {
int result;
PRINTK2((KERN_DEBUG "%s: entering init_module\n", boardname)); PRINTK2((KERN_DEBUG "%s: entering init_module\n", boardname));
/* /*
if(io <= 0 || irq == 0){ if(io <= 0 || irq == 0){
...@@ -771,29 +786,18 @@ int init_module(void) ...@@ -771,29 +786,18 @@ int init_module(void)
} }
PRINTK2((KERN_DEBUG "%s: init_module irq=%#2x, io=%#3x\n", boardname, irq, io)); PRINTK2((KERN_DEBUG "%s: init_module irq=%#2x, io=%#3x\n", boardname, irq, io));
dev_ni5010.irq=irq; dev_ni5010 = ni5010_probe(-1);
dev_ni5010.base_addr=io; if (IS_ERR(dev_ni5010))
dev_ni5010.init=ni5010_probe; return PTR_ERR(dev_ni5010);
if ((result = register_netdev(&dev_ni5010)) != 0) {
PRINTK((KERN_WARNING "%s: register_netdev returned %d.\n",
boardname, result));
return -EIO;
}
return 0; return 0;
} }
void void cleanup_module(void)
cleanup_module(void)
{ {
PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname)); PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname));
unregister_netdev(dev_ni5010);
unregister_netdev(&dev_ni5010); release_region(dev_ni5010->base_addr, NI5010_IO_EXTENT);
free_netdev(dev_ni5010);
release_region(dev_ni5010.base_addr, NI5010_IO_EXTENT);
if (dev_ni5010.priv != NULL){
kfree(dev_ni5010.priv);
dev_ni5010.priv = NULL;
}
} }
#endif /* MODULE */ #endif /* MODULE */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
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