Changed queue management to use sk_buffs.
This commit is contained in:
parent
ef7e782528
commit
170943e874
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
Loading…
Reference in New Issue