Commit f27dc99e authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] port ltpc to 2.5

parent eb748f78
...@@ -213,6 +213,7 @@ static int dma; ...@@ -213,6 +213,7 @@ static int dma;
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/spinlock.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -235,6 +236,9 @@ static int dma; ...@@ -235,6 +236,9 @@ static int dma;
/* our stuff */ /* our stuff */
#include "ltpc.h" #include "ltpc.h"
static spinlock_t txqueue_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t mbox_lock = SPIN_LOCK_UNLOCKED;
/* function prototypes */ /* function prototypes */
static int do_read(struct net_device *dev, void *cbuf, int cbuflen, static int do_read(struct net_device *dev, void *cbuf, int cbuflen,
void *dbuf, int dbuflen); void *dbuf, int dbuflen);
...@@ -283,17 +287,17 @@ static void enQ(struct xmitQel *qel) ...@@ -283,17 +287,17 @@ static void enQ(struct xmitQel *qel)
{ {
unsigned long flags; unsigned long flags;
qel->next = NULL; qel->next = NULL;
save_flags(flags);
cli(); spin_lock_irqsave(&txqueue_lock, flags);
if (xmQtl) { if (xmQtl) {
xmQtl->next = qel; xmQtl->next = qel;
} else { } else {
xmQhd = qel; xmQhd = qel;
} }
xmQtl = qel; xmQtl = qel;
restore_flags(flags); spin_unlock_irqrestore(&txqueue_lock, flags);
if (debug&DEBUG_LOWER) if (debug & DEBUG_LOWER)
printk("enqueued a 0x%02x command\n",qel->cbuf[0]); printk("enqueued a 0x%02x command\n",qel->cbuf[0]);
} }
...@@ -302,18 +306,18 @@ static struct xmitQel *deQ(void) ...@@ -302,18 +306,18 @@ static struct xmitQel *deQ(void)
unsigned long flags; unsigned long flags;
int i; int i;
struct xmitQel *qel=NULL; struct xmitQel *qel=NULL;
save_flags(flags);
cli(); spin_lock_irqsave(&txqueue_lock, flags);
if (xmQhd) { if (xmQhd) {
qel = xmQhd; qel = xmQhd;
xmQhd = qel->next; xmQhd = qel->next;
if(!xmQhd) xmQtl = NULL; if(!xmQhd) xmQtl = NULL;
} }
restore_flags(flags); spin_unlock_irqrestore(&txqueue_lock, flags);
if ((debug&DEBUG_LOWER) && qel) { if ((debug & DEBUG_LOWER) && qel) {
int n; int n;
printk("ltpc: dequeued command "); printk(KERN_DEBUG "ltpc: dequeued command ");
n = qel->cbuflen; n = qel->cbuflen;
if (n>100) n=100; if (n>100) n=100;
for(i=0;i<n;i++) printk("%02x ",qel->cbuf[i]); for(i=0;i<n;i++) printk("%02x ",qel->cbuf[i]);
...@@ -352,14 +356,13 @@ static int getmbox(void) ...@@ -352,14 +356,13 @@ static int getmbox(void)
unsigned long flags; unsigned long flags;
int i; int i;
save_flags(flags); spin_lock_irqsave(&mbox_lock, flags);
cli();
for(i=1;i<16;i++) if(!mboxinuse[i]) { for(i=1;i<16;i++) if(!mboxinuse[i]) {
mboxinuse[i]=1; mboxinuse[i]=1;
restore_flags(flags); spin_unlock_irqrestore(&mbox_lock, flags);
return i; return i;
} }
restore_flags(flags); spin_unlock_irqrestore(&mbox_lock, flags);
return 0; return 0;
} }
...@@ -503,16 +506,13 @@ static void idle(struct net_device *dev) ...@@ -503,16 +506,13 @@ static void idle(struct net_device *dev)
int i; int i;
int base = dev->base_addr; int base = dev->base_addr;
save_flags(flags); spin_lock_irqsave(&txqueue_lock, flags);
cli();
if(QInIdle) { if(QInIdle) {
restore_flags(flags); spin_unlock_irqrestore(&txqueue_lock, flags);
return; return;
} }
QInIdle = 1; QInIdle = 1;
spin_unlock_irqrestore(&txqueue_lock, flags);
restore_flags(flags);
/* this tri-states the IRQ line */ /* this tri-states the IRQ line */
(void) inb_p(base+6); (void) inb_p(base+6);
...@@ -531,17 +531,17 @@ static void idle(struct net_device *dev) ...@@ -531,17 +531,17 @@ static void idle(struct net_device *dev)
switch(state) { switch(state) {
case 0xfc: case 0xfc:
/* incoming command */ /* incoming command */
if (debug&DEBUG_LOWER) printk("idle: fc\n"); if (debug & DEBUG_LOWER) printk("idle: fc\n");
handlefc(dev); handlefc(dev);
break; break;
case 0xfd: case 0xfd:
/* incoming data */ /* incoming data */
if(debug&DEBUG_LOWER) printk("idle: fd\n"); if(debug & DEBUG_LOWER) printk("idle: fd\n");
handlefd(dev); handlefd(dev);
break; break;
case 0xf9: case 0xf9:
/* result ready */ /* result ready */
if (debug&DEBUG_LOWER) printk("idle: f9\n"); if (debug & DEBUG_LOWER) printk("idle: f9\n");
if(!mboxinuse[0]) { if(!mboxinuse[0]) {
mboxinuse[0] = 1; mboxinuse[0] = 1;
qels[0].cbuf = rescbuf; qels[0].cbuf = rescbuf;
...@@ -570,7 +570,7 @@ static void idle(struct net_device *dev) ...@@ -570,7 +570,7 @@ static void idle(struct net_device *dev)
break; break;
case 0xfa: case 0xfa:
/* waiting for command */ /* waiting for command */
if(debug&DEBUG_LOWER) printk("idle: fa\n"); if(debug & DEBUG_LOWER) printk("idle: fa\n");
if (xmQhd) { if (xmQhd) {
q=deQ(); q=deQ();
memcpy(ltdmacbuf,q->cbuf,q->cbuflen); memcpy(ltdmacbuf,q->cbuf,q->cbuflen);
...@@ -608,7 +608,7 @@ static void idle(struct net_device *dev) ...@@ -608,7 +608,7 @@ static void idle(struct net_device *dev)
break; break;
case 0Xfb: case 0Xfb:
/* data transfer ready */ /* data transfer ready */
if(debug&DEBUG_LOWER) printk("idle: fb\n"); if(debug & DEBUG_LOWER) printk("idle: fb\n");
if(q->QWrite) { if(q->QWrite) {
memcpy(ltdmabuf,q->dbuf,q->dbuflen); memcpy(ltdmabuf,q->dbuf,q->dbuflen);
handlewrite(dev); handlewrite(dev);
...@@ -826,7 +826,7 @@ static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -826,7 +826,7 @@ static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct lt_init c; struct lt_init c;
int ltflags; int ltflags;
if(debug&DEBUG_VERBOSE) printk("ltpc_ioctl called\n"); if(debug & DEBUG_VERBOSE) printk("ltpc_ioctl called\n");
switch(cmd) { switch(cmd) {
case SIOCSIFADDR: case SIOCSIFADDR:
...@@ -872,7 +872,7 @@ static void set_multicast_list(struct net_device *dev) ...@@ -872,7 +872,7 @@ static void set_multicast_list(struct net_device *dev)
static int ltpc_hard_header (struct sk_buff *skb, struct net_device *dev, static int ltpc_hard_header (struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr, unsigned len) unsigned short type, void *daddr, void *saddr, unsigned len)
{ {
if(debug&DEBUG_VERBOSE) if(debug & DEBUG_VERBOSE)
printk("ltpc_hard_header called for device %s\n", printk("ltpc_hard_header called for device %s\n",
dev->name); dev->name);
return 0; return 0;
...@@ -914,7 +914,7 @@ static void ltpc_poll(unsigned long l) ...@@ -914,7 +914,7 @@ static void ltpc_poll(unsigned long l)
del_timer(&ltpc_timer); del_timer(&ltpc_timer);
if(debug&DEBUG_VERBOSE) { if(debug & DEBUG_VERBOSE) {
if (!ltpc_poll_counter) { if (!ltpc_poll_counter) {
ltpc_poll_counter = 50; ltpc_poll_counter = 50;
printk("ltpc poll is alive\n"); printk("ltpc poll is alive\n");
...@@ -951,7 +951,7 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -951,7 +951,7 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev)
cbuf.length = skb->len; /* this is host order */ cbuf.length = skb->len; /* this is host order */
skb->h.raw=skb->data; skb->h.raw=skb->data;
if(debug&DEBUG_UPPER) { if(debug & DEBUG_UPPER) {
printk("command "); printk("command ");
for(i=0;i<6;i++) for(i=0;i<6;i++)
printk("%02x ",((unsigned char *)&cbuf)[i]); printk("%02x ",((unsigned char *)&cbuf)[i]);
...@@ -960,7 +960,7 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -960,7 +960,7 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev)
do_write(dev,&cbuf,sizeof(cbuf),skb->h.raw,skb->len); do_write(dev,&cbuf,sizeof(cbuf),skb->h.raw,skb->len);
if(debug&DEBUG_UPPER) { if(debug & DEBUG_UPPER) {
printk("sent %d ddp bytes\n",skb->len); printk("sent %d ddp bytes\n",skb->len);
for(i=0;i<skb->len;i++) printk("%02x ",skb->h.raw[i]); for(i=0;i<skb->len;i++) printk("%02x ",skb->h.raw[i]);
printk("\n"); printk("\n");
...@@ -984,7 +984,7 @@ static struct net_device_stats *ltpc_get_stats(struct net_device *dev) ...@@ -984,7 +984,7 @@ static struct net_device_stats *ltpc_get_stats(struct net_device *dev)
static int __init ltpc_probe_dma(int base) static int __init ltpc_probe_dma(int base)
{ {
int dma = 0; int dma = 0;
int timeout; unsigned long timeout;
unsigned long f; unsigned long f;
if (!request_dma(1,"ltpc")) { if (!request_dma(1,"ltpc")) {
...@@ -1055,16 +1055,13 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1055,16 +1055,13 @@ int __init ltpc_probe(struct net_device *dev)
{ {
int err; int err;
int x=0,y=0; int x=0,y=0;
int timeout;
int autoirq; int autoirq;
unsigned long flags;
unsigned long f; unsigned long f;
int portfound=0; int portfound=0;
unsigned long timeout;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
save_flags(flags);
/* probe for the I/O port address */ /* probe for the I/O port address */
if (io != 0x240 && request_region(0x220,8,"ltpc")) { if (io != 0x240 && request_region(0x220,8,"ltpc")) {
x = inb_p(0x220+6); x = inb_p(0x220+6);
...@@ -1093,15 +1090,13 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1093,15 +1090,13 @@ int __init ltpc_probe(struct net_device *dev)
} }
if(!portfound) { if(!portfound) {
/* give up in despair */ /* give up in despair */
printk ("LocalTalk card not found; 220 = %02x, 240 = %02x.\n", printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y);
x,y);
restore_flags(flags);
return -1; return -1;
} }
/* probe for the IRQ line */ /* probe for the IRQ line */
if (irq < 2) { if (irq < 2) {
unsigned long irq_mask, delay; unsigned long irq_mask;
irq_mask = probe_irq_on(); irq_mask = probe_irq_on();
/* reset the interrupt line */ /* reset the interrupt line */
...@@ -1109,14 +1104,11 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1109,14 +1104,11 @@ int __init ltpc_probe(struct net_device *dev)
inb_p(io+7); inb_p(io+7);
/* trigger an interrupt (I hope) */ /* trigger an interrupt (I hope) */
inb_p(io+6); inb_p(io+6);
mdelay(2);
delay = jiffies + HZ/50;
while (time_before(jiffies, delay)) ;
autoirq = probe_irq_off(irq_mask); autoirq = probe_irq_off(irq_mask);
if (autoirq == 0) { if (autoirq == 0) {
printk("ltpc: probe at %#x failed to detect IRQ line.\n", printk(KERN_ERR "ltpc: probe at %#x failed to detect IRQ line.\n", io);
io);
} }
else { else {
irq = autoirq; irq = autoirq;
...@@ -1129,12 +1121,11 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1129,12 +1121,11 @@ int __init ltpc_probe(struct net_device *dev)
if (ltdmabuf) ltdmacbuf = &ltdmabuf[800]; if (ltdmabuf) ltdmacbuf = &ltdmabuf[800];
if (!ltdmabuf) { if (!ltdmabuf) {
printk("ltpc: mem alloc failed\n"); printk(KERN_ERR "ltpc: mem alloc failed\n");
restore_flags(flags); return -1;
return(-1);
} }
if(debug&DEBUG_VERBOSE) { if(debug & DEBUG_VERBOSE) {
printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf); printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf);
} }
...@@ -1142,8 +1133,10 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1142,8 +1133,10 @@ int __init ltpc_probe(struct net_device *dev)
inb_p(io+1); inb_p(io+1);
inb_p(io+3); inb_p(io+3);
timeout = jiffies+2*HZ/100;
while(time_before(jiffies, timeout)) ; /* hold it in reset for a coupla jiffies */ set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(2*HZ/100);
inb_p(io+0); inb_p(io+0);
inb_p(io+2); inb_p(io+2);
inb_p(io+7); /* clear reset */ inb_p(io+7); /* clear reset */
...@@ -1152,11 +1145,8 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1152,11 +1145,8 @@ int __init ltpc_probe(struct net_device *dev)
inb_p(io+5); /* enable dma */ inb_p(io+5); /* enable dma */
inb_p(io+6); /* tri-state interrupt line */ inb_p(io+6); /* tri-state interrupt line */
timeout = jiffies+100*HZ/100; set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ);
while(time_before(jiffies, timeout)) {
/* wait for the card to complete initialization */
}
/* now, figure out which dma channel we're using, unless it's /* now, figure out which dma channel we're using, unless it's
already been specified */ already been specified */
...@@ -1165,8 +1155,7 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1165,8 +1155,7 @@ int __init ltpc_probe(struct net_device *dev)
if (dma == 0) { if (dma == 0) {
dma = ltpc_probe_dma(io); dma = ltpc_probe_dma(io);
if (!dma) { /* no dma channel */ if (!dma) { /* no dma channel */
printk("No DMA channel found on ltpc card.\n"); printk(KERN_ERR "No DMA channel found on ltpc card.\n");
restore_flags(flags);
return -1; return -1;
} }
} }
...@@ -1174,9 +1163,9 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1174,9 +1163,9 @@ int __init ltpc_probe(struct net_device *dev)
/* print out friendly message */ /* print out friendly message */
if(irq) if(irq)
printk("Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma); printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma);
else else
printk("Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma); printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma);
/* seems more logical to do this *after* probing the card... */ /* seems more logical to do this *after* probing the card... */
err = ltpc_init(dev); err = ltpc_init(dev);
...@@ -1202,20 +1191,25 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1202,20 +1191,25 @@ int __init ltpc_probe(struct net_device *dev)
(void) inb_p(io+3); (void) inb_p(io+3);
(void) inb_p(io+2); (void) inb_p(io+2);
timeout = jiffies+100*HZ/100; timeout = jiffies+100*HZ/100;
while(time_before(jiffies, timeout)) { while(time_before(jiffies, timeout)) {
if( 0xf9 == inb_p(io+6)) break; if( 0xf9 == inb_p(io+6))
break;
schedule();
} }
if(debug&DEBUG_VERBOSE) { if(debug & DEBUG_VERBOSE) {
printk("setting up timer and irq\n"); printk("setting up timer and irq\n");
} }
if (irq) {
/* grab it and don't let go :-) */ /* grab it and don't let go :-) */
(void) request_irq( irq, &ltpc_interrupt, 0, "ltpc", dev); if (irq && request_irq( irq, &ltpc_interrupt, 0, "ltpc", dev) >= 0)
{
(void) inb_p(io+7); /* enable interrupts from board */ (void) inb_p(io+7); /* enable interrupts from board */
(void) inb_p(io+7); /* and reset irq line */ (void) inb_p(io+7); /* and reset irq line */
} else { } else {
if( irq )
printk(KERN_ERR "ltpc: IRQ already in use, using polled mode.\n");
/* polled mode -- 20 times per second */ /* polled mode -- 20 times per second */
/* this is really, really slow... should it poll more often? */ /* this is really, really slow... should it poll more often? */
init_timer(&ltpc_timer); init_timer(&ltpc_timer);
...@@ -1224,7 +1218,6 @@ int __init ltpc_probe(struct net_device *dev) ...@@ -1224,7 +1218,6 @@ int __init ltpc_probe(struct net_device *dev)
ltpc_timer.expires = jiffies + 5; ltpc_timer.expires = jiffies + 5;
add_timer(&ltpc_timer); add_timer(&ltpc_timer);
restore_flags(flags);
} }
return 0; return 0;
...@@ -1294,7 +1287,7 @@ int __init init_module(void) ...@@ -1294,7 +1287,7 @@ int __init init_module(void)
printk(KERN_DEBUG "could not register Localtalk-PC device\n"); printk(KERN_DEBUG "could not register Localtalk-PC device\n");
return result; return result;
} else { } else {
if(debug&DEBUG_VERBOSE) printk("0 from register_netdev\n"); if(debug & DEBUG_VERBOSE) printk("0 from register_netdev\n");
return 0; return 0;
} }
} }
...@@ -1306,7 +1299,7 @@ static void __exit ltpc_cleanup(void) ...@@ -1306,7 +1299,7 @@ static void __exit ltpc_cleanup(void)
ltpc_timer.data = 0; /* signal the poll routine that we're done */ ltpc_timer.data = 0; /* signal the poll routine that we're done */
if(debug&DEBUG_VERBOSE) printk("freeing irq\n"); if(debug & DEBUG_VERBOSE) printk("freeing irq\n");
if(dev_ltpc.irq) { if(dev_ltpc.irq) {
free_irq(dev_ltpc.irq,&dev_ltpc); free_irq(dev_ltpc.irq,&dev_ltpc);
...@@ -1316,7 +1309,7 @@ static void __exit ltpc_cleanup(void) ...@@ -1316,7 +1309,7 @@ static void __exit ltpc_cleanup(void)
if(del_timer(&ltpc_timer)) if(del_timer(&ltpc_timer))
{ {
/* either the poll was never started, or a poll is in process */ /* either the poll was never started, or a poll is in process */
if(debug&DEBUG_VERBOSE) printk("waiting\n"); if(debug & DEBUG_VERBOSE) printk("waiting\n");
/* if it's in process, wait a bit for it to finish */ /* if it's in process, wait a bit for it to finish */
timeout = jiffies+HZ; timeout = jiffies+HZ;
add_timer(&ltpc_timer); add_timer(&ltpc_timer);
...@@ -1327,31 +1320,31 @@ static void __exit ltpc_cleanup(void) ...@@ -1327,31 +1320,31 @@ static void __exit ltpc_cleanup(void)
} }
} }
if(debug&DEBUG_VERBOSE) printk("freeing dma\n"); if(debug & DEBUG_VERBOSE) printk("freeing dma\n");
if(dev_ltpc.dma) { if(dev_ltpc.dma) {
free_dma(dev_ltpc.dma); free_dma(dev_ltpc.dma);
dev_ltpc.dma = 0; dev_ltpc.dma = 0;
} }
if(debug&DEBUG_VERBOSE) printk("freeing ioaddr\n"); if(debug & DEBUG_VERBOSE) printk("freeing ioaddr\n");
if(dev_ltpc.base_addr) { if(dev_ltpc.base_addr) {
release_region(dev_ltpc.base_addr,8); release_region(dev_ltpc.base_addr,8);
dev_ltpc.base_addr = 0; dev_ltpc.base_addr = 0;
} }
if(debug&DEBUG_VERBOSE) printk("free_pages\n"); if(debug & DEBUG_VERBOSE) printk("free_pages\n");
free_pages( (unsigned long) ltdmabuf, get_order(1000)); free_pages( (unsigned long) ltdmabuf, get_order(1000));
ltdmabuf=NULL; ltdmabuf=NULL;
ltdmacbuf=NULL; ltdmacbuf=NULL;
if(debug&DEBUG_VERBOSE) printk("unregister_netdev\n"); if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n");
unregister_netdev(&dev_ltpc); unregister_netdev(&dev_ltpc);
if(debug&DEBUG_VERBOSE) printk("returning from cleanup_module\n"); if(debug & DEBUG_VERBOSE) printk("returning from cleanup_module\n");
} }
module_exit(ltpc_cleanup); module_exit(ltpc_cleanup);
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