Changed queue management to use sk_buffs.

This commit is contained in:
Fritz Elfert 1996-05-11 21:52:34 +00:00
parent ef7e782528
commit 170943e874
3 changed files with 240 additions and 235 deletions

View File

@ -21,6 +21,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.10 1996/05/10 08:49:16 fritz
* Checkin before major changes of tty-code.
*
* Revision 1.9 1996/05/07 09:19:41 fritz
* Adapted to changes in isdn_tty.c
*
@ -116,45 +119,19 @@ void isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
}
#endif
/* Try to allocate a new buffer, link it into queue. */
u_char *
isdn_new_buf(pqueue ** queue, int length)
static void isdn_free_queue(struct sk_buff_head *queue)
{
pqueue *p;
pqueue *q;
struct sk_buff *skb;
unsigned long flags;
if ((p = *queue)) {
while (p) {
q = p;
p = (pqueue *) p->next;
}
p = (pqueue *) kmalloc(sizeof(pqueue) + length, GFP_ATOMIC);
q->next = (u_char *) p;
} else
p = *queue = (pqueue *) kmalloc(sizeof(pqueue) + length, GFP_ATOMIC);
if (p) {
p->size = sizeof(pqueue) + length;
p->length = length;
p->next = NULL;
p->rptr = p->buffer;
return p->buffer;
} else {
return (u_char *) NULL;
}
}
static void isdn_free_queue(pqueue ** queue)
{
pqueue *p;
pqueue *q;
p = *queue;
while (p) {
q = p;
p = (pqueue *) p->next;
kfree_s(q, q->size);
}
*queue = (pqueue *) 0;
save_flags(flags);
cli();
if (skb_queue_len(queue))
while ((skb = skb_dequeue(queue))) {
skb->free = 1;
kfree_skb(skb,FREE_READ);
}
restore_flags(flags);
}
int isdn_dc2minor(int di, int ch)
@ -236,57 +213,56 @@ void isdn_timer_ctrl(int tf, int onoff)
restore_flags(flags);
}
/* Receive a packet from B-Channel. (Called from low-level-module)
* Parameters:
*
* di = Driver-Index.
* channel = Number of B-Channel (0...)
* buf = pointer to packet-data
* len = Length of packet-data
*
/*
* Receive a packet from B-Channel. (Called from low-level-module)
*/
static void isdn_receive_callback(int di, int channel, u_char * buf, int len)
static void isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
{
ulong flags;
char *p;
int len;
int i;
int midx;
modem_info *info;
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
skb->free = 1;
kfree_skb(skb, FREE_READ);
return;
if ((i = isdn_dc2minor(di,channel))==-1)
}
if ((i = isdn_dc2minor(di,channel))==-1) {
skb->free = 1;
kfree_skb(skb, FREE_READ);
return;
}
/* Update statistics */
dev->ibytes[i] += len;
dev->ibytes[i] += skb->len;
/* First, try to deliver data to network-device */
if (isdn_net_receive_callback(i, buf, len))
if (isdn_net_rcv_skb(i, skb))
return;
/* No network-device found, deliver to tty or raw-channel */
if (len) {
save_flags(flags);
cli();
if (skb->len) {
if ((midx = dev->m_idx[i])<0) {
restore_flags(flags);
skb->free = 1;
kfree_skb(skb, FREE_READ);
return;
}
info = &dev->mdm.info[midx];
if ((info->online < 2) &&
(info->vonline != 1)) {
/* If Modem not listening, drop data */
restore_flags(flags);
skb->free = 1;
kfree_skb(skb, FREE_READ);
return;
}
if (info->emu.mdmreg[13] & 2)
/* T.70 decoding: Simply throw away the T.70 header (4 bytes) */
if ((buf[0] == 1) && ((buf[1] == 0) || (buf[1] == 1))) {
if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1))) {
#ifdef ISDN_DEBUG_MODEM_DUMP
isdn_dumppkt("T70strip1:", buf, len, len);
isdn_dumppkt("T70strip1:", skb->data, skb->len, skb->len);
#endif
buf += 4;
len -= 4;
skb_pull(skb,4);
#ifdef ISDN_DEBUG_MODEM_DUMP
isdn_dumppkt("T70strip2:", buf, len, len);
isdn_dumppkt("T70strip2:", skb->data, skb->len, skb->len);
#endif
}
#ifdef CONFIG_ISDN_AUDIO
@ -303,49 +279,46 @@ static void isdn_receive_callback(int di, int channel, u_char * buf, int len)
*/
len = isdn_audio_xlaw2adpcm(info->adpcmr,
ifmt,
buf,
buf,
len);
skb->data,
skb->data,
skb->len);
break;
case 5:
/* a-law */
if (!ifmt)
isdn_audio_ulaw2alaw(buf,len);
isdn_audio_ulaw2alaw(skb->data,skb->len);
break;
case 6:
/* u-law */
if (ifmt)
isdn_audio_alaw2ulaw(buf,len);
isdn_audio_alaw2ulaw(skb->data,skb->len);
break;
}
len = isdn_tty_handleDLEup(buf,len);
isdn_tty_handleDLEup(skb->data,skb->len);
}
#endif
/* Try to deliver directly via tty-flip-buf if queue is empty */
if (!dev->drv[di]->rpqueue[channel])
if (isdn_tty_try_read(info, buf, len)) {
save_flags(flags);
cli();
if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
if (isdn_tty_try_read(info, skb)) {
restore_flags(flags);
return;
}
/* Direct deliver failed or queue wasn't empty.
* Queue up for later dequeueing via timer-irq.
*/
p = isdn_new_buf(&dev->drv[di]->rpqueue[channel], len);
if (!p) {
printk(KERN_WARNING "isdn: malloc of rcvbuf failed, dropping.\n");
dev->drv[di]->rcverr[channel]++;
restore_flags(flags);
return;
} else {
memcpy(p, buf, len);
dev->drv[di]->rcvcount[channel] += len;
}
__skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb);
dev->drv[di]->rcvcount[channel] += skb->len;
restore_flags(flags);
/* Schedule dequeuing */
if ((dev->modempoll) && (info->rcvsched))
isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]);
restore_flags(flags);
}
} else {
skb->free = 1;
kfree_skb(skb, FREE_READ);
}
}
void isdn_all_eaz(int di, int ch)
@ -633,6 +606,7 @@ static int isdn_status_callback(isdn_ctrl * c)
kfree(dev->drv[di]->rcvcount);
for (i = 0; i < dev->drv[di]->channels; i++)
isdn_free_queue(&dev->drv[di]->rpqueue[i]);
kfree(dev->drv[di]->rpqueue);
kfree(dev->drv[di]->rcv_waitq);
kfree(dev->drv[di]->snd_waitq);
kfree(dev->drv[di]);
@ -667,17 +641,17 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
int copy_l;
int dflag;
int flags;
pqueue *p;
struct sk_buff *skb;
u_char *cp;
if (!dev->drv[di]->rpqueue[channel]) {
if (!dev->drv[di])
return 0;
if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
if (user)
interruptible_sleep_on(&dev->drv[di]->rcv_waitq[channel]);
else
return 0;
}
if (!dev->drv[di])
return 0;
save_flags(flags);
cli();
avail = dev->drv[di]->rcvcount[channel];
@ -686,16 +660,17 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
cp = buf;
count = 0;
while (left) {
if ((copy_l = dev->drv[di]->rpqueue[channel]->length) > left) {
if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
break;
if ((copy_l = skb->len) > left) {
copy_l = left;
dflag = 0;
} else
dflag = 1;
p = dev->drv[di]->rpqueue[channel];
if (user)
memcpy_tofs(cp, p->rptr, copy_l);
memcpy_tofs(cp, skb->data, copy_l);
else
memcpy(cp, p->rptr, copy_l);
memcpy(cp, skb->data, copy_l);
if (fp) {
memset(fp, 0, copy_l);
fp += copy_l;
@ -706,15 +681,11 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
if (dflag) {
if (fp)
*(fp - 1) = 0xff;
save_flags(flags);
cli();
dev->drv[di]->rpqueue[channel] = (pqueue *) p->next;
kfree_s(p, p->size);
restore_flags(flags);
} else {
p->rptr += copy_l;
p->length -= copy_l;
}
skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
skb->free = 1;
kfree_skb(skb, FREE_READ);
} else
skb_pull(skb,copy_l);
save_flags(flags);
cli();
dev->drv[di]->rcvcount[channel] -= copy_l;
@ -1720,31 +1691,35 @@ void isdn_unexclusive_channel(int di, int ch)
}
/*
* receive callback handler for drivers supporting sk_buff's.
* receive callback handler for drivers not supporting sk_buff's.
* Parameters:
*
* di = Driver-Index.
* channel = Number of B-Channel (0...)
* buf = pointer to packet-data
* len = Length of packet-data
*
*/
void isdn_receive_skb_callback(int drvidx, int chan, struct sk_buff *skb)
void isdn_receive_callback(int drvidx, int chan, u_char *buf, int len)
{
int i, len;
int i;
struct sk_buff *skb;
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return;
if ((i = isdn_dc2minor(drvidx,chan))==-1)
return;
len = skb->len;
if (isdn_net_rcv_skb(i, skb) == 0) {
isdn_receive_callback(drvidx, chan, skb->data, skb->len);
skb->free = 1;
kfree_skb(skb, FREE_READ);
} else
/* Update statistics */
dev->ibytes[i] += len;
skb = alloc_skb(len+16, GFP_ATOMIC);
if (skb) {
memcpy(skb_put(skb, len), buf, len);
skb->free = 1;
isdn_receive_skb_callback(drvidx, chan, skb);
}
}
/*
* writebuf replacement for SKB_ABLE drivers
*/
int isdn_writebuf_stub(int drvidx, int chan, const u_char *buf, int len,
int user)
{
@ -1846,14 +1821,17 @@ int register_isdn(isdn_if * i)
return 0;
}
memset((char *) d->rcvcount, 0, sizeof(int) * n);
if (!(d->rpqueue = (pqueue **) kmalloc(sizeof(pqueue *) * n, GFP_KERNEL))) {
printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
kfree(d->rcvcount);
kfree(d->rcverr);
kfree(d);
return 0;
}
memset((char *) d->rpqueue, 0, sizeof(pqueue *) * n);
if (!(d->rpqueue =
(struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * n, GFP_KERNEL))) {
printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
kfree(d->rcvcount);
kfree(d->rcverr);
kfree(d);
return 0;
}
for (j = 0; j < n; j++) {
skb_queue_head_init(&d->rpqueue[j]);
}
if (!(d->rcv_waitq = (struct wait_queue **)
kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
@ -1993,7 +1971,7 @@ int isdn_init(void)
tty_unregister_driver(&dev->mdm.tty_modem);
tty_unregister_driver(&dev->mdm.cua_modem);
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
kfree(dev->mdm.info[i].xmit_buf - 4);
kfree(dev->mdm.info[i].xmit_buf);
unregister_chrdev(ISDN_MAJOR, "isdn");
kfree(dev);
return -EIO;
@ -2047,8 +2025,10 @@ void cleanup_module(void)
restore_flags(flags);
return;
}
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
kfree(dev->mdm.info[i].xmit_buf - 4);
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
isdn_tty_cleanup_xmit(&dev->mdm.info[i]);
kfree(dev->mdm.info[i].xmit_buf);
}
if (unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {
printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
} else {

View File

@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.8 1996/05/10 08:49:43 fritz
* Checkin before major changes of tty-code.
*
* Revision 1.7 1996/05/07 09:15:09 fritz
* Reorganized and general cleanup.
* Bugfixes:
@ -59,7 +62,7 @@
#include "isdn_tty.h"
#ifdef CONFIG_ISDN_AUDIO
#include "isdn_audio.h"
#define VBUF 256
#define VBUF 0x300
#define VBUFX (VBUF/16)
#endif
@ -90,7 +93,7 @@ char *isdn_tty_revision = "$Revision$";
* 0 = Failure, data has to be bufferd and later processed by
* isdn_tty_readmodem().
*/
int isdn_tty_try_read(modem_info *info, u_char * buf, int len)
int isdn_tty_try_read(modem_info *info, struct sk_buff *skb)
{
int c;
struct tty_struct *tty;
@ -99,18 +102,20 @@ int isdn_tty_try_read(modem_info *info, u_char * buf, int len)
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
c = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
if (c >= len) {
if (len > 1) {
memcpy(tty->flip.char_buf_ptr, buf, len);
tty->flip.count += len;
memset(tty->flip.flag_buf_ptr, 0, len);
if (c >= skb->len) {
if (skb->len > 1) {
memcpy(tty->flip.char_buf_ptr, skb->data, skb->len);
tty->flip.count += skb->len;
memset(tty->flip.flag_buf_ptr, 0, skb->len);
if (info->emu.mdmreg[12] & 128)
tty->flip.flag_buf_ptr[len - 1] = 0xff;
tty->flip.flag_buf_ptr += len;
tty->flip.char_buf_ptr += len;
tty->flip.flag_buf_ptr[skb->len - 1] = 0xff;
tty->flip.flag_buf_ptr += skb->len;
tty->flip.char_buf_ptr += skb->len;
} else
tty_insert_flip_char(tty, buf[0], 0);
tty_insert_flip_char(tty, skb->data[0], 0);
queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
skb->free = 1;
kfree_skb(skb, FREE_READ);
return 1;
}
}
@ -174,86 +179,99 @@ void isdn_tty_readmodem(void)
isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
}
/* isdn_tty_senddow() is called either directly from within isdn_tty_write()
void isdn_tty_cleanup_xmit(modem_info *info)
{
struct sk_buff *skb;
unsigned long flags;
save_flags(flags);
cli();
if (info->xmit_buf->qlen)
while ((skb = skb_dequeue(info->xmit_buf))) {
skb->free = 1;
kfree_skb(skb,FREE_WRITE);
}
restore_flags(flags);
}
/* isdn_tty_senddown() is called either directly from within isdn_tty_write()
* or via timer-interrupt from within isdn_tty_modem_xmit(). It pulls
* outgoing data from the tty's xmit-buffer, handles voice-decompression or
* T.70 if necessary, and finally sends it out via isdn_writebuf_stub.
*/
static void isdn_tty_senddown(modem_info * info, int midx)
static void isdn_tty_senddown(modem_info * info)
{
struct tty_struct *tty = info->tty;
char *bufptr = info->xmit_buf;
int buflen = info->xmit_count;
struct sk_buff *skb = skb_dequeue(info->xmit_buf);
if (!buflen)
if (!skb)
return;
if (skb->free > 1) {
/* Post processing only once, if skb->free > 1 */
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline==2) {
/* For now, ifmt is fixed to 1 (alaw), since this
* is used with ISDN everywhere in the world, except
* US, Canadia and Japan.
* Later, when US-ISDN protocols are implemented,
* this setting will depend on the Layer-3 protocol.
*/
int ifmt = 1;
/* voice conversion/decompression */
#if 0
printk("vcode %d %d\n",info->emu.vpar[3],buflen);
#endif
switch (info->emu.vpar[3]) {
case 2:
case 3:
case 4:
/* adpcm, compatible to ZyXel 1496 modem
* with ROM revision 6.01
* xmit_size is limited to VBUF bytes
* so we take the rest of the buffer
* for decompressed data.
*/
buflen = isdn_audio_adpcm2xlaw(info->adpcms,
ifmt,
bufptr,
bufptr+VBUF,
buflen);
bufptr += VBUF;
break;
case 5:
/* a-law */
if (!ifmt)
isdn_audio_alaw2ulaw(bufptr,buflen);
break;
case 6:
/* u-law */
if (ifmt)
isdn_audio_ulaw2alaw(bufptr,buflen);
break;
if (info->vonline==2) {
char *ptr = skb->data;
int len = skb->len;
/* For now, ifmt is fixed to 1 (alaw), since this
* is used with ISDN everywhere in the world, except
* US, Canadia and Japan.
* Later, when US-ISDN protocols are implemented,
* this setting will depend on the D-channel protocol.
*/
int ifmt = 1;
/* voice conversion/decompression */
switch (info->emu.vpar[3]) {
case 4:
skb_put(skb, len);
/* fall through */
case 3:
skb_put(skb, len);
/* fall through */
case 2:
skb_put(skb, len * 2);
/* adpcm, compatible to ZyXel 1496 modem
* with ROM revision 6.01
*/
skb_pull(skb, len);
skb_trim(skb, isdn_audio_adpcm2xlaw(info->adpcms,
ifmt,
ptr,
skb->data,
len));
break;
case 5:
/* a-law */
if (!ifmt)
isdn_audio_alaw2ulaw(ptr,len);
break;
case 6:
/* u-law */
if (ifmt)
isdn_audio_ulaw2alaw(ptr,len);
break;
}
}
#endif /* CONFIG_ISDN_AUDIO */
if (info->emu.mdmreg[13] & 2)
/* Add T.70 simplified header */
memcpy(skb_push(skb,4), "\1\0\1\0", 4);
/* Mark skb post-processed */
skb->free = 1;
}
#endif /* CONFIG_ISDN_AUDIO */
if (info->emu.mdmreg[13] & 2) {
/* Add T.70 simplified header */
#ifdef ISDN_DEBUG_MODEM_DUMP
isdn_dumppkt("T70pack3:", bufptr, buflen, 40);
#endif
bufptr -= 4;
buflen += 4;
memcpy(bufptr, "\1\0\1\0", 4);
#ifdef ISDN_DEBUG_MODEM_DUMP
isdn_dumppkt("T70pack4:", bufptr, buflen, 40);
#endif
}
if (isdn_writebuf_stub(info->isdn_driver, info->isdn_channel,
bufptr, buflen, 0) > 0) {
info->xmit_count = 0;
info->xmit_size = info->emu.mdmreg[16] * 16;
info->send_outstanding++;
info->msr &= ~UART_MSR_CTS;
if (isdn_writebuf_skb_stub(info->isdn_driver, info->isdn_channel,
skb) > 0) {
if (skb_queue_empty(info->xmit_buf))
info->xmit_count = 0;
if ((info->send_outstanding++) > 10)
info->msr &= ~UART_MSR_CTS;
info->lsr |= UART_LSR_TEMT;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup) (tty);
wake_up_interruptible(&tty->write_wait);
}
} else
skb_queue_head(info->xmit_buf,skb);
}
/************************************************************
@ -310,7 +328,6 @@ static void isdn_tty_dial(char *n, modem_info * info, atemu * m)
break;
}
#ifdef CONFIG_ISDN_AUDIO
if ((m->mdmreg[18] & (1<<j)) != (1<<j))
if (si == 1) {
l2 = 4;
usg = ISDN_USAGE_VOICE;
@ -372,6 +389,7 @@ void isdn_tty_modem_hup(modem_info * info)
return;
info->rcvsched = 0;
info->online = 0;
isdn_tty_cleanup_xmit(info);
switch (info->vonline) {
case 1:
/* voice-recording, add DLE-ETX */
@ -576,9 +594,10 @@ int isdn_tty_handleDLEup(unsigned char *buf, int len)
/* This routine is called wrom within isdn_tty_write() to perform
* DLE-decoding when sending audio-data.
*/
static int isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len, int midx)
static int isdn_tty_handleDLEdown(modem_info *info, atemu *m, struct sk_buff *skb)
{
unsigned char *p = &(info->xmit_buf[info->xmit_count]);
unsigned char *p = skb->data;
int len = skb->len;
int count = 0;
while (len>0) {
@ -588,6 +607,9 @@ static int isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len, int midx)
case DLE:
/* Escape code */
printk(KERN_DEBUG "dledown: DLE-DLE\n");
if (len>1)
memmove(p,p+1,len-1);
p--;
count++;
break;
case ETX:
@ -618,6 +640,7 @@ static int isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len, int midx)
printk(KERN_WARNING "isdn_tty: len<0 in DLEdown\n");
return 0;
}
skb_trim(skb,count);
return count;
}
@ -660,9 +683,9 @@ static int isdn_tty_end_vrx(const char *buf, int c, int from_user)
static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
{
int c, total = 0;
modem_info *info = (modem_info *) tty->driver_data;
ulong flags;
int i;
modem_info *info = (modem_info *) tty->driver_data;
struct sk_buff *skb;
if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
return 0;
@ -672,13 +695,10 @@ static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char *
cli();
while (1) {
c = MIN(count, info->xmit_size - info->xmit_count);
if (info->isdn_driver >= 0) {
i = dev->drv[info->isdn_driver]->maxbufsize;
c = MIN(c, i);
}
if (info->isdn_driver >= 0)
c = MIN(c, dev->drv[info->isdn_driver]->maxbufsize);
if (c <= 0)
break;
i = info->line;
if ((info->online > 1) ||
(info->vonline == 2)) {
atemu *m = &info->emu;
@ -688,13 +708,20 @@ static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char *
&(m->pluscount),
&(m->lastplus),
from_user);
if (from_user)
memcpy_fromfs(&(info->xmit_buf[info->xmit_count]), buf, c);
else
memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
if ((skb = alloc_skb(((info->vonline == 2)?
(c+(c<<2)):c)+16,GFP_ATOMIC))==NULL) {
printk(KERN_WARNING "isdn_tty: Cannot alloc skb in tty_write\n");
restore_flags(flags);
return total;
}
skb_reserve(skb, 4); /* For T.70 header */
if (from_user)
memcpy_fromfs(skb_put(skb, c), buf, c);
else
memcpy(skb_put(skb, c), buf, c);
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline == 2) {
int cc = isdn_tty_handleDLEdown(info,m,c,i);
int cc = isdn_tty_handleDLEdown(info,m,skb);
info->xmit_count += cc;
if ((cc==0) && (c > 0)) {
/* If DLE decoding results in zero-transmit, but
@ -708,9 +735,12 @@ static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char *
} else
#endif
info->xmit_count += c;
if (m->mdmreg[13] & 1)
isdn_tty_senddown(info,i);
skb->users = c;
skb_queue_tail(info->xmit_buf,skb);
if (m->mdmreg[13] & 1) {
sti();
isdn_tty_senddown(info);
}
} else {
info->msr |= UART_MSR_CTS;
info->lsr |= UART_LSR_TEMT;
@ -736,7 +766,7 @@ static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char *
count -= c;
total += c;
}
if (info->xmit_count)
if (total)
isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
restore_flags(flags);
return total;
@ -769,14 +799,11 @@ static int isdn_tty_chars_in_buffer(struct tty_struct *tty)
static void isdn_tty_flush_buffer(struct tty_struct *tty)
{
modem_info *info = (modem_info *) tty->driver_data;
uint flags;
if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer"))
return;
save_flags(flags);
cli();
info->xmit_count = 0;
restore_flags(flags);
isdn_tty_cleanup_xmit(info);
info->xmit_count = 0;
wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
@ -789,7 +816,7 @@ static void isdn_tty_flush_chars(struct tty_struct *tty)
if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_chars"))
return;
if (info->xmit_count > 0)
if (skb_queue_len(info->xmit_buf))
isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
}
@ -1472,11 +1499,11 @@ int isdn_tty_modem_init(void)
info->isdn_channel = -1;
info->drv_index = -1;
info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_SIZE + 5, GFP_KERNEL))) {
if (!(info->xmit_buf = kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL))) {
printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
return -3;
}
info->xmit_buf += 4; /* Make room for T.70 header */
skb_queue_head_init(info->xmit_buf);
}
return 0;
}
@ -1966,6 +1993,7 @@ static int isdn_tty_cmd_ATS(char **p, modem_info * info)
if ((m->mdmreg[18] & 1) && (mval > VBUFX))
PARSE_ERROR1;
#endif
info->xmit_size = mval * 16;
break;
}
m->mdmreg[mreg] = mval;
@ -2552,14 +2580,10 @@ void isdn_tty_modem_xmit(void)
modem_info *info = &dev->mdm.info[midx];
if ((info->online > 1) ||
(info->vonline ==2 )) {
ulong flags;
save_flags(flags);
cli();
if (info->xmit_count > 0) {
if (skb_queue_len(info->xmit_buf)) {
ton = 1;
isdn_tty_senddown(info,midx);
isdn_tty_senddown(info);
}
restore_flags(flags);
}
}
isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);

View File

@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.3 1996/05/07 09:16:34 fritz
* Changed isdn_try_read parameter.
*
* Revision 1.2 1996/04/30 21:05:27 fritz
* Test commit
*
@ -35,10 +38,8 @@ extern void isdn_tty_modem_xmit(void);
extern void isdn_tty_modem_hup(modem_info *);
extern int isdn_tty_modem_init(void);
extern void isdn_tty_readmodem(void);
extern int isdn_tty_try_read(modem_info *, u_char *, int);
extern int isdn_tty_try_read(modem_info *, struct sk_buff *);
extern int isdn_tty_find_icall(int, int, char *);
extern int isdn_tty_handleDLEup(unsigned char *, int);
#define FUTURE 1
#if FUTURE
extern void isdn_tty_bsent(int, int);
#endif
extern void isdn_tty_cleanup_xmit(modem_info *);