patch-2.1.92 linux/drivers/isdn/icn/icn.c
Next file: linux/drivers/isdn/icn/icn.h
Previous file: linux/drivers/isdn/hisax/teles3c.c
Back to the patch index
Back to the overall index
- Lines: 274
- Date:
Wed Apr 1 16:21:02 1998
- Orig file:
v2.1.91/linux/drivers/isdn/icn/icn.c
- Orig date:
Thu Feb 12 20:56:06 1998
diff -u --recursive --new-file v2.1.91/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.44 1997/03/30 16:51:26 calle Exp $
+/* $Id: icn.c,v 1.49 1998/02/13 11:14:15 keil Exp $
* ISDN low-level module for the ICN active ISDN-Card.
*
@@ -19,6 +19,25 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: icn.c,v $
+ * Revision 1.49 1998/02/13 11:14:15 keil
+ * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
+ *
+ * Revision 1.48 1997/10/10 15:56:14 fritz
+ * New HL<->LL interface:
+ * New BSENT callback with nr. of bytes included.
+ * Sending without ACK.
+ *
+ * Revision 1.47 1997/10/01 09:21:51 fritz
+ * Removed old compatibility stuff for 2.0.X kernels.
+ * From now on, this code is for 2.1.X ONLY!
+ * Old stuff is still in the separate branch.
+ *
+ * Revision 1.46 1997/08/21 22:38:33 fritz
+ * Fixed a typo.
+ *
+ * Revision 1.45 1997/06/21 10:42:06 fritz
+ * Added availability to select leased mode on only one channel.
+ *
* Revision 1.44 1997/03/30 16:51:26 calle
* changed calls to copy_from_user/copy_to_user and removed verify_area
* were possible.
@@ -190,7 +209,7 @@
#undef MAP_DEBUG
static char
-*revision = "$Revision: 1.44 $";
+*revision = "$Revision: 1.49 $";
static int icn_addcard(int, char *, char *);
@@ -205,10 +224,20 @@
{
struct sk_buff_head *queue = &card->spqueue[channel];
struct sk_buff *skb;
+ unsigned long flags;
while ((skb = skb_dequeue(queue)))
dev_kfree_skb(skb);
+ save_flags(flags);
+ cli();
+ card->xlen[channel] = 0;
card->sndcount[channel] = 0;
+ if (card->xskb[channel]) {
+ card->xskb[channel] = NULL;
+ restore_flags(flags);
+ dev_kfree_skb(card->xskb[channel]);
+ } else
+ restore_flags(flags);
}
/* Put a value into a shift-register, highest bit first.
@@ -440,12 +469,14 @@
struct sk_buff *skb;
isdn_ctrl cmd;
- if (!(card->sndcount[channel] ||
+ if (!(card->sndcount[channel] || card->xskb[channel] ||
skb_queue_len(&card->spqueue[channel])))
return;
if (icn_trymaplock_channel(card, mch)) {
- while (sbfree && (card->sndcount[channel] ||
- skb_queue_len(&card->spqueue[channel]))) {
+ while (sbfree &&
+ (card->sndcount[channel] ||
+ skb_queue_len(&card->spqueue[channel]) ||
+ card->xskb[channel])) {
save_flags(flags);
cli();
if (card->xmit_lock[channel]) {
@@ -454,7 +485,19 @@
}
card->xmit_lock[channel]++;
restore_flags(flags);
- skb = skb_dequeue(&card->spqueue[channel]);
+ skb = card->xskb[channel];
+ if (!skb) {
+ skb = skb_dequeue(&card->spqueue[channel]);
+ if (skb) {
+ /* Pop ACK-flag off skb.
+ * Store length to xlen.
+ */
+ if (*(skb_pull(skb,1)))
+ card->xlen[channel] = skb->len;
+ else
+ card->xlen[channel] = 0;
+ }
+ }
if (!skb)
break;
if (skb->len > ICN_FRAGSIZE) {
@@ -471,13 +514,22 @@
sbnext; /* switch to next buffer */
icn_maprelease_channel(card, mch & 2);
if (!skb->len) {
- dev_kfree_skb(skb);
- cmd.command = ISDN_STAT_BSENT;
- cmd.driver = card->myid;
- cmd.arg = channel;
- card->interface.statcallb(&cmd);
- } else
- skb_queue_head(&card->spqueue[channel], skb);
+ save_flags(flags);
+ cli();
+ if (card->xskb[channel]) {
+ card->xskb[channel] = NULL;
+ restore_flags(flags);
+ dev_kfree_skb(skb);
+ } else
+ restore_flags(flags);
+ if (card->xlen[channel]) {
+ cmd.command = ISDN_STAT_BSENT;
+ cmd.driver = card->myid;
+ cmd.arg = channel;
+ cmd.parm.length = card->xlen[channel];
+ card->interface.statcallb(&cmd);
+ }
+ }
card->xmit_lock[channel] = 0;
if (!icn_trymaplock_channel(card, mch))
break;
@@ -557,12 +609,11 @@
* This routine is called periodically via timer.
*/
-static int
+static void
icn_parse_status(u_char * status, int channel, icn_card * card)
{
icn_stat *s = icn_stat_table;
int action = -1;
- int dflag = 0;
unsigned long flags;
isdn_ctrl cmd;
@@ -575,7 +626,7 @@
s++;
}
if (action == -1)
- return 0;
+ return;
cmd.driver = card->myid;
cmd.arg = channel;
switch (action) {
@@ -591,7 +642,6 @@
cli();
card->rcvidx[channel] = 0;
restore_flags(flags);
- dflag |= (channel + 1);
break;
case 3:
{
@@ -645,7 +695,6 @@
strncpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num) - 1);
break;
case 8:
- dflag = 3;
card->flags &= ~ICN_FLAGS_B1ACTIVE;
icn_free_queue(card, 0);
save_flags(flags);
@@ -675,7 +724,7 @@
break;
}
card->interface.statcallb(&cmd);
- return dflag;
+ return;
}
static void
@@ -701,7 +750,6 @@
icn_card *card = (icn_card *) data;
int mch = card->secondhalf ? 2 : 0;
int avail = 0;
- int dflag = 0;
int left;
u_char c;
int ch;
@@ -722,7 +770,7 @@
card->imsg[1] <= '2' && card->imsg[2] == ';') {
ch = (card->imsg[1] - '0') - 1;
p = &card->imsg[3];
- dflag |= icn_parse_status(p, ch, card);
+ icn_parse_status(p, ch, card);
} else {
p = card->imsg;
if (!strncmp(p, "DRV1.", 5)) {
@@ -771,10 +819,6 @@
cmd.arg = avail;
card->interface.statcallb(&cmd);
}
- if (dflag & 1)
- card->interface.rcvcallb(card->myid, 0, card->rcvbuf[0], 0);
- if (dflag & 2)
- card->interface.rcvcallb(card->myid, 1, card->rcvbuf[1], 0);
if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE))
if (!(card->flags & ICN_FLAGS_RBTIMER)) {
/* schedule b-channel polling */
@@ -807,7 +851,7 @@
*/
static int
-icn_sendbuf(int channel, struct sk_buff *skb, icn_card * card)
+icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card)
{
int len = skb->len;
unsigned long flags;
@@ -827,6 +871,10 @@
cli();
nskb = skb_clone(skb, GFP_ATOMIC);
if (nskb) {
+ /* Push ACK flag as one
+ * byte in front of data.
+ */
+ *(skb_push(nskb, 1)) = ack?1:0;
skb_queue_tail(&card->spqueue[channel], nskb);
dev_kfree_skb(skb);
} else
@@ -1382,7 +1430,8 @@
}
current->timeout = jiffies + ICN_BOOT_TIMEOUT1;
schedule();
- sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n");
+ sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n",
+ (a & 1)?'1':'C', (a & 2)?'2':'C');
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
printk(KERN_INFO
"icn: (%s) Leased-line mode enabled\n",
@@ -1638,14 +1687,14 @@
}
static int
-if_sendbuf(int id, int channel, struct sk_buff *skb)
+if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
{
icn_card *card = icn_findcard(id);
if (card) {
if (!card->flags & ICN_FLAGS_RUNNING)
return -ENODEV;
- return (icn_sendbuf(channel, skb, card));
+ return (icn_sendbuf(channel, ack, skb, card));
}
printk(KERN_ERR
"icn: if_sendbuf called with invalid driverId!\n");
@@ -1669,6 +1718,7 @@
}
memset((char *) card, 0, sizeof(icn_card));
card->port = port;
+ card->interface.hl_hdrlen = 1;
card->interface.channels = ICN_BCH;
card->interface.maxbufsize = 4000;
card->interface.command = if_command;
@@ -1781,11 +1831,7 @@
dev.firstload = 1;
/* No symbols to export, hide all symbols */
-#if (LINUX_VERSION_CODE < 0x020111)
- register_symtab(NULL);
-#else
EXPORT_NO_SYMBOLS;
-#endif
if ((p = strchr(revision, ':'))) {
strcpy(rev, p + 1);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov