This source file includes following definitions.
- send_break
- rs_sched_event
- UART_ISR_proc
- FourPort_ISR_proc
- rs_interrupt
- rs_probe
- rs_timer
- rs_write
- rs_throttle
- rs_close
- startup
- shutdown
- change_speed
- get_serial_info
- set_serial_info
- get_modem_info
- set_modem_info
- rs_ioctl
- rs_open
- init
- rs_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <linux/errno.h>
21 #include <linux/signal.h>
22 #include <linux/sched.h>
23 #include <linux/timer.h>
24 #include <linux/tty.h>
25 #include <linux/serial.h>
26
27 #include <asm/system.h>
28 #include <asm/io.h>
29 #include <asm/segment.h>
30 #include <asm/bitops.h>
31
32 #define WAKEUP_CHARS (3*TTY_BUF_SIZE/4)
33
34
35
36
37 #undef AUTO_IRQ
38
39
40
41
42
43 #undef NONSTANDARD_PORTS
44
45
46
47
48
49
50
51
52
53
54
55 static unsigned long rs_event = 0;
56 static unsigned long rs_write_active = 0;
57
58 static async_ISR IRQ_ISR[16];
59
60 static void UART_ISR_proc(async_ISR ISR, int line);
61
62 struct struct_ISR COM1_ISR = { 4, 0x3f8, UART_ISR_proc, 0, };
63 struct struct_ISR COM2_ISR = { 3, 0x2f8, UART_ISR_proc, 0, };
64 struct struct_ISR COM3_ISR = { 4, 0x3e8, UART_ISR_proc, 0, };
65 struct struct_ISR COM4_ISR = { 3, 0x2e8, UART_ISR_proc, 0, };
66
67 #ifdef NONSTANDARD_PORTS
68 static void FourPort_ISR_proc(async_ISR ISR, int line);
69
70 struct struct_ISR FourPort1_ISR = { 2, 0x1bf, FourPort_ISR_proc, 0, };
71 struct struct_ISR FourPort2_ISR = { 5, 0x2bf, FourPort_ISR_proc, 0, };
72
73 struct struct_ISR Accent3_ISR = { 4, 0x330, UART_ISR_proc, 0, };
74 struct struct_ISR Accent4_ISR = { 4, 0x338, UART_ISR_proc, 0, };
75 #endif
76
77
78
79
80
81
82
83
84 #define BASE_BAUD ( 1843200 / 16 )
85
86 struct async_struct rs_table[] = {
87 { BASE_BAUD, 0x3F8, &COM1_ISR, 0, },
88 { BASE_BAUD, 0x2F8, &COM2_ISR, 0, },
89 { BASE_BAUD, 0x3E8, &COM3_ISR, 0, },
90 { BASE_BAUD, 0x2E8, &COM4_ISR, 0, },
91 #ifdef NONSTANDARD_PORTS
92 { BASE_BAUD, 0x1A0, &FourPort1_ISR, ASYNC_FOURPORT },
93 { BASE_BAUD, 0x1A8, &FourPort1_ISR, ASYNC_FOURPORT },
94 { BASE_BAUD, 0x1B0, &FourPort1_ISR, ASYNC_FOURPORT },
95 { BASE_BAUD, 0x1B8, &FourPort1_ISR, ASYNC_FOURPORT | ASYNC_NOSCRATCH },
96
97 { BASE_BAUD, 0x2A0, &FourPort2_ISR, ASYNC_FOURPORT },
98 { BASE_BAUD, 0x2A8, &FourPort2_ISR, ASYNC_FOURPORT },
99 { BASE_BAUD, 0x2B0, &FourPort2_ISR, ASYNC_FOURPORT },
100 { BASE_BAUD, 0x2B8, &FourPort2_ISR, ASYNC_FOURPORT | ASYNC_NOSCRATCH },
101
102 { BASE_BAUD, 0x330, &Accent3_ISR, 0 },
103 { BASE_BAUD, 0x338, &Accent4_ISR, 0 },
104 #endif
105 };
106
107 #define NR_PORTS (sizeof(rs_table)/sizeof(struct async_struct))
108
109
110
111
112 static int baud_table[] = {
113 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
114 9600, 19200, 38400, 56000, 115200, 0 };
115
116 static void startup(struct async_struct * info);
117 static void shutdown(struct async_struct * info);
118 static void rs_throttle(struct tty_struct * tty, int status);
119
120 static void send_break( struct async_struct * info)
121 {
122 unsigned short port;
123
124 if (!(port = info->port))
125 return;
126 port += UART_LCR;
127 current->state = TASK_INTERRUPTIBLE;
128 current->timeout = jiffies + 25;
129 outb_p(inb_p(port) | UART_LCR_SBC, port);
130 schedule();
131 outb(inb_p(port) & ~UART_LCR_SBC, port);
132 }
133
134 static inline void rs_sched_event(int line,
135 struct async_struct *info,
136 int event)
137 {
138 info->event |= 1 << event;
139 rs_event |= 1 << line;
140 timer_table[RS_TIMER].expires = 0;
141 timer_active |= 1 << RS_TIMER;
142 }
143
144
145
146
147
148
149
150
151
152
153
154
155
156 static void UART_ISR_proc(async_ISR ISR, int line)
157 {
158 unsigned char status;
159 struct async_struct * info = rs_table + line;
160 struct tty_queue * queue;
161 int head, tail, count, ch;
162 int cflag, iflag;
163
164
165
166
167
168 #define VLEFT ((tail-head-1)&(TTY_BUF_SIZE-1))
169
170 if (!info || !info->tty || !info->port)
171 return;
172 cflag = info->tty->termios->c_cflag;
173 iflag = info->tty->termios->c_iflag;
174
175 do {
176 restart:
177 status = inb(UART_LSR + info->port);
178 if (status & UART_LSR_DR) {
179 queue = &info->tty->read_q;
180 head = queue->head;
181 tail = queue->tail;
182 do {
183 ch = inb(UART_RX + info->port);
184
185
186
187
188 if (VLEFT < 3)
189 continue;
190 if (status & (UART_LSR_BI |
191 UART_LSR_FE |
192 UART_LSR_PE)) {
193 if (status & (UART_LSR_BI)) {
194 if (info->flags & ASYNC_SAK)
195 rs_sched_event(line, info, RS_EVENT_DO_SAK);
196 else if (iflag & IGNBRK)
197 continue;
198 else if (iflag & BRKINT)
199 rs_sched_event(line, info, RS_EVENT_BREAK_INT);
200 else
201 ch = 0;
202 } else if (iflag & IGNPAR)
203 continue;
204 if (iflag & PARMRK) {
205 queue->buf[head++] = 0xff;
206 head &= TTY_BUF_SIZE-1;
207 queue->buf[head++] = 0;
208 head &= TTY_BUF_SIZE-1;
209 } else
210 ch = 0;
211 } else if ((iflag & PARMRK) && (ch == 0xff)) {
212 queue->buf[head++] = 0xff;
213 head &= TTY_BUF_SIZE-1;
214 }
215 queue->buf[head++] = ch;
216 head &= TTY_BUF_SIZE-1;
217 } while ((status = inb(UART_LSR + info->port)) &
218 UART_LSR_DR);
219 queue->head = head;
220 if ((VLEFT < RQ_THRESHOLD_LW)
221 && !set_bit(TTY_RQ_THROTTLED, &info->tty->flags))
222 rs_throttle(info->tty, TTY_THROTTLE_RQ_FULL);
223 rs_sched_event(line, info, RS_EVENT_READ_PROCESS);
224 }
225 if ((status & UART_LSR_THRE) &&
226 !info->tty->stopped) {
227 queue = &info->tty->write_q;
228 head = queue->head;
229 tail = queue->tail;
230 if (head==tail && !info->x_char)
231 goto no_xmit;
232 if (info->x_char) {
233 outb_p(info->x_char, UART_TX + info->port);
234 info->x_char = 0;
235 } else {
236 count = info->xmit_fifo_size;
237 while (count--) {
238 if (tail == head)
239 break;
240 outb_p(queue->buf[tail++],
241 UART_TX + info->port);
242 tail &= TTY_BUF_SIZE-1;
243 }
244 }
245 queue->tail = tail;
246 if (VLEFT > WAKEUP_CHARS)
247 rs_sched_event(line, info,
248 RS_EVENT_WRITE_WAKEUP);
249 info->timer = jiffies + info->timeout;
250 if (info->timer < timer_table[RS_TIMER].expires)
251 timer_table[RS_TIMER].expires = info->timer;
252 #ifdef i386
253 rs_write_active |= 1 << line;
254 #else
255 set_bit(line, &rs_write_active);
256 #endif
257 timer_active |= 1 << RS_TIMER;
258 }
259 no_xmit:
260 status = inb(UART_MSR + info->port);
261
262 if (!(cflag & CLOCAL) && (status & UART_MSR_DDCD)) {
263 if (!(status & UART_MSR_DCD))
264 rs_sched_event(line, info, RS_EVENT_HUP_PGRP);
265 }
266
267
268
269
270
271 if ((cflag & CRTSCTS) ||
272 ((status & UART_MSR_DSR) &&
273 !(cflag & CNORTSCTS))) {
274 if (info->tty->stopped) {
275 if (status & UART_MSR_CTS) {
276 info->tty->stopped = 0;
277 goto restart;
278 }
279 } else
280 info->tty->stopped = !(status & UART_MSR_CTS);
281 }
282 } while (!(inb(UART_IIR + info->port) & UART_IIR_NO_INT));
283 }
284
285 #ifdef NONSTANDARD_PORTS
286
287
288
289 static void FourPort_ISR_proc(async_ISR ISR, int line)
290 {
291 int i;
292 unsigned char ivec;
293
294 ivec = ~inb(ISR->port) & 0x0F;
295 do {
296 for (i = line; ivec; i++) {
297 if (ivec & 1)
298 UART_ISR_proc(ISR, i);
299 ivec = ivec >> 1;
300 }
301 ivec = ~inb(ISR->port) & 0x0F;
302 } while (ivec);
303 }
304 #endif
305
306
307
308
309 static void rs_interrupt(int irq)
310 {
311 async_ISR p = IRQ_ISR[irq];
312
313 while (p) {
314 (p->ISR_proc)(p, p->line);
315 p = p->next_ISR;
316 }
317 }
318
319 #ifdef AUTO_IRQ
320
321
322
323
324 static volatile int rs_irq_triggered;
325
326 static void rs_probe(int irq)
327 {
328 rs_irq_triggered = irq;
329 return;
330 }
331 #endif
332
333
334
335
336
337
338 #define END_OF_TIME 0xffffffff
339 static void rs_timer(void)
340 {
341 unsigned long mask;
342 struct async_struct *info;
343 unsigned long next_timeout;
344
345 info = rs_table;
346 next_timeout = END_OF_TIME;
347 for (mask = 1 ; mask ; info++, mask <<= 1) {
348 if ((mask > rs_event) &&
349 (mask > rs_write_active))
350 break;
351 if (!info->tty) {
352 rs_event &= ~mask;
353 rs_write_active &= ~mask;
354 continue;
355 }
356 if (mask & rs_event) {
357 if (!clear_bit(RS_EVENT_READ_PROCESS, &info->event)) {
358 TTY_READ_FLUSH(info->tty);
359 }
360 if (!clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
361 wake_up_interruptible(&info->tty->write_q.proc_list);
362 }
363 if (!clear_bit(RS_EVENT_HUP_PGRP, &info->event)) {
364 if (info->tty->pgrp > 0)
365 kill_pg(info->tty->pgrp,SIGHUP,1);
366 }
367 if (!clear_bit(RS_EVENT_BREAK_INT, &info->event)) {
368 flush_input(info->tty);
369 flush_output(info->tty);
370 if (info->tty->pgrp > 0)
371 kill_pg(info->tty->pgrp,SIGINT,1);
372 }
373 if (!clear_bit(RS_EVENT_DO_SAK, &info->event)) {
374 do_SAK(info->tty);
375 }
376 cli();
377 if (info->event)
378 next_timeout = 0;
379 else
380 rs_event &= ~mask;
381 sti();
382 }
383 if (mask & rs_write_active) {
384 if (info->timer <= jiffies) {
385 #ifdef i386
386 rs_write_active &= ~mask;
387 #else
388 clear_bit(info->line, &rs_write_active);
389 #endif
390 rs_write(info->tty);
391 }
392 if ((mask & rs_write_active) &&
393 (info->timer < next_timeout))
394 next_timeout = info->timer;
395 }
396 }
397 if (next_timeout != END_OF_TIME) {
398 timer_table[RS_TIMER].expires = next_timeout;
399 #ifdef i386
400
401
402
403
404
405 timer_active |= 1 << RS_TIMER;
406 #else
407 set_bit(RS_TIMER, &timer_active);
408 #endif
409 }
410 }
411
412
413
414
415
416
417 void rs_write(struct tty_struct * tty)
418 {
419 struct async_struct *info;
420
421 if (!tty || tty->stopped || EMPTY(&tty->write_q))
422 return;
423 info = rs_table + DEV_TO_SL(tty->line);
424 if (!test_bit(info->line, &rs_write_active)) {
425 cli();
426 UART_ISR_proc(info->ISR, info->line);
427 sti();
428 }
429
430 }
431
432 static void rs_throttle(struct tty_struct * tty, int status)
433 {
434 struct async_struct *info;
435 unsigned char mcr;
436
437 #ifdef notdef
438 printk("throttle tty%d: %d (%d, %d)....\n", DEV_TO_SL(tty->line),
439 status, LEFT(&tty->read_q), LEFT(&tty->secondary));
440 #endif
441 switch (status) {
442 case TTY_THROTTLE_RQ_FULL:
443 info = rs_table + DEV_TO_SL(tty->line);
444 if (tty->termios->c_iflag & IXOFF) {
445 info->x_char = STOP_CHAR(tty);
446 } else if ((tty->termios->c_cflag & CRTSCTS) ||
447 ((inb(UART_MSR + info->port) & UART_MSR_DSR) &&
448 !(tty->termios->c_cflag & CNORTSCTS))) {
449 mcr = inb(UART_MCR + info->port);
450 mcr &= ~UART_MCR_RTS;
451 outb_p(mcr, UART_MCR + info->port);
452 }
453 break;
454 case TTY_THROTTLE_RQ_AVAIL:
455 info = rs_table + DEV_TO_SL(tty->line);
456 if (tty->termios->c_iflag & IXOFF) {
457 cli();
458 if (info->x_char)
459 info->x_char = 0;
460 else
461 info->x_char = START_CHAR(tty);
462 sti();
463 } else if ((tty->termios->c_cflag & CRTSCTS) ||
464 ((inb(UART_MSR + info->port) & UART_MSR_DSR) &&
465 !(tty->termios->c_cflag & CNORTSCTS))) {
466 mcr = inb(UART_MCR + info->port);
467 mcr |= UART_MCR_RTS;
468 outb_p(mcr, UART_MCR + info->port);
469 }
470 break;
471 }
472 }
473
474
475
476
477
478
479
480 static void rs_close(struct tty_struct *tty, struct file * filp)
481 {
482 struct async_struct * info;
483 async_ISR ISR;
484 int irq, line;
485
486 line = DEV_TO_SL(tty->line);
487 if ((line < 0) || (line >= NR_PORTS))
488 return;
489 wait_until_sent(tty);
490 info = rs_table + line;
491 if (!info->port)
492 return;
493 shutdown(info);
494 #ifdef i386
495 rs_write_active &= ~(1 << line);
496 rs_event &= ~(1 << line);
497 #else
498 clear_bit(line, &rs_write_active);
499 clear_bit(line, &rs_event);
500 #endif
501 info->event = 0;
502 info->tty = 0;
503 ISR = info->ISR;
504 irq = ISR->irq;
505 if (irq == 2)
506 irq = 9;
507 if (--ISR->refcnt == 0) {
508 if (ISR->next_ISR)
509 ISR->next_ISR->prev_ISR = ISR->prev_ISR;
510 if (ISR->prev_ISR)
511 ISR->prev_ISR->next_ISR = ISR->next_ISR;
512 else
513 IRQ_ISR[irq] = ISR->next_ISR;
514 if (!IRQ_ISR[irq])
515 free_irq(irq);
516 }
517 }
518
519 static void startup(struct async_struct * info)
520 {
521 unsigned short port = info->port;
522 unsigned short ICP;
523
524
525
526
527 if (info->type == PORT_16550A)
528 outb_p(UART_FCR_CLEAR_CMD, UART_FCR + port);
529
530
531
532
533 (void)inb_p(UART_LSR + port);
534 (void)inb_p(UART_RX + port);
535 (void)inb_p(UART_IIR + port);
536 (void)inb_p(UART_MSR + port);
537
538
539
540
541 outb_p(UART_LCR_WLEN8, UART_LCR + port);
542 if (info->flags & ASYNC_FOURPORT)
543 outb_p(UART_MCR_DTR | UART_MCR_RTS,
544 UART_MCR + port);
545 else
546 outb_p(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2,
547 UART_MCR + port);
548
549
550
551
552 if (info->type == PORT_16550A) {
553 outb_p(UART_FCR_SETUP_CMD, UART_FCR + port);
554 info->xmit_fifo_size = 16;
555 } else {
556 info->xmit_fifo_size = 1;
557 }
558
559
560
561
562 outb_p(0x0f,UART_IER + port);
563 if (info->flags & ASYNC_FOURPORT) {
564
565 ICP = (port & 0xFE0) | 0x01F;
566 outb_p(0x80, ICP);
567 (void) inb(ICP);
568 }
569
570
571
572
573 (void)inb_p(UART_LSR + port);
574 (void)inb_p(UART_RX + port);
575 (void)inb_p(UART_IIR + port);
576 (void)inb_p(UART_MSR + port);
577 }
578
579 static void shutdown(struct async_struct * info)
580 {
581 unsigned short port = info->port;
582
583 outb_p(0x00, UART_IER + port);
584 if (info->tty && !(info->tty->termios->c_cflag & HUPCL))
585 outb_p(UART_MCR_DTR, UART_MCR + port);
586 else
587
588 outb_p(0x00, UART_MCR + port);
589 outb_p(UART_FCR_CLEAR_CMD, UART_FCR + info->port);
590 (void)inb(UART_RX + port);
591 }
592
593 void change_speed(unsigned int line)
594 {
595 struct async_struct * info;
596 unsigned short port;
597 int quot = 0;
598 unsigned cflag,cval,mcr;
599 int i;
600
601 if (line >= NR_PORTS)
602 return;
603 info = rs_table + line;
604 if (!info->tty || !info->tty->termios)
605 return;
606 cflag = info->tty->termios->c_cflag;
607 if (!(port = info->port))
608 return;
609 i = cflag & CBAUD;
610 if (i == 15) {
611 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
612 i += 1;
613 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
614 i += 2;
615 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
616 quot = info->custom_divisor;
617 }
618 if (quot) {
619 info->timeout = ((info->xmit_fifo_size*HZ*15*quot) /
620 info->baud_base) + 2;
621 } else if (baud_table[i] == 134) {
622 quot = (2*info->baud_base / 269);
623 info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
624 } else if (baud_table[i]) {
625 quot = info->baud_base / baud_table[i];
626 info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
627 } else {
628 quot = 0;
629 info->timeout = 0;
630 }
631 mcr = inb(UART_MCR + port);
632 if (quot)
633 outb(mcr | UART_MCR_DTR, UART_MCR + port);
634 else {
635 outb(mcr & ~UART_MCR_DTR, UART_MCR + port);
636 return;
637 }
638
639 cval = cflag & (CSIZE | CSTOPB);
640 cval >>= 4;
641 if (cflag & PARENB)
642 cval |= 8;
643 if (!(cflag & PARODD))
644 cval |= 16;
645 cli();
646 outb_p(cval | UART_LCR_DLAB, UART_LCR + port);
647 outb_p(quot & 0xff, UART_DLL + port);
648 outb_p(quot >> 8, UART_DLM + port);
649 outb(cval, UART_LCR + port);
650 sti();
651 }
652
653 static int get_serial_info(struct async_struct * info,
654 struct serial_struct * retinfo)
655 {
656 struct serial_struct tmp;
657
658 if (!retinfo)
659 return -EFAULT;
660 tmp.type = info->type;
661 tmp.line = info->line;
662 tmp.port = info->port;
663 tmp.irq = info->ISR->irq;
664
665 memcpy_tofs(retinfo,&tmp,sizeof(*retinfo));
666 return 0;
667 }
668
669 static int set_serial_info(struct async_struct * info,
670 struct serial_struct * new_info)
671 {
672 struct serial_struct tmp;
673 async_ISR ISR;
674 unsigned int new_port;
675 unsigned int irq,new_irq;
676 int retval;
677 struct sigaction sa;
678
679 if (!suser())
680 return -EPERM;
681 if (!new_info)
682 return -EFAULT;
683 memcpy_fromfs(&tmp,new_info,sizeof(tmp));
684 new_port = tmp.port;
685 new_irq = tmp.irq;
686 if (new_irq > 15 || new_port > 0xffff)
687 return -EINVAL;
688 if (new_irq == 2)
689 new_irq = 9;
690 ISR = info->ISR;
691 irq = ISR->irq;
692 if (irq == 2)
693 irq = 9;
694 if (irq != new_irq) {
695
696
697
698
699
700 if (!IRQ_ISR[new_irq]) {
701 sa.sa_handler = rs_interrupt;
702 sa.sa_flags = (SA_INTERRUPT);
703 sa.sa_mask = 0;
704 sa.sa_restorer = NULL;
705 retval = irqaction(new_irq,&sa);
706 if (retval)
707 return retval;
708 }
709
710
711
712
713
714 if (ISR->next_ISR)
715 ISR->next_ISR->prev_ISR = ISR->prev_ISR;
716 if (ISR->prev_ISR)
717 ISR->prev_ISR->next_ISR = ISR->next_ISR;
718 else
719 IRQ_ISR[irq] = ISR->next_ISR;
720 if (!IRQ_ISR[irq])
721 free_irq(irq);
722
723
724
725
726 ISR->prev_ISR = 0;
727 ISR->next_ISR = IRQ_ISR[new_irq];
728 if (ISR->next_ISR)
729 ISR->next_ISR->prev_ISR = ISR;
730 IRQ_ISR[new_irq] = ISR;
731 ISR->irq = new_irq;
732 }
733 cli();
734 if (new_port != info->port) {
735 shutdown(info);
736 info->port = new_port;
737 startup(info);
738 change_speed(info->line);
739 }
740 sti();
741 return 0;
742 }
743
744 static int get_modem_info(struct async_struct * info, unsigned int *value)
745 {
746 unsigned port;
747 unsigned char control, status;
748 unsigned int result;
749
750 port = info->port;
751 control = inb(UART_MCR + port);
752 status = inb(UART_MSR + port);
753 result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
754 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
755 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
756 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
757 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
758 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
759 put_fs_long(result,(unsigned long *) value);
760 return 0;
761 }
762
763 static int set_modem_info(struct async_struct * info, unsigned int cmd,
764 unsigned int *value)
765 {
766 unsigned port;
767 unsigned char control;
768 unsigned int arg = get_fs_long((unsigned long *) value);
769
770 port = info->port;
771 control = inb(UART_MCR + port);
772
773 switch (cmd) {
774 case TIOCMBIS:
775 if (arg & TIOCM_RTS)
776 control |= UART_MCR_RTS;
777 if (arg & TIOCM_DTR)
778 control |= UART_MCR_DTR;
779 break;
780 case TIOCMBIC:
781 if (arg & TIOCM_RTS)
782 control &= ~UART_MCR_RTS;
783 if (arg & TIOCM_DTR)
784 control &= ~UART_MCR_DTR;
785 break;
786 case TIOCMSET:
787 control = (control & ~0x03)
788 | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
789 | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0);
790 break;
791 default:
792 return -EINVAL;
793 }
794 outb(control, UART_MCR + port);
795 return 0;
796 }
797
798 static int rs_ioctl(struct tty_struct *tty, struct file * file,
799 unsigned int cmd, unsigned int arg)
800 {
801 int line;
802 struct async_struct * info;
803
804 line = DEV_TO_SL(tty->line);
805 if (line < 0 || line >= NR_PORTS)
806 return -ENODEV;
807 info = rs_table + line;
808
809 switch (cmd) {
810 case TCSBRK:
811 wait_until_sent(tty);
812 if (!arg)
813 send_break(info);
814 return 0;
815 case TIOCMGET:
816 verify_area((void *) arg,sizeof(unsigned int *));
817 return get_modem_info(info, (unsigned int *) arg);
818 case TIOCMBIS:
819 case TIOCMBIC:
820 case TIOCMSET:
821 return set_modem_info(info, cmd, (unsigned int *) arg);
822 case TIOCGSERIAL:
823 verify_area((void *) arg,sizeof(struct serial_struct));
824 return get_serial_info(info,
825 (struct serial_struct *) arg);
826 case TIOCSSERIAL:
827 return set_serial_info(info,
828 (struct serial_struct *) arg);
829
830 default:
831 return -EINVAL;
832 }
833 return 0;
834 }
835
836
837
838
839
840
841
842 int rs_open(struct tty_struct *tty, struct file * filp)
843 {
844 struct async_struct *info;
845 async_ISR ISR;
846 int irq, retval, line;
847 struct sigaction sa;
848
849 if (!tty)
850 return -ENODEV;
851 if (tty->count > 1)
852 return 0;
853 line = DEV_TO_SL(tty->line);
854 if ((line < 0) || (line >= NR_PORTS))
855 return -ENODEV;
856 info = rs_table + line;
857 if (!info->port || !info->ISR->irq)
858 return -ENODEV;
859 info->tty = tty;
860 tty->write = rs_write;
861 tty->close = rs_close;
862 tty->ioctl = rs_ioctl;
863 tty->throttle = rs_throttle;
864 ISR = info->ISR;
865 irq = ISR->irq;
866 if (irq == 2)
867 irq = 9;
868 if (!IRQ_ISR[irq]) {
869 sa.sa_handler = rs_interrupt;
870 sa.sa_flags = (SA_INTERRUPT);
871 sa.sa_mask = 0;
872 sa.sa_restorer = NULL;
873 retval = irqaction(irq,&sa);
874 if (retval)
875 return retval;
876 }
877 if (!ISR->refcnt++) {
878
879
880
881
882 ISR->prev_ISR = 0;
883 ISR->next_ISR = IRQ_ISR[irq];
884 if (ISR->next_ISR)
885 ISR->next_ISR->prev_ISR = ISR;
886 IRQ_ISR[irq] = ISR;
887 }
888 startup(info);
889 change_speed(info->line);
890 return 0;
891 }
892
893 static void init(struct async_struct * info)
894 {
895 #ifdef AUTO_IRQ
896 unsigned char status1, status2, scratch, save_ICP=0;
897 unsigned short ICP=0, port = info->port;
898 unsigned long timeout;
899
900
901
902
903 rs_irq_triggered = 0;
904 scratch = inb_p(UART_IER + port);
905 status1 = inb_p(UART_MCR + port);
906 if (info->flags & ASYNC_FOURPORT) {
907 outb_p(UART_MCR_DTR | UART_MCR_RTS, UART_MCR + port);
908 outb_p(0x0f,UART_IER + port);
909 ICP = (port & 0xFE0) | 0x01F;
910 save_ICP = inb_p(ICP);
911 outb_p(0x80, ICP);
912 (void) inb(ICP);
913 } else {
914 outb_p(UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2,
915 UART_MCR + port);
916 outb_p(0x0f,UART_IER + port);
917 }
918
919
920
921 (void)inb_p(UART_LSR + port);
922 (void)inb_p(UART_RX + port);
923 (void)inb_p(UART_IIR + port);
924 (void)inb_p(UART_MSR + port);
925 timeout = jiffies+2;
926 while (timeout >= jiffies) {
927 if (rs_irq_triggered)
928 break;
929 }
930
931
932
933 if (rs_irq_triggered) {
934 outb_p(0, UART_IER + port);
935 info->ISR->irq = rs_irq_triggered;
936 } else {
937 outb_p(scratch, UART_IER + port);
938 outb_p(status1, UART_MCR + port);
939 if (info->flags & ASYNC_FOURPORT)
940 outb_p(save_ICP, ICP);
941 info->type = PORT_UNKNOWN;
942 return;
943 }
944 #else
945 unsigned char status1, status2, scratch, scratch2;
946 unsigned short port = info->port;
947
948
949
950
951 scratch = inb_p(UART_MCR + port);
952 outb_p(UART_MCR_LOOP | scratch, UART_MCR + port);
953 scratch2 = inb_p(UART_MSR + port);
954 outb_p(UART_MCR_LOOP | 0x0A, UART_MCR + port);
955 status1 = inb_p(UART_MSR + port) & 0xF0;
956 outb_p(scratch, UART_MCR + port);
957 outb_p(scratch2, UART_MSR + port);
958 if (status1 != 0x90) {
959 info->type = PORT_UNKNOWN;
960 return;
961 }
962 #endif
963
964 if (!(info->flags & ASYNC_NOSCRATCH)) {
965 scratch = inb(UART_SCR + port);
966 outb_p(0xa5, UART_SCR + port);
967 status1 = inb(UART_SCR + port);
968 outb_p(0x5a, UART_SCR + port);
969 status2 = inb(UART_SCR + port);
970 outb_p(scratch, UART_SCR + port);
971 } else {
972 status1 = 0xa5;
973 status2 = 0x5a;
974 }
975 if (status1 == 0xa5 && status2 == 0x5a) {
976 outb_p(UART_FCR_ENABLE_FIFO, UART_FCR + port);
977 scratch = inb(UART_IIR + port) >> 6;
978 info->xmit_fifo_size = 1;
979 switch (scratch) {
980 case 0:
981 info->type = PORT_16450;
982 break;
983 case 1:
984 info->type = PORT_UNKNOWN;
985 break;
986 case 2:
987 info->type = PORT_16550;
988 break;
989 case 3:
990 info->type = PORT_16550A;
991 info->xmit_fifo_size = 16;
992 break;
993 }
994 } else
995 info->type = PORT_8250;
996 shutdown(info);
997 }
998
999 long rs_init(long kmem_start)
1000 {
1001 int i;
1002 struct async_struct * info;
1003 #ifdef AUTO_IRQ
1004 int irq_lines = 0;
1005 struct sigaction sa;
1006
1007
1008
1009 sti();
1010
1011 sa.sa_handler = rs_probe;
1012 sa.sa_flags = (SA_INTERRUPT);
1013 sa.sa_mask = 0;
1014 sa.sa_restorer = NULL;
1015 #endif
1016 timer_table[RS_TIMER].fn = rs_timer;
1017 timer_table[RS_TIMER].expires = 0;
1018
1019 for (i = 0; i < 16; i++) {
1020 IRQ_ISR[i] = 0;
1021 #ifdef AUTO_IRQ
1022 if (!irqaction(i, &sa))
1023 irq_lines |= 1 << i;
1024 #endif
1025 }
1026 for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
1027 info->line = i;
1028 info->tty = 0;
1029 info->type = PORT_UNKNOWN;
1030 info->timer = 0;
1031 info->custom_divisor = 0;
1032 info->x_char = 0;
1033 info->event = 0;
1034 if (!info->ISR->line) {
1035 info->ISR->line = i;
1036 info->ISR->refcnt = 0;
1037 info->ISR->next_ISR = 0;
1038 info->ISR->prev_ISR = 0;
1039 }
1040 init(info);
1041 if (info->type == PORT_UNKNOWN)
1042 continue;
1043 printk("ttys%d%s at 0x%04x (irq = %d)", info->line,
1044 (info->flags & ASYNC_FOURPORT) ? " FourPort" : "",
1045 info->port, info->ISR->irq);
1046 switch (info->type) {
1047 case PORT_8250:
1048 printk(" is a 8250\n");
1049 break;
1050 case PORT_16450:
1051 printk(" is a 16450\n");
1052 break;
1053 case PORT_16550:
1054 printk(" is a 16550\n");
1055 break;
1056 case PORT_16550A:
1057 printk(" is a 16550A\n");
1058 break;
1059 default:
1060 printk("\n");
1061 break;
1062 }
1063 }
1064 #ifdef AUTO_IRQ
1065 cli();
1066 for (i = 0; i < 16; i++) {
1067 if (irq_lines & (1 << i))
1068 free_irq(i);
1069 }
1070 sti();
1071 #endif
1072 return kmem_start;
1073 }
1074