This source file includes following definitions.
- isdn_tty_try_read
- isdn_tty_readmodem
- isdn_tty_dial
- isdn_tty_modem_hup
- isdn_tty_paranoia_check
- isdn_tty_change_speed
- isdn_tty_startup
- isdn_tty_shutdown
- isdn_tty_write
- isdn_tty_write_room
- isdn_tty_chars_in_buffer
- isdn_tty_flush_buffer
- isdn_tty_flush_chars
- isdn_tty_throttle
- isdn_tty_unthrottle
- isdn_tty_get_lsr_info
- isdn_tty_get_modem_info
- isdn_tty_set_modem_info
- isdn_tty_ioctl
- isdn_tty_set_termios
- isdn_tty_block_til_ready
- isdn_tty_open
- isdn_tty_close
- isdn_tty_hangup
- isdn_tty_reset_profile
- isdn_tty_modem_reset_regs
- modem_write_profile
- isdn_tty_modem_init
- isdn_tty_find_icall
- isdn_tty_at_cout
- isdn_tty_on_hook
- isdn_tty_off_hook
- isdn_tty_check_esc
- isdn_tty_modem_result
- isdn_tty_show_profile
- isdn_tty_get_msnstr
- isdn_tty_getdial
- isdn_tty_parse_at
- isdn_tty_edit_at
- isdn_tty_modem_escape
- isdn_tty_modem_ring
- isdn_tty_modem_xmit
- isdn_tty_bsent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #define __NO_VERSION__
40 #include <linux/module.h>
41 #include <linux/isdn.h>
42 #include "isdn_common.h"
43 #include "isdn_tty.h"
44
45
46
47 static int isdn_tty_edit_at(const char *, int, modem_info *, int);
48 static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
49 static void isdn_tty_modem_reset_regs(atemu *, int);
50
51
52 #define MODEM_PARANOIA_CHECK
53 #define MODEM_DO_RESTART
54
55 static char *isdn_ttyname_ttyI = "ttyI";
56 static char *isdn_ttyname_cui = "cui";
57 char *isdn_tty_revision = "$Revision: 1.4 $";
58
59 int isdn_tty_try_read(int i, u_char * buf, int len)
60 {
61 int c;
62 struct tty_struct *tty;
63
64 if (i < 0)
65 return 0;
66 if (dev->mdm.online[i]) {
67 if ((tty = dev->mdm.info[i].tty)) {
68 if (dev->mdm.info[i].MCR & UART_MCR_RTS) {
69 c = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
70 if (c >= len) {
71 if (len > 1) {
72 memcpy(tty->flip.char_buf_ptr, buf, len);
73 tty->flip.count += len;
74 memset(tty->flip.flag_buf_ptr, 0, len);
75 if (dev->mdm.atmodem[i].mdmreg[12] & 128)
76 tty->flip.flag_buf_ptr[len - 1] = 0xff;
77 tty->flip.flag_buf_ptr += len;
78 tty->flip.char_buf_ptr += len;
79 } else
80 tty_insert_flip_char(tty, buf[0], 0);
81 queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
82 return 1;
83 }
84 }
85 }
86 }
87 return 0;
88 }
89
90 void isdn_tty_readmodem(void)
91 {
92 int resched = 0;
93 int midx;
94 int i;
95 int c;
96 int r;
97 ulong flags;
98 struct tty_struct *tty;
99 modem_info *info;
100
101 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
102 if ((midx = dev->m_idx[i]) >= 0)
103 if (dev->mdm.online[midx]) {
104 save_flags(flags);
105 cli();
106 r = 0;
107 info = &dev->mdm.info[midx];
108 if ((tty = info->tty)) {
109 if (info->MCR & UART_MCR_RTS) {
110 c = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
111 if (c > 0) {
112 r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
113 tty->flip.char_buf_ptr,
114 tty->flip.flag_buf_ptr, c, 0);
115 if (!(dev->mdm.atmodem[midx].mdmreg[12] & 128))
116 memset(tty->flip.flag_buf_ptr, 0, r);
117 tty->flip.count += r;
118 tty->flip.flag_buf_ptr += r;
119 tty->flip.char_buf_ptr += r;
120 if (r)
121 queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
122 }
123 } else
124 r = 1;
125 } else
126 r = 1;
127 restore_flags(flags);
128 if (r) {
129 dev->mdm.rcvsched[midx] = 0;
130 resched = 1;
131 } else
132 dev->mdm.rcvsched[midx] = 1;
133 }
134 }
135 if (!resched)
136 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
137 }
138
139
140
141
142
143
144
145
146
147 static void isdn_tty_dial(char *n, modem_info * info, atemu * m)
148 {
149 isdn_ctrl cmd;
150 ulong flags;
151 int i;
152
153 save_flags(flags);
154 cli();
155 i = isdn_get_free_channel(ISDN_USAGE_MODEM, m->mdmreg[14], m->mdmreg[15], -1, -1);
156 if (i < 0) {
157 restore_flags(flags);
158 isdn_tty_modem_result(6, info);
159 } else {
160 if (strlen(m->msn)) {
161 info->isdn_driver = dev->drvmap[i];
162 info->isdn_channel = dev->chanmap[i];
163 info->drv_index = i;
164 dev->m_idx[i] = info->line;
165 dev->usage[i] |= ISDN_USAGE_OUTGOING;
166 isdn_info_update();
167 restore_flags(flags);
168 cmd.driver = info->isdn_driver;
169 cmd.arg = info->isdn_channel;
170 cmd.command = ISDN_CMD_CLREAZ;
171 dev->drv[info->isdn_driver]->interface->command(&cmd);
172 strcpy(cmd.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
173 cmd.driver = info->isdn_driver;
174 cmd.command = ISDN_CMD_SETEAZ;
175 dev->drv[info->isdn_driver]->interface->command(&cmd);
176 cmd.driver = info->isdn_driver;
177 cmd.command = ISDN_CMD_SETL2;
178 cmd.arg = info->isdn_channel + (m->mdmreg[14] << 8);
179 dev->drv[info->isdn_driver]->interface->command(&cmd);
180 cmd.driver = info->isdn_driver;
181 cmd.command = ISDN_CMD_SETL3;
182 cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
183 dev->drv[info->isdn_driver]->interface->command(&cmd);
184 cmd.driver = info->isdn_driver;
185 cmd.arg = info->isdn_channel;
186 sprintf(cmd.num, "%s,%s,%d,%d", n, isdn_map_eaz2msn(m->msn, info->isdn_driver),
187 m->mdmreg[18], m->mdmreg[19]);
188 cmd.command = ISDN_CMD_DIAL;
189 dev->mdm.dialing[info->line] = 1;
190 strcpy(dev->num[i], n);
191 isdn_info_update();
192 dev->drv[info->isdn_driver]->interface->command(&cmd);
193 } else
194 restore_flags(flags);
195 }
196 }
197
198 void isdn_tty_modem_hup(modem_info * info)
199 {
200 isdn_ctrl cmd;
201
202 if (!info)
203 return;
204 dev->mdm.rcvsched[info->line] = 0;
205 dev->mdm.online[info->line] = 0;
206 if (info->isdn_driver >= 0) {
207 cmd.driver = info->isdn_driver;
208 cmd.command = ISDN_CMD_HANGUP;
209 cmd.arg = info->isdn_channel;
210 dev->drv[info->isdn_driver]->interface->command(&cmd);
211 isdn_all_eaz(info->isdn_driver, info->isdn_channel);
212 isdn_free_channel(info->isdn_driver, info->isdn_channel, ISDN_USAGE_MODEM);
213 }
214 info->isdn_driver = -1;
215 info->isdn_channel = -1;
216 if (info->drv_index >= 0) {
217 info->drv_index = -1;
218 dev->m_idx[info->drv_index] = -1;
219 }
220 }
221
222 static inline int isdn_tty_paranoia_check(modem_info * info, dev_t device, const char *routine)
223 {
224 #ifdef MODEM_PARANOIA_CHECK
225 if (!info) {
226 printk(KERN_WARNING "isdn_tty: null info_struct for (%d, %d) in %s\n",
227 MAJOR(device), MINOR(device), routine);
228 return 1;
229 }
230 if (info->magic != ISDN_ASYNC_MAGIC) {
231 printk(KERN_WARNING "isdn_tty: bad magic for modem struct (%d, %d) in %s\n",
232 MAJOR(device), MINOR(device), routine);
233 return 1;
234 }
235 #endif
236 return 0;
237 }
238
239
240
241
242
243 static void isdn_tty_change_speed(modem_info * info)
244 {
245 uint cflag, cval, fcr, quot;
246 int i;
247
248 if (!info->tty || !info->tty->termios)
249 return;
250 cflag = info->tty->termios->c_cflag;
251
252 quot = i = cflag & CBAUD;
253 if (i & CBAUDEX) {
254 i &= ~CBAUDEX;
255 if (i < 1 || i > 2)
256 info->tty->termios->c_cflag &= ~CBAUDEX;
257 else
258 i += 15;
259 }
260 if (quot) {
261 info->MCR |= UART_MCR_DTR;
262 } else {
263 info->MCR &= ~UART_MCR_DTR;
264 isdn_tty_modem_reset_regs(&dev->mdm.atmodem[info->line], 0);
265 #ifdef ISDN_DEBUG_MODEM_HUP
266 printk(KERN_DEBUG "Mhup in changespeed\n");
267 #endif
268 isdn_tty_modem_hup(info);
269 if (dev->mdm.online[info->line])
270 isdn_tty_modem_result(3, info);
271 return;
272 }
273
274 cval = cflag & (CSIZE | CSTOPB);
275 cval >>= 4;
276 if (cflag & PARENB)
277 cval |= UART_LCR_PARITY;
278 if (!(cflag & PARODD))
279 cval |= UART_LCR_EPAR;
280 fcr = 0;
281
282
283 if (cflag & CRTSCTS) {
284 info->flags |= ISDN_ASYNC_CTS_FLOW;
285 } else
286 info->flags &= ~ISDN_ASYNC_CTS_FLOW;
287 if (cflag & CLOCAL)
288 info->flags &= ~ISDN_ASYNC_CHECK_CD;
289 else {
290 info->flags |= ISDN_ASYNC_CHECK_CD;
291 }
292 }
293
294 static int isdn_tty_startup(modem_info * info)
295 {
296 ulong flags;
297
298 if (info->flags & ISDN_ASYNC_INITIALIZED)
299 return 0;
300 if (!info->type) {
301 if (info->tty)
302 set_bit(TTY_IO_ERROR, &info->tty->flags);
303 return 0;
304 }
305 save_flags(flags);
306 cli();
307
308 #ifdef ISDN_DEBUG_MODEM_OPEN
309 printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);
310 #endif
311
312
313
314 info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
315 if (info->tty)
316 clear_bit(TTY_IO_ERROR, &info->tty->flags);
317
318
319
320 isdn_tty_change_speed(info);
321
322 info->flags |= ISDN_ASYNC_INITIALIZED;
323 dev->mdm.msr[info->line] |= UART_MSR_DSR;
324 #if FUTURE
325 info->send_outstanding = 0;
326 #endif
327 restore_flags(flags);
328 return 0;
329 }
330
331
332
333
334
335 static void isdn_tty_shutdown(modem_info * info)
336 {
337 ulong flags;
338
339 if (!(info->flags & ISDN_ASYNC_INITIALIZED))
340 return;
341 #ifdef ISDN_DEBUG_MODEM_OPEN
342 printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
343 #endif
344 save_flags(flags);
345 cli();
346 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
347 info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
348 isdn_tty_modem_reset_regs(&dev->mdm.atmodem[info->line], 0);
349 #ifdef ISDN_DEBUG_MODEM_HUP
350 printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
351 #endif
352 isdn_tty_modem_hup(info);
353 }
354 if (info->tty)
355 set_bit(TTY_IO_ERROR, &info->tty->flags);
356
357 info->flags &= ~ISDN_ASYNC_INITIALIZED;
358 restore_flags(flags);
359 }
360
361 static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
362 {
363 int c, total = 0;
364 modem_info *info = (modem_info *) tty->driver_data;
365 ulong flags;
366 int i;
367
368 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
369 return 0;
370 if (!tty)
371 return 0;
372 save_flags(flags);
373 cli();
374 while (1) {
375 c = MIN(count, info->xmit_size - info->xmit_count - 1);
376 if (info->isdn_driver >= 0) {
377 #if 0
378 if (info->isdn_driver != 0) {
379 printk(KERN_DEBUG "FIDO: Zwei HW-Treiber geladen? Ansonsten ist was faul.\n");
380 break;
381 }
382 int drvidx = info->isdn_driver;
383 driver *driv = dev->drv[drvidx];
384 i = driv->maxbufsize;
385 #else
386 i = dev->drv[info->isdn_driver]->maxbufsize;
387 #endif
388 c = MIN(c, i);
389 }
390 if (c <= 0)
391 break;
392 i = info->line;
393 if (dev->mdm.online[i]) {
394 isdn_tty_check_esc(buf, dev->mdm.atmodem[i].mdmreg[2], c,
395 &(dev->mdm.atmodem[i].pluscount),
396 &(dev->mdm.atmodem[i].lastplus), from_user);
397 if (from_user)
398 memcpy_fromfs(&(info->xmit_buf[info->xmit_count]), buf, c);
399 else
400 memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
401 info->xmit_count += c;
402 if (dev->mdm.atmodem[i].mdmreg[13] & 1) {
403 char *bufptr;
404 int buflen;
405 #if 0
406 printk(KERN_DEBUG "WB1: %d\n", info->xmit_count);
407 #endif
408 bufptr = info->xmit_buf;
409 buflen = info->xmit_count;
410 if (dev->mdm.atmodem[i].mdmreg[13] & 2) {
411
412
413 #ifdef ISDN_DEBUG_MODEM_DUMP
414 isdn_dumppkt("T70pack1:", bufptr, buflen, 40);
415 #endif
416 bufptr -= 4;
417 buflen += 4;
418 memcpy(bufptr, "\1\0\1\0", 4);
419 #ifdef ISDN_DEBUG_MODEM_DUMP
420 isdn_dumppkt("T70pack2:", bufptr, buflen, 40);
421 #endif
422 }
423 if (isdn_writebuf_stub(info->isdn_driver, info->isdn_channel, bufptr,
424 buflen, 0) > 0) {
425 info->xmit_count = 0;
426 info->xmit_size = dev->mdm.atmodem[i].mdmreg[16] * 16;
427 #if FUTURE
428 info->send_outstanding++;
429 dev->mdm.msr[i] &= ~UART_MSR_CTS;
430 #endif
431 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
432 tty->ldisc.write_wakeup)
433 (tty->ldisc.write_wakeup) (tty);
434 wake_up_interruptible(&tty->write_wait);
435 }
436 }
437 } else {
438 if (dev->mdm.dialing[i]) {
439 dev->mdm.dialing[i] = 0;
440 #ifdef ISDN_DEBUG_MODEM_HUP
441 printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
442 #endif
443 isdn_tty_modem_hup(info);
444 isdn_tty_modem_result(3, info);
445 } else
446 c = isdn_tty_edit_at(buf, c, info, from_user);
447 }
448 buf += c;
449 count -= c;
450 total += c;
451 }
452 if (info->xmit_count)
453 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
454 restore_flags(flags);
455 return total;
456 }
457
458 static int isdn_tty_write_room(struct tty_struct *tty)
459 {
460 modem_info *info = (modem_info *) tty->driver_data;
461 int ret;
462
463 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write_room"))
464 return 0;
465 if (!dev->mdm.online[info->line])
466 return info->xmit_size - 1;
467 ret = info->xmit_size - info->xmit_count - 1;
468 return (ret < 0) ? 0 : ret;
469 }
470
471 static int isdn_tty_chars_in_buffer(struct tty_struct *tty)
472 {
473 modem_info *info = (modem_info *) tty->driver_data;
474
475 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_chars_in_buffer"))
476 return 0;
477 if (!dev->mdm.online[info->line])
478 return 0;
479 return (info->xmit_count);
480 }
481
482 static void isdn_tty_flush_buffer(struct tty_struct *tty)
483 {
484 modem_info *info = (modem_info *) tty->driver_data;
485 uint flags;
486
487 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer"))
488 return;
489 save_flags(flags);
490 cli();
491 info->xmit_count = 0;
492 restore_flags(flags);
493 wake_up_interruptible(&tty->write_wait);
494 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
495 tty->ldisc.write_wakeup)
496 (tty->ldisc.write_wakeup) (tty);
497 }
498
499 static void isdn_tty_flush_chars(struct tty_struct *tty)
500 {
501 modem_info *info = (modem_info *) tty->driver_data;
502
503 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_chars"))
504 return;
505 if (info->xmit_count > 0)
506 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
507 }
508
509
510
511
512
513
514
515
516
517 static void isdn_tty_throttle(struct tty_struct *tty)
518 {
519 modem_info *info = (modem_info *) tty->driver_data;
520
521 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_throttle"))
522 return;
523 if (I_IXOFF(tty))
524 info->x_char = STOP_CHAR(tty);
525 info->MCR &= ~UART_MCR_RTS;
526 }
527
528 static void isdn_tty_unthrottle(struct tty_struct *tty)
529 {
530 modem_info *info = (modem_info *) tty->driver_data;
531
532 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_unthrottle"))
533 return;
534 if (I_IXOFF(tty)) {
535 if (info->x_char)
536 info->x_char = 0;
537 else
538 info->x_char = START_CHAR(tty);
539 }
540 info->MCR |= UART_MCR_RTS;
541 }
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559 static int isdn_tty_get_lsr_info(modem_info * info, uint * value)
560 {
561 u_char status;
562 uint result;
563 ulong flags;
564
565 save_flags(flags);
566 cli();
567 status = dev->mdm.msr[info->line];
568 restore_flags(flags);
569 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
570 put_fs_long(result, (ulong *) value);
571 return 0;
572 }
573
574
575 static int isdn_tty_get_modem_info(modem_info * info, uint * value)
576 {
577 u_char control, status;
578 uint result;
579 ulong flags;
580
581 control = info->MCR;
582 save_flags(flags);
583 cli();
584 status = dev->mdm.msr[info->line];
585 restore_flags(flags);
586 result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
587 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
588 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
589 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
590 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
591 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
592 put_fs_long(result, (ulong *) value);
593 return 0;
594 }
595
596 static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
597 {
598 uint arg = get_fs_long((ulong *) value);
599
600 switch (cmd) {
601 case TIOCMBIS:
602 if (arg & TIOCM_RTS) {
603 info->MCR |= UART_MCR_RTS;
604 }
605 if (arg & TIOCM_DTR) {
606 info->MCR |= UART_MCR_DTR;
607 }
608 break;
609 case TIOCMBIC:
610 if (arg & TIOCM_RTS) {
611 info->MCR &= ~UART_MCR_RTS;
612 }
613 if (arg & TIOCM_DTR) {
614 info->MCR &= ~UART_MCR_DTR;
615 isdn_tty_modem_reset_regs(&dev->mdm.atmodem[info->line], 0);
616 #ifdef ISDN_DEBUG_MODEM_HUP
617 printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
618 #endif
619 isdn_tty_modem_hup(info);
620 if (dev->mdm.online[info->line])
621 isdn_tty_modem_result(3, info);
622 }
623 break;
624 case TIOCMSET:
625 info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR))
626 | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
627 | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
628 if (!(info->MCR & UART_MCR_DTR)) {
629 isdn_tty_modem_reset_regs(&dev->mdm.atmodem[info->line], 0);
630 #ifdef ISDN_DEBUG_MODEM_HUP
631 printk(KERN_DEBUG "Mhup in TIOCMSET\n");
632 #endif
633 isdn_tty_modem_hup(info);
634 if (dev->mdm.online[info->line])
635 isdn_tty_modem_result(3, info);
636 }
637 break;
638 default:
639 return -EINVAL;
640 }
641 return 0;
642 }
643
644 static int isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
645 uint cmd, ulong arg)
646 {
647 modem_info *info = (modem_info *) tty->driver_data;
648 int error;
649 int retval;
650
651 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_ioctl"))
652 return -ENODEV;
653 switch (cmd) {
654 case TCSBRK:
655 retval = tty_check_change(tty);
656 if (retval)
657 return retval;
658 tty_wait_until_sent(tty, 0);
659 return 0;
660 case TCSBRKP:
661 retval = tty_check_change(tty);
662 if (retval)
663 return retval;
664 tty_wait_until_sent(tty, 0);
665 return 0;
666 case TIOCGSOFTCAR:
667 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
668 if (error)
669 return error;
670 put_fs_long(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
671 return 0;
672 case TIOCSSOFTCAR:
673 arg = get_fs_long((ulong *) arg);
674 tty->termios->c_cflag =
675 ((tty->termios->c_cflag & ~CLOCAL) |
676 (arg ? CLOCAL : 0));
677 return 0;
678 case TIOCMGET:
679 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
680 if (error)
681 return error;
682 return isdn_tty_get_modem_info(info, (uint *) arg);
683 case TIOCMBIS:
684 case TIOCMBIC:
685 case TIOCMSET:
686 return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
687 case TIOCSERGETLSR:
688 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
689 if (error)
690 return error;
691 else
692 return isdn_tty_get_lsr_info(info, (uint *) arg);
693
694 case TIOCGSERIAL:
695 return -ENOIOCTLCMD;
696 #if 0
697 error = verify_area(VERIFY_WRITE, (void *) arg,
698 sizeof(struct serial_struct));
699 if (error)
700 return error;
701 return get_serial_info(info,
702 (struct serial_struct *) arg);
703 #endif
704 case TIOCSSERIAL:
705 return -ENOIOCTLCMD;
706 #if 0
707 return set_serial_info(info,
708 (struct serial_struct *) arg);
709 #endif
710 case TIOCSERCONFIG:
711 return -ENOIOCTLCMD;
712 #if 0
713 return do_autoconfig(info);
714 #endif
715
716 case TIOCSERGWILD:
717 return -ENOIOCTLCMD;
718 #if 0
719 error = verify_area(VERIFY_WRITE, (void *) arg,
720 sizeof(int));
721 if (error)
722 return error;
723 put_fs_long(modem_wild_int_mask, (ulong *) arg);
724 return 0;
725 #endif
726 case TIOCSERSWILD:
727 return -ENOIOCTLCMD;
728 #if 0
729 if (!suser())
730 return -EPERM;
731 modem_wild_int_mask = get_fs_long((ulong *) arg);
732 if (modem_wild_int_mask < 0)
733 modem_wild_int_mask = check_wild_interrupts(0);
734 return 0;
735 #endif
736 case TIOCSERGSTRUCT:
737 return -ENOIOCTLCMD;
738 #if 0
739 error = verify_area(VERIFY_WRITE, (void *) arg,
740 sizeof(modem_info));
741 if (error)
742 return error;
743 memcpy_tofs((modem_info *) arg,
744 info, sizeof(modem_info));
745 return 0;
746 #endif
747 default:
748 #ifdef ISDN_DEBUG_MODEM_IOCTL
749 printk(KERN_DEBUG "unsupp. ioctl 0x%08x on ttyi%d\n", cmd, info->line);
750 #endif
751 return -ENOIOCTLCMD;
752 }
753 return 0;
754 }
755
756 static void isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
757 {
758 modem_info *info = (modem_info *) tty->driver_data;
759
760 if (tty->termios->c_cflag == old_termios->c_cflag)
761 return;
762 isdn_tty_change_speed(info);
763 if ((old_termios->c_cflag & CRTSCTS) &&
764 !(tty->termios->c_cflag & CRTSCTS)) {
765 tty->hw_stopped = 0;
766 }
767 }
768
769
770
771
772
773
774 static int isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
775 {
776 struct wait_queue wait = {current, NULL};
777 int do_clocal = 0;
778 unsigned long flags;
779 int retval;
780
781
782
783
784
785 if (tty_hung_up_p(filp) ||
786 (info->flags & ISDN_ASYNC_CLOSING)) {
787 if (info->flags & ISDN_ASYNC_CLOSING)
788 interruptible_sleep_on(&info->close_wait);
789 #ifdef MODEM_DO_RESTART
790 if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
791 return -EAGAIN;
792 else
793 return -ERESTARTSYS;
794 #else
795 return -EAGAIN;
796 #endif
797 }
798
799
800
801
802 if (tty->driver.subtype == ISDN_SERIAL_TYPE_CALLOUT) {
803 if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
804 return -EBUSY;
805 if ((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
806 (info->flags & ISDN_ASYNC_SESSION_LOCKOUT) &&
807 (info->session != current->session))
808 return -EBUSY;
809 if ((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
810 (info->flags & ISDN_ASYNC_PGRP_LOCKOUT) &&
811 (info->pgrp != current->pgrp))
812 return -EBUSY;
813 info->flags |= ISDN_ASYNC_CALLOUT_ACTIVE;
814 return 0;
815 }
816
817
818
819
820 if (filp->f_flags & O_NONBLOCK) {
821 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
822 return -EBUSY;
823 info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
824 return 0;
825 }
826 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) {
827 if (info->normal_termios.c_cflag & CLOCAL)
828 do_clocal = 1;
829 } else {
830 if (tty->termios->c_cflag & CLOCAL)
831 do_clocal = 1;
832 }
833
834
835
836
837
838
839
840 retval = 0;
841 add_wait_queue(&info->open_wait, &wait);
842 #ifdef ISDN_DEBUG_MODEM_OPEN
843 printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n",
844 info->line, info->count);
845 #endif
846 save_flags(flags);
847 cli();
848 if (!(tty_hung_up_p(filp)))
849 info->count--;
850 restore_flags(flags);
851 info->blocked_open++;
852 while (1) {
853 current->state = TASK_INTERRUPTIBLE;
854 if (tty_hung_up_p(filp) ||
855 !(info->flags & ISDN_ASYNC_INITIALIZED)) {
856 #ifdef MODEM_DO_RESTART
857 if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
858 retval = -EAGAIN;
859 else
860 retval = -ERESTARTSYS;
861 #else
862 retval = -EAGAIN;
863 #endif
864 break;
865 }
866 if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
867 !(info->flags & ISDN_ASYNC_CLOSING) &&
868 (do_clocal || (
869 dev->mdm.msr[info->line] &
870 UART_MSR_DCD))) {
871 break;
872 }
873 if (current->signal & ~current->blocked) {
874 retval = -ERESTARTSYS;
875 break;
876 }
877 #ifdef ISDN_DEBUG_MODEM_OPEN
878 printk(KERN_DEBUG "isdn_tty_block_til_ready blocking: ttyi%d, count = %d\n",
879 info->line, info->count);
880 #endif
881 schedule();
882 }
883 current->state = TASK_RUNNING;
884 remove_wait_queue(&info->open_wait, &wait);
885 if (!tty_hung_up_p(filp))
886 info->count++;
887 info->blocked_open--;
888 #ifdef ISDN_DEBUG_MODEM_OPEN
889 printk(KERN_DEBUG "isdn_tty_block_til_ready after blocking: ttyi%d, count = %d\n",
890 info->line, info->count);
891 #endif
892 if (retval)
893 return retval;
894 info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
895 return 0;
896 }
897
898
899
900
901
902
903
904 static int isdn_tty_open(struct tty_struct *tty, struct file *filp)
905 {
906 modem_info *info;
907 int retval, line;
908
909 line = MINOR(tty->device) - tty->driver.minor_start;
910 if (line < 0 || line > ISDN_MAX_CHANNELS)
911 return -ENODEV;
912 info = &dev->mdm.info[line];
913 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_open"))
914 return -ENODEV;
915 #ifdef ISDN_DEBUG_MODEM_OPEN
916 printk(KERN_DEBUG "isdn_tty_open %s%d, count = %d\n", tty->driver.name,
917 info->line, info->count);
918 #endif
919 info->count++;
920 tty->driver_data = info;
921 info->tty = tty;
922
923
924
925 retval = isdn_tty_startup(info);
926 if (retval) {
927 #ifdef ISDN_DEBUG_MODEM_OPEN
928 printk(KERN_DEBUG "isdn_tty_open return after startup\n");
929 #endif
930 return retval;
931 }
932 retval = isdn_tty_block_til_ready(tty, filp, info);
933 if (retval) {
934 #ifdef ISDN_DEBUG_MODEM_OPEN
935 printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n");
936 #endif
937 return retval;
938 }
939 if ((info->count == 1) && (info->flags & ISDN_ASYNC_SPLIT_TERMIOS)) {
940 if (tty->driver.subtype == ISDN_SERIAL_TYPE_NORMAL)
941 *tty->termios = info->normal_termios;
942 else
943 *tty->termios = info->callout_termios;
944 isdn_tty_change_speed(info);
945 }
946 info->session = current->session;
947 info->pgrp = current->pgrp;
948 #ifdef ISDN_DEBUG_MODEM_OPEN
949 printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
950 #endif
951 dev->modempoll++;
952 #ifdef ISDN_DEBUG_MODEM_OPEN
953 printk(KERN_DEBUG "isdn_tty_open normal exit\n");
954 #endif
955 return 0;
956 }
957
958 static void isdn_tty_close(struct tty_struct *tty, struct file *filp)
959 {
960 modem_info *info = (modem_info *) tty->driver_data;
961 ulong flags;
962 ulong timeout;
963
964 if (!info || isdn_tty_paranoia_check(info, tty->device, "isdn_tty_close"))
965 return;
966 save_flags(flags);
967 cli();
968 if (tty_hung_up_p(filp)) {
969 restore_flags(flags);
970 #ifdef ISDN_DEBUG_MODEM_OPEN
971 printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n");
972 #endif
973 return;
974 }
975 dev->modempoll--;
976 if ((tty->count == 1) && (info->count != 1)) {
977
978
979
980
981
982
983
984 printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, "
985 "info->count is %d\n", info->count);
986 info->count = 1;
987 }
988 if (--info->count < 0) {
989 printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n",
990 info->line, info->count);
991 info->count = 0;
992 }
993 if (info->count) {
994 restore_flags(flags);
995 #ifdef ISDN_DEBUG_MODEM_OPEN
996 printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
997 #endif
998 return;
999 }
1000 info->flags |= ISDN_ASYNC_CLOSING;
1001
1002
1003
1004
1005 if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
1006 info->normal_termios = *tty->termios;
1007 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
1008 info->callout_termios = *tty->termios;
1009
1010 tty->closing = 1;
1011
1012
1013
1014
1015
1016
1017
1018 if (info->flags & ISDN_ASYNC_INITIALIZED) {
1019 tty_wait_until_sent(tty, 3000);
1020
1021
1022
1023
1024
1025 timeout = jiffies + HZ;
1026 while (!(dev->mdm.mlr[info->line]
1027 & UART_LSR_TEMT)) {
1028 current->state = TASK_INTERRUPTIBLE;
1029 current->timeout = jiffies + 20;
1030 schedule();
1031 if (jiffies > timeout)
1032 break;
1033 }
1034 }
1035 isdn_tty_shutdown(info);
1036 if (tty->driver.flush_buffer)
1037 tty->driver.flush_buffer(tty);
1038 if (tty->ldisc.flush_buffer)
1039 tty->ldisc.flush_buffer(tty);
1040 info->tty = 0;
1041 tty->closing = 0;
1042 #if 00
1043 if (tty->ldisc.num != ldiscs[N_TTY].num) {
1044 if (tty->ldisc.close)
1045 (tty->ldisc.close) (tty);
1046 tty->ldisc = ldiscs[N_TTY];
1047 tty->termios->c_line = N_TTY;
1048 if (tty->ldisc.open)
1049 (tty->ldisc.open) (tty);
1050 }
1051 #endif
1052 if (info->blocked_open) {
1053 if (info->close_delay) {
1054 current->state = TASK_INTERRUPTIBLE;
1055 current->timeout = jiffies + info->close_delay;
1056 schedule();
1057 }
1058 wake_up_interruptible(&info->open_wait);
1059 }
1060 info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE |
1061 ISDN_ASYNC_CLOSING);
1062 wake_up_interruptible(&info->close_wait);
1063 restore_flags(flags);
1064 #ifdef ISDN_DEBUG_MODEM_OPEN
1065 printk(KERN_DEBUG "isdn_tty_close normal exit\n");
1066 #endif
1067 }
1068
1069
1070
1071
1072 static void isdn_tty_hangup(struct tty_struct *tty)
1073 {
1074 modem_info *info = (modem_info *) tty->driver_data;
1075
1076 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_hangup"))
1077 return;
1078 isdn_tty_shutdown(info);
1079 info->count = 0;
1080 info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE);
1081 info->tty = 0;
1082 wake_up_interruptible(&info->open_wait);
1083 }
1084
1085 static void isdn_tty_reset_profile(atemu * m)
1086 {
1087 m->profile[0] = 0;
1088 m->profile[1] = 0;
1089 m->profile[2] = 43;
1090 m->profile[3] = 13;
1091 m->profile[4] = 10;
1092 m->profile[5] = 8;
1093 m->profile[6] = 3;
1094 m->profile[7] = 60;
1095 m->profile[8] = 2;
1096 m->profile[9] = 6;
1097 m->profile[10] = 7;
1098 m->profile[11] = 70;
1099 m->profile[12] = 0x45;
1100 m->profile[13] = 0;
1101 m->profile[14] = ISDN_PROTO_L2_X75I;
1102 m->profile[15] = ISDN_PROTO_L3_TRANS;
1103 m->profile[16] = ISDN_SERIAL_XMIT_SIZE / 16;
1104 m->profile[17] = ISDN_MODEM_WINSIZE;
1105 m->profile[18] = 7;
1106 m->profile[19] = 0;
1107 m->pmsn[0] = '\0';
1108 }
1109
1110 static void isdn_tty_modem_reset_regs(atemu * m, int force)
1111 {
1112 if ((m->mdmreg[12] & 32) || force) {
1113 memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
1114 memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
1115 }
1116 m->mdmcmdl = 0;
1117 }
1118
1119 static void modem_write_profile(atemu * m)
1120 {
1121 memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG);
1122 memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
1123 if (dev->profd)
1124 send_sig(SIGIO, dev->profd, 1);
1125 }
1126
1127 int isdn_tty_modem_init(void)
1128 {
1129 modem *m;
1130 int i;
1131 modem_info *info;
1132
1133 m = &dev->mdm;
1134 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1135 isdn_tty_reset_profile(&(m->atmodem[i]));
1136 isdn_tty_modem_reset_regs(&(m->atmodem[i]), 1);
1137 }
1138 memset(&m->tty_modem, 0, sizeof(struct tty_driver));
1139 m->tty_modem.magic = TTY_DRIVER_MAGIC;
1140 m->tty_modem.name = isdn_ttyname_ttyI;
1141 m->tty_modem.major = ISDN_TTY_MAJOR;
1142 m->tty_modem.minor_start = 0;
1143 m->tty_modem.num = ISDN_MAX_CHANNELS;
1144 m->tty_modem.type = TTY_DRIVER_TYPE_SERIAL;
1145 m->tty_modem.subtype = ISDN_SERIAL_TYPE_NORMAL;
1146 m->tty_modem.init_termios = tty_std_termios;
1147 m->tty_modem.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1148 m->tty_modem.flags = TTY_DRIVER_REAL_RAW;
1149 m->tty_modem.refcount = &m->refcount;
1150 m->tty_modem.table = m->modem_table;
1151 m->tty_modem.termios = m->modem_termios;
1152 m->tty_modem.termios_locked = m->modem_termios_locked;
1153 m->tty_modem.open = isdn_tty_open;
1154 m->tty_modem.close = isdn_tty_close;
1155 m->tty_modem.write = isdn_tty_write;
1156 m->tty_modem.put_char = NULL;
1157 m->tty_modem.flush_chars = isdn_tty_flush_chars;
1158 m->tty_modem.write_room = isdn_tty_write_room;
1159 m->tty_modem.chars_in_buffer = isdn_tty_chars_in_buffer;
1160 m->tty_modem.flush_buffer = isdn_tty_flush_buffer;
1161 m->tty_modem.ioctl = isdn_tty_ioctl;
1162 m->tty_modem.throttle = isdn_tty_throttle;
1163 m->tty_modem.unthrottle = isdn_tty_unthrottle;
1164 m->tty_modem.set_termios = isdn_tty_set_termios;
1165 m->tty_modem.stop = NULL;
1166 m->tty_modem.start = NULL;
1167 m->tty_modem.hangup = isdn_tty_hangup;
1168
1169
1170
1171
1172 m->cua_modem = m->tty_modem;
1173 m->cua_modem.name = isdn_ttyname_cui;
1174 m->cua_modem.major = ISDN_TTYAUX_MAJOR;
1175 m->tty_modem.minor_start = 0;
1176 m->cua_modem.subtype = ISDN_SERIAL_TYPE_CALLOUT;
1177
1178 if (tty_register_driver(&m->tty_modem)) {
1179 printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n");
1180 return -1;
1181 }
1182 if (tty_register_driver(&m->cua_modem)) {
1183 printk(KERN_WARNING "isdn_tty: Couldn't register modem-callout-device\n");
1184 return -2;
1185 }
1186 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1187 info = &(m->info[i]);
1188 info->magic = ISDN_ASYNC_MAGIC;
1189 info->line = i;
1190 info->tty = 0;
1191 info->close_delay = 50;
1192 info->x_char = 0;
1193 info->count = 0;
1194 info->blocked_open = 0;
1195 info->callout_termios = m->cua_modem.init_termios;
1196 info->normal_termios = m->tty_modem.init_termios;
1197 info->open_wait = 0;
1198 info->close_wait = 0;
1199 info->type = ISDN_PORT_16550A;
1200 info->isdn_driver = -1;
1201 info->isdn_channel = -1;
1202 info->drv_index = -1;
1203 info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
1204 if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_SIZE + 5, GFP_KERNEL))) {
1205 printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
1206 return -3;
1207 }
1208 info->xmit_buf += 4;
1209 }
1210 return 0;
1211 }
1212
1213
1214
1215
1216
1217
1218
1219 int isdn_tty_find_icall(int di, int ch, char *num)
1220 {
1221 char *eaz;
1222 int i;
1223 int idx;
1224 int si1;
1225 int si2;
1226 char *s;
1227 char nr[31];
1228 ulong flags;
1229
1230 save_flags(flags);
1231 cli();
1232 if (num[0] == ',') {
1233 nr[0] = '0';
1234 strncpy(&nr[1], num, 29);
1235 printk(KERN_WARNING "isdn_tty: Incoming call without OAD, assuming '0'\n");
1236 } else
1237 strncpy(nr, num, 30);
1238 s = strtok(nr, ",");
1239 s = strtok(NULL, ",");
1240 if (!s) {
1241 printk(KERN_WARNING "isdn_tty: Incoming callinfo garbled, ignored: %s\n",
1242 num);
1243 restore_flags(flags);
1244 return -1;
1245 }
1246 si1 = (int)simple_strtoul(s,NULL,10);
1247 s = strtok(NULL, ",");
1248 if (!s) {
1249 printk(KERN_WARNING "isdn_tty: Incoming callinfo garbled, ignored: %s\n",
1250 num);
1251 restore_flags(flags);
1252 return -1;
1253 }
1254 si2 = (int)simple_strtoul(s,NULL,10);
1255 eaz = strtok(NULL, ",");
1256 if (!eaz) {
1257 printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n");
1258 eaz = "0";
1259 }
1260 #ifdef ISDN_DEBUG_MODEM_ICALL
1261 printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
1262 #endif
1263 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1264 #ifdef ISDN_DEBUG_MODEM_ICALL
1265 printk(KERN_DEBUG "m_fi: i=%d msn=%s mmsn=%s mreg18=%d mreg19=%d\n", i,
1266 dev->mdm.atmodem[i].msn, isdn_map_eaz2msn(dev->mdm.atmodem[i].msn, di),
1267 dev->mdm.atmodem[i].mdmreg[18], dev->mdm.atmodem[i].mdmreg[19]);
1268 #endif
1269 if ((!strcmp(isdn_map_eaz2msn(dev->mdm.atmodem[i].msn, di)
1270 ,eaz)) &&
1271 (dev->mdm.atmodem[i].mdmreg[18] == si1) &&
1272 (dev->mdm.atmodem[i].mdmreg[19] == si2)) {
1273 modem_info *info = &dev->mdm.info[i];
1274 idx = isdn_dc2minor(di, ch);
1275 #ifdef ISDN_DEBUG_MODEM_ICALL
1276 printk(KERN_DEBUG "m_fi: match1\n");
1277 printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
1278 info->flags, info->isdn_driver, info->isdn_channel,
1279 dev->usage[idx]);
1280 #endif
1281 if ((info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
1282 (info->isdn_driver == -1) &&
1283 (info->isdn_channel == -1) &&
1284 (USG_NONE(dev->usage[idx]))) {
1285 info->isdn_driver = di;
1286 info->isdn_channel = ch;
1287 info->drv_index = idx;
1288 dev->m_idx[idx] = info->line;
1289 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
1290 dev->usage[idx] |= ISDN_USAGE_MODEM;
1291 strcpy(dev->num[idx], nr);
1292 isdn_info_update();
1293 restore_flags(flags);
1294 printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
1295 info->line);
1296 return info->line;
1297 }
1298 }
1299 }
1300 printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
1301 dev->drv[di]->reject_bus ? "rejected" : "ignored");
1302 restore_flags(flags);
1303 return -1;
1304 }
1305
1306
1307
1308
1309
1310 #define cmdchar(c) ((c>' ')&&(c<=0x7f))
1311
1312
1313
1314
1315
1316 static void isdn_tty_at_cout(char *msg, modem_info * info)
1317 {
1318 struct tty_struct *tty;
1319 atemu *m = &(dev->mdm.atmodem[info->line]);
1320 char *p;
1321 char c;
1322 ulong flags;
1323
1324 if (!msg) {
1325 printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
1326 return;
1327 }
1328 save_flags(flags);
1329 cli();
1330 tty = info->tty;
1331 for (p = msg; *p; p++) {
1332 switch (*p) {
1333 case '\r':
1334 c = m->mdmreg[3];
1335 break;
1336 case '\n':
1337 c = m->mdmreg[4];
1338 break;
1339 case '\b':
1340 c = m->mdmreg[5];
1341 break;
1342 default:
1343 c = *p;
1344 }
1345 if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
1346 restore_flags(flags);
1347 return;
1348 }
1349 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
1350 break;
1351 tty_insert_flip_char(tty, c, 0);
1352 }
1353 restore_flags(flags);
1354 queue_task(&tty->flip.tqueue, &tq_timer);
1355 }
1356
1357
1358
1359
1360 static void isdn_tty_on_hook(modem_info * info)
1361 {
1362 if (info->isdn_channel >= 0) {
1363 #ifdef ISDN_DEBUG_MODEM_HUP
1364 printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
1365 #endif
1366 isdn_tty_modem_hup(info);
1367 isdn_tty_modem_result(3, info);
1368 }
1369 }
1370
1371 static void isdn_tty_off_hook(void)
1372 {
1373 printk(KERN_DEBUG "isdn_tty_off_hook\n");
1374 }
1375
1376 #define PLUSWAIT1 (HZ/2)
1377 #define PLUSWAIT2 (HZ*3/2)
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390 static void isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
1391 int *lastplus, int from_user)
1392 {
1393 char cbuf[3];
1394
1395 if (plus > 127)
1396 return;
1397 if (count > 3) {
1398 p += count - 3;
1399 count = 3;
1400 *pluscount = 0;
1401 }
1402 if (from_user) {
1403 memcpy_fromfs(cbuf, p, count);
1404 p = cbuf;
1405 }
1406 while (count > 0) {
1407 if (*(p++) == plus) {
1408 if ((*pluscount)++) {
1409
1410 if ((jiffies - *lastplus) > PLUSWAIT1)
1411 *pluscount = 1;
1412 } else {
1413
1414 if ((jiffies - *lastplus) < PLUSWAIT2)
1415 *pluscount = 0;
1416 }
1417 if ((*pluscount == 3) && (count = 1))
1418 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
1419 if (*pluscount > 3)
1420 *pluscount = 1;
1421 } else
1422 *pluscount = 0;
1423 *lastplus = jiffies;
1424 count--;
1425 }
1426 }
1427
1428
1429
1430
1431
1432
1433
1434 void isdn_tty_modem_result(int code, modem_info * info)
1435 {
1436 atemu *m = &dev->mdm.atmodem[info->line];
1437 static char *msg[] =
1438 {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
1439 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
1440 "RINGING", "NO MSN/EAZ"};
1441 ulong flags;
1442 char s[4];
1443
1444 switch (code) {
1445 case 2:
1446 m->mdmreg[1]++;
1447 if (m->mdmreg[1] == m->mdmreg[0]) {
1448
1449 isdn_ctrl cmd;
1450 m->mdmreg[1] = 0;
1451 dev->mdm.msr[info->line] &= ~UART_MSR_RI;
1452 cmd.driver = info->isdn_driver;
1453 cmd.arg = info->isdn_channel;
1454 cmd.command = ISDN_CMD_ACCEPTD;
1455 dev->drv[info->isdn_driver]->interface->command(&cmd);
1456 }
1457 break;
1458 case 3:
1459
1460 save_flags(flags);
1461 cli();
1462 dev->mdm.msr[info->line] &= ~(UART_MSR_DCD | UART_MSR_RI);
1463 if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
1464 restore_flags(flags);
1465 return;
1466 }
1467 restore_flags(flags);
1468 break;
1469 case 1:
1470 case 5:
1471 dev->mdm.online[info->line] = 1;
1472 break;
1473 }
1474 if (m->mdmreg[12] & 1) {
1475
1476 isdn_tty_at_cout("\r\n", info);
1477 if (m->mdmreg[12] & 2) {
1478
1479 sprintf(s, "%d", code);
1480 isdn_tty_at_cout(s, info);
1481 } else {
1482 if (code == 2) {
1483 isdn_tty_at_cout("CALLER NUMBER: ", info);
1484 isdn_tty_at_cout(dev->num[info->drv_index], info);
1485 isdn_tty_at_cout("\r\n", info);
1486 }
1487 isdn_tty_at_cout(msg[code], info);
1488 if (code == 5) {
1489
1490 isdn_tty_at_cout((m->mdmreg[14] != 3) ? "/X.75" : "/HDLC", info);
1491 if (m->mdmreg[13] & 2)
1492 isdn_tty_at_cout("/T.70", info);
1493 }
1494 }
1495 isdn_tty_at_cout("\r\n", info);
1496 }
1497 if (code == 3) {
1498 save_flags(flags);
1499 cli();
1500 if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
1501 restore_flags(flags);
1502 return;
1503 }
1504 if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
1505 (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
1506 (info->flags & ISDN_ASYNC_CALLOUT_NOHUP))))
1507 tty_hangup(info->tty);
1508 restore_flags(flags);
1509 }
1510 }
1511
1512
1513
1514
1515 static void isdn_tty_show_profile(int ridx, modem_info * info)
1516 {
1517 char v[6];
1518
1519 sprintf(v, "%d\r\n", dev->mdm.atmodem[info->line].mdmreg[ridx]);
1520 isdn_tty_at_cout(v, info);
1521 }
1522
1523
1524
1525
1526 static void isdn_tty_get_msnstr(char *n, char **p)
1527 {
1528 while ((*p[0] >= '0' && *p[0] <= '9') || (*p[0] == ','))
1529 *n++ = *p[0]++;
1530 *n = '\0';
1531 }
1532
1533
1534
1535
1536 static void isdn_tty_getdial(char *p, char *q)
1537 {
1538 int first = 1;
1539
1540 while (strchr("0123456789,#.*WPTS-", *p) && *p) {
1541 if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first))
1542 *q++ = *p;
1543 p++;
1544 first = 0;
1545 }
1546 *q = 0;
1547 }
1548
1549
1550
1551
1552
1553
1554
1555 static void isdn_tty_parse_at(modem_info * info)
1556 {
1557 atemu *m = &dev->mdm.atmodem[info->line];
1558 char *p;
1559 int mreg;
1560 int mval;
1561 int i;
1562 char rb[100];
1563 char ds[40];
1564 isdn_ctrl cmd;
1565
1566 #ifdef ISDN_DEBUG_AT
1567 printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
1568 #endif
1569 for (p = &m->mdmcmd[2]; *p;) {
1570 switch (*p) {
1571 case 'A':
1572
1573 p++;
1574 if (dev->mdm.msr[info->line] & UART_MSR_RI) {
1575 #define FIDOBUG
1576 #ifdef FIDOBUG
1577
1578 driver *fido_drv;
1579 isdn_if *fido_if;
1580 int fido_isdn_driver;
1581 modem_info *fido_modem_info;
1582 int (*fido_command) (isdn_ctrl *);
1583 #endif
1584
1585 m->mdmreg[1] = 0;
1586 dev->mdm.msr[info->line] &= ~UART_MSR_RI;
1587 cmd.driver = info->isdn_driver;
1588 cmd.command = ISDN_CMD_SETL2;
1589 cmd.arg = info->isdn_channel + (m->mdmreg[14] << 8);
1590 dev->drv[info->isdn_driver]->interface->command(&cmd);
1591 cmd.driver = info->isdn_driver;
1592 cmd.command = ISDN_CMD_SETL3;
1593 cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
1594 dev->drv[info->isdn_driver]->interface->command(&cmd);
1595 cmd.driver = info->isdn_driver;
1596 cmd.arg = info->isdn_channel;
1597 cmd.command = ISDN_CMD_ACCEPTD;
1598 #ifdef FIDOBUG
1599 fido_modem_info = info;
1600 fido_isdn_driver = fido_modem_info->isdn_driver;
1601 fido_drv = dev->drv[fido_isdn_driver];
1602 fido_if = fido_drv->interface;
1603 fido_command = fido_if->command;
1604 fido_command(&cmd);
1605 #else
1606 dev->drv[info->isdn_driver]->interface->command(&cmd);
1607 #endif
1608 } else {
1609 isdn_tty_modem_result(8, info);
1610 return;
1611 }
1612 break;
1613 case 'D':
1614
1615 isdn_tty_getdial(++p, ds);
1616 p += strlen(p);
1617 if (!strlen(m->msn))
1618 isdn_tty_modem_result(10, info);
1619 else if (strlen(ds))
1620 isdn_tty_dial(ds, info, m);
1621 else
1622 isdn_tty_modem_result(4, info);
1623 return;
1624 case 'E':
1625
1626 p++;
1627 switch (*p) {
1628 case '0':
1629 p++;
1630 m->mdmreg[12] &= ~4;
1631 break;
1632 case '1':
1633 p++;
1634 m->mdmreg[12] |= 4;
1635 break;
1636 default:
1637 isdn_tty_modem_result(4, info);
1638 return;
1639 }
1640 break;
1641 case 'H':
1642
1643 p++;
1644 switch (*p) {
1645 case '0':
1646 p++;
1647 isdn_tty_on_hook(info);
1648 break;
1649 case '1':
1650 p++;
1651 isdn_tty_off_hook();
1652 break;
1653 default:
1654 isdn_tty_on_hook(info);
1655 break;
1656 }
1657 break;
1658 case 'I':
1659
1660 p++;
1661 isdn_tty_at_cout("ISDN for Linux (c) by Fritz Elfert\r\n", info);
1662 switch (*p) {
1663 case '0':
1664 case '1':
1665 p++;
1666 break;
1667 default:
1668 }
1669 break;
1670 case 'O':
1671
1672 p++;
1673 if (dev->mdm.msr[info->line] & UART_MSR_DCD)
1674 isdn_tty_modem_result(5, info);
1675 else
1676 isdn_tty_modem_result(3, info);
1677 return;
1678 case 'Q':
1679
1680 p++;
1681 switch (*p) {
1682 case '0':
1683 p++;
1684 m->mdmreg[12] |= 1;
1685 break;
1686 case '1':
1687 p++;
1688 m->mdmreg[12] &= ~1;
1689 break;
1690 default:
1691 isdn_tty_modem_result(4, info);
1692 return;
1693 }
1694 break;
1695 case 'S':
1696
1697 p++;
1698 mreg = isdn_getnum(&p);
1699 if (mreg < 0 || mreg > ISDN_MODEM_ANZREG) {
1700 isdn_tty_modem_result(4, info);
1701 return;
1702 }
1703 switch (*p) {
1704 case '=':
1705 p++;
1706 mval = isdn_getnum(&p);
1707 if (mval >= 0 && mval <= 255) {
1708 if ((mreg == 16) && ((mval * 16) > ISDN_SERIAL_XMIT_SIZE)) {
1709 isdn_tty_modem_result(4, info);
1710 return;
1711 }
1712 m->mdmreg[mreg] = mval;
1713 } else {
1714 isdn_tty_modem_result(4, info);
1715 return;
1716 }
1717 break;
1718 case '?':
1719 p++;
1720 isdn_tty_show_profile(mreg, info);
1721 return;
1722 break;
1723 default:
1724 isdn_tty_modem_result(4, info);
1725 return;
1726 }
1727 break;
1728 case 'V':
1729
1730 p++;
1731 switch (*p) {
1732 case '0':
1733 p++;
1734 m->mdmreg[12] |= 2;
1735 break;
1736 case '1':
1737 p++;
1738 m->mdmreg[12] &= ~2;
1739 break;
1740 default:
1741 isdn_tty_modem_result(4, info);
1742 return;
1743 }
1744 break;
1745 case 'Z':
1746
1747 p++;
1748 isdn_tty_modem_reset_regs(m, 1);
1749 break;
1750 case '+':
1751 p++;
1752 switch (*p) {
1753 case 'F':
1754 break;
1755 }
1756 break;
1757 case '&':
1758 p++;
1759 switch (*p) {
1760 case 'B':
1761
1762 p++;
1763 i = isdn_getnum(&p);
1764 if ((i < 0) || (i > ISDN_SERIAL_XMIT_SIZE)) {
1765 isdn_tty_modem_result(4, info);
1766 return;
1767 }
1768 m->mdmreg[16] = i / 16;
1769 break;
1770 case 'D':
1771
1772 p++;
1773 switch (isdn_getnum(&p)) {
1774 case 2:
1775 m->mdmreg[12] &= ~32;
1776 break;
1777 case 3:
1778 m->mdmreg[12] |= 32;
1779 break;
1780 default:
1781 isdn_tty_modem_result(4, info);
1782 return;
1783 }
1784 break;
1785 case 'E':
1786
1787 p++;
1788 isdn_tty_get_msnstr(m->msn, &p);
1789 break;
1790 case 'F':
1791
1792 p++;
1793 isdn_tty_reset_profile(m);
1794 isdn_tty_modem_reset_regs(m, 1);
1795 break;
1796 case 'S':
1797
1798 p++;
1799 i = isdn_getnum(&p);
1800 if ((i > 0) && (i < 9))
1801 m->mdmreg[17] = i;
1802 else {
1803 isdn_tty_modem_result(4, info);
1804 return;
1805 }
1806 break;
1807 case 'V':
1808
1809 p++;
1810 for (i = 0; i < ISDN_MODEM_ANZREG; i++) {
1811 sprintf(rb, "S%d=%d%s", i, m->mdmreg[i], (i == 6) ? "\r\n" : " ");
1812 isdn_tty_at_cout(rb, info);
1813 }
1814 sprintf(rb, "\r\nEAZ/MSN: %s\r\n", strlen(m->msn) ? m->msn : "None");
1815 isdn_tty_at_cout(rb, info);
1816 break;
1817 case 'W':
1818
1819 p++;
1820 switch (*p) {
1821 case '0':
1822 p++;
1823 modem_write_profile(m);
1824 break;
1825 default:
1826 isdn_tty_modem_result(4, info);
1827 return;
1828 }
1829 break;
1830 case 'X':
1831
1832 p++;
1833 switch (*p) {
1834 case '0':
1835 p++;
1836 m->mdmreg[13] &= ~2;
1837 break;
1838 case '1':
1839 p++;
1840 m->mdmreg[13] |= 2;
1841 m->mdmreg[14] = 0;
1842 m->mdmreg[16] = 7;
1843 m->mdmreg[18] = 7;
1844 m->mdmreg[19] = 0;
1845 break;
1846 default:
1847 isdn_tty_modem_result(4, info);
1848 return;
1849 }
1850 break;
1851 default:
1852 isdn_tty_modem_result(4, info);
1853 return;
1854 }
1855 break;
1856 default:
1857 isdn_tty_modem_result(4, info);
1858 return;
1859 }
1860 }
1861 isdn_tty_modem_result(0, info);
1862 }
1863
1864
1865
1866
1867 #define my_toupper(c) (((c>='a')&&(c<='z'))?(c&0xdf):c)
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 static int isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
1879 {
1880 atemu *m = &dev->mdm.atmodem[info->line];
1881 int total = 0;
1882 u_char c;
1883 char eb[2];
1884 int cnt;
1885
1886 for (cnt = count; cnt > 0; p++, cnt--) {
1887 if (user)
1888 c = get_fs_byte(p);
1889 else
1890 c = *p;
1891 total++;
1892 if (c == m->mdmreg[3] || c == m->mdmreg[4]) {
1893
1894 m->mdmcmd[m->mdmcmdl] = 0;
1895 if (m->mdmreg[12] & 4) {
1896 eb[0] = c;
1897 eb[1] = 0;
1898 isdn_tty_at_cout(eb, info);
1899 }
1900 if (m->mdmcmdl >= 2)
1901 isdn_tty_parse_at(info);
1902 m->mdmcmdl = 0;
1903 continue;
1904 }
1905 if (c == m->mdmreg[5] && m->mdmreg[5] < 128) {
1906
1907 if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) {
1908 if (m->mdmcmdl)
1909 m->mdmcmdl--;
1910 if (m->mdmreg[12] & 4)
1911 isdn_tty_at_cout("\b", info);
1912 }
1913 continue;
1914 }
1915 if (cmdchar(c)) {
1916 if (m->mdmreg[12] & 4) {
1917 eb[0] = c;
1918 eb[1] = 0;
1919 isdn_tty_at_cout(eb, info);
1920 }
1921 if (m->mdmcmdl < 255) {
1922 c = my_toupper(c);
1923 switch (m->mdmcmdl) {
1924 case 0:
1925 if (c == 'A')
1926 m->mdmcmd[m->mdmcmdl++] = c;
1927 break;
1928 case 1:
1929 if (c == 'T')
1930 m->mdmcmd[m->mdmcmdl++] = c;
1931 break;
1932 default:
1933 m->mdmcmd[m->mdmcmdl++] = c;
1934 }
1935 }
1936 }
1937 }
1938 return total;
1939 }
1940
1941
1942
1943
1944
1945
1946
1947 void isdn_tty_modem_escape(void)
1948 {
1949 int ton = 0;
1950 int i;
1951 int midx;
1952
1953 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1954 if (USG_MODEM(dev->usage[i]))
1955 if ((midx = dev->m_idx[i]) >= 0)
1956 if (dev->mdm.online[midx]) {
1957 ton = 1;
1958 if ((dev->mdm.atmodem[midx].pluscount == 3) &&
1959 ((jiffies - dev->mdm.atmodem[midx].lastplus) > PLUSWAIT2)) {
1960 dev->mdm.atmodem[midx].pluscount = 0;
1961 dev->mdm.online[midx] = 0;
1962 isdn_tty_modem_result(0, &dev->mdm.info[midx]);
1963 }
1964 }
1965 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
1966 }
1967
1968
1969
1970
1971
1972
1973 void isdn_tty_modem_ring(void)
1974 {
1975 int ton = 0;
1976 int i;
1977 int midx;
1978
1979 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1980 if (USG_MODEM(dev->usage[i]))
1981 if ((midx = dev->m_idx[i]) >= 0)
1982 if (dev->mdm.msr[midx] & UART_MSR_RI) {
1983 ton = 1;
1984 isdn_tty_modem_result(2, &dev->mdm.info[midx]);
1985 }
1986 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
1987 }
1988
1989 void isdn_tty_modem_xmit(void)
1990 {
1991 int ton = 0;
1992 int i;
1993 int midx;
1994 char *bufptr;
1995 int buflen;
1996
1997 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1998 if (USG_MODEM(dev->usage[i]))
1999 if ((midx = dev->m_idx[i]) >= 0)
2000 if (dev->mdm.online[midx]) {
2001 modem_info *info = &(dev->mdm.info[midx]);
2002 ulong flags;
2003
2004 save_flags(flags);
2005 cli();
2006 if (info->xmit_count > 0) {
2007 struct tty_struct *tty = info->tty;
2008 ton = 1;
2009 #if 0
2010 printk(KERN_DEBUG "WB2: %d\n", info->xmit_count);
2011 #endif
2012 bufptr = info->xmit_buf;
2013 buflen = info->xmit_count;
2014 if (dev->mdm.atmodem[midx].mdmreg[13] & 2) {
2015
2016 #ifdef ISDN_DEBUG_MODEM_DUMP
2017 isdn_dumppkt("T70pack3:", bufptr, buflen, 40);
2018 #endif
2019 bufptr -= 4;
2020 buflen += 4;
2021 memcpy(bufptr, "\1\0\1\0", 4);
2022 #ifdef ISDN_DEBUG_MODEM_DUMP
2023 isdn_dumppkt("T70pack4:", bufptr, buflen, 40);
2024 #endif
2025 }
2026 if (isdn_writebuf_stub(info->isdn_driver, info->isdn_channel,
2027 bufptr, buflen, 0) > 0) {
2028 info->xmit_count = 0;
2029 info->xmit_size = dev->mdm.atmodem[midx].mdmreg[16] * 16;
2030 #if FUTURE
2031 info->send_outstanding++;
2032 dev->mdm.msr[midx] &= ~UART_MSR_CTS;
2033 #endif
2034 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
2035 tty->ldisc.write_wakeup)
2036 (tty->ldisc.write_wakeup) (tty);
2037 wake_up_interruptible(&tty->write_wait);
2038 }
2039 }
2040 restore_flags(flags);
2041 }
2042 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
2043 }
2044
2045 #if FUTURE
2046
2047
2048
2049
2050
2051 void isdn_tty_bsent(int drv, int chan)
2052 {
2053 int i;
2054 ulong flags;
2055
2056 save_flags(flags);
2057 cli();
2058 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2059 modem_info *info = &dev->mdm.info[i];
2060 if ((info->isdn_driver == drv) &&
2061 (info->isdn_channel == chan) &&
2062 (info->send_outstanding)) {
2063 if (!(--info->send_outstanding))
2064 dev->mdm.msr[i] |= UART_MSR_CTS;
2065 restore_flags(flags);
2066 return;
2067 }
2068 }
2069 restore_flags(flags);
2070 return;
2071 }
2072 #endif