riscom8: split open and close methods up
[deliverable/linux.git] / drivers / char / riscom8.c
CommitLineData
1da177e4
LT
1/*
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
9492e135
AC
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
1da177e4
LT
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
9492e135 36#include <linux/io.h>
1da177e4
LT
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>
33f0f88f 49#include <linux/tty_flip.h>
405f5571 50#include <linux/smp_lock.h>
d9afa435 51#include <linux/spinlock.h>
5c9f5806 52#include <linux/device.h>
1da177e4 53
9492e135 54#include <linux/uaccess.h>
1da177e4
LT
55
56#include "riscom8.h"
57#include "riscom8_reg.h"
58
59/* Am I paranoid or not ? ;-) */
60#define RISCOM_PARANOIA_CHECK
61
9492e135
AC
62/*
63 * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals.
1da177e4 64 * You can slightly speed up things by #undefing the following option,
9492e135 65 * if you are REALLY sure that your board is correct one.
1da177e4
LT
66 */
67
68#define RISCOM_BRAIN_DAMAGED_CTS
69
9492e135 70/*
1da177e4
LT
71 * The following defines are mostly for testing purposes. But if you need
72 * some nice reporting in your syslog, you can define them also.
73 */
74#undef RC_REPORT_FIFO
75#undef RC_REPORT_OVERRUN
76
77
78#define RISCOM_LEGAL_FLAGS \
79 (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \
80 ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \
81 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
82
1da177e4 83static struct tty_driver *riscom_driver;
1da177e4 84
d9afa435
JG
85static DEFINE_SPINLOCK(riscom_lock);
86
1da177e4
LT
87static struct riscom_board rc_board[RC_NBOARD] = {
88 {
89 .base = RC_IOBASE1,
90 },
91 {
92 .base = RC_IOBASE2,
93 },
94 {
95 .base = RC_IOBASE3,
96 },
97 {
98 .base = RC_IOBASE4,
99 },
100};
101
102static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
103
104/* RISCom/8 I/O ports addresses (without address translation) */
105static unsigned short rc_ioport[] = {
fe971071 106#if 1
1da177e4 107 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
fe971071 108#else
1da177e4
LT
109 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
110 0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
111 0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
fe971071 112#endif
1da177e4 113};
fe971071 114#define RC_NIOPORT ARRAY_SIZE(rc_ioport)
1da177e4
LT
115
116
9492e135 117static int rc_paranoia_check(struct riscom_port const *port,
1da177e4
LT
118 char *name, const char *routine)
119{
120#ifdef RISCOM_PARANOIA_CHECK
121 static const char badmagic[] = KERN_INFO
122 "rc: Warning: bad riscom port magic number for device %s in %s\n";
123 static const char badinfo[] = KERN_INFO
124 "rc: Warning: null riscom port for device %s in %s\n";
125
126 if (!port) {
127 printk(badinfo, name, routine);
128 return 1;
129 }
130 if (port->magic != RISCOM8_MAGIC) {
131 printk(badmagic, name, routine);
132 return 1;
133 }
134#endif
135 return 0;
136}
137
138/*
9492e135 139 *
1da177e4 140 * Service functions for RISCom/8 driver.
9492e135 141 *
1da177e4
LT
142 */
143
144/* Get board number from pointer */
9492e135 145static inline int board_No(struct riscom_board const *bp)
1da177e4
LT
146{
147 return bp - rc_board;
148}
149
150/* Get port number from pointer */
9492e135 151static inline int port_No(struct riscom_port const *port)
1da177e4 152{
9492e135 153 return RC_PORT(port - rc_port);
1da177e4
LT
154}
155
156/* Get pointer to board from pointer to port */
9492e135 157static inline struct riscom_board *port_Board(struct riscom_port const *port)
1da177e4
LT
158{
159 return &rc_board[RC_BOARD(port - rc_port)];
160}
161
162/* Input Byte from CL CD180 register */
9492e135
AC
163static inline unsigned char rc_in(struct riscom_board const *bp,
164 unsigned short reg)
1da177e4
LT
165{
166 return inb(bp->base + RC_TO_ISA(reg));
167}
168
169/* Output Byte to CL CD180 register */
9492e135 170static inline void rc_out(struct riscom_board const *bp, unsigned short reg,
1da177e4
LT
171 unsigned char val)
172{
173 outb(val, bp->base + RC_TO_ISA(reg));
174}
175
176/* Wait for Channel Command Register ready */
9492e135 177static void rc_wait_CCR(struct riscom_board const *bp)
1da177e4
LT
178{
179 unsigned long delay;
180
181 /* FIXME: need something more descriptive then 100000 :) */
9492e135 182 for (delay = 100000; delay; delay--)
1da177e4
LT
183 if (!rc_in(bp, CD180_CCR))
184 return;
9492e135 185
1da177e4
LT
186 printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp));
187}
188
189/*
190 * RISCom/8 probe functions.
191 */
192
9492e135 193static int rc_request_io_range(struct riscom_board * const bp)
1da177e4
LT
194{
195 int i;
9492e135
AC
196
197 for (i = 0; i < RC_NIOPORT; i++)
1da177e4
LT
198 if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1,
199 "RISCom/8")) {
200 goto out_release;
201 }
202 return 0;
203out_release:
204 printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n",
205 board_No(bp), bp->base);
9492e135 206 while (--i >= 0)
1da177e4
LT
207 release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
208 return 1;
209}
210
9492e135 211static void rc_release_io_range(struct riscom_board * const bp)
1da177e4
LT
212{
213 int i;
9492e135
AC
214
215 for (i = 0; i < RC_NIOPORT; i++)
1da177e4
LT
216 release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
217}
9492e135 218
1da177e4 219/* Reset and setup CD180 chip */
9492e135 220static void __init rc_init_CD180(struct riscom_board const *bp)
1da177e4
LT
221{
222 unsigned long flags;
9492e135 223
d9afa435
JG
224 spin_lock_irqsave(&riscom_lock, flags);
225
9492e135
AC
226 rc_out(bp, RC_CTOUT, 0); /* Clear timeout */
227 rc_wait_CCR(bp); /* Wait for CCR ready */
228 rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */
d9afa435 229 spin_unlock_irqrestore(&riscom_lock, flags);
9492e135 230 msleep(50); /* Delay 0.05 sec */
d9afa435 231 spin_lock_irqsave(&riscom_lock, flags);
9492e135
AC
232 rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */
233 rc_out(bp, CD180_GICR, 0); /* Clear all bits */
234 rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */
235 rc_out(bp, CD180_PILR2, RC_ACK_TINT); /* Prio for tx intr */
236 rc_out(bp, CD180_PILR3, RC_ACK_RINT); /* Prio for rx intr */
237
1da177e4
LT
238 /* Setting up prescaler. We need 4 ticks per 1 ms */
239 rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
240 rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
9492e135 241
d9afa435 242 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
243}
244
245/* Main probing routine, also sets irq. */
246static int __init rc_probe(struct riscom_board *bp)
247{
248 unsigned char val1, val2;
249 int irqs = 0;
250 int retries;
9492e135 251
1da177e4
LT
252 bp->irq = 0;
253
254 if (rc_request_io_range(bp))
255 return 1;
9492e135 256
1da177e4
LT
257 /* Are the I/O ports here ? */
258 rc_out(bp, CD180_PPRL, 0x5a);
259 outb(0xff, 0x80);
260 val1 = rc_in(bp, CD180_PPRL);
261 rc_out(bp, CD180_PPRL, 0xa5);
262 outb(0x00, 0x80);
263 val2 = rc_in(bp, CD180_PPRL);
9492e135 264
1da177e4
LT
265 if ((val1 != 0x5a) || (val2 != 0xa5)) {
266 printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n",
267 board_No(bp), bp->base);
268 goto out_release;
269 }
9492e135 270
1da177e4 271 /* It's time to find IRQ for this board */
9492e135 272 for (retries = 0; retries < 5 && irqs <= 0; retries++) {
1da177e4 273 irqs = probe_irq_on();
9492e135
AC
274 rc_init_CD180(bp); /* Reset CD180 chip */
275 rc_out(bp, CD180_CAR, 2); /* Select port 2 */
1da177e4 276 rc_wait_CCR(bp);
9492e135
AC
277 rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter */
278 rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr */
c4ebd927 279 msleep(50);
1da177e4 280 irqs = probe_irq_off(irqs);
9492e135
AC
281 val1 = rc_in(bp, RC_BSR); /* Get Board Status reg */
282 val2 = rc_in(bp, RC_ACK_TINT); /* ACK interrupt */
283 rc_init_CD180(bp); /* Reset CD180 again */
284
1da177e4
LT
285 if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX))) {
286 printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not "
287 "found.\n", board_No(bp), bp->base);
288 goto out_release;
289 }
290 }
9492e135 291
1da177e4
LT
292 if (irqs <= 0) {
293 printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board "
294 "at 0x%03x.\n", board_No(bp), bp->base);
295 goto out_release;
296 }
297 bp->irq = irqs;
298 bp->flags |= RC_BOARD_PRESENT;
9492e135 299
1da177e4
LT
300 printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at "
301 "0x%03x, IRQ %d.\n",
302 board_No(bp),
303 (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A', /* Board revision */
304 bp->base, bp->irq);
9492e135 305
1da177e4
LT
306 return 0;
307out_release:
308 rc_release_io_range(bp);
309 return 1;
310}
311
9492e135
AC
312/*
313 *
1da177e4 314 * Interrupt processing routines.
9492e135 315 *
1da177e4
LT
316 */
317
9492e135
AC
318static struct riscom_port *rc_get_port(struct riscom_board const *bp,
319 unsigned char const *what)
1da177e4
LT
320{
321 unsigned char channel;
9492e135
AC
322 struct riscom_port *port;
323
1da177e4
LT
324 channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF;
325 if (channel < CD180_NCH) {
326 port = &rc_port[board_No(bp) * RC_NPORT + channel];
85f8f810 327 if (port->port.flags & ASYNC_INITIALIZED)
1da177e4 328 return port;
1da177e4 329 }
9492e135 330 printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
1da177e4
LT
331 board_No(bp), what, channel);
332 return NULL;
333}
334
9492e135 335static void rc_receive_exc(struct riscom_board const *bp)
1da177e4
LT
336{
337 struct riscom_port *port;
338 struct tty_struct *tty;
339 unsigned char status;
33f0f88f 340 unsigned char ch, flag;
9492e135
AC
341
342 port = rc_get_port(bp, "Receive");
343 if (port == NULL)
1da177e4
LT
344 return;
345
85f8f810 346 tty = port->port.tty;
9492e135
AC
347
348#ifdef RC_REPORT_OVERRUN
1da177e4 349 status = rc_in(bp, CD180_RCSR);
33f0f88f 350 if (status & RCSR_OE)
1da177e4 351 port->overrun++;
1da177e4 352 status &= port->mark_mask;
9492e135 353#else
1da177e4 354 status = rc_in(bp, CD180_RCSR) & port->mark_mask;
9492e135 355#endif
1da177e4 356 ch = rc_in(bp, CD180_RDR);
9492e135 357 if (!status)
1da177e4 358 return;
1da177e4
LT
359 if (status & RCSR_TOUT) {
360 printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
9492e135 361 "Hardware problems ?\n",
1da177e4
LT
362 board_No(bp), port_No(port));
363 return;
9492e135 364
1da177e4
LT
365 } else if (status & RCSR_BREAK) {
366 printk(KERN_INFO "rc%d: port %d: Handling break...\n",
367 board_No(bp), port_No(port));
33f0f88f 368 flag = TTY_BREAK;
85f8f810 369 if (port->port.flags & ASYNC_SAK)
1da177e4 370 do_SAK(tty);
9492e135
AC
371
372 } else if (status & RCSR_PE)
33f0f88f 373 flag = TTY_PARITY;
9492e135
AC
374
375 else if (status & RCSR_FE)
33f0f88f 376 flag = TTY_FRAME;
9492e135
AC
377
378 else if (status & RCSR_OE)
33f0f88f 379 flag = TTY_OVERRUN;
1da177e4 380 else
33f0f88f 381 flag = TTY_NORMAL;
9492e135 382
33f0f88f
AC
383 tty_insert_flip_char(tty, ch, flag);
384 tty_flip_buffer_push(tty);
1da177e4
LT
385}
386
9492e135 387static void rc_receive(struct riscom_board const *bp)
1da177e4
LT
388{
389 struct riscom_port *port;
390 struct tty_struct *tty;
391 unsigned char count;
9492e135
AC
392
393 port = rc_get_port(bp, "Receive");
394 if (port == NULL)
1da177e4 395 return;
9492e135 396
85f8f810 397 tty = port->port.tty;
9492e135 398
1da177e4 399 count = rc_in(bp, CD180_RDCR);
9492e135 400
1da177e4
LT
401#ifdef RC_REPORT_FIFO
402 port->hits[count > 8 ? 9 : count]++;
9492e135
AC
403#endif
404
1da177e4 405 while (count--) {
33f0f88f 406 if (tty_buffer_request_room(tty, 1) == 0) {
1da177e4
LT
407 printk(KERN_WARNING "rc%d: port %d: Working around "
408 "flip buffer overflow.\n",
409 board_No(bp), port_No(port));
410 break;
411 }
33f0f88f 412 tty_insert_flip_char(tty, rc_in(bp, CD180_RDR), TTY_NORMAL);
1da177e4 413 }
33f0f88f 414 tty_flip_buffer_push(tty);
1da177e4
LT
415}
416
9492e135 417static void rc_transmit(struct riscom_board const *bp)
1da177e4
LT
418{
419 struct riscom_port *port;
420 struct tty_struct *tty;
421 unsigned char count;
9492e135
AC
422
423 port = rc_get_port(bp, "Transmit");
424 if (port == NULL)
1da177e4 425 return;
9492e135 426
85f8f810 427 tty = port->port.tty;
9492e135
AC
428
429 if (port->IER & IER_TXEMPTY) {
1da177e4
LT
430 /* FIFO drained */
431 rc_out(bp, CD180_CAR, port_No(port));
432 port->IER &= ~IER_TXEMPTY;
433 rc_out(bp, CD180_IER, port->IER);
434 return;
435 }
9492e135 436
1da177e4
LT
437 if ((port->xmit_cnt <= 0 && !port->break_length)
438 || tty->stopped || tty->hw_stopped) {
439 rc_out(bp, CD180_CAR, port_No(port));
440 port->IER &= ~IER_TXRDY;
441 rc_out(bp, CD180_IER, port->IER);
442 return;
443 }
9492e135 444
1da177e4
LT
445 if (port->break_length) {
446 if (port->break_length > 0) {
447 if (port->COR2 & COR2_ETC) {
448 rc_out(bp, CD180_TDR, CD180_C_ESC);
449 rc_out(bp, CD180_TDR, CD180_C_SBRK);
450 port->COR2 &= ~COR2_ETC;
451 }
452 count = min_t(int, port->break_length, 0xff);
453 rc_out(bp, CD180_TDR, CD180_C_ESC);
454 rc_out(bp, CD180_TDR, CD180_C_DELAY);
455 rc_out(bp, CD180_TDR, count);
9492e135
AC
456 port->break_length -= count;
457 if (port->break_length == 0)
1da177e4
LT
458 port->break_length--;
459 } else {
460 rc_out(bp, CD180_TDR, CD180_C_ESC);
461 rc_out(bp, CD180_TDR, CD180_C_EBRK);
462 rc_out(bp, CD180_COR2, port->COR2);
463 rc_wait_CCR(bp);
464 rc_out(bp, CD180_CCR, CCR_CORCHG2);
465 port->break_length = 0;
466 }
467 return;
468 }
9492e135 469
1da177e4
LT
470 count = CD180_NFIFO;
471 do {
85f8f810 472 rc_out(bp, CD180_TDR, port->port.xmit_buf[port->xmit_tail++]);
1da177e4
LT
473 port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
474 if (--port->xmit_cnt <= 0)
475 break;
476 } while (--count > 0);
9492e135 477
1da177e4
LT
478 if (port->xmit_cnt <= 0) {
479 rc_out(bp, CD180_CAR, port_No(port));
480 port->IER &= ~IER_TXRDY;
481 rc_out(bp, CD180_IER, port->IER);
482 }
483 if (port->xmit_cnt <= port->wakeup_chars)
b98e70de 484 tty_wakeup(tty);
1da177e4
LT
485}
486
9492e135 487static void rc_check_modem(struct riscom_board const *bp)
1da177e4
LT
488{
489 struct riscom_port *port;
490 struct tty_struct *tty;
491 unsigned char mcr;
9492e135
AC
492
493 port = rc_get_port(bp, "Modem");
494 if (port == NULL)
1da177e4 495 return;
9492e135 496
85f8f810 497 tty = port->port.tty;
9492e135 498
1da177e4 499 mcr = rc_in(bp, CD180_MCR);
9492e135
AC
500 if (mcr & MCR_CDCHG) {
501 if (rc_in(bp, CD180_MSVR) & MSVR_CD)
85f8f810 502 wake_up_interruptible(&port->port.open_wait);
1da177e4 503 else
b98e70de 504 tty_hangup(tty);
1da177e4 505 }
9492e135 506
1da177e4
LT
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)
b98e70de 513 tty_wakeup(tty);
1da177e4
LT
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)
b98e70de 525 tty_wakeup(tty);
1da177e4
LT
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 */
9492e135 533
1da177e4
LT
534 /* Clear change bits */
535 rc_out(bp, CD180_MCR, 0);
536}
537
538/* The main interrupt processing routine */
9492e135 539static irqreturn_t rc_interrupt(int dummy, void *dev_id)
1da177e4
LT
540{
541 unsigned char status;
542 unsigned char ack;
f07ef395 543 struct riscom_board *bp = dev_id;
1da177e4
LT
544 unsigned long loop = 0;
545 int handled = 0;
546
c7bec5ab 547 if (!(bp->flags & RC_BOARD_ACTIVE))
1da177e4 548 return IRQ_NONE;
c7bec5ab 549
1da177e4
LT
550 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;
9492e135 554 if (status & RC_BSR_TOUT)
1da177e4
LT
555 printk(KERN_WARNING "rc%d: Got timeout. Hardware "
556 "error?\n", board_No(bp));
1da177e4
LT
557 else if (status & RC_BSR_RINT) {
558 ack = rc_in(bp, RC_ACK_RINT);
1da177e4
LT
559 if (ack == (RC_ID | GIVR_IT_RCV))
560 rc_receive(bp);
561 else if (ack == (RC_ID | GIVR_IT_REXC))
562 rc_receive_exc(bp);
563 else
564 printk(KERN_WARNING "rc%d: Bad receive ack "
565 "0x%02x.\n",
566 board_No(bp), ack);
1da177e4
LT
567 } else if (status & RC_BSR_TINT) {
568 ack = rc_in(bp, RC_ACK_TINT);
1da177e4
LT
569 if (ack == (RC_ID | GIVR_IT_TX))
570 rc_transmit(bp);
571 else
572 printk(KERN_WARNING "rc%d: Bad transmit ack "
573 "0x%02x.\n",
574 board_No(bp), ack);
1da177e4
LT
575 } else /* if (status & RC_BSR_MINT) */ {
576 ack = rc_in(bp, RC_ACK_MINT);
9492e135 577 if (ack == (RC_ID | GIVR_IT_MODEM))
1da177e4
LT
578 rc_check_modem(bp);
579 else
580 printk(KERN_WARNING "rc%d: Bad modem ack "
581 "0x%02x.\n",
582 board_No(bp), ack);
9492e135 583 }
1da177e4
LT
584 rc_out(bp, CD180_EOIR, 0); /* Mark end of interrupt */
585 rc_out(bp, RC_CTOUT, 0); /* Clear timeout flag */
586 }
587 return IRQ_RETVAL(handled);
588}
589
590/*
591 * Routines for open & close processing.
592 */
593
594/* Called with disabled interrupts */
9492e135 595static int rc_setup_board(struct riscom_board *bp)
1da177e4
LT
596{
597 int error;
598
9492e135 599 if (bp->flags & RC_BOARD_ACTIVE)
1da177e4 600 return 0;
9492e135 601
0f2ed4c6 602 error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
f07ef395 603 "RISCom/8", bp);
9492e135 604 if (error)
1da177e4 605 return error;
9492e135 606
1da177e4
LT
607 rc_out(bp, RC_CTOUT, 0); /* Just in case */
608 bp->DTR = ~0;
609 rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
9492e135 610
1da177e4 611 bp->flags |= RC_BOARD_ACTIVE;
9492e135 612
1da177e4
LT
613 return 0;
614}
615
616/* Called with disabled interrupts */
f07ef395 617static void rc_shutdown_board(struct riscom_board *bp)
1da177e4
LT
618{
619 if (!(bp->flags & RC_BOARD_ACTIVE))
620 return;
9492e135 621
1da177e4 622 bp->flags &= ~RC_BOARD_ACTIVE;
9492e135 623
1da177e4 624 free_irq(bp->irq, NULL);
9492e135 625
1da177e4
LT
626 bp->DTR = ~0;
627 rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */
9492e135 628
1da177e4
LT
629}
630
631/*
9492e135 632 * Setting up port characteristics.
1da177e4
LT
633 * Must be called with disabled interrupts
634 */
635static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
636{
85f8f810 637 struct tty_struct *tty = port->port.tty;
1da177e4
LT
638 unsigned long baud;
639 long tmp;
640 unsigned char cor1 = 0, cor3 = 0;
641 unsigned char mcor1 = 0, mcor2 = 0;
9492e135 642
1da177e4
LT
643 port->IER = 0;
644 port->COR2 = 0;
645 port->MSVR = MSVR_RTS;
9492e135 646
c7bce309 647 baud = tty_get_baud_rate(tty);
9492e135 648
1da177e4
LT
649 /* Select port on the board */
650 rc_out(bp, CD180_CAR, port_No(port));
9492e135 651
c7bce309 652 if (!baud) {
1da177e4
LT
653 /* Drop DTR & exit */
654 bp->DTR |= (1u << port_No(port));
655 rc_out(bp, RC_DTR, bp->DTR);
656 return;
657 } else {
658 /* Set DTR on */
659 bp->DTR &= ~(1u << port_No(port));
660 rc_out(bp, RC_DTR, bp->DTR);
661 }
9492e135 662
1da177e4 663 /*
9492e135 664 * Now we must calculate some speed depended things
1da177e4 665 */
9492e135 666
1da177e4 667 /* Set baud rate for port */
c7bce309 668 tmp = (((RC_OSCFREQ + baud/2) / baud +
1da177e4
LT
669 CD180_TPC/2) / CD180_TPC);
670
9492e135
AC
671 rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
672 rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
673 rc_out(bp, CD180_RBPRL, tmp & 0xff);
1da177e4 674 rc_out(bp, CD180_TBPRL, tmp & 0xff);
9492e135 675
c7bce309 676 baud = (baud + 5) / 10; /* Estimated CPS */
9492e135 677
1da177e4 678 /* Two timer ticks seems enough to wakeup something like SLIP driver */
9492e135 679 tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
1da177e4
LT
680 port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
681 SERIAL_XMIT_SIZE - 1 : tmp);
9492e135 682
1da177e4
LT
683 /* Receiver timeout will be transmission time for 1.5 chars */
684 tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;
685 tmp = (tmp > 0xff) ? 0xff : tmp;
686 rc_out(bp, CD180_RTPR, tmp);
9492e135
AC
687
688 switch (C_CSIZE(tty)) {
689 case CS5:
1da177e4
LT
690 cor1 |= COR1_5BITS;
691 break;
9492e135 692 case CS6:
1da177e4
LT
693 cor1 |= COR1_6BITS;
694 break;
9492e135 695 case CS7:
1da177e4
LT
696 cor1 |= COR1_7BITS;
697 break;
9492e135 698 case CS8:
1da177e4
LT
699 cor1 |= COR1_8BITS;
700 break;
701 }
9492e135 702 if (C_CSTOPB(tty))
1da177e4 703 cor1 |= COR1_2SB;
9492e135 704
1da177e4 705 cor1 |= COR1_IGNORE;
9492e135 706 if (C_PARENB(tty)) {
1da177e4 707 cor1 |= COR1_NORMPAR;
9492e135 708 if (C_PARODD(tty))
1da177e4 709 cor1 |= COR1_ODDP;
9492e135 710 if (I_INPCK(tty))
1da177e4
LT
711 cor1 &= ~COR1_IGNORE;
712 }
713 /* Set marking of some errors */
714 port->mark_mask = RCSR_OE | RCSR_TOUT;
9492e135 715 if (I_INPCK(tty))
1da177e4 716 port->mark_mask |= RCSR_FE | RCSR_PE;
9492e135 717 if (I_BRKINT(tty) || I_PARMRK(tty))
1da177e4 718 port->mark_mask |= RCSR_BREAK;
9492e135 719 if (I_IGNPAR(tty))
1da177e4 720 port->mark_mask &= ~(RCSR_FE | RCSR_PE);
9492e135 721 if (I_IGNBRK(tty)) {
1da177e4 722 port->mark_mask &= ~RCSR_BREAK;
9492e135 723 if (I_IGNPAR(tty))
1da177e4
LT
724 /* Real raw mode. Ignore all */
725 port->mark_mask &= ~RCSR_OE;
726 }
727 /* Enable Hardware Flow Control */
728 if (C_CRTSCTS(tty)) {
729#ifdef RISCOM_BRAIN_DAMAGED_CTS
730 port->IER |= IER_DSR | IER_CTS;
731 mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
732 mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
9492e135
AC
733 tty->hw_stopped = !(rc_in(bp, CD180_MSVR) &
734 (MSVR_CTS|MSVR_DSR));
1da177e4
LT
735#else
736 port->COR2 |= COR2_CTSAE;
737#endif
738 }
739 /* Enable Software Flow Control. FIXME: I'm not sure about this */
740 /* Some people reported that it works, but I still doubt */
741 if (I_IXON(tty)) {
742 port->COR2 |= COR2_TXIBE;
743 cor3 |= (COR3_FCT | COR3_SCDE);
744 if (I_IXANY(tty))
745 port->COR2 |= COR2_IXM;
746 rc_out(bp, CD180_SCHR1, START_CHAR(tty));
747 rc_out(bp, CD180_SCHR2, STOP_CHAR(tty));
748 rc_out(bp, CD180_SCHR3, START_CHAR(tty));
749 rc_out(bp, CD180_SCHR4, STOP_CHAR(tty));
750 }
751 if (!C_CLOCAL(tty)) {
752 /* Enable CD check */
753 port->IER |= IER_CD;
754 mcor1 |= MCOR1_CDZD;
755 mcor2 |= MCOR2_CDOD;
756 }
9492e135
AC
757
758 if (C_CREAD(tty))
1da177e4
LT
759 /* Enable receiver */
760 port->IER |= IER_RXD;
9492e135 761
1da177e4 762 /* Set input FIFO size (1-8 bytes) */
9492e135 763 cor3 |= RISCOM_RXFIFO;
1da177e4
LT
764 /* Setting up CD180 channel registers */
765 rc_out(bp, CD180_COR1, cor1);
766 rc_out(bp, CD180_COR2, port->COR2);
767 rc_out(bp, CD180_COR3, cor3);
768 /* Make CD180 know about registers change */
769 rc_wait_CCR(bp);
770 rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
771 /* Setting up modem option registers */
772 rc_out(bp, CD180_MCOR1, mcor1);
773 rc_out(bp, CD180_MCOR2, mcor2);
774 /* Enable CD180 transmitter & receiver */
775 rc_wait_CCR(bp);
776 rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN);
777 /* Enable interrupts */
778 rc_out(bp, CD180_IER, port->IER);
779 /* And finally set RTS on */
780 rc_out(bp, CD180_MSVR, port->MSVR);
781}
782
783/* Must be called with interrupts enabled */
784static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
785{
786 unsigned long flags;
9492e135 787
85f8f810 788 if (port->port.flags & ASYNC_INITIALIZED)
1da177e4 789 return 0;
9492e135 790
85f8f810
AC
791 if (tty_port_alloc_xmit_buf(&port->port) < 0)
792 return -ENOMEM;
793
d9afa435
JG
794 spin_lock_irqsave(&riscom_lock, flags);
795
d99101fd 796 clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
85f8f810 797 if (port->port.count == 1)
1da177e4 798 bp->count++;
1da177e4
LT
799 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
800 rc_change_speed(bp, port);
85f8f810 801 port->port.flags |= ASYNC_INITIALIZED;
9492e135 802
d9afa435 803 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
804 return 0;
805}
806
807/* Must be called with interrupts disabled */
d99101fd
AC
808static void rc_shutdown_port(struct tty_struct *tty,
809 struct riscom_board *bp, struct riscom_port *port)
1da177e4 810{
85f8f810 811 if (!(port->port.flags & ASYNC_INITIALIZED))
1da177e4 812 return;
9492e135 813
1da177e4
LT
814#ifdef RC_REPORT_OVERRUN
815 printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
816 board_No(bp), port_No(port), port->overrun);
9492e135 817#endif
1da177e4
LT
818#ifdef RC_REPORT_FIFO
819 {
820 int i;
9492e135 821
1da177e4
LT
822 printk(KERN_INFO "rc%d: port %d: FIFO hits [ ",
823 board_No(bp), port_No(port));
9492e135 824 for (i = 0; i < 10; i++)
1da177e4 825 printk("%ld ", port->hits[i]);
1da177e4
LT
826 printk("].\n");
827 }
9492e135 828#endif
85f8f810 829 tty_port_free_xmit_buf(&port->port);
d99101fd 830 if (C_HUPCL(tty)) {
1da177e4
LT
831 /* Drop DTR */
832 bp->DTR |= (1u << port_No(port));
833 rc_out(bp, RC_DTR, bp->DTR);
834 }
9492e135
AC
835
836 /* Select port */
1da177e4
LT
837 rc_out(bp, CD180_CAR, port_No(port));
838 /* Reset port */
839 rc_wait_CCR(bp);
840 rc_out(bp, CD180_CCR, CCR_SOFTRESET);
841 /* Disable all interrupts from this port */
842 port->IER = 0;
843 rc_out(bp, CD180_IER, port->IER);
9492e135 844
d99101fd 845 set_bit(TTY_IO_ERROR, &tty->flags);
85f8f810 846 port->port.flags &= ~ASYNC_INITIALIZED;
9492e135 847
1da177e4
LT
848 if (--bp->count < 0) {
849 printk(KERN_INFO "rc%d: rc_shutdown_port: "
850 "bad board count: %d\n",
851 board_No(bp), bp->count);
852 bp->count = 0;
853 }
1da177e4
LT
854 /*
855 * If this is the last opened port on the board
856 * shutdown whole board
857 */
9492e135 858 if (!bp->count)
1da177e4
LT
859 rc_shutdown_board(bp);
860}
861
31f35939
AC
862static int carrier_raised(struct tty_port *port)
863{
864 struct riscom_port *p = container_of(port, struct riscom_port, port);
865 struct riscom_board *bp = port_Board(p);
866 unsigned long flags;
867 int CD;
868
869 spin_lock_irqsave(&riscom_lock, flags);
870 rc_out(bp, CD180_CAR, port_No(p));
871 CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
872 rc_out(bp, CD180_MSVR, MSVR_RTS);
873 bp->DTR &= ~(1u << port_No(p));
874 rc_out(bp, RC_DTR, bp->DTR);
875 spin_unlock_irqrestore(&riscom_lock, flags);
876 return CD;
877}
878
9492e135 879static int rc_open(struct tty_struct *tty, struct file *filp)
1da177e4
LT
880{
881 int board;
882 int error;
9492e135
AC
883 struct riscom_port *port;
884 struct riscom_board *bp;
885
1da177e4
LT
886 board = RC_BOARD(tty->index);
887 if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
888 return -ENODEV;
9492e135 889
1da177e4
LT
890 bp = &rc_board[board];
891 port = rc_port + board * RC_NPORT + RC_PORT(tty->index);
892 if (rc_paranoia_check(port, tty->name, "rc_open"))
893 return -ENODEV;
9492e135
AC
894
895 error = rc_setup_board(bp);
896 if (error)
1da177e4 897 return error;
9492e135 898
85f8f810 899 port->port.count++;
1da177e4 900 tty->driver_data = port;
85f8f810 901 port->port.tty = tty;
9492e135
AC
902
903 error = rc_setup_port(bp, port);
904 if (error == 0)
36c621d8 905 error = tty_port_block_til_ready(&port->port, tty, filp);
9492e135 906 return error;
1da177e4
LT
907}
908
978e595f
AC
909static void rc_flush_buffer(struct tty_struct *tty)
910{
c9f19e96 911 struct riscom_port *port = tty->driver_data;
978e595f
AC
912 unsigned long flags;
913
914 if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
915 return;
916
917 spin_lock_irqsave(&riscom_lock, flags);
978e595f 918 port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
978e595f
AC
919 spin_unlock_irqrestore(&riscom_lock, flags);
920
921 tty_wakeup(tty);
922}
923
c1469425 924static void rc_close_port(struct tty_struct *tty, struct tty_port *port)
1da177e4 925{
1da177e4 926 unsigned long flags;
c1469425
AC
927 struct riscom_port *rp = container_of(port, struct riscom_port, port);
928 struct riscom_board *bp = port_Board(rp);
1da177e4 929 unsigned long timeout;
a6614999 930
1da177e4
LT
931 /*
932 * At this point we stop accepting input. To do this, we
933 * disable the receive line status interrupts, and tell the
934 * interrupt driver to stop checking the data ready bit in the
935 * line status register.
936 */
c2ba38cd
AC
937
938 spin_lock_irqsave(&riscom_lock, flags);
c1469425
AC
939 rp->IER &= ~IER_RXD;
940 if (port->flags & ASYNC_INITIALIZED) {
941 rp->IER &= ~IER_TXRDY;
942 rp->IER |= IER_TXEMPTY;
943 rc_out(bp, CD180_CAR, port_No(rp));
944 rc_out(bp, CD180_IER, rp->IER);
1da177e4
LT
945 /*
946 * Before we drop DTR, make sure the UART transmitter
947 * has completely drained; this is especially
948 * important if there is a transmit FIFO!
949 */
9492e135 950 timeout = jiffies + HZ;
c1469425 951 while (rp->IER & IER_TXEMPTY) {
c2ba38cd 952 spin_unlock_irqrestore(&riscom_lock, flags);
c1469425 953 msleep_interruptible(jiffies_to_msecs(rp->timeout));
c2ba38cd 954 spin_lock_irqsave(&riscom_lock, flags);
1da177e4
LT
955 if (time_after(jiffies, timeout))
956 break;
957 }
958 }
c1469425 959 rc_shutdown_port(tty, bp, rp);
c2ba38cd 960 spin_unlock_irqrestore(&riscom_lock, flags);
c1469425
AC
961}
962
963static void rc_close(struct tty_struct *tty, struct file *filp)
964{
965 struct riscom_port *port = tty->driver_data;
966
967 if (!port || rc_paranoia_check(port, tty->name, "close"))
968 return;
969
970 if (tty_port_close_start(&port->port, tty, filp) == 0)
971 return;
972
973 rc_close_port(tty, &port->port);
974 rc_flush_buffer(tty);
d9afa435 975
a6614999 976 tty_port_close_end(&port->port, tty);
1da177e4
LT
977}
978
9492e135 979static int rc_write(struct tty_struct *tty,
1da177e4
LT
980 const unsigned char *buf, int count)
981{
c9f19e96 982 struct riscom_port *port = tty->driver_data;
1da177e4
LT
983 struct riscom_board *bp;
984 int c, total = 0;
985 unsigned long flags;
9492e135 986
1da177e4
LT
987 if (rc_paranoia_check(port, tty->name, "rc_write"))
988 return 0;
9492e135 989
1da177e4
LT
990 bp = port_Board(port);
991
1da177e4 992 while (1) {
d9afa435
JG
993 spin_lock_irqsave(&riscom_lock, flags);
994
1da177e4
LT
995 c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
996 SERIAL_XMIT_SIZE - port->xmit_head));
d9afa435
JG
997 if (c <= 0)
998 break; /* lock continues to be held */
1da177e4 999
85f8f810 1000 memcpy(port->port.xmit_buf + port->xmit_head, buf, c);
1da177e4
LT
1001 port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1002 port->xmit_cnt += c;
d9afa435
JG
1003
1004 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1005
1006 buf += c;
1007 count -= c;
1008 total += c;
1009 }
1010
1da177e4
LT
1011 if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
1012 !(port->IER & IER_TXRDY)) {
1013 port->IER |= IER_TXRDY;
1014 rc_out(bp, CD180_CAR, port_No(port));
1015 rc_out(bp, CD180_IER, port->IER);
1016 }
d9afa435
JG
1017
1018 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1019
1020 return total;
1021}
1022
9492e135 1023static int rc_put_char(struct tty_struct *tty, unsigned char ch)
1da177e4 1024{
c9f19e96 1025 struct riscom_port *port = tty->driver_data;
1da177e4 1026 unsigned long flags;
bbbbb96f 1027 int ret = 0;
1da177e4
LT
1028
1029 if (rc_paranoia_check(port, tty->name, "rc_put_char"))
bbbbb96f 1030 return 0;
1da177e4 1031
d9afa435 1032 spin_lock_irqsave(&riscom_lock, flags);
9492e135 1033
1da177e4
LT
1034 if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
1035 goto out;
1036
85f8f810 1037 port->port.xmit_buf[port->xmit_head++] = ch;
1da177e4
LT
1038 port->xmit_head &= SERIAL_XMIT_SIZE - 1;
1039 port->xmit_cnt++;
bbbbb96f 1040 ret = 1;
d9afa435
JG
1041
1042out:
1043 spin_unlock_irqrestore(&riscom_lock, flags);
bbbbb96f 1044 return ret;
1da177e4
LT
1045}
1046
9492e135 1047static void rc_flush_chars(struct tty_struct *tty)
1da177e4 1048{
c9f19e96 1049 struct riscom_port *port = tty->driver_data;
1da177e4 1050 unsigned long flags;
9492e135 1051
1da177e4
LT
1052 if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
1053 return;
9492e135 1054
d99101fd 1055 if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped)
1da177e4
LT
1056 return;
1057
d9afa435
JG
1058 spin_lock_irqsave(&riscom_lock, flags);
1059
1da177e4
LT
1060 port->IER |= IER_TXRDY;
1061 rc_out(port_Board(port), CD180_CAR, port_No(port));
1062 rc_out(port_Board(port), CD180_IER, port->IER);
d9afa435
JG
1063
1064 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1065}
1066
9492e135 1067static int rc_write_room(struct tty_struct *tty)
1da177e4 1068{
c9f19e96 1069 struct riscom_port *port = tty->driver_data;
1da177e4 1070 int ret;
9492e135 1071
1da177e4
LT
1072 if (rc_paranoia_check(port, tty->name, "rc_write_room"))
1073 return 0;
1074
1075 ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
1076 if (ret < 0)
1077 ret = 0;
1078 return ret;
1079}
1080
1081static int rc_chars_in_buffer(struct tty_struct *tty)
1082{
c9f19e96 1083 struct riscom_port *port = tty->driver_data;
9492e135 1084
1da177e4
LT
1085 if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
1086 return 0;
9492e135 1087
1da177e4
LT
1088 return port->xmit_cnt;
1089}
1090
1da177e4
LT
1091static int rc_tiocmget(struct tty_struct *tty, struct file *file)
1092{
c9f19e96 1093 struct riscom_port *port = tty->driver_data;
9492e135 1094 struct riscom_board *bp;
1da177e4
LT
1095 unsigned char status;
1096 unsigned int result;
1097 unsigned long flags;
1098
bf9d8929 1099 if (rc_paranoia_check(port, tty->name, __func__))
1da177e4
LT
1100 return -ENODEV;
1101
1102 bp = port_Board(port);
d9afa435
JG
1103
1104 spin_lock_irqsave(&riscom_lock, flags);
1105
1da177e4
LT
1106 rc_out(bp, CD180_CAR, port_No(port));
1107 status = rc_in(bp, CD180_MSVR);
1108 result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
d9afa435
JG
1109
1110 spin_unlock_irqrestore(&riscom_lock, flags);
1111
1da177e4
LT
1112 result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0)
1113 | ((status & MSVR_DTR) ? TIOCM_DTR : 0)
1114 | ((status & MSVR_CD) ? TIOCM_CAR : 0)
1115 | ((status & MSVR_DSR) ? TIOCM_DSR : 0)
1116 | ((status & MSVR_CTS) ? TIOCM_CTS : 0);
1117 return result;
1118}
1119
1120static int rc_tiocmset(struct tty_struct *tty, struct file *file,
1121 unsigned int set, unsigned int clear)
1122{
c9f19e96 1123 struct riscom_port *port = tty->driver_data;
1da177e4
LT
1124 unsigned long flags;
1125 struct riscom_board *bp;
1126
bf9d8929 1127 if (rc_paranoia_check(port, tty->name, __func__))
1da177e4
LT
1128 return -ENODEV;
1129
1130 bp = port_Board(port);
1131
d9afa435
JG
1132 spin_lock_irqsave(&riscom_lock, flags);
1133
1da177e4
LT
1134 if (set & TIOCM_RTS)
1135 port->MSVR |= MSVR_RTS;
1136 if (set & TIOCM_DTR)
1137 bp->DTR &= ~(1u << port_No(port));
1138
1139 if (clear & TIOCM_RTS)
1140 port->MSVR &= ~MSVR_RTS;
1141 if (clear & TIOCM_DTR)
1142 bp->DTR |= (1u << port_No(port));
1143
1144 rc_out(bp, CD180_CAR, port_No(port));
1145 rc_out(bp, CD180_MSVR, port->MSVR);
1146 rc_out(bp, RC_DTR, bp->DTR);
d9afa435
JG
1147
1148 spin_unlock_irqrestore(&riscom_lock, flags);
1149
1da177e4
LT
1150 return 0;
1151}
1152
781cff5c 1153static int rc_send_break(struct tty_struct *tty, int length)
1da177e4 1154{
c9f19e96 1155 struct riscom_port *port = tty->driver_data;
1da177e4
LT
1156 struct riscom_board *bp = port_Board(port);
1157 unsigned long flags;
9492e135 1158
781cff5c
AC
1159 if (length == 0 || length == -1)
1160 return -EOPNOTSUPP;
1161
d9afa435
JG
1162 spin_lock_irqsave(&riscom_lock, flags);
1163
1da177e4
LT
1164 port->break_length = RISCOM_TPS / HZ * length;
1165 port->COR2 |= COR2_ETC;
1166 port->IER |= IER_TXRDY;
1167 rc_out(bp, CD180_CAR, port_No(port));
1168 rc_out(bp, CD180_COR2, port->COR2);
1169 rc_out(bp, CD180_IER, port->IER);
1170 rc_wait_CCR(bp);
1171 rc_out(bp, CD180_CCR, CCR_CORCHG2);
1172 rc_wait_CCR(bp);
d9afa435
JG
1173
1174 spin_unlock_irqrestore(&riscom_lock, flags);
781cff5c 1175 return 0;
1da177e4
LT
1176}
1177
9492e135
AC
1178static int rc_set_serial_info(struct riscom_port *port,
1179 struct serial_struct __user *newinfo)
1da177e4
LT
1180{
1181 struct serial_struct tmp;
1182 struct riscom_board *bp = port_Board(port);
1183 int change_speed;
9492e135 1184
1da177e4
LT
1185 if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
1186 return -EFAULT;
9492e135
AC
1187
1188#if 0
1da177e4
LT
1189 if ((tmp.irq != bp->irq) ||
1190 (tmp.port != bp->base) ||
1191 (tmp.type != PORT_CIRRUS) ||
1192 (tmp.baud_base != (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC) ||
1193 (tmp.custom_divisor != 0) ||
1194 (tmp.xmit_fifo_size != CD180_NFIFO) ||
1195 (tmp.flags & ~RISCOM_LEGAL_FLAGS))
1196 return -EINVAL;
9492e135
AC
1197#endif
1198
85f8f810 1199 change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
1da177e4 1200 (tmp.flags & ASYNC_SPD_MASK));
9492e135 1201
1da177e4 1202 if (!capable(CAP_SYS_ADMIN)) {
44b7d1b3
AC
1203 if ((tmp.close_delay != port->port.close_delay) ||
1204 (tmp.closing_wait != port->port.closing_wait) ||
1da177e4 1205 ((tmp.flags & ~ASYNC_USR_MASK) !=
85f8f810 1206 (port->port.flags & ~ASYNC_USR_MASK)))
1da177e4 1207 return -EPERM;
85f8f810 1208 port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
1da177e4
LT
1209 (tmp.flags & ASYNC_USR_MASK));
1210 } else {
85f8f810 1211 port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
1da177e4 1212 (tmp.flags & ASYNC_FLAGS));
44b7d1b3
AC
1213 port->port.close_delay = tmp.close_delay;
1214 port->port.closing_wait = tmp.closing_wait;
1da177e4
LT
1215 }
1216 if (change_speed) {
d9afa435
JG
1217 unsigned long flags;
1218
1219 spin_lock_irqsave(&riscom_lock, flags);
1da177e4 1220 rc_change_speed(bp, port);
d9afa435 1221 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1222 }
1223 return 0;
1224}
1225
9492e135 1226static int rc_get_serial_info(struct riscom_port *port,
1da177e4
LT
1227 struct serial_struct __user *retinfo)
1228{
1229 struct serial_struct tmp;
1230 struct riscom_board *bp = port_Board(port);
9492e135 1231
1da177e4
LT
1232 memset(&tmp, 0, sizeof(tmp));
1233 tmp.type = PORT_CIRRUS;
1234 tmp.line = port - rc_port;
1235 tmp.port = bp->base;
1236 tmp.irq = bp->irq;
85f8f810 1237 tmp.flags = port->port.flags;
1da177e4 1238 tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;
44b7d1b3
AC
1239 tmp.close_delay = port->port.close_delay * HZ/100;
1240 tmp.closing_wait = port->port.closing_wait * HZ/100;
1da177e4
LT
1241 tmp.xmit_fifo_size = CD180_NFIFO;
1242 return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
1243}
1244
9492e135 1245static int rc_ioctl(struct tty_struct *tty, struct file *filp,
1da177e4 1246 unsigned int cmd, unsigned long arg)
1da177e4 1247{
c9f19e96 1248 struct riscom_port *port = tty->driver_data;
1da177e4 1249 void __user *argp = (void __user *)arg;
781cff5c 1250 int retval;
9492e135 1251
1da177e4
LT
1252 if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
1253 return -ENODEV;
9492e135 1254
1da177e4 1255 switch (cmd) {
9492e135
AC
1256 case TIOCGSERIAL:
1257 lock_kernel();
eb174552
AC
1258 retval = rc_get_serial_info(port, argp);
1259 unlock_kernel();
1da177e4 1260 break;
9492e135
AC
1261 case TIOCSSERIAL:
1262 lock_kernel();
eb174552
AC
1263 retval = rc_set_serial_info(port, argp);
1264 unlock_kernel();
1265 break;
9492e135 1266 default:
eb174552 1267 retval = -ENOIOCTLCMD;
1da177e4 1268 }
eb174552 1269 return retval;
1da177e4
LT
1270}
1271
9492e135 1272static void rc_throttle(struct tty_struct *tty)
1da177e4 1273{
c9f19e96 1274 struct riscom_port *port = tty->driver_data;
1da177e4
LT
1275 struct riscom_board *bp;
1276 unsigned long flags;
9492e135 1277
1da177e4
LT
1278 if (rc_paranoia_check(port, tty->name, "rc_throttle"))
1279 return;
1da177e4 1280 bp = port_Board(port);
d9afa435
JG
1281
1282 spin_lock_irqsave(&riscom_lock, flags);
1da177e4
LT
1283 port->MSVR &= ~MSVR_RTS;
1284 rc_out(bp, CD180_CAR, port_No(port));
d9afa435 1285 if (I_IXOFF(tty)) {
1da177e4
LT
1286 rc_wait_CCR(bp);
1287 rc_out(bp, CD180_CCR, CCR_SSCH2);
1288 rc_wait_CCR(bp);
1289 }
1290 rc_out(bp, CD180_MSVR, port->MSVR);
d9afa435 1291 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1292}
1293
9492e135 1294static void rc_unthrottle(struct tty_struct *tty)
1da177e4 1295{
c9f19e96 1296 struct riscom_port *port = tty->driver_data;
1da177e4
LT
1297 struct riscom_board *bp;
1298 unsigned long flags;
9492e135 1299
1da177e4
LT
1300 if (rc_paranoia_check(port, tty->name, "rc_unthrottle"))
1301 return;
1da177e4 1302 bp = port_Board(port);
d9afa435 1303
9492e135 1304 spin_lock_irqsave(&riscom_lock, flags);
1da177e4
LT
1305 port->MSVR |= MSVR_RTS;
1306 rc_out(bp, CD180_CAR, port_No(port));
1307 if (I_IXOFF(tty)) {
1308 rc_wait_CCR(bp);
1309 rc_out(bp, CD180_CCR, CCR_SSCH1);
1310 rc_wait_CCR(bp);
1311 }
1312 rc_out(bp, CD180_MSVR, port->MSVR);
d9afa435 1313 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1314}
1315
9492e135 1316static void rc_stop(struct tty_struct *tty)
1da177e4 1317{
c9f19e96 1318 struct riscom_port *port = tty->driver_data;
1da177e4
LT
1319 struct riscom_board *bp;
1320 unsigned long flags;
9492e135 1321
1da177e4
LT
1322 if (rc_paranoia_check(port, tty->name, "rc_stop"))
1323 return;
9492e135 1324
1da177e4 1325 bp = port_Board(port);
d9afa435 1326
9492e135 1327 spin_lock_irqsave(&riscom_lock, flags);
1da177e4
LT
1328 port->IER &= ~IER_TXRDY;
1329 rc_out(bp, CD180_CAR, port_No(port));
1330 rc_out(bp, CD180_IER, port->IER);
d9afa435 1331 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1332}
1333
9492e135 1334static void rc_start(struct tty_struct *tty)
1da177e4 1335{
c9f19e96 1336 struct riscom_port *port = tty->driver_data;
1da177e4
LT
1337 struct riscom_board *bp;
1338 unsigned long flags;
9492e135 1339
1da177e4
LT
1340 if (rc_paranoia_check(port, tty->name, "rc_start"))
1341 return;
9492e135 1342
1da177e4 1343 bp = port_Board(port);
9492e135 1344
d9afa435
JG
1345 spin_lock_irqsave(&riscom_lock, flags);
1346
85f8f810 1347 if (port->xmit_cnt && port->port.xmit_buf && !(port->IER & IER_TXRDY)) {
1da177e4
LT
1348 port->IER |= IER_TXRDY;
1349 rc_out(bp, CD180_CAR, port_No(port));
1350 rc_out(bp, CD180_IER, port->IER);
1351 }
d9afa435 1352 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1353}
1354
9492e135 1355static void rc_hangup(struct tty_struct *tty)
1da177e4 1356{
c9f19e96 1357 struct riscom_port *port = tty->driver_data;
1da177e4 1358 struct riscom_board *bp;
c2ba38cd 1359 unsigned long flags;
9492e135 1360
1da177e4
LT
1361 if (rc_paranoia_check(port, tty->name, "rc_hangup"))
1362 return;
9492e135 1363
1da177e4 1364 bp = port_Board(port);
9492e135 1365
d99101fd 1366 rc_shutdown_port(tty, bp, port);
c2ba38cd 1367 spin_lock_irqsave(&port->port.lock, flags);
85f8f810
AC
1368 port->port.count = 0;
1369 port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
1370 port->port.tty = NULL;
1371 wake_up_interruptible(&port->port.open_wait);
c2ba38cd 1372 spin_unlock_irqrestore(&port->port.lock, flags);
1da177e4
LT
1373}
1374
9492e135
AC
1375static void rc_set_termios(struct tty_struct *tty,
1376 struct ktermios *old_termios)
1da177e4 1377{
c9f19e96 1378 struct riscom_port *port = tty->driver_data;
1da177e4 1379 unsigned long flags;
9492e135 1380
1da177e4
LT
1381 if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
1382 return;
1da177e4 1383
d9afa435 1384 spin_lock_irqsave(&riscom_lock, flags);
1da177e4 1385 rc_change_speed(port_Board(port), port);
d9afa435 1386 spin_unlock_irqrestore(&riscom_lock, flags);
1da177e4
LT
1387
1388 if ((old_termios->c_cflag & CRTSCTS) &&
1389 !(tty->termios->c_cflag & CRTSCTS)) {
1390 tty->hw_stopped = 0;
1391 rc_start(tty);
1392 }
1393}
1394
b68e31d0 1395static const struct tty_operations riscom_ops = {
1da177e4
LT
1396 .open = rc_open,
1397 .close = rc_close,
1398 .write = rc_write,
1399 .put_char = rc_put_char,
1400 .flush_chars = rc_flush_chars,
1401 .write_room = rc_write_room,
1402 .chars_in_buffer = rc_chars_in_buffer,
1403 .flush_buffer = rc_flush_buffer,
1404 .ioctl = rc_ioctl,
1405 .throttle = rc_throttle,
1406 .unthrottle = rc_unthrottle,
1407 .set_termios = rc_set_termios,
1408 .stop = rc_stop,
1409 .start = rc_start,
1410 .hangup = rc_hangup,
1411 .tiocmget = rc_tiocmget,
1412 .tiocmset = rc_tiocmset,
781cff5c 1413 .break_ctl = rc_send_break,
1da177e4
LT
1414};
1415
31f35939
AC
1416static const struct tty_port_operations riscom_port_ops = {
1417 .carrier_raised = carrier_raised,
1418};
1419
1420
1386a820 1421static int __init rc_init_drivers(void)
1da177e4
LT
1422{
1423 int error;
1424 int i;
1425
1426 riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
9492e135 1427 if (!riscom_driver)
1da177e4 1428 return -ENOMEM;
9492e135 1429
1da177e4
LT
1430 riscom_driver->owner = THIS_MODULE;
1431 riscom_driver->name = "ttyL";
1da177e4
LT
1432 riscom_driver->major = RISCOM8_NORMAL_MAJOR;
1433 riscom_driver->type = TTY_DRIVER_TYPE_SERIAL;
1434 riscom_driver->subtype = SERIAL_TYPE_NORMAL;
1435 riscom_driver->init_termios = tty_std_termios;
1436 riscom_driver->init_termios.c_cflag =
1437 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
606d099c
AC
1438 riscom_driver->init_termios.c_ispeed = 9600;
1439 riscom_driver->init_termios.c_ospeed = 9600;
781cff5c 1440 riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
1da177e4 1441 tty_set_operations(riscom_driver, &riscom_ops);
9492e135
AC
1442 error = tty_register_driver(riscom_driver);
1443 if (error != 0) {
1da177e4
LT
1444 put_tty_driver(riscom_driver);
1445 printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
9492e135 1446 "error = %d\n", error);
1da177e4
LT
1447 return 1;
1448 }
1da177e4
LT
1449 memset(rc_port, 0, sizeof(rc_port));
1450 for (i = 0; i < RC_NPORT * RC_NBOARD; i++) {
85f8f810 1451 tty_port_init(&rc_port[i].port);
31f35939 1452 rc_port[i].port.ops = &riscom_port_ops;
44b7d1b3 1453 rc_port[i].magic = RISCOM8_MAGIC;
1da177e4 1454 }
1da177e4
LT
1455 return 0;
1456}
1457
1458static void rc_release_drivers(void)
1459{
1da177e4
LT
1460 tty_unregister_driver(riscom_driver);
1461 put_tty_driver(riscom_driver);
1da177e4
LT
1462}
1463
1464#ifndef MODULE
1465/*
1466 * Called at boot time.
9492e135 1467 *
1da177e4
LT
1468 * You can specify IO base for up to RC_NBOARD cards,
1469 * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
1470 * Note that there will be no probing at default
1471 * addresses in this case.
1472 *
9492e135 1473 */
1da177e4
LT
1474static int __init riscom8_setup(char *str)
1475{
1476 int ints[RC_NBOARD];
1477 int i;
1478
1479 str = get_options(str, ARRAY_SIZE(ints), ints);
1480
1481 for (i = 0; i < RC_NBOARD; i++) {
1482 if (i < ints[0])
1483 rc_board[i].base = ints[i+1];
9492e135 1484 else
1da177e4
LT
1485 rc_board[i].base = 0;
1486 }
1487 return 1;
1488}
1489
1490__setup("riscom8=", riscom8_setup);
1491#endif
1492
1493static char banner[] __initdata =
1494 KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin "
1495 "1994-1996.\n";
1496static char no_boards_msg[] __initdata =
1497 KERN_INFO "rc: No RISCom/8 boards detected.\n";
1498
9492e135
AC
1499/*
1500 * This routine must be called by kernel at boot time
1da177e4
LT
1501 */
1502static int __init riscom8_init(void)
1503{
1504 int i;
1505 int found = 0;
1506
1507 printk(banner);
1508
9492e135 1509 if (rc_init_drivers())
1da177e4
LT
1510 return -EIO;
1511
9492e135
AC
1512 for (i = 0; i < RC_NBOARD; i++)
1513 if (rc_board[i].base && !rc_probe(&rc_board[i]))
1da177e4 1514 found++;
1da177e4
LT
1515 if (!found) {
1516 rc_release_drivers();
1517 printk(no_boards_msg);
1518 return -EIO;
1519 }
1520 return 0;
1521}
1522
1523#ifdef MODULE
1524static int iobase;
1525static int iobase1;
1526static int iobase2;
1527static int iobase3;
8d3b33f6
RR
1528module_param(iobase, int, 0);
1529module_param(iobase1, int, 0);
1530module_param(iobase2, int, 0);
1531module_param(iobase3, int, 0);
1da177e4
LT
1532
1533MODULE_LICENSE("GPL");
5c9f5806 1534MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR);
1da177e4
LT
1535#endif /* MODULE */
1536
1537/*
1538 * You can setup up to 4 boards (current value of RC_NBOARD)
1539 * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
1540 *
1541 */
9492e135 1542static int __init riscom8_init_module(void)
1da177e4
LT
1543{
1544#ifdef MODULE
1545 int i;
1546
1547 if (iobase || iobase1 || iobase2 || iobase3) {
9492e135 1548 for (i = 0; i < RC_NBOARD; i++)
9efda797 1549 rc_board[i].base = 0;
1da177e4
LT
1550 }
1551
1552 if (iobase)
1553 rc_board[0].base = iobase;
1554 if (iobase1)
1555 rc_board[1].base = iobase1;
1556 if (iobase2)
1557 rc_board[2].base = iobase2;
1558 if (iobase3)
1559 rc_board[3].base = iobase3;
1560#endif /* MODULE */
1561
1562 return riscom8_init();
1563}
9492e135
AC
1564
1565static void __exit riscom8_exit_module(void)
1da177e4
LT
1566{
1567 int i;
9492e135 1568
1da177e4 1569 rc_release_drivers();
9492e135
AC
1570 for (i = 0; i < RC_NBOARD; i++)
1571 if (rc_board[i].flags & RC_BOARD_PRESENT)
1da177e4 1572 rc_release_io_range(&rc_board[i]);
9492e135 1573
1da177e4
LT
1574}
1575
1576module_init(riscom8_init_module);
1577module_exit(riscom8_exit_module);
This page took 0.697171 seconds and 5 git commands to generate.