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

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