patch-2.2.12 linux/drivers/isdn/eicon/eicon_idi.c

Next file: linux/drivers/isdn/eicon/eicon_idi.h
Previous file: linux/drivers/isdn/eicon/eicon_dsp.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.11/linux/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.10 1999/07/11 17:16:24 armin Exp $
+/* $Id: eicon_idi.c,v 1.11 1999/07/25 15:12:03 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  *        IDI interface 
@@ -21,6 +21,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.c,v $
+ * Revision 1.11  1999/07/25 15:12:03  armin
+ * fix of some debug logs.
+ * enabled ISA-cards option.
+ *
  * Revision 1.10  1999/07/11 17:16:24  armin
  * Bugfixes in queue handling.
  * Added DSP-DTMF decoder functions.
@@ -73,7 +77,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.10 $";
+char *eicon_idi_revision = "$Revision: 1.11 $";
 
 eicon_manifbuf *manbuf;
 
@@ -91,6 +95,7 @@
 
 int eicon_idi_manage_assign(eicon_card *card);
 int eicon_idi_manage_remove(eicon_card *card);
+int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer);
 
 int
 idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
@@ -141,10 +146,25 @@
 		case ISDN_PROTO_L2_MODEM:
 			reqbuf->XBuffer.P[l++] = 2;
 			break;
+		case ISDN_PROTO_L2_FAX:
+  			if (chan->fsm_state == EICON_STATE_IWAIT)
+				reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */
+			else
+				reqbuf->XBuffer.P[l++] = 2;
+			break;
 		default:
 			reqbuf->XBuffer.P[l++] = 1;
 	}
 	switch(chan->l3prot) {
+		case ISDN_PROTO_L3_FAX:
+#ifdef CONFIG_ISDN_TTY_FAX
+			reqbuf->XBuffer.P[l++] = 6;
+			reqbuf->XBuffer.P[l++] = NLC;
+			tmp = idi_fill_in_T30(chan, &reqbuf->XBuffer.P[l+1]);
+			reqbuf->XBuffer.P[l++] = tmp; 
+			l += tmp;
+			break;
+#endif
 		case ISDN_PROTO_L3_TRANS:
 		default:
 			reqbuf->XBuffer.P[l++] = 4;
@@ -218,6 +238,14 @@
 			reqbuf->XBuffer.P[6] = 128;
 			reqbuf->XBuffer.P[7] = 0;
 			break;
+		case ISDN_PROTO_L2_FAX:
+			reqbuf->XBuffer.P[2] = 0x10;
+			reqbuf->XBuffer.P[3] = 0;
+			reqbuf->XBuffer.P[4] = 0;
+			reqbuf->XBuffer.P[5] = 0;
+			reqbuf->XBuffer.P[6] = 128;
+			reqbuf->XBuffer.P[7] = 0;
+			break;
 		case ISDN_PROTO_L2_TRANS:
 			switch(chan->l3prot) {
 				case ISDN_PROTO_L3_TRANSDSP:
@@ -236,8 +264,8 @@
 int
 idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
 {
-        struct sk_buff *skb;
-        struct sk_buff *skb2;
+        struct sk_buff *skb = 0;
+        struct sk_buff *skb2 = 0;
 	eicon_REQ *reqbuf;
 	eicon_chan_ptr *chan2;
 
@@ -246,7 +274,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No);
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
                 return -ENOMEM; 
 	}
 
@@ -255,7 +287,7 @@
 
 	reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
 	if (DebugVar & 8)
-		printk(KERN_DEBUG "idi_req: Ch%d: 0x%02x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
+		printk(KERN_DEBUG "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
 	if (layer) cmd |= 0x700;
 	switch(cmd) {
 		case ASSIGN:
@@ -296,6 +328,8 @@
 		default:
 			if (DebugVar & 1)
 				printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No);
+			dev_kfree_skb(skb);
+			dev_kfree_skb(skb2);
 			return(-1);
 	}
 
@@ -372,6 +406,9 @@
 	chan->fsm_state = EICON_STATE_NULL;
 	if (DebugVar & 8)
 		printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No);
+#ifdef CONFIG_ISDN_TTY_FAX
+	chan->fax = 0;
+#endif
   return(0);
 }
 
@@ -403,7 +440,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No);
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
                 return -ENOMEM; 
 	}
 
@@ -486,6 +527,14 @@
 			reqbuf->XBuffer.P[l-2] = 128;
 			reqbuf->XBuffer.P[l-1] = 0;
                         break;
+                case ISDN_PROTO_L2_FAX:
+			reqbuf->XBuffer.P[l-6] = 0x10;
+			reqbuf->XBuffer.P[l-5] = 0;
+			reqbuf->XBuffer.P[l-4] = 0;
+			reqbuf->XBuffer.P[l-3] = 0;
+			reqbuf->XBuffer.P[l-2] = 128;
+			reqbuf->XBuffer.P[l-1] = 0;
+                        break;
 		case ISDN_PROTO_L2_TRANS:
 			switch(chan->l3prot) {
 				case ISDN_PROTO_L3_TRANSDSP:
@@ -833,6 +882,7 @@
   }
 }
 
+
 int
 idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len)
 {
@@ -855,8 +905,12 @@
 
 	if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-			printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
-			return -ENOMEM;
+			printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No);
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
+		return -ENOMEM;
 	}
 
 	chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
@@ -991,7 +1045,7 @@
 	
 	if ((DebugVar & 128) || 
 	   ((DebugVar & 16) && (ind->Ind != 8))) {
-        	printk(KERN_DEBUG "idi_hdl: Ch%d: Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No,
+        	printk(KERN_DEBUG "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No,
 		        ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
 	}
 
@@ -1025,6 +1079,9 @@
 				cmd.command = ISDN_STAT_DHUP;
 				ccard->interface.statcallb(&cmd);
 				eicon_idi_listen_req(ccard, chan);
+#ifdef CONFIG_ISDN_TTY_FAX
+				chan->fax = 0;
+#endif
 				break;
 			case INDICATE_IND:
 				if (DebugVar & 8)
@@ -1098,7 +1155,15 @@
 					cmd.command = ISDN_STAT_DCONN;
 					cmd.arg = chan->No;
 					ccard->interface.statcallb(&cmd);
-					idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+					if (chan->l2prot != ISDN_PROTO_L2_FAX) {
+						idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+					}
+#ifdef CONFIG_ISDN_TTY_FAX
+					else {
+						if (chan->fax)
+							chan->fax->phase = ISDN_FAX_PHASE_A;
+					}
+#endif
 				} else
 					idi_hangup(ccard, chan);
 				break;
@@ -1113,6 +1178,12 @@
 					ccard->interface.statcallb(&cmd);
 					idi_do_req(ccard, chan, ASSIGN, 1); 
 					idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+#ifdef CONFIG_ISDN_TTY_FAX
+					if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+						if (chan->fax)
+							chan->fax->phase = ISDN_FAX_PHASE_A;
+					}
+#endif
 				} else
 				idi_hangup(ccard, chan);
 				break;
@@ -1142,6 +1213,27 @@
 					chan->fsm_state = EICON_STATE_WMCONN;
 					break;
 				}
+				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+#ifdef CONFIG_ISDN_TTY_FAX
+					chan->fsm_state = EICON_STATE_ACTIVE;
+					idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
+					if (chan->fax) {
+						if (chan->fax->phase == ISDN_FAX_PHASE_B) {
+							idi_fax_send_header(ccard, chan, 2);
+							cmd.driver = ccard->myid;
+							cmd.command = ISDN_STAT_FAXIND;
+							cmd.arg = chan->No;
+							chan->fax->r_code = ISDN_TTY_FAX_DCS;
+							ccard->interface.statcallb(&cmd);
+						}
+					}
+					else {
+						if (DebugVar & 1)
+							printk(KERN_DEBUG "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
+					}
+#endif
+					break;
+				}
 				chan->fsm_state = EICON_STATE_ACTIVE;
 				cmd.driver = ccard->myid;
 				cmd.command = ISDN_STAT_BCONN;
@@ -1152,6 +1244,9 @@
 				if (DebugVar & 16)
   					printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect\n", chan->No);
 				if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
+				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+					break;
+				}
 				if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
 					chan->fsm_state = EICON_STATE_WMCONN;
 					break;
@@ -1169,6 +1264,12 @@
 					idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
 					idi_do_req(ccard, chan, REMOVE, 1);
 				}
+#ifdef CONFIG_ISDN_TTY_FAX
+				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+					idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
+					idi_fax_hangup(ccard, chan);
+				}
+#endif
 				chan->queued = 0;
 				chan->waitq = 0;
 				chan->waitpq = 0;
@@ -1182,6 +1283,12 @@
 			case IDI_N_DISC_ACK:
 				if (DebugVar & 16)
   					printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
+#ifdef CONFIG_ISDN_TTY_FAX
+				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+					idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
+					idi_fax_hangup(ccard, chan);
+				}
+#endif
 				break; 
 			case IDI_N_DATA_ACK:
 				if (DebugVar & 16)
@@ -1191,12 +1298,23 @@
 				skb_pull(skb, sizeof(eicon_IND) - 1);
 				if (DebugVar & 128)
 					printk(KERN_DEBUG"idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
-				ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);
-				free_buff = 0; 
+				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+#ifdef CONFIG_ISDN_TTY_FAX
+					idi_faxdata_rcv(ccard, chan, skb);
+#endif
+				} else {
+					ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);
+					free_buff = 0; 
+				}
 				break; 
 			case IDI_N_UDATA:
 				idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
 				break; 
+#ifdef CONFIG_ISDN_TTY_FAX
+			case IDI_N_EDATA:
+				idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
+				break; 
+#endif
 			default:
 				if (DebugVar & 8)
 					printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind);
@@ -1231,21 +1349,19 @@
 
 	/* Remove an Id */
 	if (chan->e.Req == REMOVE) {
-		if (ack->Reference == chan->e.ref) {
-			ccard->IdTable[ack->RcId] = NULL;
-			if (DebugVar & 16)
-				printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%d Ch=%d (%s)\n", chan->No,
-					ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
-			if (!chan->e.ReqCh) 
-				chan->e.D3Id = 0;
-			else
-				chan->e.B2Id = 0;
-		}
-		else {
+		if (ack->Reference != chan->e.ref) {
 			if (DebugVar & 1)
 				printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
 					ack->Reference, chan->e.ref);
 		}
+		ccard->IdTable[ack->RcId] = NULL;
+		if (DebugVar & 16)
+			printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%d Ch=%d (%s)\n", chan->No,
+				ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
+		if (!chan->e.ReqCh) 
+			chan->e.D3Id = 0;
+		else
+			chan->e.B2Id = 0;
 		return;
 	}
 
@@ -1268,6 +1384,25 @@
 						ccard->interface.statcallb(&cmd);
 					}
 					chan->waitpq = 0;
+#ifdef CONFIG_ISDN_TTY_FAX
+					if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+						if (((chan->queued - chan->waitq) < 1) &&
+						    (chan->fax2.Eop)) {
+							chan->fax2.Eop = 0;
+							if (chan->fax) {
+								cmd.driver = ccard->myid;
+								cmd.command = ISDN_STAT_FAXIND;
+								cmd.arg = chan->No;
+								chan->fax->r_code = ISDN_TTY_FAX_SENT;
+								ccard->interface.statcallb(&cmd);
+							}
+							else {
+								if (DebugVar & 1)
+									printk(KERN_DEBUG "idi_ack: Sent with NULL fax struct, ERROR\n");
+							}
+						}
+					}
+#endif
 				}
 				chan->queued -= chan->waitq;
 				if (chan->queued < 0) chan->queued = 0;
@@ -1300,6 +1435,7 @@
 			if (DebugVar & 1)
 				printk(KERN_ERR "idi_ack: Ch%d: unhandled RC 0x%x\n",
 					dCh, ack->Rc);
+			break;
 		case READY_INT:
 		case TIMER_INT:
 			/* we do nothing here */
@@ -1317,7 +1453,7 @@
 		case ASSIGN_OK:
 			if (chan) {
 				if (DebugVar & 1)
-					printk(KERN_ERR "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%d,%d)\n",
+					printk(KERN_ERR "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n",
 						chan->No, chan->e.D3Id, chan->e.B2Id);
 			}
 			for(j = 0; j < ccard->nchannels + 1; j++) {
@@ -1330,7 +1466,7 @@
 					ccard->bch[j].e.busy = 0;
 					ccard->bch[j].e.ref = 0;
 					if (DebugVar & 16)
-						printk(KERN_DEBUG"idi_ack: Ch%d: Id %d assigned (%s)\n", j, 
+						printk(KERN_DEBUG"idi_ack: Ch%d: Id %x assigned (%s)\n", j, 
 							ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
 					break;
 				}
@@ -1407,10 +1543,14 @@
 	        xmit_skb = alloc_skb(plen + sizeof(eicon_REQ), GFP_ATOMIC);
         	skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
-	        if ((!skb) || (!skb2)) {
+	        if ((!xmit_skb) || (!skb2)) {
 			restore_flags(flags);
 			if (DebugVar & 1)
-	        	        printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+	        	        printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No);
+			if (xmit_skb) 
+				dev_kfree_skb(skb);
+			if (skb2) 
+				dev_kfree_skb(skb2);
                 	return -ENOMEM;
 	        }
 
@@ -1462,7 +1602,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-			printk(KERN_WARNING "idi_err: alloc_skb failed\n");
+			printk(KERN_WARNING "idi_err: alloc_skb failed in manage_assign()\n");
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
                 return -ENOMEM;
         }
 
@@ -1501,7 +1645,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: alloc_skb failed\n");
+                	printk(KERN_WARNING "idi_err: alloc_skb failed in manage_remove()\n");
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
                 return -ENOMEM;
         }
 
@@ -1538,7 +1686,8 @@
 
         chan = &(card->bch[card->nchannels]);
 
-	if (chan->e.D3Id) return -EBUSY;
+	if (chan->e.D3Id)
+		return -EBUSY;
 	chan->e.D3Id = 1;
 	while((skb2 = skb_dequeue(&chan->e.X)))
 		dev_kfree_skb(skb2);
@@ -1568,6 +1717,7 @@
 		return -ENOMEM;
 	}
 	if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) {
+		kfree(manbuf);
 		chan->e.D3Id = 0;
 		return -EFAULT;
 	}
@@ -1577,7 +1727,11 @@
 
         if ((!skb) || (!skb2)) {
 		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err_manif: alloc_skb failed\n");
+                	printk(KERN_WARNING "idi_err_manif: alloc_skb failed in manage()\n");
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
 		kfree(manbuf);
 		chan->e.D3Id = 0;
                 return -ENOMEM;
@@ -1623,11 +1777,13 @@
 	}
 
 	if ((ret = eicon_idi_manage_remove(card))) {
+		kfree(manbuf);
 		chan->e.D3Id = 0;
 		return(ret);
 	}
 
 	if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) {
+		kfree(manbuf);
 		chan->e.D3Id = 0;
 		return -EFAULT;
 	}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)