summaryrefslogtreecommitdiffstats
path: root/drivers/isdn/icn
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/icn')
-rw-r--r--drivers/isdn/icn/icn.c112
-rw-r--r--drivers/isdn/icn/icn.h17
2 files changed, 93 insertions, 36 deletions
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 0d839512d..2cc0e17f4 100644
--- a/drivers/isdn/icn/icn.c
+++ b/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 @@ icn_free_queue(icn_card * card, int channel)
{
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 @@ icn_pollbchan_send(int channel, icn_card * card)
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 @@ icn_pollbchan_send(int channel, icn_card * card)
}
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 @@ icn_pollbchan_send(int channel, icn_card * card)
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 @@ static icn_stat icn_stat_table[] =
* 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 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
s++;
}
if (action == -1)
- return 0;
+ return;
cmd.driver = card->myid;
cmd.arg = channel;
switch (action) {
@@ -591,7 +642,6 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
cli();
card->rcvidx[channel] = 0;
restore_flags(flags);
- dflag |= (channel + 1);
break;
case 3:
{
@@ -645,7 +695,6 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
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 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
break;
}
card->interface.statcallb(&cmd);
- return dflag;
+ return;
}
static void
@@ -701,7 +750,6 @@ icn_polldchan(unsigned long data)
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 @@ icn_polldchan(unsigned long data)
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 @@ icn_polldchan(unsigned long data)
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 @@ icn_polldchan(unsigned long data)
*/
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 @@ icn_sendbuf(int channel, struct sk_buff *skb, icn_card * card)
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 @@ icn_command(isdn_ctrl * c, icn_card * card)
}
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 @@ if_readstatus(u_char * buf, int len, int user, int id, int channel)
}
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 @@ icn_initcard(int port, char *id)
}
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 @@ icn_init(void)
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);
diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h
index 991d57e4d..3bd2819ce 100644
--- a/drivers/isdn/icn/icn.h
+++ b/drivers/isdn/icn/icn.h
@@ -1,4 +1,4 @@
-/* $Id: icn.h,v 1.26 1997/02/14 12:23:16 fritz Exp $
+/* $Id: icn.h,v 1.28 1997/10/10 15:56:18 fritz Exp $
* ISDN lowlevel-module for the ICN active ISDN-Card.
*
@@ -19,6 +19,16 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: icn.h,v $
+ * Revision 1.28 1997/10/10 15:56:18 fritz
+ * New HL<->LL interface:
+ * New BSENT callback with nr. of bytes included.
+ * Sending without ACK.
+ *
+ * Revision 1.27 1997/10/01 09:21:56 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.26 1997/02/14 12:23:16 fritz
* Added support for new insmod parameter handling.
*
@@ -265,6 +275,9 @@ typedef struct icn_card {
char *msg_buf_read; /* Readpointer for statusbuffer */
char *msg_buf_end; /* Pointer to end of statusbuffer */
int sndcount[ICN_BCH]; /* Byte-counters for B-Ch.-send */
+ int xlen[ICN_BCH]; /* Byte-counters/Flags for sent-ACK */
+ struct sk_buff *xskb[ICN_BCH];
+ /* Current transmitted skb */
struct sk_buff_head
spqueue[ICN_BCH]; /* Sendqueue */
char regname[35]; /* Name used for request_region */
@@ -303,7 +316,6 @@ static char *icn_id = "\0";
static char *icn_id2 = "\0";
#ifdef MODULE
-#if (LINUX_VERSION_CODE > 0x020111)
MODULE_AUTHOR("Fritz Elfert");
MODULE_PARM(portbase, "i");
MODULE_PARM_DESC(portbase, "Port adress of first card");
@@ -314,7 +326,6 @@ MODULE_PARM_DESC(icn_id, "ID-String of first card");
MODULE_PARM(icn_id2, "s");
MODULE_PARM_DESC(icn_id2, "ID-String of first card, second S0 (4B only)");
#endif
-#endif
#endif /* __KERNEL__ */