isdn/mISDN: add __init/__exit macros to dsp_core.c
[safe/jmp/linux-2.6] / drivers / isdn / i4l / isdn_tty.c
index 8c404b4..2881a66 100644 (file)
@@ -11,9 +11,9 @@
  */
 #undef ISDN_TTY_STAT_DEBUG
 
-#include <linux/config.h>
 #include <linux/isdn.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
 #include "isdn_common.h"
 #include "isdn_tty.h"
 #ifdef CONFIG_ISDN_AUDIO
@@ -64,37 +64,44 @@ isdn_tty_try_read(modem_info * info, struct sk_buff *skb)
        int c;
        int len;
        struct tty_struct *tty;
+       char last;
 
        if (info->online) {
                if ((tty = info->tty)) {
                        if (info->mcr & UART_MCR_RTS) {
-                               c = TTY_FLIPBUF_SIZE - tty->flip.count;
                                len = skb->len
 #ifdef CONFIG_ISDN_AUDIO
                                        + ISDN_AUDIO_SKB_DLECOUNT(skb)
 #endif
                                        ;
+
+                               c = tty_buffer_request_room(tty, len);
                                if (c >= len) {
 #ifdef CONFIG_ISDN_AUDIO
-                                       if (ISDN_AUDIO_SKB_DLECOUNT(skb))
-                                               while (skb->len--) {
-                                                       if (*skb->data == DLE)
+                                       if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
+                                               int l = skb->len;
+                                               unsigned char *dp = skb->data;
+                                               while (--l) {
+                                                       if (*dp == DLE)
                                                                tty_insert_flip_char(tty, DLE, 0);
-                                                       tty_insert_flip_char(tty, *skb->data++, 0);
+                                                       tty_insert_flip_char(tty, *dp++, 0);
+                                               }
+                                               if (*dp == DLE)
+                                                       tty_insert_flip_char(tty, DLE, 0);
+                                               last = *dp;
                                        } else {
 #endif
-                                               memcpy(tty->flip.char_buf_ptr,
-                                                      skb->data, len);
-                                               tty->flip.count += len;
-                                               tty->flip.char_buf_ptr += len;
-                                               memset(tty->flip.flag_buf_ptr, 0, len);
-                                               tty->flip.flag_buf_ptr += len;
+                                               if(len > 1)
+                                                       tty_insert_flip_string(tty, skb->data, len - 1);
+                                               last = skb->data[len - 1];
 #ifdef CONFIG_ISDN_AUDIO
                                        }
 #endif
                                        if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
-                                               tty->flip.flag_buf_ptr[len - 1] = 0xff;
-                                       schedule_delayed_work(&tty->flip.work, 1);
+                                               tty_insert_flip_char(tty, last, 0xFF);
+                                       else
+                                               tty_insert_flip_char(tty, last, TTY_NORMAL);
+                                       tty_flip_buffer_push(tty);
                                        kfree_skb(skb);
                                        return 1;
                                }
@@ -114,7 +121,6 @@ isdn_tty_readmodem(void)
        int resched = 0;
        int midx;
        int i;
-       int c;
        int r;
        struct tty_struct *tty;
        modem_info *info;
@@ -131,20 +137,13 @@ isdn_tty_readmodem(void)
 #endif
                                if ((tty = info->tty)) {
                                        if (info->mcr & UART_MCR_RTS) {
-                                               c = TTY_FLIPBUF_SIZE - tty->flip.count;
-                                               if (c > 0) {
-                                                       r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
-                                                                          tty->flip.char_buf_ptr,
-                                                                          tty->flip.flag_buf_ptr, c, NULL);
-                                                       /* CISCO AsyncPPP Hack */
-                                                       if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
-                                                               memset(tty->flip.flag_buf_ptr, 0, r);
-                                                       tty->flip.count += r;
-                                                       tty->flip.flag_buf_ptr += r;
-                                                       tty->flip.char_buf_ptr += r;
-                                                       if (r)
-                                                               schedule_delayed_work(&tty->flip.work, 1);
-                                               }
+                                               /* CISCO AsyncPPP Hack */
+                                               if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
+                                                       r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 0);
+                                               else
+                                                       r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 1);
+                                               if (r)
+                                                       tty_flip_buffer_push(tty);
                                        } else
                                                r = 1;
                                } else
@@ -249,7 +248,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
        }
 #endif
 #endif
-       /* Try to deliver directly via tty-flip-buf if queue is empty */
+       /* Try to deliver directly via tty-buf if queue is empty */
        spin_lock_irqsave(&info->readlock, flags);
        if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
                if (isdn_tty_try_read(info, skb)) {
@@ -534,7 +533,7 @@ isdn_tty_senddown(modem_info * info)
 /* The next routine is called once from within timer-interrupt
  * triggered within isdn_tty_modem_ncarrier(). It calls
  * isdn_tty_modem_result() to stuff a "NO CARRIER" Message
- * into the tty's flip-buffer.
+ * into the tty's buffer.
  */
 static void
 isdn_tty_modem_do_ncarrier(unsigned long data)
@@ -1265,7 +1264,6 @@ isdn_tty_flush_buffer(struct tty_struct *tty)
        }
        isdn_tty_cleanup_xmit(info);
        info->xmit_count = 0;
-       wake_up_interruptible(&tty->write_wait);
        tty_wakeup(tty);
 }
 
@@ -1350,17 +1348,19 @@ isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
        modem_info *info = (modem_info *) tty->driver_data;
        u_char control, status;
 
-       if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
+       if (isdn_tty_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
                return -EIO;
 
+       lock_kernel();
 #ifdef ISDN_DEBUG_MODEM_IOCTL
        printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
 #endif
 
        control = info->mcr;
        status = info->msr;
+       unlock_kernel();
        return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
            | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
            | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1375,7 +1375,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
 {
        modem_info *info = (modem_info *) tty->driver_data;
 
-       if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
+       if (isdn_tty_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
                return -EIO;
@@ -1384,6 +1384,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
        printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
 #endif
 
+       lock_kernel();
        if (set & TIOCM_RTS)
                info->mcr |= UART_MCR_RTS;
        if (set & TIOCM_DTR) {
@@ -1405,6 +1406,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
                        isdn_tty_modem_hup(info, 1);
                }
        }
+       unlock_kernel();
        return 0;
 }
 
@@ -1438,21 +1440,6 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
                                return retval;
                        tty_wait_until_sent(tty, 0);
                        return 0;
-               case TIOCGSOFTCAR:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
-#endif
-                       return put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
-               case TIOCSSOFTCAR:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
-#endif
-                       if (get_user(arg, (ulong __user *) arg))
-                               return -EFAULT;
-                       tty->termios->c_cflag =
-                           ((tty->termios->c_cflag & ~CLOCAL) |
-                            (arg ? CLOCAL : 0));
-                       return 0;
                case TIOCSERGETLSR:     /* Get line status register */
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                        printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
@@ -1468,20 +1455,21 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
 }
 
 static void
-isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
+isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        modem_info *info = (modem_info *) tty->driver_data;
 
        if (!old_termios)
                isdn_tty_change_speed(info);
        else {
-               if (tty->termios->c_cflag == old_termios->c_cflag)
+               if (tty->termios->c_cflag == old_termios->c_cflag &&
+                   tty->termios->c_ispeed == old_termios->c_ispeed &&
+                   tty->termios->c_ospeed == old_termios->c_ospeed)
                        return;
                isdn_tty_change_speed(info);
                if ((old_termios->c_cflag & CRTSCTS) &&
-                   !(tty->termios->c_cflag & CRTSCTS)) {
+                   !(tty->termios->c_cflag & CRTSCTS))
                        tty->hw_stopped = 0;
-               }
        }
 }
 
@@ -1605,13 +1593,13 @@ isdn_tty_open(struct tty_struct *tty, struct file *filp)
        int retval, line;
 
        line = tty->index;
-       if (line < 0 || line > ISDN_MAX_CHANNELS)
+       if (line < 0 || line >= ISDN_MAX_CHANNELS)
                return -ENODEV;
        info = &dev->mdm.info[line];
        if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
                return -ENODEV;
        if (!try_module_get(info->owner)) {
-               printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__);
+               printk(KERN_WARNING "%s: cannot reserve module\n", __func__);
                return -ENODEV;
        }
 #ifdef ISDN_DEBUG_MODEM_OPEN
@@ -1685,6 +1673,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
 #ifdef ISDN_DEBUG_MODEM_OPEN
                printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
 #endif
+               module_put(info->owner);
                return;
        }
        info->flags |= ISDN_ASYNC_CLOSING;
@@ -1720,9 +1709,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
        }
        dev->modempoll--;
        isdn_tty_shutdown(info);
-       
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       isdn_tty_flush_buffer(tty);
        tty_ldisc_flush(tty);
        info->tty = NULL;
        info->ncarrier = 0;
@@ -1863,7 +1850,7 @@ modem_write_profile(atemu * m)
                send_sig(SIGIO, dev->profd, 1);
 }
 
-static struct tty_operations modem_ops = {
+static const struct tty_operations modem_ops = {
         .open = isdn_tty_open,
        .close = isdn_tty_close,
        .write = isdn_tty_write,
@@ -1892,14 +1879,13 @@ isdn_tty_modem_init(void)
        if (!m->tty_modem)
                return -ENOMEM;
        m->tty_modem->name = "ttyI";
-       m->tty_modem->devfs_name = "isdn/ttyI";
        m->tty_modem->major = ISDN_TTY_MAJOR;
        m->tty_modem->minor_start = 0;
        m->tty_modem->type = TTY_DRIVER_TYPE_SERIAL;
        m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
        m->tty_modem->init_termios = tty_std_termios;
        m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+       m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        m->tty_modem->driver_name = "isdn_tty";
        tty_set_operations(m->tty_modem, &modem_ops);
        retval = tty_register_driver(m->tty_modem);
@@ -1920,7 +1906,6 @@ isdn_tty_modem_init(void)
                info->owner = THIS_MODULE;
 #endif
                spin_lock_init(&info->readlock);
-               init_MUTEX(&info->write_sem);
                sprintf(info->last_cause, "0000");
                sprintf(info->last_num, "none");
                info->last_dir = 0;
@@ -2347,11 +2332,15 @@ isdn_tty_at_cout(char *msg, modem_info * info)
        u_long flags;
        struct sk_buff *skb = NULL;
        char *sp = NULL;
+       int l;
 
        if (!msg) {
                printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
                return;
        }
+
+       l = strlen(msg);
+
        spin_lock_irqsave(&info->readlock, flags);
        tty = info->tty;
        if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
@@ -2359,16 +2348,16 @@ isdn_tty_at_cout(char *msg, modem_info * info)
                return;
        }
 
-       /* use queue instead of direct flip, if online and */
-       /* data is in queue or flip buffer is full */
-       if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
-           (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
-               skb = alloc_skb(strlen(msg), GFP_ATOMIC);
+       /* use queue instead of direct, if online and */
+       /* data is in queue or buffer is full */
+       if (info->online && ((tty_buffer_request_room(tty, l) < l) ||
+           !skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
+               skb = alloc_skb(l, GFP_ATOMIC);
                if (!skb) {
                        spin_unlock_irqrestore(&info->readlock, flags);
                        return;
                }
-               sp = skb_put(skb, strlen(msg));
+               sp = skb_put(skb, l);
 #ifdef CONFIG_ISDN_AUDIO
                ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
                ISDN_AUDIO_SKB_LOCK(skb) = 0;
@@ -2392,9 +2381,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
                if (skb) {
                        *sp++ = c;
                } else {
-                       if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+                       if(tty_insert_flip_char(tty, c, TTY_NORMAL) == 0)
                                break;
-                       tty_insert_flip_char(tty, c, 0);
                }
        }
        if (skb) {
@@ -2402,12 +2390,12 @@ isdn_tty_at_cout(char *msg, modem_info * info)
                dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
                spin_unlock_irqrestore(&info->readlock, flags);
                /* Schedule dequeuing */
-               if ((dev->modempoll) && (info->rcvsched))
+               if (dev->modempoll && info->rcvsched)
                        isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
 
        } else {
                spin_unlock_irqrestore(&info->readlock, flags);
-               schedule_delayed_work(&tty->flip.work, 1);
+               tty_flip_buffer_push(tty);
        }
 }
 
@@ -2647,7 +2635,12 @@ isdn_tty_modem_result(int code, modem_info * info)
                if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
                        return;
                }
+#ifdef CONFIG_ISDN_AUDIO
+               if ( !info->vonline )
+                       tty_ldisc_flush(info->tty);
+#else
                tty_ldisc_flush(info->tty);
+#endif
                if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
                    (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
                       (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
@@ -2695,8 +2688,9 @@ isdn_tty_getdial(char *p, char *q,int cnt)
        int limit = ISDN_MSNLEN - 1;    /* MUST match the size of interface var to avoid
                                        buffer overflow */
 
-       while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
+       while (strchr(" 0123456789,#.*WPTSR-", *p) && *p && --cnt>0) {
                if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
+                   ((*p == 'R') && first) ||
                    (*p == '*') || (*p == '#')) {
                        *q++ = *p;
                        limit--;
@@ -2879,7 +2873,7 @@ isdn_tty_cmd_ATand(char **p, modem_info * info)
                        p[0]++;
                        i = 0;
                        while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
-                              (i < ISDN_LMSNLEN))
+                              (i < ISDN_LMSNLEN - 1))
                                m->lmsn[i++] = *p[0]++;
                        m->lmsn[i] = '\0';
                        break;