X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fisdn%2Fi4l%2Fisdn_tty.c;h=fc80afe555b9e9063229dca25739aa5b33afe29a;hb=refs%2Fheads%2Fvserver;hp=921c3c2ab97a19bcce843dbb5a93cca81ff03fee;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 921c3c2ab..fc80afe55 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -11,8 +11,8 @@ */ #undef ISDN_TTY_STAT_DEBUG -#include #include +#include #include "isdn_common.h" #include "isdn_tty.h" #ifdef CONFIG_ISDN_AUDIO @@ -26,8 +26,8 @@ /* Prototypes */ -static int isdn_tty_edit_at(const char *, int, modem_info *, int); -static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *, int); +static int isdn_tty_edit_at(const char *, int, modem_info *); +static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *); static void isdn_tty_modem_reset_regs(modem_info *, int); static void isdn_tty_cmd_ATA(modem_info *); static void isdn_tty_flush_buffer(struct tty_struct *); @@ -63,37 +63,42 @@ 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); + } + 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; } @@ -113,7 +118,6 @@ isdn_tty_readmodem(void) int resched = 0; int midx; int i; - int c; int r; struct tty_struct *tty; modem_info *info; @@ -130,20 +134,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 @@ -248,7 +245,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)) { @@ -272,7 +269,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb) return 1; } -void +static void isdn_tty_cleanup_xmit(modem_info * info) { skb_queue_purge(&info->xmit_queue); @@ -390,15 +387,12 @@ isdn_tty_handleDLEdown(modem_info * info, atemu * m, int len) * ^S or ^Q is sent. */ static int -isdn_tty_end_vrx(const char *buf, int c, int from_user) +isdn_tty_end_vrx(const char *buf, int c) { char ch; while (c--) { - if (from_user) - get_user(ch, buf); - else - ch = *buf; + ch = *buf; if ((ch != 0x11) && (ch != 0x13)) return 1; buf++; @@ -536,7 +530,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) @@ -562,7 +556,7 @@ isdn_tty_modem_ncarrier(modem_info * info) /* * return the usage calculated by si and layer 2 protocol */ -int +static int isdn_calc_usage(int si, int l2) { int usg = ISDN_USAGE_MODEM; @@ -714,22 +708,14 @@ isdn_tty_modem_hup(modem_info * info, int local) #endif info->emu.vpar[4] = 0; info->emu.vpar[5] = 8; - if (info->dtmf_state) { - kfree(info->dtmf_state); - info->dtmf_state = NULL; - } - if (info->silence_state) { - kfree(info->silence_state); - info->silence_state = NULL; - } - if (info->adpcms) { - kfree(info->adpcms); - info->adpcms = NULL; - } - if (info->adpcmr) { - kfree(info->adpcmr); - info->adpcmr = NULL; - } + kfree(info->dtmf_state); + info->dtmf_state = NULL; + kfree(info->silence_state); + info->silence_state = NULL; + kfree(info->adpcms); + info->adpcms = NULL; + kfree(info->adpcmr); + info->adpcmr = NULL; #endif if ((info->msr & UART_MSR_RI) && (info->emu.mdmreg[REG_RUNG] & BIT_RUNG)) @@ -1126,7 +1112,7 @@ isdn_tty_shutdown(modem_info * info) * - If dialing, abort dial. */ static int -isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count) +isdn_tty_write(struct tty_struct *tty, const u_char * buf, int count) { int c; int total = 0; @@ -1135,8 +1121,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write")) return 0; - if (from_user) - down(&info->write_sem); /* See isdn_tty_senddown() */ atomic_inc(&info->xmit_lock); while (1) { @@ -1157,12 +1141,8 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co #endif isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c, &(m->pluscount), - &(m->lastplus), - from_user); - if (from_user) - copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c); - else - memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); + &(m->lastplus)); + memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); #ifdef CONFIG_ISDN_AUDIO if (info->vonline) { int cc = isdn_tty_handleDLEdown(info, m, c); @@ -1181,7 +1161,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co /* Do NOT handle Ctrl-Q or Ctrl-S * when in full-duplex audio mode. */ - if (isdn_tty_end_vrx(buf, c, from_user)) { + if (isdn_tty_end_vrx(buf, c)) { info->vonline &= ~1; #ifdef ISDN_DEBUG_MODEM_VOICE printk(KERN_DEBUG @@ -1224,22 +1204,20 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co isdn_tty_modem_result(RESULT_NO_CARRIER, info); isdn_tty_modem_hup(info, 1); } else - c = isdn_tty_edit_at(buf, c, info, from_user); + c = isdn_tty_edit_at(buf, c, info); } buf += c; count -= c; total += c; } atomic_dec(&info->xmit_lock); - if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) { + if ((info->xmit_count) || !skb_queue_empty(&info->xmit_queue)) { if (m->mdmreg[REG_DXMT] & BIT_DXMT) { isdn_tty_senddown(info); isdn_tty_tint(info); } isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); } - if (from_user) - up(&info->write_sem); return total; } @@ -1294,7 +1272,7 @@ isdn_tty_flush_chars(struct tty_struct *tty) if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_chars")) return; - if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) + if ((info->xmit_count) || !skb_queue_empty(&info->xmit_queue)) isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); } @@ -1486,7 +1464,7 @@ 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; @@ -1703,6 +1681,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; @@ -1731,8 +1710,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) */ timeout = jiffies + HZ; while (!(info->lsr & UART_LSR_TEMT)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(20); + schedule_timeout_interruptible(20); if (time_after(jiffies,timeout)) break; } @@ -1748,8 +1726,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) tty->closing = 0; module_put(info->owner); if (info->blocked_open) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/2); + msleep_interruptible(500); wake_up_interruptible(&info->open_wait); } info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CLOSING); @@ -1883,7 +1860,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, @@ -1912,14 +1889,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); @@ -2367,11 +2343,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)) { @@ -2379,16 +2359,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; @@ -2412,9 +2392,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) { @@ -2422,12 +2401,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); } } @@ -2467,10 +2446,8 @@ isdn_tty_off_hook(void) */ static void isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, - u_long *lastplus, int from_user) + u_long *lastplus) { - char cbuf[3]; - if (plus > 127) return; if (count > 3) { @@ -2478,10 +2455,6 @@ isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, count = 3; *pluscount = 0; } - if (from_user) { - copy_from_user(cbuf, p, count); - p = cbuf; - } while (count > 0) { if (*(p++) == plus) { if ((*pluscount)++) { @@ -2905,7 +2878,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; @@ -3761,10 +3734,9 @@ isdn_tty_parse_at(modem_info * info) * p inputbuffer * count length of buffer * channel index to line (minor-device) - * user flag: buffer is in userspace */ static int -isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) +isdn_tty_edit_at(const char *p, int count, modem_info * info) { atemu *m = &info->emu; int total = 0; @@ -3773,10 +3745,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) int cnt; for (cnt = count; cnt > 0; p++, cnt--) { - if (user) - get_user(c, p); - else - c = *p; + c = *p; total++; if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) { /* Separator (CR or LF) */