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
- Lines: 488
- Date:
Wed Aug 25 17:29:47 1999
- Orig file:
v2.2.11/linux/drivers/isdn/eicon/eicon_idi.c
- Orig date:
Mon Aug 9 16:05:55 1999
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)