patch-2.0.1 linux/drivers/isdn/icn/icn.c
Next file: linux/drivers/isdn/icn/icn.h
Previous file: linux/drivers/char/tty_io.c
Back to the patch index
Back to the overall index
- Lines: 300
- Date:
Sat Jun 29 20:36:22 1996
- Orig file:
v2.0.0/linux/drivers/isdn/icn/icn.c
- Orig date:
Sun Jun 9 13:28:42 1996
diff -u --recursive --new-file v2.0.0/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.24 1996/06/06 13:58:33 fritz Exp $
+/* $Id: icn.c,v 1.28 1996/06/28 17:02:53 fritz Exp $
*
* ISDN low-level module for the ICN active ISDN-Card.
*
@@ -19,6 +19,23 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: icn.c,v $
+ * Revision 1.28 1996/06/28 17:02:53 fritz
+ * replaced memcpy_fromfs_toio.
+ *
+ * Revision 1.27 1996/06/25 18:38:59 fritz
+ * Fixed function name in error message.
+ *
+ * Revision 1.26 1996/06/24 17:20:35 fritz
+ * Bugfixes in pollbchan_send():
+ * - Using lock field of skbuff breaks networking.
+ * - Added channel locking
+ * - changed dequeuing scheme.
+ * Eliminated misc. compiler warnings.
+ *
+ * Revision 1.25 1996/06/11 22:53:35 tsbogend
+ * fixed problem with large array on stack
+ * made the driver working on Linux/alpha
+ *
* Revision 1.24 1996/06/06 13:58:33 fritz
* Changed code to be architecture independent
*
@@ -119,7 +136,7 @@
#undef MAP_DEBUG
static char
-*revision = "$Revision: 1.24 $";
+*revision = "$Revision: 1.28 $";
static int icn_addcard(int, char *, char *);
@@ -135,10 +152,8 @@
save_flags(flags);
cli();
- while ((skb = skb_dequeue(queue))) {
- skb->free = 1;
- kfree_skb(skb, FREE_WRITE);
- }
+ while ((skb = skb_dequeue(queue)))
+ dev_kfree_skb(skb, FREE_WRITE);
restore_flags(flags);
}
@@ -312,7 +327,7 @@
if (icn_trymaplock_channel(card,mch)) {
while (rbavl) {
- cnt = rbuf_l;
+ cnt = readb(&rbuf_l);
if ((card->rcvidx[channel] + cnt) > 4000) {
printk(KERN_WARNING
"icn: (%s) bogus packet on ch%d, dropping.\n",
@@ -322,9 +337,9 @@
eflag = 0;
} else {
memcpy_fromio(&card->rcvbuf[channel][card->rcvidx[channel]],
- rbuf_d, cnt);
+ &rbuf_d, cnt);
card->rcvidx[channel] += cnt;
- eflag = rbuf_f;
+ eflag = readb(&rbuf_f);
}
rbnext;
icn_maprelease_channel(card, mch & 2);
@@ -367,36 +382,37 @@
while (sbfree && card->sndcount[channel]) {
save_flags(flags);
cli();
- skb = skb_peek(&card->spqueue[channel]);
- if (!skb) {
- restore_flags(flags);
- break;
- }
- if (skb->lock) {
+ if (card->xmit_lock[channel]) {
restore_flags(flags);
break;
}
- skb->lock = 1;
+ card->xmit_lock[channel]++;
restore_flags(flags);
- cnt =
- (sbuf_l =
- (skb->len > ICN_FRAGSIZE) ? ((sbuf_f = 0xff), ICN_FRAGSIZE) : ((sbuf_f = 0), skb->len));
- memcpy(sbuf_d, skb->data, cnt);
+ skb = skb_dequeue(&card->spqueue[channel]);
+ if (!skb)
+ break;
+ if (skb->len > ICN_FRAGSIZE) {
+ writeb (0xff, &sbuf_f);
+ cnt = ICN_FRAGSIZE;
+ } else {
+ writeb (0x0, &sbuf_f);
+ cnt = skb->len;
+ }
+ writeb (cnt, &sbuf_l);
+ memcpy_toio(&sbuf_d, skb->data, cnt);
skb_pull(skb, cnt);
card->sndcount[channel] -= cnt;
sbnext; /* switch to next buffer */
icn_maprelease_channel(card, mch & 2);
if (!skb->len) {
- skb = skb_dequeue(&card->spqueue[channel]);
- skb->free = 1;
- skb->lock = 0;
- kfree_skb(skb, FREE_WRITE);
+ dev_kfree_skb(skb, FREE_WRITE);
cmd.command = ISDN_STAT_BSENT;
cmd.driver = card->myid;
cmd.arg = channel;
card->interface.statcallb(&cmd);
} else
- skb->lock = 0;
+ skb_queue_head(&card->spqueue[channel], skb);
+ card->xmit_lock[channel] = 0;
if (!icn_trymaplock_channel(card, mch))
break;
}
@@ -426,6 +442,7 @@
/* schedule b-channel polling again */
save_flags(flags);
cli();
+ del_timer(&card->rb_timer);
card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
add_timer(&card->rb_timer);
card->flags |= ICN_FLAGS_RBTIMER;
@@ -649,6 +666,7 @@
/* schedule again */
save_flags(flags);
cli();
+ del_timer(&card->st_timer);
card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
add_timer(&card->st_timer);
restore_flags(flags);
@@ -671,8 +689,8 @@
unsigned long flags;
if (len > 4000) {
- skb->free = 1;
- kfree_skb(skb, FREE_WRITE);
+ printk(KERN_WARNING
+ "icn: Send packet too large\n");
return -EINVAL;
}
if (len) {
@@ -685,7 +703,6 @@
card->sndcount[channel] += len;
skb_queue_tail(&card->spqueue[channel], skb);
restore_flags(flags);
- icn_pollbchan_send(channel, card);
}
return len;
}
@@ -751,13 +768,17 @@
{
int ret;
ulong flags;
- unsigned char codebuf[ICN_CODE_STAGE1];
+ u_char *codebuf;
#ifdef BOOT_DEBUG
printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);
#endif
if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE1)))
return ret;
+ if (!(codebuf = kmalloc(ICN_CODE_STAGE1,GFP_KERNEL))) {
+ printk(KERN_WARNING "icn: Could not allocate code buffer\n");
+ return -ENOMEM;
+ }
save_flags(flags);
cli();
if (!card->rvalid) {
@@ -768,6 +789,7 @@
card->port,
card->port + ICN_PORTLEN);
restore_flags(flags);
+ kfree(codebuf);
return -EBUSY;
}
request_region(card->port, ICN_PORTLEN, card->regname);
@@ -804,8 +826,8 @@
icn_lock_channel(card,0); /* Lock Bank 0 */
restore_flags(flags);
SLEEP(1);
- memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1); /* Copy code */
- memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);
+ memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1);
+ memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
#ifdef BOOT_DEBUG
printk(KERN_DEBUG "Bootloader transfered\n");
#endif
@@ -821,12 +843,12 @@
icn_lock_channel(card,2); /* Lock Bank 8 */
restore_flags(flags);
SLEEP(1);
- memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1); /* Copy code */
- memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);
+ memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
#ifdef BOOT_DEBUG
printk(KERN_DEBUG "Bootloader transfered\n");
#endif
}
+ kfree(codebuf);
SLEEP(1);
OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */
if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1)))
@@ -849,6 +871,7 @@
static int icn_loadproto(u_char * buffer, icn_card * card)
{
register u_char *p = buffer;
+ u_char codebuf[256];
uint left = ICN_CODE_STAGE2;
uint cnt;
int timer;
@@ -874,7 +897,8 @@
while (left) {
if (sbfree) { /* If there is a free buffer... */
cnt = MIN(256, left);
- memcpy_fromfs(&sbuf_l, p, cnt); /* copy data */
+ memcpy_fromfs(codebuf, p, cnt);
+ memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data */
sbnext; /* switch to next buffer */
p += cnt;
left -= cnt;
@@ -892,7 +916,7 @@
schedule();
}
}
- sbuf_n = 0x20;
+ writeb (0x20, &sbuf_n);
timer = 0;
while (1) {
if (readb(&cmd_o) || readb(&cmd_i)) {
@@ -1094,7 +1118,7 @@
}
break;
case ICN_IOCTL_GETMMIO:
- return (int) dev.shmem;
+ return (long) dev.shmem;
case ICN_IOCTL_SETPORT:
if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330
|| a == 0x340 || a == 0x350 || a == 0x360 ||
@@ -1391,7 +1415,8 @@
if (card)
return (icn_command(c, card));
printk(KERN_ERR
- "icn: if_command called with invalid driverId!\n");
+ "icn: if_command %d called with invalid driverId %d!\n",
+ c->command, c->driver);
return -ENODEV;
}
@@ -1433,7 +1458,7 @@
return (icn_sendbuf(channel, skb, card));
}
printk(KERN_ERR
- "icn: if_readstatus called with invalid driverId!\n");
+ "icn: if_sendbuf called with invalid driverId!\n");
return -ENODEV;
}
@@ -1455,9 +1480,6 @@
card->interface.channels = ICN_BCH;
card->interface.maxbufsize = 4000;
card->interface.command = if_command;
- /*
- card->interface.writebuf = if_sendbuf;
- */
card->interface.writebuf_skb = if_sendbuf;
card->interface.writecmd = if_writecmd;
card->interface.readstat = if_readstatus;
@@ -1558,7 +1580,7 @@
char rev[10];
memset(&dev, 0, sizeof(icn_dev));
- dev.shmem = (icn_shmem *) (membase & 0x0ffc000);
+ dev.shmem = (icn_shmem *) ((unsigned long)membase & 0x0ffc000);
dev.channel = -1;
dev.mcard = NULL;
@@ -1571,8 +1593,8 @@
*p = 0;
} else
strcpy(rev, " ??? ");
- printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08x\n", rev,
- (uint) dev.shmem);
+ printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
+ (ulong) dev.shmem);
return (icn_addcard(portbase,icn_id,icn_id2));
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov