Commit a96e1f22 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Import 2.0.1

parent 81e05330
......@@ -6,6 +6,7 @@
* Copyright 1993 by Theodore Ts'o. Redistribution of this file is
* permitted under the GNU Public License.
*
* more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996
* DES encryption plus some minor changes by Werner Almesberger, 30-MAY-1993
*
* Modularized and updated for 1.1.16 kernel - Mitch Dsouza 28th May 1994
......@@ -15,6 +16,7 @@
#include <linux/module.h>
#include <linux/config.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/errno.h>
......@@ -22,9 +24,14 @@
#include <asm/segment.h>
#ifdef DES_AVAILABLE
#include "des.h"
#ifdef CONFIG_BLK_DEV_LOOP_DES
#include <linux/des.h>
#endif
#ifdef CONFIG_BLK_DEV_LOOP_IDEA
#include <linux/idea.h>
#endif
#include <linux/loop.h> /* must follow des.h */
#define MAJOR_NR LOOP_MAJOR
......@@ -113,6 +120,23 @@ static int transfer_des(struct loop_device *lo, int cmd, char *raw_buf,
}
#endif
#ifdef IDEA_AVAILABLE
extern void idea_encrypt_block(idea_key,char *,char *,int);
static int transfer_idea(struct loop_device *lo, int cmd, char *raw_buf,
char *loop_buf, int size)
{
if (cmd==READ) {
idea_encrypt_block(lo->lo_idea_en_key,raw_buf,loop_buf,size);
}
else {
idea_encrypt_block(lo->lo_idea_de_key,loop_buf,raw_buf,size);
}
return 0;
}
#endif
static transfer_proc_t xfer_funcs[MAX_LOOP] = {
transfer_none, /* LO_CRYPT_NONE */
transfer_xor, /* LO_CRYPT_XOR */
......@@ -121,7 +145,11 @@ static transfer_proc_t xfer_funcs[MAX_LOOP] = {
#else
NULL, /* LO_CRYPT_DES */
#endif
0 /* LO_CRYPT_IDEA */
#ifdef IDEA_AVAILABLE /* LO_CRYPT_IDEA */
transfer_idea
#else
NULL
#endif
};
......@@ -225,8 +253,10 @@ static void do_lo_request(void)
brelse(bh);
goto error_out;
}
if (CURRENT->cmd == WRITE)
if (CURRENT->cmd == WRITE) {
mark_buffer_uptodate(bh, 1);
mark_buffer_dirty(bh, 1);
}
brelse(bh);
dest_addr += size;
len -= size;
......@@ -334,6 +364,20 @@ static int loop_set_status(struct loop_device *lo, struct loop_info *arg)
lo->lo_des_key);
memcpy(lo->lo_des_init,info.lo_init,8);
break;
#endif
#ifdef IDEA_AVAILABLE
case LO_CRYPT_IDEA:
{
uint16 tmpkey[8];
if (info.lo_encrypt_key_size != IDEAKEYSIZE)
return -EINVAL;
/* create key in lo-> from info.lo_encrypt_key */
memcpy(tmpkey,info.lo_encrypt_key,sizeof(tmpkey));
en_key_idea(tmpkey,lo->lo_idea_en_key);
de_key_idea(lo->lo_idea_en_key,lo->lo_idea_de_key);
break;
}
#endif
default:
return -EINVAL;
......@@ -494,6 +538,12 @@ loop_init( void ) {
}
#ifndef MODULE
printk("loop: registered device at major %d\n", MAJOR_NR);
#ifdef DES_AVAILABLE
printk("loop: DES encryption available\n");
#endif
#ifdef IDEA_AVAILABLE
printk("loop: IDEA encryption available\n");
#endif
#endif
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
......
......@@ -163,6 +163,7 @@ static int do_md_run (int minor, int repart)
{
md_dev[minor].devices[i].size &= ~(min - 1);
md_size[minor] += md_dev[minor].devices[i].size;
md_dev[minor].devices[i].offset=i ? (md_dev[minor].devices[i-1].offset + md_dev[minor].devices[i-1].size) : 0;
}
md_dev[minor].pers=pers[pnum];
......@@ -218,6 +219,7 @@ static int do_md_stop (int minor, struct inode *inode)
clear_inode (md_dev[minor].devices[i].inode);
md_dev[minor].nb_dev=md_size[minor]=0;
md_hd_struct[minor].nr_sects=0;
md_dev[minor].pers=NULL;
set_ra (); /* calculate new read_ahead */
......@@ -257,14 +259,7 @@ static int do_md_add (int minor, kdev_t dev)
/* Sizes are now rounded at run time */
md_dev[minor].devices[i].size=gen_real->sizes[MINOR(dev)];
md_dev[minor].devices[i].offset=i ?
(md_dev[minor].devices[i-1].offset + md_dev[minor].devices[i-1].size) : 0;
if (!i)
md_size[minor]=0;
md_size[minor]+=md_dev[minor].devices[i].size;
printk ("REGISTER_DEV %s to md%x done\n", partition_name(dev), minor);
return (0);
}
......@@ -372,11 +367,33 @@ static void md_release (struct inode *inode, struct file *file)
}
static int md_read (struct inode *inode, struct file *file,
char *buf, int count)
{
int minor=MINOR(inode->i_rdev);
if (!md_dev[minor].pers) /* Check if device is being run */
return -ENXIO;
return block_read (inode, file, buf, count);
}
static int md_write (struct inode *inode, struct file *file,
const char *buf, int count)
{
int minor=MINOR(inode->i_rdev);
if (!md_dev[minor].pers) /* Check if device is being run */
return -ENXIO;
return block_write (inode, file, buf, count);
}
static struct file_operations md_fops=
{
NULL,
block_read,
block_write,
md_read,
md_write,
NULL,
NULL,
md_ioctl,
......@@ -431,6 +448,7 @@ static void md_geninit (struct gendisk *gdisk)
{
md_blocksizes[i] = 1024;
md_gendisk.part[i].start_sect=-1; /* avoid partition check */
md_gendisk.part[i].nr_sects=0;
md_dev[i].pers=NULL;
}
......@@ -448,7 +466,7 @@ static void md_geninit (struct gendisk *gdisk)
int get_md_status (char *page)
{
int sz=0, i, j;
int sz=0, i, j, size;
sz+=sprintf( page+sz, "Personalities : ");
for (i=0; i<MAX_PERSONALITY; i++)
......@@ -470,12 +488,16 @@ int get_md_status (char *page)
if (md_dev[i].pers)
sz+=sprintf (page+sz, " %s", md_dev[i].pers->name);
size=0;
for (j=0; j<md_dev[i].nb_dev; j++)
{
sz+=sprintf (page+sz, " %s",
partition_name(md_dev[i].devices[j].dev));
size+=md_dev[i].devices[j].size;
}
if (md_dev[i].nb_dev)
sz+=sprintf (page+sz, " %d blocks", md_size[i]);
sz+=sprintf (page+sz, " %d blocks", size);
if (!md_dev[i].pers)
{
......
......@@ -233,7 +233,7 @@ static int rd_open(struct inode * inode, struct file * filp)
#endif
if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
return -ENODEV;
return -ENXIO;
MOD_INC_USE_COUNT;
......
......@@ -211,7 +211,7 @@ static int xd_open (struct inode *inode,struct file *file)
return (0);
}
else
return (-ENODEV);
return -ENXIO;
}
/* do_xd_request: handle an incoming request */
......
......@@ -236,7 +236,6 @@ struct modem_state_par96 {
unsigned int dcd_shreg;
unsigned long descram;
unsigned long scram;
unsigned char last_rxbit;
};
struct modem_state {
......@@ -581,8 +580,7 @@ static inline unsigned int tenms_to_flags(struct baycom_state *bc,
/* ---------------------------------------------------------------------- */
/*
* The HDLC routines could be more efficient; they could take more than
* one bit per call
* The HDLC routines
*/
static inline int hdlc_rx_add_bytes(struct baycom_state *bc,
......@@ -1212,7 +1210,7 @@ static void baycom_par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
register struct baycom_state *bc = (struct baycom_state *)dev_id;
int i;
unsigned int data, rawdata, mask, mask2;
unsigned int data, mask, mask2;
if (!bc || bc->magic != BAYCOM_MAGIC)
return;
......@@ -1270,7 +1268,7 @@ static void baycom_par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* do receiver; differential decode and descramble on the fly
*/
for(rawdata = data = i = 0; i < PAR96_BURSTBITS; i++) {
for(data = i = 0; i < PAR96_BURSTBITS; i++) {
unsigned int descx;
bc->modem.par96.descram = (bc->modem.par96.descram << 1);
if (inb(LPT_STATUS(bc->iobase)) & PAR96_RXBIT)
......@@ -1281,14 +1279,9 @@ static void baycom_par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outb(PAR97_POWER | PAR96_PTT, LPT_DATA(bc->iobase));
descx ^= ((descx >> PAR96_DESCRAM_TAPSH1) ^
(descx >> PAR96_DESCRAM_TAPSH2));
if (descx & 1)
bc->modem.par96.last_rxbit =
!bc->modem.par96.last_rxbit;
data >>= 1;
if (bc->modem.par96.last_rxbit)
if (!(descx & 1))
data |= 0x8000;
rawdata <<= 1;
rawdata |= !(descx & 1);
outb(PAR97_POWER | PAR96_PTT | PAR96_BURST,
LPT_DATA(bc->iobase));
}
......@@ -1304,16 +1297,16 @@ static void baycom_par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* do DCD algorithm
*/
if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
bc->modem.par96.dcd_shreg = (bc->modem.par96.dcd_shreg << 16)
| rawdata;
bc->modem.par96.dcd_shreg = (bc->modem.par96.dcd_shreg >> 16)
| (data << 16);
/* search for flags and set the dcd counter appropriately */
for(mask = 0x7f8000, mask2 = 0x3f0000, i = 0;
i < PAR96_BURSTBITS; i++, mask >>= 1, mask2 >>= 1)
for(mask = 0x1fe00, mask2 = 0xfc00, i = 0;
i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
if ((bc->modem.par96.dcd_shreg & mask) == mask2)
bc->modem.par96.dcd_count = BAYCOM_MAXFLEN+4;
/* check for abort/noise sequences */
for(mask = 0x3f8000, mask2 = 0x3f8000, i = 0;
i < PAR96_BURSTBITS; i++, mask >>= 1, mask2 >>= 1)
for(mask = 0x1fe00, mask2 = 0x1fe00, i = 0;
i < PAR96_BURSTBITS; i++, mask <<= 1, mask2 <<= 1)
if ((bc->modem.par96.dcd_shreg & mask) == mask2)
if (bc->modem.par96.dcd_count >= 0)
bc->modem.par96.dcd_count -=
......
......@@ -306,7 +306,7 @@ int vc_cons_allocated(unsigned int i)
int vc_allocate(unsigned int i) /* return 0 on success */
{
if (i >= MAX_NR_CONSOLES)
return -ENODEV;
return -ENXIO;
if (!vc_cons[i].d) {
long p, q;
......
......@@ -322,9 +322,9 @@ static int lp_open(struct inode * inode, struct file * file)
unsigned int irq;
if (minor >= LP_NO)
return -ENODEV;
return -ENXIO;
if ((LP_F(minor) & LP_EXIST) == 0)
return -ENODEV;
return -ENXIO;
if (LP_F(minor) & LP_BUSY)
return -EBUSY;
......
......@@ -358,7 +358,7 @@ static int memory_open(struct inode * inode, struct file * filp)
filp->f_op = &urandom_fops;
break;
default:
return -ENODEV;
return -ENXIO;
}
if (filp->f_op && filp->f_op->open)
return filp->f_op->open(inode,filp);
......
......@@ -201,7 +201,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
tty->read_head = tty->canon_head;
return;
}
if (!L_ECHOK(tty) || !L_ECHOKE(tty)) {
if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
tty->read_cnt -= ((tty->read_head - tty->canon_head) &
(N_TTY_BUF_SIZE - 1));
tty->read_head = tty->canon_head;
......@@ -236,7 +236,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
tty->erasing = 1;
}
echo_char(c, tty);
} else if (!L_ECHOE(tty)) {
} else if (kill_type == ERASE && !L_ECHOE(tty)) {
echo_char(ERASE_CHAR(tty), tty);
} else if (c == '\t') {
unsigned int col = tty->canon_column;
......@@ -290,11 +290,11 @@ static void eraser(unsigned char c, struct tty_struct *tty)
finish_erasing(tty);
}
static void isig(int sig, struct tty_struct *tty)
static inline void isig(int sig, struct tty_struct *tty, int flush)
{
if (tty->pgrp > 0)
kill_pg(tty->pgrp, sig, 1);
if (!L_NOFLSH(tty)) {
if (flush || !L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
if (tty->driver.flush_buffer)
tty->driver.flush_buffer(tty);
......@@ -306,7 +306,7 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
if (I_IGNBRK(tty))
return;
if (I_BRKINT(tty)) {
isig(SIGINT, tty);
isig(SIGINT, tty, 1);
return;
}
if (I_PARMRK(tty)) {
......@@ -340,8 +340,10 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
put_tty_queue('\377', tty);
put_tty_queue('\0', tty);
put_tty_queue(c, tty);
} else
} else if (I_INPCK(tty))
put_tty_queue('\0', tty);
else
put_tty_queue(c, tty);
wake_up_interruptible(&tty->read_wait);
}
......@@ -415,17 +417,17 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
}
}
if (L_ISIG(tty)) {
if (c == INTR_CHAR(tty)) {
isig(SIGINT, tty);
return;
}
if (c == QUIT_CHAR(tty)) {
isig(SIGQUIT, tty);
return;
}
int signal;
signal = SIGINT;
if (c == INTR_CHAR(tty))
goto send_signal;
signal = SIGQUIT;
if (c == QUIT_CHAR(tty))
goto send_signal;
signal = SIGTSTP;
if (c == SUSP_CHAR(tty)) {
if (!is_orphaned_pgrp(tty->pgrp))
isig(SIGTSTP, tty);
send_signal:
isig(signal, tty, 0);
return;
}
}
......
......@@ -244,6 +244,12 @@ int pty_open(struct tty_struct *tty, struct file * filp)
return retval;
}
static void pty_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
tty->termios->c_cflag &= ~(CSIZE | PARENB);
tty->termios->c_cflag |= (CS8 | CREAD);
}
int pty_init(void)
{
memset(&pty_state, 0, sizeof(pty_state));
......@@ -274,6 +280,7 @@ int pty_init(void)
pty_driver.flush_buffer = pty_flush_buffer;
pty_driver.chars_in_buffer = pty_chars_in_buffer;
pty_driver.unthrottle = pty_unthrottle;
pty_driver.set_termios = pty_set_termios;
pty_slave_driver = pty_driver;
pty_slave_driver.name = "ttyp";
......
......@@ -357,8 +357,6 @@ static void add_entropy_word(struct random_bucket *r,
#if (!defined (__i386__))
extern inline __u32 rotate_left(int i, __u32 word)
{
__u32 nbits = 0;
return (word << i) | (word >> (32 - i));
}
......
......@@ -2755,9 +2755,8 @@ int rs_init(void)
serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
serial_driver.subtype = SERIAL_TYPE_NORMAL;
serial_driver.init_termios = tty_std_termios;
serial_driver.init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver.flags = TTY_DRIVER_REAL_RAW;
serial_driver.init_termios.c_lflag &=~ (ISIG | ICANON | ECHO);
serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
serial_driver.refcount = &serial_refcount;
serial_driver.table = serial_table;
serial_driver.termios = serial_termios;
......
......@@ -73,6 +73,7 @@ static int softdog_open(struct inode *inode, struct file *file)
/*
* Activate timer
*/
del_timer(&watchdog_ticktock);
watchdog_ticktock.expires=jiffies + (soft_margin * HZ);
add_timer(&watchdog_ticktock);
timer_alive++;
......
......@@ -330,7 +330,7 @@ static int hung_up_tty_select(struct inode * inode, struct file * filp, int sel_
static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
return -EIO;
return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
}
static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
......@@ -475,8 +475,10 @@ void disassociate_ctty(int on_exit)
{
struct tty_struct *tty = current->tty;
struct task_struct *p;
int tty_pgrp = -1;
if (tty) {
tty_pgrp = tty->pgrp;
if (on_exit && tty->driver.type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
} else {
......@@ -486,9 +488,10 @@ void disassociate_ctty(int on_exit)
}
return;
}
if (tty->pgrp > 0) {
kill_pg(tty->pgrp, SIGHUP, on_exit);
kill_pg(tty->pgrp, SIGCONT, on_exit);
if (tty_pgrp > 0) {
kill_pg(tty_pgrp, SIGHUP, on_exit);
if (!on_exit)
kill_pg(tty_pgrp, SIGCONT, on_exit);
}
current->tty_old_pgrp = 0;
......@@ -1496,6 +1499,8 @@ static int tty_ioctl(struct inode * inode, struct file * file,
return 0;
case TIOCSPGRP:
retval = tty_check_change(real_tty);
if (retval == -EIO)
return -ENOTTY;
if (retval)
return retval;
if (!current->tty ||
......@@ -1816,7 +1821,7 @@ long console_init(long kmem_start, long kmem_end)
memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS);
tty_std_termios.c_iflag = ICRNL | IXON;
tty_std_termios.c_oflag = OPOST | ONLCR;
tty_std_termios.c_cflag = B38400 | CS8 | CREAD;
tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL;
tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
ECHOCTL | ECHOKE | IEXTEN;
......
/* $Id: icn.c,v 1.24 1996/06/06 13:58:33 fritz Exp $
/* $Id: icn.c,v 1.28 1996/06/28 17:02:53 fritz Exp $
*
* ISDN low-level module for the ICN active ISDN-Card.
*
......@@ -19,6 +19,23 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: icn.c,v $
* Revision 1.28 1996/06/28 17:02:53 fritz
* replaced memcpy_fromfs_toio.
*
* Revision 1.27 1996/06/25 18:38:59 fritz
* Fixed function name in error message.
*
* Revision 1.26 1996/06/24 17:20:35 fritz
* Bugfixes in pollbchan_send():
* - Using lock field of skbuff breaks networking.
* - Added channel locking
* - changed dequeuing scheme.
* Eliminated misc. compiler warnings.
*
* Revision 1.25 1996/06/11 22:53:35 tsbogend
* fixed problem with large array on stack
* made the driver working on Linux/alpha
*
* Revision 1.24 1996/06/06 13:58:33 fritz
* Changed code to be architecture independent
*
......@@ -119,7 +136,7 @@
#undef MAP_DEBUG
static char
*revision = "$Revision: 1.24 $";
*revision = "$Revision: 1.28 $";
static int icn_addcard(int, char *, char *);
......@@ -135,10 +152,8 @@ static void icn_free_queue(struct sk_buff_head *queue)
save_flags(flags);
cli();
while ((skb = skb_dequeue(queue))) {
skb->free = 1;
kfree_skb(skb, FREE_WRITE);
}
while ((skb = skb_dequeue(queue)))
dev_kfree_skb(skb, FREE_WRITE);
restore_flags(flags);
}
......@@ -312,7 +327,7 @@ static void icn_pollbchan_receive(int channel, icn_card *card)
if (icn_trymaplock_channel(card,mch)) {
while (rbavl) {
cnt = rbuf_l;
cnt = readb(&rbuf_l);
if ((card->rcvidx[channel] + cnt) > 4000) {
printk(KERN_WARNING
"icn: (%s) bogus packet on ch%d, dropping.\n",
......@@ -322,9 +337,9 @@ static void icn_pollbchan_receive(int channel, icn_card *card)
eflag = 0;
} else {
memcpy_fromio(&card->rcvbuf[channel][card->rcvidx[channel]],
rbuf_d, cnt);
&rbuf_d, cnt);
card->rcvidx[channel] += cnt;
eflag = rbuf_f;
eflag = readb(&rbuf_f);
}
rbnext;
icn_maprelease_channel(card, mch & 2);
......@@ -367,36 +382,37 @@ static void icn_pollbchan_send(int channel, icn_card *card)
while (sbfree && card->sndcount[channel]) {
save_flags(flags);
cli();
skb = skb_peek(&card->spqueue[channel]);
if (!skb) {
if (card->xmit_lock[channel]) {
restore_flags(flags);
break;
}
if (skb->lock) {
restore_flags(flags);
break;
}
skb->lock = 1;
card->xmit_lock[channel]++;
restore_flags(flags);
cnt =
(sbuf_l =
(skb->len > ICN_FRAGSIZE) ? ((sbuf_f = 0xff), ICN_FRAGSIZE) : ((sbuf_f = 0), skb->len));
memcpy(sbuf_d, skb->data, cnt);
skb = skb_dequeue(&card->spqueue[channel]);
if (!skb)
break;
if (skb->len > ICN_FRAGSIZE) {
writeb (0xff, &sbuf_f);
cnt = ICN_FRAGSIZE;
} else {
writeb (0x0, &sbuf_f);
cnt = skb->len;
}
writeb (cnt, &sbuf_l);
memcpy_toio(&sbuf_d, skb->data, cnt);
skb_pull(skb, cnt);
card->sndcount[channel] -= cnt;
sbnext; /* switch to next buffer */
icn_maprelease_channel(card, mch & 2);
if (!skb->len) {
skb = skb_dequeue(&card->spqueue[channel]);
skb->free = 1;
skb->lock = 0;
kfree_skb(skb, FREE_WRITE);
dev_kfree_skb(skb, FREE_WRITE);
cmd.command = ISDN_STAT_BSENT;
cmd.driver = card->myid;
cmd.arg = channel;
card->interface.statcallb(&cmd);
} else
skb->lock = 0;
skb_queue_head(&card->spqueue[channel], skb);
card->xmit_lock[channel] = 0;
if (!icn_trymaplock_channel(card, mch))
break;
}
......@@ -426,6 +442,7 @@ static void icn_pollbchan(unsigned long data)
/* schedule b-channel polling again */
save_flags(flags);
cli();
del_timer(&card->rb_timer);
card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
add_timer(&card->rb_timer);
card->flags |= ICN_FLAGS_RBTIMER;
......@@ -649,6 +666,7 @@ static void icn_polldchan(unsigned long data)
/* schedule again */
save_flags(flags);
cli();
del_timer(&card->st_timer);
card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
add_timer(&card->st_timer);
restore_flags(flags);
......@@ -671,8 +689,8 @@ static int icn_sendbuf(int channel, struct sk_buff *skb, icn_card * card)
unsigned long flags;
if (len > 4000) {
skb->free = 1;
kfree_skb(skb, FREE_WRITE);
printk(KERN_WARNING
"icn: Send packet too large\n");
return -EINVAL;
}
if (len) {
......@@ -685,7 +703,6 @@ static int icn_sendbuf(int channel, struct sk_buff *skb, icn_card * card)
card->sndcount[channel] += len;
skb_queue_tail(&card->spqueue[channel], skb);
restore_flags(flags);
icn_pollbchan_send(channel, card);
}
return len;
}
......@@ -751,13 +768,17 @@ static int icn_loadboot(u_char * buffer, icn_card * card)
{
int ret;
ulong flags;
unsigned char codebuf[ICN_CODE_STAGE1];
u_char *codebuf;
#ifdef BOOT_DEBUG
printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);
#endif
if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE1)))
return ret;
if (!(codebuf = kmalloc(ICN_CODE_STAGE1,GFP_KERNEL))) {
printk(KERN_WARNING "icn: Could not allocate code buffer\n");
return -ENOMEM;
}
save_flags(flags);
cli();
if (!card->rvalid) {
......@@ -768,6 +789,7 @@ static int icn_loadboot(u_char * buffer, icn_card * card)
card->port,
card->port + ICN_PORTLEN);
restore_flags(flags);
kfree(codebuf);
return -EBUSY;
}
request_region(card->port, ICN_PORTLEN, card->regname);
......@@ -804,8 +826,8 @@ static int icn_loadboot(u_char * buffer, icn_card * card)
icn_lock_channel(card,0); /* Lock Bank 0 */
restore_flags(flags);
SLEEP(1);
memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1); /* Copy code */
memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);
memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1);
memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
#ifdef BOOT_DEBUG
printk(KERN_DEBUG "Bootloader transfered\n");
#endif
......@@ -821,12 +843,12 @@ static int icn_loadboot(u_char * buffer, icn_card * card)
icn_lock_channel(card,2); /* Lock Bank 8 */
restore_flags(flags);
SLEEP(1);
memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1); /* Copy code */
memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);
memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */
#ifdef BOOT_DEBUG
printk(KERN_DEBUG "Bootloader transfered\n");
#endif
}
kfree(codebuf);
SLEEP(1);
OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */
if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1)))
......@@ -849,6 +871,7 @@ static int icn_loadboot(u_char * buffer, icn_card * card)
static int icn_loadproto(u_char * buffer, icn_card * card)
{
register u_char *p = buffer;
u_char codebuf[256];
uint left = ICN_CODE_STAGE2;
uint cnt;
int timer;
......@@ -874,7 +897,8 @@ static int icn_loadproto(u_char * buffer, icn_card * card)
while (left) {
if (sbfree) { /* If there is a free buffer... */
cnt = MIN(256, left);
memcpy_fromfs(&sbuf_l, p, cnt); /* copy data */
memcpy_fromfs(codebuf, p, cnt);
memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data */
sbnext; /* switch to next buffer */
p += cnt;
left -= cnt;
......@@ -892,7 +916,7 @@ static int icn_loadproto(u_char * buffer, icn_card * card)
schedule();
}
}
sbuf_n = 0x20;
writeb (0x20, &sbuf_n);
timer = 0;
while (1) {
if (readb(&cmd_o) || readb(&cmd_i)) {
......@@ -1094,7 +1118,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
}
break;
case ICN_IOCTL_GETMMIO:
return (int) dev.shmem;
return (long) dev.shmem;
case ICN_IOCTL_SETPORT:
if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330
|| a == 0x340 || a == 0x350 || a == 0x360 ||
......@@ -1391,7 +1415,8 @@ static int if_command(isdn_ctrl * c)
if (card)
return (icn_command(c, card));
printk(KERN_ERR
"icn: if_command called with invalid driverId!\n");
"icn: if_command %d called with invalid driverId %d!\n",
c->command, c->driver);
return -ENODEV;
}
......@@ -1433,7 +1458,7 @@ static int if_sendbuf(int id, int channel, struct sk_buff *skb)
return (icn_sendbuf(channel, skb, card));
}
printk(KERN_ERR
"icn: if_readstatus called with invalid driverId!\n");
"icn: if_sendbuf called with invalid driverId!\n");
return -ENODEV;
}
......@@ -1455,9 +1480,6 @@ static icn_card *icn_initcard(int port, char *id) {
card->interface.channels = ICN_BCH;
card->interface.maxbufsize = 4000;
card->interface.command = if_command;
/*
card->interface.writebuf = if_sendbuf;
*/
card->interface.writebuf_skb = if_sendbuf;
card->interface.writecmd = if_writecmd;
card->interface.readstat = if_readstatus;
......@@ -1558,7 +1580,7 @@ int icn_init(void)
char rev[10];
memset(&dev, 0, sizeof(icn_dev));
dev.shmem = (icn_shmem *) (membase & 0x0ffc000);
dev.shmem = (icn_shmem *) ((unsigned long)membase & 0x0ffc000);
dev.channel = -1;
dev.mcard = NULL;
......@@ -1571,8 +1593,8 @@ int icn_init(void)
*p = 0;
} else
strcpy(rev, " ??? ");
printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08x\n", rev,
(uint) dev.shmem);
printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
(ulong) dev.shmem);
return (icn_addcard(portbase,icn_id,icn_id2));
}
......
/* $Id: icn.h,v 1.19 1996/06/06 13:58:35 fritz Exp $
/* $Id: icn.h,v 1.20 1996/06/24 17:20:37 fritz Exp $
*
* ISDN lowlevel-module for the ICN active ISDN-Card.
*
......@@ -19,6 +19,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: icn.h,v $
* Revision 1.20 1996/06/24 17:20:37 fritz
* Bugfixes in pollbchan_send():
* - Using lock field of skbuff breaks networking.
* - Added channel locking
* - changed dequeuing scheme.
* Eliminated misc. compiler warnings.
*
* Revision 1.19 1996/06/06 13:58:35 fritz
* Changed code to be architecture independent
*
......@@ -155,7 +162,7 @@ typedef struct icn_cdef {
#define ICN_CODE_STAGE1 4096 /* Size of bootcode */
#define ICN_CODE_STAGE2 65536 /* Size of protocol-code */
#define ICN_MAX_SQUEUE 65536 /* Max. outstanding send-data */
#define ICN_MAX_SQUEUE 8000 /* Max. outstanding send-data (2* hw-buf.) */
#define ICN_FRAGSIZE (250) /* Max. size of send-fragments */
#define ICN_BCH 2 /* Number of supported channels per card */
......@@ -240,6 +247,7 @@ typedef struct icn_card {
struct sk_buff_head
spqueue[ICN_BCH]; /* Sendqueue */
char regname[35]; /* Name used for request_region */
u_char xmit_lock[ICN_BCH]; /* Semaphore for pollbchan_send() */
} icn_card;
/*
......
/* $Id: isdn_common.c,v 1.18 1996/06/06 14:51:51 fritz Exp $
/* $Id: isdn_common.c,v 1.23 1996/06/25 18:35:38 fritz Exp $
*
* Linux ISDN subsystem, common used functions (linklevel).
*
......@@ -21,6 +21,25 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_common.c,v $
* Revision 1.23 1996/06/25 18:35:38 fritz
* Fixed bogus memory access in isdn_set_allcfg().
*
* Revision 1.22 1996/06/24 17:37:37 fritz
* Bugfix: isdn_timer_ctrl() did restart timer, even if it
* was already running.
* lowlevel driver locking did use wrong parameters.
*
* Revision 1.21 1996/06/15 14:58:20 fritz
* Added version signatures for data structures used
* by userlevel programs.
*
* Revision 1.20 1996/06/12 16:01:49 fritz
* Bugfix: Remote B-channel hangup sometimes did not result
* in a NO CARRIER on tty.
*
* Revision 1.19 1996/06/11 14:52:04 hipp
* minor bugfix in isdn_writebuf_skb_stub()
*
* Revision 1.18 1996/06/06 14:51:51 fritz
* Changed to support DTMF decoding on audio playback also.
*
......@@ -115,11 +134,12 @@
/* Debugflags */
#undef ISDN_DEBUG_STATCALLB
#define NEW_ISDN_TIMER_CTRL
isdn_dev *dev = (isdn_dev *) 0;
static int has_exported = 0;
static char *isdn_revision = "$Revision: 1.18 $";
static char *isdn_revision = "$Revision: 1.23 $";
extern char *isdn_net_revision;
extern char *isdn_tty_revision;
......@@ -222,8 +242,10 @@ static void isdn_timer_funct(ulong dummy)
save_flags(flags);
cli();
del_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
del_timer(&dev->timer);
#ifndef NEW_ISDN_TIMER_CTRL
dev->timer.function = isdn_timer_funct;
#endif
dev->timer.expires = jiffies + ISDN_TIMER_RES;
add_timer(&dev->timer);
restore_flags(flags);
......@@ -245,12 +267,20 @@ void isdn_timer_ctrl(int tf, int onoff)
dev->tflags |= tf;
else
dev->tflags &= ~tf;
#ifdef NEW_ISDN_TIMER_CTRL
if (dev->tflags) {
del_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
if (!del_timer(&dev->timer)) /* del_timer is 1, when active */
dev->timer.expires = jiffies + ISDN_TIMER_RES;
add_timer(&dev->timer);
}
#else
if (dev->tflags) {
del_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
dev->timer.expires = jiffies + ISDN_TIMER_RES;
add_timer(&dev->timer);
}
#endif
restore_flags(flags);
}
......@@ -277,6 +307,7 @@ static void isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
if (isdn_net_rcv_skb(i, skb))
return;
/* No network-device found, deliver to tty or raw-channel */
skb->free = 1;
if (skb->len) {
if ((midx = dev->m_idx[i])<0) {
/* if midx is invalid, drop packet */
......@@ -599,9 +630,9 @@ static int isdn_status_callback(isdn_ctrl * c)
info = &dev->mdm.info[mi];
if (info->flags &
(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE)) {
info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
if (info->online)
if (info->msr & UART_MSR_DCD)
isdn_tty_modem_result(3, info);
info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
#ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "Mhup in ISDN_STAT_BHUP\n");
#endif
......@@ -807,6 +838,8 @@ static __inline int isdn_minor2chan(int minor)
return (dev->chanmap[minor]);
}
#define INF_DV 0x01 /* Data version for /dev/isdninfo */
static char *
isdn_statstr(void)
{
......@@ -1043,7 +1076,8 @@ static int isdn_set_allcfg(char *src)
restore_flags(flags);
return ret;
}
memcpy_tofs((char *) &i, src, sizeof(int));
memcpy_fromfs((char *) &i, src, sizeof(int));
src += sizeof(int);
while (i) {
char *c;
char *c2;
......@@ -1185,6 +1219,10 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
if (minor == ISDN_MINOR_STATUS) {
switch (cmd) {
case IIOCGETDVR:
return(TTY_DV +
(NET_DV << 8) +
(INF_DV << 16));
case IIOCGETCPS:
if (arg) {
ulong *p = (ulong *)arg;
......@@ -1728,7 +1766,7 @@ int isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
dev->usage[i] |= usage;
isdn_info_update();
cmd.driver = i;
cmd.driver = d;
cmd.arg = 0;
cmd.command = ISDN_CMD_LOCK;
(void) dev->drv[d]->interface->command(&cmd);
......@@ -1739,7 +1777,7 @@ int isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
dev->usage[i] |= usage;
isdn_info_update();
cmd.driver = i;
cmd.driver = d;
cmd.arg = 0;
cmd.command = ISDN_CMD_LOCK;
(void) dev->drv[d]->interface->command(&cmd);
......@@ -1878,17 +1916,18 @@ int isdn_writebuf_stub(int drvidx, int chan, const u_char *buf, int len,
int isdn_writebuf_skb_stub(int drvidx, int chan, struct sk_buff * skb)
{
int ret;
int len = skb->len; /* skb pointer no longer valid after free */
if (dev->drv[drvidx]->interface->writebuf_skb)
ret = dev->drv[drvidx]->interface->
writebuf_skb(drvidx, chan, skb);
else {
if ((ret = dev->drv[drvidx]->interface->
writebuf(drvidx,chan,skb->data,skb->len,0)) == skb->len)
writebuf(drvidx,chan,skb->data,skb->len,0)) == len)
dev_kfree_skb(skb, FREE_WRITE);
}
if (ret > 0)
dev->obytes[isdn_dc2minor(drvidx,chan)] += skb->len;
dev->obytes[isdn_dc2minor(drvidx,chan)] += len;
return ret;
}
......@@ -2063,6 +2102,10 @@ int isdn_init(void)
return -EIO;
}
memset((char *) dev, 0, sizeof(isdn_dev));
#ifdef NEW_ISDN_TIMER_CTRL
init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
#endif
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
dev->drvmap[i] = -1;
dev->chanmap[i] = -1;
......
/* $Id: isdn_net.c,v 1.13 1996/06/06 14:25:44 fritz Exp $
/* $Id: isdn_net.c,v 1.17 1996/06/25 18:37:37 fritz Exp $
*
* Linux ISDN subsystem, network interfaces and related functions (linklevel).
*
......@@ -21,6 +21,22 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_net.c,v $
* Revision 1.17 1996/06/25 18:37:37 fritz
* Fixed return count for empty return string in isdn_net_getphones().
*
* Revision 1.16 1996/06/24 17:48:08 fritz
* Bugfixes:
* - Did not free channel on unbinding.
* - ioctl returned wrong callback settings.
*
* Revision 1.15 1996/06/16 17:42:54 tsbogend
* fixed problem with IP addresses on Linux/Alpha (long is 8 byte there)
*
* Revision 1.14 1996/06/11 14:54:08 hipp
* minor bugfix in isdn_net_send_skb
* changes in BSENT callback handler for syncPPP
* added lp->sav_skb stuff
*
* Revision 1.13 1996/06/06 14:25:44 fritz
* Changed loglevel of "incoming ... without OAD" message, since
* with audio support this is quite normal.
......@@ -105,7 +121,7 @@ static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
extern void dev_purge_queues(struct device *dev); /* move this to net/core/dev.c */
char *isdn_net_revision = "$Revision: 1.13 $";
char *isdn_net_revision = "$Revision: 1.17 $";
/*
* Code for raw-networking over ISDN
......@@ -133,9 +149,9 @@ isdn_net_open(struct device *dev)
isdn_net_reset(dev);
dev->start = 1;
/* Fill in the MAC-level header. */
for (i = 0; i < ETH_ALEN - sizeof(ulong); i++)
for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
dev->dev_addr[i] = 0xfc;
memcpy(&(dev->dev_addr[i]), &dev->pa_addr, sizeof(ulong));
memcpy(&(dev->dev_addr[i]), &dev->pa_addr, sizeof(u32));
/* If this interface has slaves, start them also */
......@@ -182,6 +198,10 @@ isdn_net_unbind_channel(isdn_net_local * lp)
dev_kfree_skb(lp->first_skb,FREE_WRITE);
lp->first_skb = NULL;
}
if(lp->sav_skb) {
dev_kfree_skb(lp->sav_skb,FREE_WRITE);
lp->sav_skb = NULL;
}
dev_purge_queues(&lp->netdev->dev);
lp->dialstate = 0;
dev->rx_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
......@@ -263,14 +283,19 @@ isdn_net_stat_callback(int idx, int cmd)
if ((lp->flags & ISDN_NET_CONNECTED) &&
(!lp->dialstate)) {
lp->stats.tx_packets++;
if(lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->first_skb) {
if(!isdn_net_send_skb(&lp->netdev->dev,lp,lp->first_skb)) {
dev_kfree_skb(lp->first_skb,FREE_WRITE);
lp->first_skb = NULL;
if(lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) {
struct device *mdev;
if(lp->master)
mdev = lp->master;
else
mdev = &lp->netdev->dev;
if(!isdn_net_send_skb(mdev,lp,lp->sav_skb)) {
lp->sav_skb = NULL;
mark_bh(NET_BH);
}
else
else {
return 1;
}
}
if (clear_bit(0,(void*)&(p->dev.tbusy)))
mark_bh(NET_BH);
......@@ -293,8 +318,14 @@ isdn_net_stat_callback(int idx, int cmd)
/* Either D-Channel-hangup or error during dialout */
if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
lp->flags &= ~ISDN_NET_CONNECTED;
if(lp->first_skb)
if(lp->first_skb) {
dev_kfree_skb(lp->first_skb,FREE_WRITE);
lp->first_skb = NULL;
}
if(lp->sav_skb) {
dev_kfree_skb(lp->sav_skb,FREE_WRITE);
lp->sav_skb = NULL;
}
isdn_free_channel(lp->isdn_device, lp->isdn_channel,
ISDN_USAGE_NET);
#ifdef CONFIG_ISDN_PPP
......@@ -596,35 +627,20 @@ isdn_net_hangup(struct device *d)
{
isdn_net_local *lp = (isdn_net_local *) d->priv;
isdn_ctrl cmd;
ulong flags;
save_flags(flags);
cli();
if (lp->first_skb) {
dev_kfree_skb(lp->first_skb,FREE_WRITE);
lp->first_skb = NULL;
}
dev_purge_queues(d);
if (lp->flags & ISDN_NET_CONNECTED) {
printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
lp->dialstate = 0;
dev->rx_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
dev->st_netdev[isdn_dc2minor(lp->isdn_device,lp->isdn_channel)] = NULL;
isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
#ifdef CONFIG_ISDN_PPP
isdn_ppp_free(lp);
#endif
lp->flags &= ~ISDN_NET_CONNECTED;
cmd.driver = lp->isdn_device;
cmd.command = ISDN_CMD_HANGUP;
cmd.arg = lp->isdn_channel;
(void) dev->drv[cmd.driver]->interface->command(&cmd);
printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
lp->isdn_device = -1;
lp->isdn_channel = -1;
}
restore_flags(flags);
isdn_net_unbind_channel(lp);
}
typedef struct {
......@@ -732,13 +748,21 @@ isdn_net_send_skb(struct device *ndev, isdn_net_local *lp,
struct sk_buff *skb)
{
int ret;
int len = skb->len; /* save len */
lp->transcount += skb->len;
ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, skb);
if (ret == skb->len) {
if (ret == len) {
lp->transcount += len;
clear_bit(0, (void *)&(ndev->tbusy));
return 0;
}
if (ret < 0) {
skb->free = 1;
dev_kfree_skb(skb, FREE_WRITE);
lp->stats.tx_errors++;
clear_bit(0, (void *)&(ndev->tbusy));
return 0;
}
return 1;
}
......@@ -762,8 +786,7 @@ isdn_net_xmit(struct device *ndev, isdn_net_local *lp, struct sk_buff *skb)
/* For the other encaps the header has already been built */
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
ndev->tbusy = ret = isdn_ppp_xmit(skb, ndev);
return ret;
return isdn_ppp_xmit(skb, ndev);
}
#endif
/* Reset hangup-timeout */
......@@ -877,7 +900,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
/* no 'first_skb' handling for syncPPP */
if (isdn_ppp_bind(lp) < 0) {
lp->first_skb = skb; /* net_unbind will free skb */
dev_kfree_skb(skb,FREE_WRITE);
isdn_net_unbind_channel(lp);
restore_flags(flags);
return 0; /* STN (skb to nirvana) ;) */
......@@ -1241,7 +1264,7 @@ isdn_net_header(struct sk_buff *skb, struct device *dev, unsigned short type,
* guaranteed to be invalid. Need that to check
* for already compressed packets in isdn_ppp_xmit().
*/
*((unsigned long *)skb_push(skb, len)) = 0;
*((u32 *)skb_push(skb, len)) = 0;
break;
#endif
}
......@@ -1251,7 +1274,7 @@ isdn_net_header(struct sk_buff *skb, struct device *dev, unsigned short type,
/* We don't need to send arp, because we have point-to-point connections. */
static int
isdn_net_rebuild_header(void *buff, struct device *dev, ulong dst,
isdn_net_rebuild_header(void *buff, struct device *dev, unsigned long dst,
struct sk_buff *skb)
{
isdn_net_local *lp = dev->priv;
......@@ -1266,8 +1289,8 @@ isdn_net_rebuild_header(void *buff, struct device *dev, ulong dst,
if(eth->h_proto != htons(ETH_P_IP)) {
printk(KERN_WARNING
"isdn_net_rebuild_header: Don't know how to resolve type %d addresses?\n",
(int)eth->h_proto);
"isdn_net: %s don't know how to resolve type %d addresses?\n",
dev->name, (int)eth->h_proto);
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
return 0;
}
......@@ -1275,7 +1298,7 @@ isdn_net_rebuild_header(void *buff, struct device *dev, ulong dst,
* Try to get ARP to resolve the header.
*/
#ifdef CONFIG_INET
ret = arp_find((unsigned char *)&(eth->h_dest), dst, dev, dev->pa_addr,skb)? 1 : 0;
ret = arp_find(eth->h_dest, dst, dev, dev->pa_addr, skb)? 1 : 0;
#endif
}
return ret;
......@@ -2034,6 +2057,7 @@ int isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
p->local.exclusive = -1;
if ((p->local.pre_device != -1) && (cfg->exclusive == -1)) {
isdn_unexclusive_channel(p->local.pre_device, p->local.pre_channel);
isdn_free_channel(p->local.pre_device, p->local.pre_channel,ISDN_USAGE_NET);
drvidx = -1;
chidx = -1;
}
......@@ -2059,7 +2083,7 @@ int isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
p->local.flags &= ~ISDN_NET_CBHUP;
switch (cfg->callback) {
case 0:
p->local.flags &= ~(ISDN_NET_CALLBACK&ISDN_NET_CBOUT);
p->local.flags &= ~(ISDN_NET_CALLBACK|ISDN_NET_CBOUT);
break;
case 1:
p->local.flags |= ISDN_NET_CALLBACK;
......@@ -2126,7 +2150,9 @@ int isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
cfg->secure = (p->local.flags & ISDN_NET_SECURE) ? 1 : 0;
cfg->callback = 0;
if (p->local.flags & ISDN_NET_CALLBACK)
cfg->callback = (p->local.flags & ISDN_NET_CBOUT)?2:1;
cfg->callback = 1;
if (p->local.flags & ISDN_NET_CBOUT)
cfg->callback = 2;
cfg->cbhup = (p->local.flags & ISDN_NET_CBHUP) ? 1 : 0;
cfg->chargehup = (p->local.hupflags & 4) ? 1 : 0;
cfg->ihup = (p->local.hupflags & 8) ? 1 : 0;
......@@ -2186,10 +2212,7 @@ int isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
save_flags(flags);
cli();
inout &= 1;
n = p->local.phone[inout];
if (n)
count++;
while (n) {
for (n = p->local.phone[inout]; n; n = n->next) {
if (more) {
put_fs_byte(' ', phones++);
count++;
......@@ -2201,10 +2224,10 @@ int isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
memcpy_tofs(phones, n->num, strlen(n->num) + 1);
phones += strlen(n->num);
count += strlen(n->num);
n = n->next;
more = 1;
}
put_fs_byte(0,phones);
count++;
restore_flags(flags);
return count;
}
......
/* $Id: isdn_ppp.c,v 1.9 1996/05/18 01:37:01 fritz Exp $
/* $Id: isdn_ppp.c,v 1.12 1996/06/24 17:42:03 fritz Exp $
*
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
......@@ -19,6 +19,16 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_ppp.c,v $
* Revision 1.12 1996/06/24 17:42:03 fritz
* Minor bugfixes.
*
* Revision 1.11 1996/06/16 17:46:05 tsbogend
* changed unsigned long to u32 to make Alpha people happy
*
* Revision 1.10 1996/06/11 14:50:29 hipp
* Lot of changes and bugfixes.
* New scheme to resend packets to busy LL devices.
*
* Revision 1.9 1996/05/18 01:37:01 fritz
* Added spelling corrections and some minor changes
* to stay in sync with kernel.
......@@ -69,7 +79,7 @@
#endif
/* Prototypes */
static int isdn_ppp_fill_rq(char *buf, int len,int proto, int minor);
static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int minor);
static int isdn_ppp_closewait(int);
static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
struct sk_buff *skb, int proto);
......@@ -83,7 +93,7 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
int BEbyte, int *sqno, int min_sqno);
#endif
char *isdn_ppp_revision = "$Revision: 1.9 $";
char *isdn_ppp_revision = "$Revision: 1.12 $";
struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
extern int isdn_net_force_dial_lp(isdn_net_local *);
......@@ -95,10 +105,13 @@ extern int isdn_net_force_dial_lp(isdn_net_local *);
int isdn_ppp_free(isdn_net_local *lp)
{
isdn_net_local *master_lp=lp;
unsigned long flags;
if (lp->ppp_minor < 0)
return 0;
save_flags(flags);
cli();
#ifdef CONFIG_ISDN_MPP
if(lp->master)
master_lp = (isdn_net_local *) lp->master->priv;
......@@ -123,7 +136,7 @@ int isdn_ppp_free(isdn_net_local *lp)
ippp_table[lp->ppp_minor]->lp = NULL; /* link is down .. set lp to NULL */
lp->ppp_minor = -1; /* is this OK ?? */
restore_flags(flags);
return 0;
}
......@@ -286,6 +299,7 @@ void isdn_ppp_release(int minor, struct file *file)
#ifdef CONFIG_ISDN_PPP_VJ
slhc_free(ippp_table[minor]->slcomp);
ippp_table[minor]->slcomp = NULL;
kfree(ippp_table[minor]->cbuf);
#endif
......@@ -394,7 +408,25 @@ int isdn_ppp_ioctl(int minor, struct file *file, unsigned int cmd, unsigned long
case PPPIOCSMAXCID: /* set the maximum compression slot id */
if ((r = get_arg((void *) arg, &val)))
return r;
ippp_table[minor]->maxcid = val;
val++;
if(ippp_table[minor]->maxcid != val) {
#ifdef CONFIG_ISDN_PPP_VJ
struct slcompress *sltmp;
#endif
if(ippp_table[minor]->debug & 0x1)
printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n",val);
ippp_table[minor]->maxcid = val;
#ifdef CONFIG_ISDN_PPP_VJ
sltmp = slhc_init(16,val);
if(!sltmp) {
printk(KERN_ERR "ippp, can't realloc slhc struct\n");
return -ENOMEM;
}
if(ippp_table[minor]->slcomp)
slhc_free(ippp_table[minor]->slcomp);
ippp_table[minor]->slcomp = sltmp;
#endif
}
break;
case PPPIOCGDEBUG:
if ((r = set_arg((void *) arg, ippp_table[minor]->debug)))
......@@ -453,10 +485,11 @@ int isdn_ppp_select(int minor, struct file *file, int type, select_table * st)
* fill up isdn_ppp_read() queue ..
*/
static int isdn_ppp_fill_rq(char *buf, int len,int proto, int minor)
static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int minor)
{
struct ippp_buf_queue *bf, *bl;
unsigned long flags;
unsigned char *nbuf;
if (minor < 0 || minor >= ISDN_MAX_CHANNELS) {
printk(KERN_WARNING "ippp: illegal minor.\n");
......@@ -466,6 +499,18 @@ static int isdn_ppp_fill_rq(char *buf, int len,int proto, int minor)
printk(KERN_DEBUG "ippp: device not activated.\n");
return 0;
}
nbuf = (unsigned char *) kmalloc(len+4, GFP_ATOMIC);
if(!nbuf) {
printk(KERN_WARNING "ippp: Can't alloc buf\n");
return 0;
}
nbuf[0] = PPP_ALLSTATIONS;
nbuf[1] = PPP_UI;
nbuf[2] = proto >> 8;
nbuf[3] = proto & 0xff;
memcpy(nbuf+4, buf, len);
save_flags(flags);
cli();
......@@ -478,20 +523,9 @@ static int isdn_ppp_fill_rq(char *buf, int len,int proto, int minor)
kfree(bf->buf);
ippp_table[minor]->first = bf;
}
bl->buf = (char *) kmalloc(len+4, GFP_ATOMIC);
if (!bl->buf) {
printk(KERN_WARNING "ippp: Can't alloc buf\n");
restore_flags(flags);
return 0;
}
bl->buf = (char *) nbuf;
bl->len = len+4;
bl->buf[0] = PPP_ALLSTATIONS;
bl->buf[1] = PPP_UI;
bl->buf[2] = proto >> 8;
bl->buf[3] = proto & 0xff;
memcpy(bl->buf+4, buf, len);
ippp_table[minor]->last = bl->next;
restore_flags(flags);
......@@ -561,9 +595,23 @@ int isdn_ppp_write(int minor, struct file *file, const char *buf, int count)
return 0;
if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 &&
(lp->flags & ISDN_NET_CONNECTED))
isdn_writebuf_stub(lp->isdn_device,lp->isdn_channel,
buf, count, 1);
(lp->flags & ISDN_NET_CONNECTED)) {
struct sk_buff *skb;
skb = dev_alloc_skb(count);
if(!skb) {
printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
return count;
}
skb->free = 1;
memcpy_fromfs(skb_put(skb, count), buf, count);
if(isdn_writebuf_skb_stub(lp->isdn_device,lp->isdn_channel,skb) != count) {
if(lp->sav_skb) {
dev_kfree_skb(lp->sav_skb,FREE_WRITE);
printk(KERN_INFO "isdn_ppp_write: freeing sav_skb!\n");
}
lp->sav_skb = skb;
}
}
}
return count;
......@@ -617,6 +665,11 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
if(ippp_table[lp->ppp_minor]->debug & 0x4)
printk(KERN_DEBUG "recv skb, len: %ld\n",skb->len);
if(net_dev->local.master) {
printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
net_dev = ((isdn_net_local*) net_dev->local.master->priv)->netdev;
}
if(skb->data[0] == 0xff && skb->data[1] == 0x03)
skb_pull(skb,2);
else if (ippp_table[lp->ppp_minor]->pppcfg & SC_REJ_COMP_AC) {
......@@ -819,8 +872,13 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
skb->mac.raw = skb->data;
pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_minor]->slcomp,
skb->data, skb_old->len);
skb_trim(skb, pkt_len);
dev_kfree_skb(skb_old,FREE_WRITE);
if(pkt_len < 0) {
dev_kfree_skb(skb,FREE_WRITE);
lp->stats.rx_dropped++;
return;
}
skb_trim(skb, pkt_len);
skb->protocol = htons(ETH_P_IP);
}
#else
......@@ -848,6 +906,7 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
* send ppp frame .. we expect a PIDCOMPressable proto --
* (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
*/
int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
{
struct device *mdev = ((isdn_net_local *) (dev->priv) )->master; /* get master (for redundancy) */
......@@ -861,32 +920,43 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
else
mlp = (isdn_net_local *) (dev->priv);
nd = mlp->netdev; /* get master lp */
lp = nd->queue; /* get lp on top of queue */
ipt = ippp_table[lp->ppp_minor];
ipts = ippp_table[mlp->ppp_minor];
if (!(ipt->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
printk(KERN_INFO "isdn, xmit: Packet blocked: %d %d\n", lp->isdn_device, lp->isdn_channel);
if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
printk(KERN_INFO "%s: IP frame delayed.\n",dev->name);
return 1;
}
lp = nd->queue; /* get lp on top of queue */
if(lp->sav_skb) { /* find a non-busy device */
isdn_net_local *nlp = lp->next;
while(lp->sav_skb) {
if(lp == nlp)
return 1;
nlp = nd->queue = nd->queue->next;
}
lp = nlp;
}
ipt = ippp_table[lp->ppp_minor];
lp->huptimer = 0;
/* If packet is to be resent, it has already been processed and
* therefore its first bytes are already initialized. In this case
* send it immediately ...
*/
if (*((unsigned long *)skb->data) != 0)
if (*((u32 *)skb->data) != 0) {
printk(KERN_ERR "%s: Whoops .. packet resend should no longer happen!\n",dev->name);
return (isdn_net_send_skb(dev , lp , skb));
}
/* ... else packet needs processing. */
/* future: step to next 'lp' when this lp is 'tbusy' */
if(ippp_table[lp->ppp_minor]->debug & 0x4)
printk(KERN_DEBUG "xmit skb, len %ld\n",skb->len);
#ifdef CONFIG_ISDN_PPP_VJ
if (ipt->pppcfg & SC_COMP_TCP) { /* ipt or ipts ? -> check this again! */
if (ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes .. but check again */
u_char *buf = skb->data;
int pktlen;
int len = 4;
......@@ -947,7 +1017,15 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
skb->data[3] = proto & 0xff;
/* tx-stats are now updated via BSENT-callback */
return (isdn_net_send_skb(dev , lp , skb));
if(isdn_net_send_skb(dev , lp , skb)) {
if(lp->sav_skb) { /* whole sav_skb processing with disabled IRQs ?? */
printk(KERN_ERR "%s: whoops .. there is another stored skb!\n!",dev->name);
dev_kfree_skb(skb,FREE_WRITE);
}
else
lp->sav_skb = skb;
}
return 0;
}
void isdn_ppp_free_sqqueue(isdn_net_dev * p)
......@@ -1165,6 +1243,9 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int
static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min_sqno)
{
#ifdef CONFIG_ISDN_PPP_VJ
int toss = 0;
#endif
/* z.z einfaches aussortieren gammeliger pakete. Fuer die Zukunft:
eventuell, solange vorne kein B-paket ist und sqno<=min_sqno: auch rauswerfen
wenn sqno<min_sqno und Luecken vorhanden sind: auch weg (die koennen nicht mehr gefuellt werden)
......@@ -1183,6 +1264,9 @@ static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min_sqno)
ql = q->last;
dev_kfree_skb(q->skb,FREE_WRITE);
kfree(q);
#ifdef CONFIG_ISDN_PPP_VJ
toss = 1;
#endif
q = ql;
}
q = dev->mp_last;
......@@ -1191,6 +1275,11 @@ static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min_sqno)
} else
break;
}
#ifdef CONFIG_ISDN_PPP_VJ
/* did we free a stale frame ? */
if(toss)
slhc_toss(ippp_table[dev->local.ppp_minor]->slcomp);
#endif
}
/*
......@@ -1207,7 +1296,7 @@ void isdn_ppp_timer_timeout(void)
while (net_dev) {
isdn_net_local *lp = &net_dev->local;
if (net_dev->ib.modify) { /* interface locked? */
if (net_dev->ib.modify || lp->master) { /* interface locked or slave?*/
net_dev = net_dev->next;
continue;
}
......@@ -1215,6 +1304,13 @@ void isdn_ppp_timer_timeout(void)
q = net_dev->ib.sq;
while (q) {
if (q->sqno_start == net_dev->ib.next_num || q->timer < jiffies) {
#ifdef CONFIG_ISDN_PPP_VJ
/* did we step over a missing frame ? */
if(q->sqno_start != net_dev->ib.next_num)
slhc_toss(ippp_table[lp->ppp_minor]->slcomp);
#endif
ql = net_dev->ib.sq;
net_dev->ib.sq = q->next;
net_dev->ib.next_num = q->sqno_end + 1;
......@@ -1234,6 +1330,49 @@ void isdn_ppp_timer_timeout(void)
#endif
}
/*
* network device ioctl handlers
*/
static int isdn_ppp_dev_ioctl_stats(int minor,struct ifreq *ifr,struct device *dev)
{
struct ppp_stats *res, t;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
int err;
res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
err = verify_area (VERIFY_WRITE, res,sizeof(struct ppp_stats));
if(err)
return err;
/* build a temporary stat struct and copy it to user space */
memset (&t, 0, sizeof(struct ppp_stats));
if(dev->flags & IFF_UP) {
t.p.ppp_ipackets = lp->stats.rx_packets;
t.p.ppp_ierrors = lp->stats.rx_errors;
t.p.ppp_opackets = lp->stats.tx_packets;
t.p.ppp_oerrors = lp->stats.tx_errors;
#ifdef CONFIG_ISDN_PPP_VJ
if(minor >= 0 && ippp_table[minor]->slcomp) {
struct slcompress *slcomp = ippp_table[minor]->slcomp;
t.vj.vjs_packets = slcomp->sls_o_compressed+slcomp->sls_o_uncompressed;
t.vj.vjs_compressed = slcomp->sls_o_compressed;
t.vj.vjs_searches = slcomp->sls_o_searches;
t.vj.vjs_misses = slcomp->sls_o_misses;
t.vj.vjs_errorin = slcomp->sls_i_error;
t.vj.vjs_tossed = slcomp->sls_i_tossed;
t.vj.vjs_uncompressedin = slcomp->sls_i_uncompressed;
t.vj.vjs_compressedin = slcomp->sls_i_compressed;
}
#endif
}
memcpy_tofs (res, &t, sizeof (struct ppp_stats));
return 0;
}
int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
{
int error;
......@@ -1241,19 +1380,27 @@ int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
int len;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
#if 1
printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n",cmd,lp->ppp_minor);
#endif
if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
return -EINVAL;
switch (cmd) {
case SIOCGPPPVER:
r = (char *) ifr->ifr_ifru.ifru_data;
len = strlen(PPP_VERSION) + 1;
error = verify_area(VERIFY_WRITE, r, len);
if (!error)
memcpy_tofs(r, PPP_VERSION, len);
break;
default:
error = -EINVAL;
case SIOCGPPPVER:
r = (char *) ifr->ifr_ifru.ifru_data;
len = strlen(PPP_VERSION) + 1;
error = verify_area(VERIFY_WRITE, r, len);
if (!error)
memcpy_tofs(r, PPP_VERSION, len);
break;
case SIOCGPPPSTATS:
error = isdn_ppp_dev_ioctl_stats (lp->ppp_minor, ifr, dev);
break;
default:
error = -EINVAL;
break;
}
return error;
}
......
/* $Id: isdn_tty.c,v 1.18 1996/06/07 11:17:33 tsbogend Exp $
/* $Id: isdn_tty.c,v 1.21 1996/06/24 17:40:28 fritz Exp $
*
* Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
*
......@@ -20,6 +20,18 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_tty.c,v $
* Revision 1.21 1996/06/24 17:40:28 fritz
* Bugfix: Did not compile without CONFIG_ISDN_AUDIO
*
* Revision 1.20 1996/06/15 14:59:39 fritz
* Fixed isdn_tty_tint() to handle partially sent
* sk_buffs.
*
* Revision 1.19 1996/06/12 15:53:56 fritz
* Bugfix: AT+VTX and AT+VRX could be executed without
* having a connection.
* Missing check for NULL tty in isdn_tty_flush_buffer().
*
* Revision 1.18 1996/06/07 11:17:33 tsbogend
* added missing #ifdef CONFIG_ISDN_AUDIO to make compiling without
* audio support possible
......@@ -127,7 +139,7 @@ static char *isdn_ttyname_cui = "cui";
static int bit2si[8] = {1,5,7,7,7,7,7,7};
static int si2bit[8] = {4,1,4,4,4,4,4,4};
char *isdn_tty_revision = "$Revision: 1.18 $";
char *isdn_tty_revision = "$Revision: 1.21 $";
#define DLE 0x10
#define ETX 0x03
......@@ -262,10 +274,13 @@ void isdn_tty_cleanup_xmit(modem_info *info)
static void isdn_tty_tint(modem_info *info)
{
struct sk_buff *skb = skb_dequeue(&info->xmit_queue);
int len, slen;
if (!skb)
return;
if (isdn_writebuf_skb_stub(info->isdn_driver, info->isdn_channel, skb) > 0) {
len = skb->len;
if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
info->isdn_channel, skb)) == len) {
struct tty_struct *tty = info->tty;
info->send_outstanding++;
info->msr |= UART_MSR_CTS;
......@@ -276,6 +291,8 @@ static void isdn_tty_tint(modem_info *info)
wake_up_interruptible(&tty->write_wait);
return;
}
if (slen > 0)
skb_pull(skb,slen);
skb_queue_head(&info->xmit_queue, skb);
}
......@@ -369,10 +386,11 @@ static int isdn_tty_end_vrx(const char *buf, int c, int from_user)
}
return 0;
}
#endif /* CONFIG_ISDN_AUDIO */
static int voice_cf[7] = { 1, 1, 4, 3, 2, 1, 1 };
#endif /* CONFIG_ISDN_AUDIO */
/* 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
......@@ -398,8 +416,8 @@ static void isdn_tty_senddown(modem_info * info)
return;
}
skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
if (info->vonline & 2) {
#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, Canada and Japan.
......@@ -454,8 +472,8 @@ static void isdn_tty_senddown(modem_info * info)
if (!info->vonline)
isdn_tty_at_cout("\r\nVCON\r\n",info);
}
#endif /* CONFIG_ISDN_AUDIO */
} else {
#endif /* CONFIG_ISDN_AUDIO */
skb = dev_alloc_skb(buflen + skb_res);
if (!skb) {
printk(KERN_WARNING
......@@ -467,7 +485,9 @@ static void isdn_tty_senddown(modem_info * info)
memcpy(skb_put(skb,buflen),buf,buflen);
info->xmit_count = 0;
restore_flags(flags);
#ifdef CONFIG_ISDN_AUDIO
}
#endif
skb->free = 1;
if (info->emu.mdmreg[13] & 2)
/* Add T.70 simplified header */
......@@ -591,6 +611,9 @@ void isdn_tty_modem_hup(modem_info * info)
if (!info)
return;
#ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
#endif
info->rcvsched = 0;
info->online = 0;
isdn_tty_flush_buffer(info->tty);
......@@ -896,13 +919,20 @@ 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;
modem_info *info;
unsigned long flags;
if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer"))
return;
save_flags(flags);
cli();
if (!tty) {
restore_flags(flags);
return;
}
info = (modem_info *) tty->driver_data;
if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer")) {
restore_flags(flags);
return;
}
isdn_tty_cleanup_xmit(info);
info->xmit_count = 0;
restore_flags(flags);
......@@ -2324,6 +2354,10 @@ static int isdn_tty_cmd_PLUSV(char **p, modem_info * info)
/* AT+VRX - Start recording */
if (!m->vpar[0])
PARSE_ERROR1;
if (info->online != 1) {
isdn_tty_modem_result(8, info);
return 1;
}
info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
if (!info->dtmf_state) {
printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
......@@ -2430,6 +2464,10 @@ static int isdn_tty_cmd_PLUSV(char **p, modem_info * info)
/* AT+VTX - Start sending */
if (!m->vpar[0])
PARSE_ERROR1;
if (info->online != 1) {
isdn_tty_modem_result(8, info);
return 1;
}
info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
if (!info->dtmf_state) {
printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment