blob: 102ece4c4e0e8050efe26b36745db83e45069e4b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/char/riscom.c -- RISCom/8 multiport serial driver.
3 *
4 * Copyright (C) 1994-1996 Dmitry Gorodchanin (pgmdsg@ibi.com)
5 *
6 * This code is loosely based on the Linux serial driver, written by
7 * Linus Torvalds, Theodore T'so and others. The RISCom/8 card
8 * programming info was obtained from various drivers for other OSes
9 * (FreeBSD, ISC, etc), but no source code from those drivers were
10 * directly included in this driver.
11 *
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 * Revision 1.1
28 *
29 * ChangeLog:
30 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 27-Jun-2001
31 * - get rid of check_region and several cleanups
32 */
33
34#include <linux/module.h>
35
36#include <asm/io.h>
37#include <linux/kernel.h>
38#include <linux/sched.h>
39#include <linux/ioport.h>
40#include <linux/interrupt.h>
41#include <linux/errno.h>
42#include <linux/tty.h>
43#include <linux/mm.h>
44#include <linux/serial.h>
45#include <linux/fcntl.h>
46#include <linux/major.h>
47#include <linux/init.h>
48#include <linux/delay.h>
Alan Cox33f0f882006-01-09 20:54:13 -080049#include <linux/tty_flip.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#include <asm/uaccess.h>
52
53#include "riscom8.h"
54#include "riscom8_reg.h"
55
56/* Am I paranoid or not ? ;-) */
57#define RISCOM_PARANOIA_CHECK
58
59/*
60 * Crazy InteliCom/8 boards sometimes has swapped CTS & DSR signals.
61 * You can slightly speed up things by #undefing the following option,
62 * if you are REALLY sure that your board is correct one.
63 */
64
65#define RISCOM_BRAIN_DAMAGED_CTS
66
67/*
68 * The following defines are mostly for testing purposes. But if you need
69 * some nice reporting in your syslog, you can define them also.
70 */
71#undef RC_REPORT_FIFO
72#undef RC_REPORT_OVERRUN
73
74
75#define RISCOM_LEGAL_FLAGS \
76 (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \
77 ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \
78 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
79
80#define RS_EVENT_WRITE_WAKEUP 0
81
Linus Torvalds1da177e2005-04-16 15:20:36 -070082static struct tty_driver *riscom_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Linus Torvalds1da177e2005-04-16 15:20:36 -070084static struct riscom_board rc_board[RC_NBOARD] = {
85 {
86 .base = RC_IOBASE1,
87 },
88 {
89 .base = RC_IOBASE2,
90 },
91 {
92 .base = RC_IOBASE3,
93 },
94 {
95 .base = RC_IOBASE4,
96 },
97};
98
99static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
100
101/* RISCom/8 I/O ports addresses (without address translation) */
102static unsigned short rc_ioport[] = {
Tobias Klauserfe971072006-01-09 20:54:02 -0800103#if 1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
Tobias Klauserfe971072006-01-09 20:54:02 -0800105#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
107 0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
108 0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
Tobias Klauserfe971072006-01-09 20:54:02 -0800109#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110};
Tobias Klauserfe971072006-01-09 20:54:02 -0800111#define RC_NIOPORT ARRAY_SIZE(rc_ioport)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113
114static inline int rc_paranoia_check(struct riscom_port const * port,
115 char *name, const char *routine)
116{
117#ifdef RISCOM_PARANOIA_CHECK
118 static const char badmagic[] = KERN_INFO
119 "rc: Warning: bad riscom port magic number for device %s in %s\n";
120 static const char badinfo[] = KERN_INFO
121 "rc: Warning: null riscom port for device %s in %s\n";
122
123 if (!port) {
124 printk(badinfo, name, routine);
125 return 1;
126 }
127 if (port->magic != RISCOM8_MAGIC) {
128 printk(badmagic, name, routine);
129 return 1;
130 }
131#endif
132 return 0;
133}
134
135/*
136 *
137 * Service functions for RISCom/8 driver.
138 *
139 */
140
141/* Get board number from pointer */
142static inline int board_No (struct riscom_board const * bp)
143{
144 return bp - rc_board;
145}
146
147/* Get port number from pointer */
148static inline int port_No (struct riscom_port const * port)
149{
150 return RC_PORT(port - rc_port);
151}
152
153/* Get pointer to board from pointer to port */
154static inline struct riscom_board * port_Board(struct riscom_port const * port)
155{
156 return &rc_board[RC_BOARD(port - rc_port)];
157}
158
159/* Input Byte from CL CD180 register */
160static inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg)
161{
162 return inb(bp->base + RC_TO_ISA(reg));
163}
164
165/* Output Byte to CL CD180 register */
166static inline void rc_out(struct riscom_board const * bp, unsigned short reg,
167 unsigned char val)
168{
169 outb(val, bp->base + RC_TO_ISA(reg));
170}
171
172/* Wait for Channel Command Register ready */
173static inline void rc_wait_CCR(struct riscom_board const * bp)
174{
175 unsigned long delay;
176
177 /* FIXME: need something more descriptive then 100000 :) */
178 for (delay = 100000; delay; delay--)
179 if (!rc_in(bp, CD180_CCR))
180 return;
181
182 printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp));
183}
184
185/*
186 * RISCom/8 probe functions.
187 */
188
189static inline int rc_request_io_range(struct riscom_board * const bp)
190{
191 int i;
192
193 for (i = 0; i < RC_NIOPORT; i++)
194 if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1,
195 "RISCom/8")) {
196 goto out_release;
197 }
198 return 0;
199out_release:
200 printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n",
201 board_No(bp), bp->base);
202 while(--i >= 0)
203 release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
204 return 1;
205}
206
207static inline void rc_release_io_range(struct riscom_board * const bp)
208{
209 int i;
210
211 for (i = 0; i < RC_NIOPORT; i++)
212 release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
213}
214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215/* Reset and setup CD180 chip */
216static void __init rc_init_CD180(struct riscom_board const * bp)
217{
218 unsigned long flags;
219
220 save_flags(flags); cli();
221 rc_out(bp, RC_CTOUT, 0); /* Clear timeout */
222 rc_wait_CCR(bp); /* Wait for CCR ready */
223 rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */
224 sti();
Jiri Slabyc4ebd922007-07-17 04:05:20 -0700225 msleep(50); /* Delay 0.05 sec */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 cli();
227 rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */
228 rc_out(bp, CD180_GICR, 0); /* Clear all bits */
229 rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */
230 rc_out(bp, CD180_PILR2, RC_ACK_TINT); /* Prio for transmitter intr */
231 rc_out(bp, CD180_PILR3, RC_ACK_RINT); /* Prio for receiver intr */
232
233 /* Setting up prescaler. We need 4 ticks per 1 ms */
234 rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
235 rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
236
237 restore_flags(flags);
238}
239
240/* Main probing routine, also sets irq. */
241static int __init rc_probe(struct riscom_board *bp)
242{
243 unsigned char val1, val2;
244 int irqs = 0;
245 int retries;
246
247 bp->irq = 0;
248
249 if (rc_request_io_range(bp))
250 return 1;
251
252 /* Are the I/O ports here ? */
253 rc_out(bp, CD180_PPRL, 0x5a);
254 outb(0xff, 0x80);
255 val1 = rc_in(bp, CD180_PPRL);
256 rc_out(bp, CD180_PPRL, 0xa5);
257 outb(0x00, 0x80);
258 val2 = rc_in(bp, CD180_PPRL);
259
260 if ((val1 != 0x5a) || (val2 != 0xa5)) {
261 printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n",
262 board_No(bp), bp->base);
263 goto out_release;
264 }
265
266 /* It's time to find IRQ for this board */
267 for (retries = 0; retries < 5 && irqs <= 0; retries++) {
268 irqs = probe_irq_on();
269 rc_init_CD180(bp); /* Reset CD180 chip */
270 rc_out(bp, CD180_CAR, 2); /* Select port 2 */
271 rc_wait_CCR(bp);
272 rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter */
273 rc_out(bp, CD180_IER, IER_TXRDY); /* Enable tx empty intr */
Jiri Slabyc4ebd922007-07-17 04:05:20 -0700274 msleep(50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 irqs = probe_irq_off(irqs);
276 val1 = rc_in(bp, RC_BSR); /* Get Board Status reg */
277 val2 = rc_in(bp, RC_ACK_TINT); /* ACK interrupt */
278 rc_init_CD180(bp); /* Reset CD180 again */
279
280 if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX))) {
281 printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not "
282 "found.\n", board_No(bp), bp->base);
283 goto out_release;
284 }
285 }
286
287 if (irqs <= 0) {
288 printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board "
289 "at 0x%03x.\n", board_No(bp), bp->base);
290 goto out_release;
291 }
292 bp->irq = irqs;
293 bp->flags |= RC_BOARD_PRESENT;
294
295 printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at "
296 "0x%03x, IRQ %d.\n",
297 board_No(bp),
298 (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A', /* Board revision */
299 bp->base, bp->irq);
300
301 return 0;
302out_release:
303 rc_release_io_range(bp);
304 return 1;
305}
306
307/*
308 *
309 * Interrupt processing routines.
310 *
311 */
312
313static inline void rc_mark_event(struct riscom_port * port, int event)
314{
315 set_bit(event, &port->event);
316 schedule_work(&port->tqueue);
317}
318
319static inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
320 unsigned char const * what)
321{
322 unsigned char channel;
323 struct riscom_port * port;
324
325 channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF;
326 if (channel < CD180_NCH) {
327 port = &rc_port[board_No(bp) * RC_NPORT + channel];
328 if (port->flags & ASYNC_INITIALIZED) {
329 return port;
330 }
331 }
332 printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
333 board_No(bp), what, channel);
334 return NULL;
335}
336
337static inline void rc_receive_exc(struct riscom_board const * bp)
338{
339 struct riscom_port *port;
340 struct tty_struct *tty;
341 unsigned char status;
Alan Cox33f0f882006-01-09 20:54:13 -0800342 unsigned char ch, flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
344 if (!(port = rc_get_port(bp, "Receive")))
345 return;
346
347 tty = port->tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
349#ifdef RC_REPORT_OVERRUN
350 status = rc_in(bp, CD180_RCSR);
Alan Cox33f0f882006-01-09 20:54:13 -0800351 if (status & RCSR_OE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 port->overrun++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 status &= port->mark_mask;
354#else
355 status = rc_in(bp, CD180_RCSR) & port->mark_mask;
356#endif
357 ch = rc_in(bp, CD180_RDR);
358 if (!status) {
359 return;
360 }
361 if (status & RCSR_TOUT) {
362 printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
363 "Hardware problems ?\n",
364 board_No(bp), port_No(port));
365 return;
366
367 } else if (status & RCSR_BREAK) {
368 printk(KERN_INFO "rc%d: port %d: Handling break...\n",
369 board_No(bp), port_No(port));
Alan Cox33f0f882006-01-09 20:54:13 -0800370 flag = TTY_BREAK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 if (port->flags & ASYNC_SAK)
372 do_SAK(tty);
373
374 } else if (status & RCSR_PE)
Alan Cox33f0f882006-01-09 20:54:13 -0800375 flag = TTY_PARITY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
377 else if (status & RCSR_FE)
Alan Cox33f0f882006-01-09 20:54:13 -0800378 flag = TTY_FRAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
380 else if (status & RCSR_OE)
Alan Cox33f0f882006-01-09 20:54:13 -0800381 flag = TTY_OVERRUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383 else
Alan Cox33f0f882006-01-09 20:54:13 -0800384 flag = TTY_NORMAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
Alan Cox33f0f882006-01-09 20:54:13 -0800386 tty_insert_flip_char(tty, ch, flag);
387 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388}
389
390static inline void rc_receive(struct riscom_board const * bp)
391{
392 struct riscom_port *port;
393 struct tty_struct *tty;
394 unsigned char count;
395
396 if (!(port = rc_get_port(bp, "Receive")))
397 return;
398
399 tty = port->tty;
400
401 count = rc_in(bp, CD180_RDCR);
402
403#ifdef RC_REPORT_FIFO
404 port->hits[count > 8 ? 9 : count]++;
405#endif
406
407 while (count--) {
Alan Cox33f0f882006-01-09 20:54:13 -0800408 if (tty_buffer_request_room(tty, 1) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 printk(KERN_WARNING "rc%d: port %d: Working around "
410 "flip buffer overflow.\n",
411 board_No(bp), port_No(port));
412 break;
413 }
Alan Cox33f0f882006-01-09 20:54:13 -0800414 tty_insert_flip_char(tty, rc_in(bp, CD180_RDR), TTY_NORMAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 }
Alan Cox33f0f882006-01-09 20:54:13 -0800416 tty_flip_buffer_push(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417}
418
419static inline void rc_transmit(struct riscom_board const * bp)
420{
421 struct riscom_port *port;
422 struct tty_struct *tty;
423 unsigned char count;
424
425
426 if (!(port = rc_get_port(bp, "Transmit")))
427 return;
428
429 tty = port->tty;
430
431 if (port->IER & IER_TXEMPTY) {
432 /* FIFO drained */
433 rc_out(bp, CD180_CAR, port_No(port));
434 port->IER &= ~IER_TXEMPTY;
435 rc_out(bp, CD180_IER, port->IER);
436 return;
437 }
438
439 if ((port->xmit_cnt <= 0 && !port->break_length)
440 || tty->stopped || tty->hw_stopped) {
441 rc_out(bp, CD180_CAR, port_No(port));
442 port->IER &= ~IER_TXRDY;
443 rc_out(bp, CD180_IER, port->IER);
444 return;
445 }
446
447 if (port->break_length) {
448 if (port->break_length > 0) {
449 if (port->COR2 & COR2_ETC) {
450 rc_out(bp, CD180_TDR, CD180_C_ESC);
451 rc_out(bp, CD180_TDR, CD180_C_SBRK);
452 port->COR2 &= ~COR2_ETC;
453 }
454 count = min_t(int, port->break_length, 0xff);
455 rc_out(bp, CD180_TDR, CD180_C_ESC);
456 rc_out(bp, CD180_TDR, CD180_C_DELAY);
457 rc_out(bp, CD180_TDR, count);
458 if (!(port->break_length -= count))
459 port->break_length--;
460 } else {
461 rc_out(bp, CD180_TDR, CD180_C_ESC);
462 rc_out(bp, CD180_TDR, CD180_C_EBRK);
463 rc_out(bp, CD180_COR2, port->COR2);
464 rc_wait_CCR(bp);
465 rc_out(bp, CD180_CCR, CCR_CORCHG2);
466 port->break_length = 0;
467 }
468 return;
469 }
470
471 count = CD180_NFIFO;
472 do {
473 rc_out(bp, CD180_TDR, port->xmit_buf[port->xmit_tail++]);
474 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
475 if (--port->xmit_cnt <= 0)
476 break;
477 } while (--count > 0);
478
479 if (port->xmit_cnt <= 0) {
480 rc_out(bp, CD180_CAR, port_No(port));
481 port->IER &= ~IER_TXRDY;
482 rc_out(bp, CD180_IER, port->IER);
483 }
484 if (port->xmit_cnt <= port->wakeup_chars)
485 rc_mark_event(port, RS_EVENT_WRITE_WAKEUP);
486}
487
488static inline void rc_check_modem(struct riscom_board const * bp)
489{
490 struct riscom_port *port;
491 struct tty_struct *tty;
492 unsigned char mcr;
493
494 if (!(port = rc_get_port(bp, "Modem")))
495 return;
496
497 tty = port->tty;
498
499 mcr = rc_in(bp, CD180_MCR);
500 if (mcr & MCR_CDCHG) {
501 if (rc_in(bp, CD180_MSVR) & MSVR_CD)
502 wake_up_interruptible(&port->open_wait);
503 else
504 schedule_work(&port->tqueue_hangup);
505 }
506
507#ifdef RISCOM_BRAIN_DAMAGED_CTS
508 if (mcr & MCR_CTSCHG) {
509 if (rc_in(bp, CD180_MSVR) & MSVR_CTS) {
510 tty->hw_stopped = 0;
511 port->IER |= IER_TXRDY;
512 if (port->xmit_cnt <= port->wakeup_chars)
513 rc_mark_event(port, RS_EVENT_WRITE_WAKEUP);
514 } else {
515 tty->hw_stopped = 1;
516 port->IER &= ~IER_TXRDY;
517 }
518 rc_out(bp, CD180_IER, port->IER);
519 }
520 if (mcr & MCR_DSRCHG) {
521 if (rc_in(bp, CD180_MSVR) & MSVR_DSR) {
522 tty->hw_stopped = 0;
523 port->IER |= IER_TXRDY;
524 if (port->xmit_cnt <= port->wakeup_chars)
525 rc_mark_event(port, RS_EVENT_WRITE_WAKEUP);
526 } else {
527 tty->hw_stopped = 1;
528 port->IER &= ~IER_TXRDY;
529 }
530 rc_out(bp, CD180_IER, port->IER);
531 }
532#endif /* RISCOM_BRAIN_DAMAGED_CTS */
533
534 /* Clear change bits */
535 rc_out(bp, CD180_MCR, 0);
536}
537
538/* The main interrupt processing routine */
Jeff Garzikf07ef392007-10-23 19:12:11 -0400539static irqreturn_t rc_interrupt(int dummy, void * dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540{
541 unsigned char status;
542 unsigned char ack;
Jeff Garzikf07ef392007-10-23 19:12:11 -0400543 struct riscom_board *bp = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 unsigned long loop = 0;
545 int handled = 0;
546
Jeff Garzikc7bec5a2006-10-06 15:00:58 -0400547 if (!(bp->flags & RC_BOARD_ACTIVE))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 return IRQ_NONE;
Jeff Garzikc7bec5a2006-10-06 15:00:58 -0400549
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) &
551 (RC_BSR_TOUT | RC_BSR_TINT |
552 RC_BSR_MINT | RC_BSR_RINT))) {
553 handled = 1;
554 if (status & RC_BSR_TOUT)
555 printk(KERN_WARNING "rc%d: Got timeout. Hardware "
556 "error?\n", board_No(bp));
557
558 else if (status & RC_BSR_RINT) {
559 ack = rc_in(bp, RC_ACK_RINT);
560
561 if (ack == (RC_ID | GIVR_IT_RCV))
562 rc_receive(bp);
563 else if (ack == (RC_ID | GIVR_IT_REXC))
564 rc_receive_exc(bp);
565 else
566 printk(KERN_WARNING "rc%d: Bad receive ack "
567 "0x%02x.\n",
568 board_No(bp), ack);
569
570 } else if (status & RC_BSR_TINT) {
571 ack = rc_in(bp, RC_ACK_TINT);
572
573 if (ack == (RC_ID | GIVR_IT_TX))
574 rc_transmit(bp);
575 else
576 printk(KERN_WARNING "rc%d: Bad transmit ack "
577 "0x%02x.\n",
578 board_No(bp), ack);
579
580 } else /* if (status & RC_BSR_MINT) */ {
581 ack = rc_in(bp, RC_ACK_MINT);
582
583 if (ack == (RC_ID | GIVR_IT_MODEM))
584 rc_check_modem(bp);
585 else
586 printk(KERN_WARNING "rc%d: Bad modem ack "
587 "0x%02x.\n",
588 board_No(bp), ack);
589
590 }
591
592 rc_out(bp, CD180_EOIR, 0); /* Mark end of interrupt */
593 rc_out(bp, RC_CTOUT, 0); /* Clear timeout flag */
594 }
595 return IRQ_RETVAL(handled);
596}
597
598/*
599 * Routines for open & close processing.
600 */
601
602/* Called with disabled interrupts */
Jeff Garzikf07ef392007-10-23 19:12:11 -0400603static int rc_setup_board(struct riscom_board * bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604{
605 int error;
606
607 if (bp->flags & RC_BOARD_ACTIVE)
608 return 0;
609
Thomas Gleixner0f2ed4c2006-07-01 19:29:33 -0700610 error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
Jeff Garzikf07ef392007-10-23 19:12:11 -0400611 "RISCom/8", bp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 if (error)
613 return error;
614
615 rc_out(bp, RC_CTOUT, 0); /* Just in case */
616 bp->DTR = ~0;
617 rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 bp->flags |= RC_BOARD_ACTIVE;
620
621 return 0;
622}
623
624/* Called with disabled interrupts */
Jeff Garzikf07ef392007-10-23 19:12:11 -0400625static void rc_shutdown_board(struct riscom_board *bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626{
627 if (!(bp->flags & RC_BOARD_ACTIVE))
628 return;
629
630 bp->flags &= ~RC_BOARD_ACTIVE;
631
632 free_irq(bp->irq, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
634 bp->DTR = ~0;
635 rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
636
637}
638
639/*
640 * Setting up port characteristics.
641 * Must be called with disabled interrupts
642 */
643static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
644{
645 struct tty_struct *tty;
646 unsigned long baud;
647 long tmp;
648 unsigned char cor1 = 0, cor3 = 0;
649 unsigned char mcor1 = 0, mcor2 = 0;
650
651 if (!(tty = port->tty) || !tty->termios)
652 return;
653
654 port->IER = 0;
655 port->COR2 = 0;
656 port->MSVR = MSVR_RTS;
657
Alan Coxc7bce302006-09-30 23:27:24 -0700658 baud = tty_get_baud_rate(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 /* Select port on the board */
661 rc_out(bp, CD180_CAR, port_No(port));
662
Alan Coxc7bce302006-09-30 23:27:24 -0700663 if (!baud) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 /* Drop DTR & exit */
665 bp->DTR |= (1u << port_No(port));
666 rc_out(bp, RC_DTR, bp->DTR);
667 return;
668 } else {
669 /* Set DTR on */
670 bp->DTR &= ~(1u << port_No(port));
671 rc_out(bp, RC_DTR, bp->DTR);
672 }
673
674 /*
675 * Now we must calculate some speed depended things
676 */
677
678 /* Set baud rate for port */
Alan Coxc7bce302006-09-30 23:27:24 -0700679 tmp = (((RC_OSCFREQ + baud/2) / baud +
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 CD180_TPC/2) / CD180_TPC);
681
682 rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
683 rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
684 rc_out(bp, CD180_RBPRL, tmp & 0xff);
685 rc_out(bp, CD180_TBPRL, tmp & 0xff);
686
Alan Coxc7bce302006-09-30 23:27:24 -0700687 baud = (baud + 5) / 10; /* Estimated CPS */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
689 /* Two timer ticks seems enough to wakeup something like SLIP driver */
690 tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
691 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
692 SERIAL_XMIT_SIZE - 1 : tmp);
693
694 /* Receiver timeout will be transmission time for 1.5 chars */
695 tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;
696 tmp = (tmp > 0xff) ? 0xff : tmp;
697 rc_out(bp, CD180_RTPR, tmp);
698
699 switch (C_CSIZE(tty)) {
700 case CS5:
701 cor1 |= COR1_5BITS;
702 break;
703 case CS6:
704 cor1 |= COR1_6BITS;
705 break;
706 case CS7:
707 cor1 |= COR1_7BITS;
708 break;
709 case CS8:
710 cor1 |= COR1_8BITS;
711 break;
712 }
713
714 if (C_CSTOPB(tty))
715 cor1 |= COR1_2SB;
716
717 cor1 |= COR1_IGNORE;
718 if (C_PARENB(tty)) {
719 cor1 |= COR1_NORMPAR;
720 if (C_PARODD(tty))
721 cor1 |= COR1_ODDP;
722 if (I_INPCK(tty))
723 cor1 &= ~COR1_IGNORE;
724 }
725 /* Set marking of some errors */
726 port->mark_mask = RCSR_OE | RCSR_TOUT;
727 if (I_INPCK(tty))
728 port->mark_mask |= RCSR_FE | RCSR_PE;
729 if (I_BRKINT(tty) || I_PARMRK(tty))
730 port->mark_mask |= RCSR_BREAK;
731 if (I_IGNPAR(tty))
732 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
733 if (I_IGNBRK(tty)) {
734 port->mark_mask &= ~RCSR_BREAK;
735 if (I_IGNPAR(tty))
736 /* Real raw mode. Ignore all */
737 port->mark_mask &= ~RCSR_OE;
738 }
739 /* Enable Hardware Flow Control */
740 if (C_CRTSCTS(tty)) {
741#ifdef RISCOM_BRAIN_DAMAGED_CTS
742 port->IER |= IER_DSR | IER_CTS;
743 mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
744 mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
745 tty->hw_stopped = !(rc_in(bp, CD180_MSVR) & (MSVR_CTS|MSVR_DSR));
746#else
747 port->COR2 |= COR2_CTSAE;
748#endif
749 }
750 /* Enable Software Flow Control. FIXME: I'm not sure about this */
751 /* Some people reported that it works, but I still doubt */
752 if (I_IXON(tty)) {
753 port->COR2 |= COR2_TXIBE;
754 cor3 |= (COR3_FCT | COR3_SCDE);
755 if (I_IXANY(tty))
756 port->COR2 |= COR2_IXM;
757 rc_out(bp, CD180_SCHR1, START_CHAR(tty));
758 rc_out(bp, CD180_SCHR2, STOP_CHAR(tty));
759 rc_out(bp, CD180_SCHR3, START_CHAR(tty));
760 rc_out(bp, CD180_SCHR4, STOP_CHAR(tty));
761 }
762 if (!C_CLOCAL(tty)) {
763 /* Enable CD check */
764 port->IER |= IER_CD;
765 mcor1 |= MCOR1_CDZD;
766 mcor2 |= MCOR2_CDOD;
767 }
768
769 if (C_CREAD(tty))
770 /* Enable receiver */
771 port->IER |= IER_RXD;
772
773 /* Set input FIFO size (1-8 bytes) */
774 cor3 |= RISCOM_RXFIFO;
775 /* Setting up CD180 channel registers */
776 rc_out(bp, CD180_COR1, cor1);
777 rc_out(bp, CD180_COR2, port->COR2);
778 rc_out(bp, CD180_COR3, cor3);
779 /* Make CD180 know about registers change */
780 rc_wait_CCR(bp);
781 rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
782 /* Setting up modem option registers */
783 rc_out(bp, CD180_MCOR1, mcor1);
784 rc_out(bp, CD180_MCOR2, mcor2);
785 /* Enable CD180 transmitter & receiver */
786 rc_wait_CCR(bp);
787 rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN);
788 /* Enable interrupts */
789 rc_out(bp, CD180_IER, port->IER);
790 /* And finally set RTS on */
791 rc_out(bp, CD180_MSVR, port->MSVR);
792}
793
794/* Must be called with interrupts enabled */
795static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
796{
797 unsigned long flags;
798
799 if (port->flags & ASYNC_INITIALIZED)
800 return 0;
801
802 if (!port->xmit_buf) {
803 /* We may sleep in get_zeroed_page() */
804 unsigned long tmp;
805
806 if (!(tmp = get_zeroed_page(GFP_KERNEL)))
807 return -ENOMEM;
808
809 if (port->xmit_buf) {
810 free_page(tmp);
811 return -ERESTARTSYS;
812 }
813 port->xmit_buf = (unsigned char *) tmp;
814 }
815
816 save_flags(flags); cli();
817
818 if (port->tty)
819 clear_bit(TTY_IO_ERROR, &port->tty->flags);
820
821 if (port->count == 1)
822 bp->count++;
823
824 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
825 rc_change_speed(bp, port);
826 port->flags |= ASYNC_INITIALIZED;
827
828 restore_flags(flags);
829 return 0;
830}
831
832/* Must be called with interrupts disabled */
833static void rc_shutdown_port(struct riscom_board *bp, struct riscom_port *port)
834{
835 struct tty_struct *tty;
836
837 if (!(port->flags & ASYNC_INITIALIZED))
838 return;
839
840#ifdef RC_REPORT_OVERRUN
841 printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
842 board_No(bp), port_No(port), port->overrun);
843#endif
844#ifdef RC_REPORT_FIFO
845 {
846 int i;
847
848 printk(KERN_INFO "rc%d: port %d: FIFO hits [ ",
849 board_No(bp), port_No(port));
850 for (i = 0; i < 10; i++) {
851 printk("%ld ", port->hits[i]);
852 }
853 printk("].\n");
854 }
855#endif
856 if (port->xmit_buf) {
857 free_page((unsigned long) port->xmit_buf);
858 port->xmit_buf = NULL;
859 }
860
861 if (!(tty = port->tty) || C_HUPCL(tty)) {
862 /* Drop DTR */
863 bp->DTR |= (1u << port_No(port));
864 rc_out(bp, RC_DTR, bp->DTR);
865 }
866
867 /* Select port */
868 rc_out(bp, CD180_CAR, port_No(port));
869 /* Reset port */
870 rc_wait_CCR(bp);
871 rc_out(bp, CD180_CCR, CCR_SOFTRESET);
872 /* Disable all interrupts from this port */
873 port->IER = 0;
874 rc_out(bp, CD180_IER, port->IER);
875
876 if (tty)
877 set_bit(TTY_IO_ERROR, &tty->flags);
878 port->flags &= ~ASYNC_INITIALIZED;
879
880 if (--bp->count < 0) {
881 printk(KERN_INFO "rc%d: rc_shutdown_port: "
882 "bad board count: %d\n",
883 board_No(bp), bp->count);
884 bp->count = 0;
885 }
886
887 /*
888 * If this is the last opened port on the board
889 * shutdown whole board
890 */
891 if (!bp->count)
892 rc_shutdown_board(bp);
893}
894
895
896static int block_til_ready(struct tty_struct *tty, struct file * filp,
897 struct riscom_port *port)
898{
899 DECLARE_WAITQUEUE(wait, current);
900 struct riscom_board *bp = port_Board(port);
901 int retval;
902 int do_clocal = 0;
903 int CD;
904
905 /*
906 * If the device is in the middle of being closed, then block
907 * until it's done, and then try again.
908 */
909 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
910 interruptible_sleep_on(&port->close_wait);
911 if (port->flags & ASYNC_HUP_NOTIFY)
912 return -EAGAIN;
913 else
914 return -ERESTARTSYS;
915 }
916
917 /*
918 * If non-blocking mode is set, or the port is not enabled,
919 * then make the check up front and then exit.
920 */
921 if ((filp->f_flags & O_NONBLOCK) ||
922 (tty->flags & (1 << TTY_IO_ERROR))) {
923 port->flags |= ASYNC_NORMAL_ACTIVE;
924 return 0;
925 }
926
927 if (C_CLOCAL(tty))
928 do_clocal = 1;
929
930 /*
931 * Block waiting for the carrier detect and the line to become
932 * free (i.e., not in use by the callout). While we are in
933 * this loop, info->count is dropped by one, so that
934 * rs_close() knows when to free things. We restore it upon
935 * exit, either normal or abnormal.
936 */
937 retval = 0;
938 add_wait_queue(&port->open_wait, &wait);
939 cli();
940 if (!tty_hung_up_p(filp))
941 port->count--;
942 sti();
943 port->blocked_open++;
944 while (1) {
945 cli();
946 rc_out(bp, CD180_CAR, port_No(port));
947 CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
948 rc_out(bp, CD180_MSVR, MSVR_RTS);
949 bp->DTR &= ~(1u << port_No(port));
950 rc_out(bp, RC_DTR, bp->DTR);
951 sti();
952 set_current_state(TASK_INTERRUPTIBLE);
953 if (tty_hung_up_p(filp) ||
954 !(port->flags & ASYNC_INITIALIZED)) {
955 if (port->flags & ASYNC_HUP_NOTIFY)
956 retval = -EAGAIN;
957 else
958 retval = -ERESTARTSYS;
959 break;
960 }
961 if (!(port->flags & ASYNC_CLOSING) &&
962 (do_clocal || CD))
963 break;
964 if (signal_pending(current)) {
965 retval = -ERESTARTSYS;
966 break;
967 }
968 schedule();
969 }
Milind Arun Choudharycc0a8fb2007-05-08 00:30:52 -0700970 __set_current_state(TASK_RUNNING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 remove_wait_queue(&port->open_wait, &wait);
972 if (!tty_hung_up_p(filp))
973 port->count++;
974 port->blocked_open--;
975 if (retval)
976 return retval;
977
978 port->flags |= ASYNC_NORMAL_ACTIVE;
979 return 0;
980}
981
982static int rc_open(struct tty_struct * tty, struct file * filp)
983{
984 int board;
985 int error;
986 struct riscom_port * port;
987 struct riscom_board * bp;
988
989 board = RC_BOARD(tty->index);
990 if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
991 return -ENODEV;
992
993 bp = &rc_board[board];
994 port = rc_port + board * RC_NPORT + RC_PORT(tty->index);
995 if (rc_paranoia_check(port, tty->name, "rc_open"))
996 return -ENODEV;
997
998 if ((error = rc_setup_board(bp)))
999 return error;
1000
1001 port->count++;
1002 tty->driver_data = port;
1003 port->tty = tty;
1004
1005 if ((error = rc_setup_port(bp, port)))
1006 return error;
1007
1008 if ((error = block_til_ready(tty, filp, port)))
1009 return error;
1010
1011 return 0;
1012}
1013
1014static void rc_close(struct tty_struct * tty, struct file * filp)
1015{
1016 struct riscom_port *port = (struct riscom_port *) tty->driver_data;
1017 struct riscom_board *bp;
1018 unsigned long flags;
1019 unsigned long timeout;
1020
1021 if (!port || rc_paranoia_check(port, tty->name, "close"))
1022 return;
1023
1024 save_flags(flags); cli();
1025 if (tty_hung_up_p(filp))
1026 goto out;
1027
1028 bp = port_Board(port);
1029 if ((tty->count == 1) && (port->count != 1)) {
1030 printk(KERN_INFO "rc%d: rc_close: bad port count;"
1031 " tty->count is 1, port count is %d\n",
1032 board_No(bp), port->count);
1033 port->count = 1;
1034 }
1035 if (--port->count < 0) {
1036 printk(KERN_INFO "rc%d: rc_close: bad port count "
1037 "for tty%d: %d\n",
1038 board_No(bp), port_No(port), port->count);
1039 port->count = 0;
1040 }
1041 if (port->count)
1042 goto out;
1043 port->flags |= ASYNC_CLOSING;
1044 /*
1045 * Now we wait for the transmit buffer to clear; and we notify
1046 * the line discipline to only process XON/XOFF characters.
1047 */
1048 tty->closing = 1;
1049 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1050 tty_wait_until_sent(tty, port->closing_wait);
1051 /*
1052 * At this point we stop accepting input. To do this, we
1053 * disable the receive line status interrupts, and tell the
1054 * interrupt driver to stop checking the data ready bit in the
1055 * line status register.
1056 */
1057 port->IER &= ~IER_RXD;
1058 if (port->flags & ASYNC_INITIALIZED) {
1059 port->IER &= ~IER_TXRDY;
1060 port->IER |= IER_TXEMPTY;
1061 rc_out(bp, CD180_CAR, port_No(port));
1062 rc_out(bp, CD180_IER, port->IER);
1063 /*
1064 * Before we drop DTR, make sure the UART transmitter
1065 * has completely drained; this is especially
1066 * important if there is a transmit FIFO!
1067 */
1068 timeout = jiffies+HZ;
1069 while(port->IER & IER_TXEMPTY) {
1070 msleep_interruptible(jiffies_to_msecs(port->timeout));
1071 if (time_after(jiffies, timeout))
1072 break;
1073 }
1074 }
1075 rc_shutdown_port(bp, port);
1076 if (tty->driver->flush_buffer)
1077 tty->driver->flush_buffer(tty);
1078 tty_ldisc_flush(tty);
1079
1080 tty->closing = 0;
1081 port->event = 0;
1082 port->tty = NULL;
1083 if (port->blocked_open) {
1084 if (port->close_delay) {
1085 msleep_interruptible(jiffies_to_msecs(port->close_delay));
1086 }
1087 wake_up_interruptible(&port->open_wait);
1088 }
1089 port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
1090 wake_up_interruptible(&port->close_wait);
1091out: restore_flags(flags);
1092}
1093
1094static int rc_write(struct tty_struct * tty,
1095 const unsigned char *buf, int count)
1096{
1097 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1098 struct riscom_board *bp;
1099 int c, total = 0;
1100 unsigned long flags;
1101
1102 if (rc_paranoia_check(port, tty->name, "rc_write"))
1103 return 0;
1104
1105 bp = port_Board(port);
1106
Jiri Slabyb3218a72006-10-04 02:15:27 -07001107 if (!tty || !port->xmit_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 return 0;
1109
1110 save_flags(flags);
1111 while (1) {
1112 cli();
1113 c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
1114 SERIAL_XMIT_SIZE - port->xmit_head));
1115 if (c <= 0) {
1116 restore_flags(flags);
1117 break;
1118 }
1119
1120 memcpy(port->xmit_buf + port->xmit_head, buf, c);
1121 port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1122 port->xmit_cnt += c;
1123 restore_flags(flags);
1124
1125 buf += c;
1126 count -= c;
1127 total += c;
1128 }
1129
1130 cli();
1131 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1132 !(port->IER & IER_TXRDY)) {
1133 port->IER |= IER_TXRDY;
1134 rc_out(bp, CD180_CAR, port_No(port));
1135 rc_out(bp, CD180_IER, port->IER);
1136 }
1137 restore_flags(flags);
1138
1139 return total;
1140}
1141
1142static void rc_put_char(struct tty_struct * tty, unsigned char ch)
1143{
1144 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1145 unsigned long flags;
1146
1147 if (rc_paranoia_check(port, tty->name, "rc_put_char"))
1148 return;
1149
1150 if (!tty || !port->xmit_buf)
1151 return;
1152
1153 save_flags(flags); cli();
1154
1155 if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
1156 goto out;
1157
1158 port->xmit_buf[port->xmit_head++] = ch;
1159 port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1160 port->xmit_cnt++;
1161out: restore_flags(flags);
1162}
1163
1164static void rc_flush_chars(struct tty_struct * tty)
1165{
1166 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1167 unsigned long flags;
1168
1169 if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
1170 return;
1171
1172 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
1173 !port->xmit_buf)
1174 return;
1175
1176 save_flags(flags); cli();
1177 port->IER |= IER_TXRDY;
1178 rc_out(port_Board(port), CD180_CAR, port_No(port));
1179 rc_out(port_Board(port), CD180_IER, port->IER);
1180 restore_flags(flags);
1181}
1182
1183static int rc_write_room(struct tty_struct * tty)
1184{
1185 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1186 int ret;
1187
1188 if (rc_paranoia_check(port, tty->name, "rc_write_room"))
1189 return 0;
1190
1191 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1192 if (ret < 0)
1193 ret = 0;
1194 return ret;
1195}
1196
1197static int rc_chars_in_buffer(struct tty_struct *tty)
1198{
1199 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1200
1201 if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
1202 return 0;
1203
1204 return port->xmit_cnt;
1205}
1206
1207static void rc_flush_buffer(struct tty_struct *tty)
1208{
1209 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1210 unsigned long flags;
1211
1212 if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
1213 return;
1214
1215 save_flags(flags); cli();
1216 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
1217 restore_flags(flags);
1218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 tty_wakeup(tty);
1220}
1221
1222static int rc_tiocmget(struct tty_struct *tty, struct file *file)
1223{
1224 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1225 struct riscom_board * bp;
1226 unsigned char status;
1227 unsigned int result;
1228 unsigned long flags;
1229
1230 if (rc_paranoia_check(port, tty->name, __FUNCTION__))
1231 return -ENODEV;
1232
1233 bp = port_Board(port);
1234 save_flags(flags); cli();
1235 rc_out(bp, CD180_CAR, port_No(port));
1236 status = rc_in(bp, CD180_MSVR);
1237 result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
1238 restore_flags(flags);
1239 result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0)
1240 | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1241 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1242 | ((status & MSVR_DSR) ? TIOCM_DSR : 0)
1243 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1244 return result;
1245}
1246
1247static int rc_tiocmset(struct tty_struct *tty, struct file *file,
1248 unsigned int set, unsigned int clear)
1249{
1250 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1251 unsigned long flags;
1252 struct riscom_board *bp;
1253
1254 if (rc_paranoia_check(port, tty->name, __FUNCTION__))
1255 return -ENODEV;
1256
1257 bp = port_Board(port);
1258
1259 save_flags(flags); cli();
1260 if (set & TIOCM_RTS)
1261 port->MSVR |= MSVR_RTS;
1262 if (set & TIOCM_DTR)
1263 bp->DTR &= ~(1u << port_No(port));
1264
1265 if (clear & TIOCM_RTS)
1266 port->MSVR &= ~MSVR_RTS;
1267 if (clear & TIOCM_DTR)
1268 bp->DTR |= (1u << port_No(port));
1269
1270 rc_out(bp, CD180_CAR, port_No(port));
1271 rc_out(bp, CD180_MSVR, port->MSVR);
1272 rc_out(bp, RC_DTR, bp->DTR);
1273 restore_flags(flags);
1274 return 0;
1275}
1276
1277static inline void rc_send_break(struct riscom_port * port, unsigned long length)
1278{
1279 struct riscom_board *bp = port_Board(port);
1280 unsigned long flags;
1281
1282 save_flags(flags); cli();
1283 port->break_length = RISCOM_TPS / HZ * length;
1284 port->COR2 |= COR2_ETC;
1285 port->IER |= IER_TXRDY;
1286 rc_out(bp, CD180_CAR, port_No(port));
1287 rc_out(bp, CD180_COR2, port->COR2);
1288 rc_out(bp, CD180_IER, port->IER);
1289 rc_wait_CCR(bp);
1290 rc_out(bp, CD180_CCR, CCR_CORCHG2);
1291 rc_wait_CCR(bp);
1292 restore_flags(flags);
1293}
1294
1295static inline int rc_set_serial_info(struct riscom_port * port,
1296 struct serial_struct __user * newinfo)
1297{
1298 struct serial_struct tmp;
1299 struct riscom_board *bp = port_Board(port);
1300 int change_speed;
1301 unsigned long flags;
1302
1303 if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
1304 return -EFAULT;
1305
1306#if 0
1307 if ((tmp.irq != bp->irq) ||
1308 (tmp.port != bp->base) ||
1309 (tmp.type != PORT_CIRRUS) ||
1310 (tmp.baud_base != (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC) ||
1311 (tmp.custom_divisor != 0) ||
1312 (tmp.xmit_fifo_size != CD180_NFIFO) ||
1313 (tmp.flags & ~RISCOM_LEGAL_FLAGS))
1314 return -EINVAL;
1315#endif
1316
1317 change_speed = ((port->flags & ASYNC_SPD_MASK) !=
1318 (tmp.flags & ASYNC_SPD_MASK));
1319
1320 if (!capable(CAP_SYS_ADMIN)) {
1321 if ((tmp.close_delay != port->close_delay) ||
1322 (tmp.closing_wait != port->closing_wait) ||
1323 ((tmp.flags & ~ASYNC_USR_MASK) !=
1324 (port->flags & ~ASYNC_USR_MASK)))
1325 return -EPERM;
1326 port->flags = ((port->flags & ~ASYNC_USR_MASK) |
1327 (tmp.flags & ASYNC_USR_MASK));
1328 } else {
1329 port->flags = ((port->flags & ~ASYNC_FLAGS) |
1330 (tmp.flags & ASYNC_FLAGS));
1331 port->close_delay = tmp.close_delay;
1332 port->closing_wait = tmp.closing_wait;
1333 }
1334 if (change_speed) {
1335 save_flags(flags); cli();
1336 rc_change_speed(bp, port);
1337 restore_flags(flags);
1338 }
1339 return 0;
1340}
1341
1342static inline int rc_get_serial_info(struct riscom_port * port,
1343 struct serial_struct __user *retinfo)
1344{
1345 struct serial_struct tmp;
1346 struct riscom_board *bp = port_Board(port);
1347
1348 memset(&tmp, 0, sizeof(tmp));
1349 tmp.type = PORT_CIRRUS;
1350 tmp.line = port - rc_port;
1351 tmp.port = bp->base;
1352 tmp.irq = bp->irq;
1353 tmp.flags = port->flags;
1354 tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;
1355 tmp.close_delay = port->close_delay * HZ/100;
1356 tmp.closing_wait = port->closing_wait * HZ/100;
1357 tmp.xmit_fifo_size = CD180_NFIFO;
1358 return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
1359}
1360
1361static int rc_ioctl(struct tty_struct * tty, struct file * filp,
1362 unsigned int cmd, unsigned long arg)
1363
1364{
1365 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1366 void __user *argp = (void __user *)arg;
1367 int retval;
1368
1369 if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
1370 return -ENODEV;
1371
1372 switch (cmd) {
1373 case TCSBRK: /* SVID version: non-zero arg --> no break */
1374 retval = tty_check_change(tty);
1375 if (retval)
1376 return retval;
1377 tty_wait_until_sent(tty, 0);
1378 if (!arg)
1379 rc_send_break(port, HZ/4); /* 1/4 second */
1380 break;
1381 case TCSBRKP: /* support for POSIX tcsendbreak() */
1382 retval = tty_check_change(tty);
1383 if (retval)
1384 return retval;
1385 tty_wait_until_sent(tty, 0);
1386 rc_send_break(port, arg ? arg*(HZ/10) : HZ/4);
1387 break;
1388 case TIOCGSOFTCAR:
1389 return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned __user *)argp);
1390 case TIOCSSOFTCAR:
1391 if (get_user(arg,(unsigned __user *) argp))
1392 return -EFAULT;
1393 tty->termios->c_cflag =
1394 ((tty->termios->c_cflag & ~CLOCAL) |
1395 (arg ? CLOCAL : 0));
1396 break;
1397 case TIOCGSERIAL:
1398 return rc_get_serial_info(port, argp);
1399 case TIOCSSERIAL:
1400 return rc_set_serial_info(port, argp);
1401 default:
1402 return -ENOIOCTLCMD;
1403 }
1404 return 0;
1405}
1406
1407static void rc_throttle(struct tty_struct * tty)
1408{
1409 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1410 struct riscom_board *bp;
1411 unsigned long flags;
1412
1413 if (rc_paranoia_check(port, tty->name, "rc_throttle"))
1414 return;
1415
1416 bp = port_Board(port);
1417
1418 save_flags(flags); cli();
1419 port->MSVR &= ~MSVR_RTS;
1420 rc_out(bp, CD180_CAR, port_No(port));
1421 if (I_IXOFF(tty)) {
1422 rc_wait_CCR(bp);
1423 rc_out(bp, CD180_CCR, CCR_SSCH2);
1424 rc_wait_CCR(bp);
1425 }
1426 rc_out(bp, CD180_MSVR, port->MSVR);
1427 restore_flags(flags);
1428}
1429
1430static void rc_unthrottle(struct tty_struct * tty)
1431{
1432 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1433 struct riscom_board *bp;
1434 unsigned long flags;
1435
1436 if (rc_paranoia_check(port, tty->name, "rc_unthrottle"))
1437 return;
1438
1439 bp = port_Board(port);
1440
1441 save_flags(flags); cli();
1442 port->MSVR |= MSVR_RTS;
1443 rc_out(bp, CD180_CAR, port_No(port));
1444 if (I_IXOFF(tty)) {
1445 rc_wait_CCR(bp);
1446 rc_out(bp, CD180_CCR, CCR_SSCH1);
1447 rc_wait_CCR(bp);
1448 }
1449 rc_out(bp, CD180_MSVR, port->MSVR);
1450 restore_flags(flags);
1451}
1452
1453static void rc_stop(struct tty_struct * tty)
1454{
1455 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1456 struct riscom_board *bp;
1457 unsigned long flags;
1458
1459 if (rc_paranoia_check(port, tty->name, "rc_stop"))
1460 return;
1461
1462 bp = port_Board(port);
1463
1464 save_flags(flags); cli();
1465 port->IER &= ~IER_TXRDY;
1466 rc_out(bp, CD180_CAR, port_No(port));
1467 rc_out(bp, CD180_IER, port->IER);
1468 restore_flags(flags);
1469}
1470
1471static void rc_start(struct tty_struct * tty)
1472{
1473 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1474 struct riscom_board *bp;
1475 unsigned long flags;
1476
1477 if (rc_paranoia_check(port, tty->name, "rc_start"))
1478 return;
1479
1480 bp = port_Board(port);
1481
1482 save_flags(flags); cli();
1483 if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
1484 port->IER |= IER_TXRDY;
1485 rc_out(bp, CD180_CAR, port_No(port));
1486 rc_out(bp, CD180_IER, port->IER);
1487 }
1488 restore_flags(flags);
1489}
1490
1491/*
1492 * This routine is called from the work queue when the interrupt
1493 * routine has signalled that a hangup has occurred. The path of
1494 * hangup processing is:
1495 *
1496 * serial interrupt routine -> (workqueue) ->
1497 * do_rc_hangup() -> tty->hangup() -> rc_hangup()
1498 *
1499 */
Al Viro3e577a82006-12-06 18:41:45 +00001500static void do_rc_hangup(struct work_struct *ugly_api)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501{
Al Viro3e577a82006-12-06 18:41:45 +00001502 struct riscom_port *port = container_of(ugly_api, struct riscom_port, tqueue_hangup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 struct tty_struct *tty;
1504
1505 tty = port->tty;
1506 if (tty)
1507 tty_hangup(tty); /* FIXME: module removal race still here */
1508}
1509
1510static void rc_hangup(struct tty_struct * tty)
1511{
1512 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1513 struct riscom_board *bp;
1514
1515 if (rc_paranoia_check(port, tty->name, "rc_hangup"))
1516 return;
1517
1518 bp = port_Board(port);
1519
1520 rc_shutdown_port(bp, port);
1521 port->event = 0;
1522 port->count = 0;
1523 port->flags &= ~ASYNC_NORMAL_ACTIVE;
1524 port->tty = NULL;
1525 wake_up_interruptible(&port->open_wait);
1526}
1527
Alan Cox606d0992006-12-08 02:38:45 -08001528static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529{
1530 struct riscom_port *port = (struct riscom_port *)tty->driver_data;
1531 unsigned long flags;
1532
1533 if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
1534 return;
1535
1536 if (tty->termios->c_cflag == old_termios->c_cflag &&
1537 tty->termios->c_iflag == old_termios->c_iflag)
1538 return;
1539
1540 save_flags(flags); cli();
1541 rc_change_speed(port_Board(port), port);
1542 restore_flags(flags);
1543
1544 if ((old_termios->c_cflag & CRTSCTS) &&
1545 !(tty->termios->c_cflag & CRTSCTS)) {
1546 tty->hw_stopped = 0;
1547 rc_start(tty);
1548 }
1549}
1550
Al Viro3e577a82006-12-06 18:41:45 +00001551static void do_softint(struct work_struct *ugly_api)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552{
Al Viro3e577a82006-12-06 18:41:45 +00001553 struct riscom_port *port = container_of(ugly_api, struct riscom_port, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 struct tty_struct *tty;
1555
1556 if(!(tty = port->tty))
1557 return;
1558
Jiri Slabyb963a842007-02-10 01:44:55 -08001559 if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 tty_wakeup(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561}
1562
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001563static const struct tty_operations riscom_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 .open = rc_open,
1565 .close = rc_close,
1566 .write = rc_write,
1567 .put_char = rc_put_char,
1568 .flush_chars = rc_flush_chars,
1569 .write_room = rc_write_room,
1570 .chars_in_buffer = rc_chars_in_buffer,
1571 .flush_buffer = rc_flush_buffer,
1572 .ioctl = rc_ioctl,
1573 .throttle = rc_throttle,
1574 .unthrottle = rc_unthrottle,
1575 .set_termios = rc_set_termios,
1576 .stop = rc_stop,
1577 .start = rc_start,
1578 .hangup = rc_hangup,
1579 .tiocmget = rc_tiocmget,
1580 .tiocmset = rc_tiocmset,
1581};
1582
1583static inline int rc_init_drivers(void)
1584{
1585 int error;
1586 int i;
1587
1588 riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
1589 if (!riscom_driver)
1590 return -ENOMEM;
1591
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 riscom_driver->owner = THIS_MODULE;
1593 riscom_driver->name = "ttyL";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 riscom_driver->major = RISCOM8_NORMAL_MAJOR;
1595 riscom_driver->type = TTY_DRIVER_TYPE_SERIAL;
1596 riscom_driver->subtype = SERIAL_TYPE_NORMAL;
1597 riscom_driver->init_termios = tty_std_termios;
1598 riscom_driver->init_termios.c_cflag =
1599 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Alan Cox606d0992006-12-08 02:38:45 -08001600 riscom_driver->init_termios.c_ispeed = 9600;
1601 riscom_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 riscom_driver->flags = TTY_DRIVER_REAL_RAW;
1603 tty_set_operations(riscom_driver, &riscom_ops);
1604 if ((error = tty_register_driver(riscom_driver))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 put_tty_driver(riscom_driver);
1606 printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
1607 "error = %d\n",
1608 error);
1609 return 1;
1610 }
1611
1612 memset(rc_port, 0, sizeof(rc_port));
1613 for (i = 0; i < RC_NPORT * RC_NBOARD; i++) {
1614 rc_port[i].magic = RISCOM8_MAGIC;
Al Viro3e577a82006-12-06 18:41:45 +00001615 INIT_WORK(&rc_port[i].tqueue, do_softint);
1616 INIT_WORK(&rc_port[i].tqueue_hangup, do_rc_hangup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 rc_port[i].close_delay = 50 * HZ/100;
1618 rc_port[i].closing_wait = 3000 * HZ/100;
1619 init_waitqueue_head(&rc_port[i].open_wait);
1620 init_waitqueue_head(&rc_port[i].close_wait);
1621 }
1622
1623 return 0;
1624}
1625
1626static void rc_release_drivers(void)
1627{
1628 unsigned long flags;
1629
1630 save_flags(flags);
1631 cli();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 tty_unregister_driver(riscom_driver);
1633 put_tty_driver(riscom_driver);
1634 restore_flags(flags);
1635}
1636
1637#ifndef MODULE
1638/*
1639 * Called at boot time.
1640 *
1641 * You can specify IO base for up to RC_NBOARD cards,
1642 * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
1643 * Note that there will be no probing at default
1644 * addresses in this case.
1645 *
1646 */
1647static int __init riscom8_setup(char *str)
1648{
1649 int ints[RC_NBOARD];
1650 int i;
1651
1652 str = get_options(str, ARRAY_SIZE(ints), ints);
1653
1654 for (i = 0; i < RC_NBOARD; i++) {
1655 if (i < ints[0])
1656 rc_board[i].base = ints[i+1];
1657 else
1658 rc_board[i].base = 0;
1659 }
1660 return 1;
1661}
1662
1663__setup("riscom8=", riscom8_setup);
1664#endif
1665
1666static char banner[] __initdata =
1667 KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin "
1668 "1994-1996.\n";
1669static char no_boards_msg[] __initdata =
1670 KERN_INFO "rc: No RISCom/8 boards detected.\n";
1671
1672/*
1673 * This routine must be called by kernel at boot time
1674 */
1675static int __init riscom8_init(void)
1676{
1677 int i;
1678 int found = 0;
1679
1680 printk(banner);
1681
1682 if (rc_init_drivers())
1683 return -EIO;
1684
1685 for (i = 0; i < RC_NBOARD; i++)
1686 if (rc_board[i].base && !rc_probe(&rc_board[i]))
1687 found++;
1688
1689 if (!found) {
1690 rc_release_drivers();
1691 printk(no_boards_msg);
1692 return -EIO;
1693 }
1694 return 0;
1695}
1696
1697#ifdef MODULE
1698static int iobase;
1699static int iobase1;
1700static int iobase2;
1701static int iobase3;
Rusty Russell8d3b33f2006-03-25 03:07:05 -08001702module_param(iobase, int, 0);
1703module_param(iobase1, int, 0);
1704module_param(iobase2, int, 0);
1705module_param(iobase3, int, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
1707MODULE_LICENSE("GPL");
1708#endif /* MODULE */
1709
1710/*
1711 * You can setup up to 4 boards (current value of RC_NBOARD)
1712 * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
1713 *
1714 */
1715static int __init riscom8_init_module (void)
1716{
1717#ifdef MODULE
1718 int i;
1719
1720 if (iobase || iobase1 || iobase2 || iobase3) {
1721 for(i = 0; i < RC_NBOARD; i++)
1722 rc_board[0].base = 0;
1723 }
1724
1725 if (iobase)
1726 rc_board[0].base = iobase;
1727 if (iobase1)
1728 rc_board[1].base = iobase1;
1729 if (iobase2)
1730 rc_board[2].base = iobase2;
1731 if (iobase3)
1732 rc_board[3].base = iobase3;
1733#endif /* MODULE */
1734
1735 return riscom8_init();
1736}
1737
1738static void __exit riscom8_exit_module (void)
1739{
1740 int i;
1741
1742 rc_release_drivers();
1743 for (i = 0; i < RC_NBOARD; i++)
1744 if (rc_board[i].flags & RC_BOARD_PRESENT)
1745 rc_release_io_range(&rc_board[i]);
1746
1747}
1748
1749module_init(riscom8_init_module);
1750module_exit(riscom8_exit_module);
1751