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