blob: 62d6f2e0fd1881c960fd322ca12f4d75ff1cc22d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/char/serial167.c
3 *
4 * Driver for MVME166/7 board serial ports, which are via a CD2401.
5 * Based very much on cyclades.c.
6 *
7 * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk]
8 *
9 * ==============================================================
10 *
11 * static char rcsid[] =
12 * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $";
13 *
14 * linux/kernel/cyclades.c
15 *
16 * Maintained by Marcio Saito (cyclades@netcom.com) and
17 * Randolph Bentson (bentson@grieg.seaslug.org)
18 *
19 * Much of the design and some of the code came from serial.c
20 * which was copyright (C) 1991, 1992 Linus Torvalds. It was
21 * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
22 * and then fixed as suggested by Michael K. Johnson 12/12/92.
23 *
24 * This version does not support shared irq's.
25 *
26 * $Log: cyclades.c,v $
27 * Revision 1.36.1.4 1995/03/29 06:14:14 bentson
28 * disambiguate between Cyclom-16Y and Cyclom-32Ye;
29 *
30 * Changes:
31 *
32 * 200 lines of changes record removed - RGH 11-10-95, starting work on
33 * converting this to drive serial ports on mvme166 (cd2401).
34 *
35 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25
36 * - get rid of verify_area
37 * - use get_user to access memory from userspace in set_threshold,
38 * set_default_threshold and set_timeout
39 * - don't use the panic function in serial167_init
40 * - do resource release on failure on serial167_init
41 * - include missing restore_flags in mvme167_serial_console_setup
42 *
43 * Kars de Jong <jongk@linux-m68k.org> - 2004/09/06
44 * - replace bottom half handler with task queue handler
45 */
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/errno.h>
48#include <linux/signal.h>
49#include <linux/sched.h>
50#include <linux/timer.h>
51#include <linux/tty.h>
52#include <linux/interrupt.h>
53#include <linux/serial.h>
54#include <linux/serialP.h>
55#include <linux/string.h>
56#include <linux/fcntl.h>
57#include <linux/ptrace.h>
58#include <linux/serial167.h>
59#include <linux/delay.h>
60#include <linux/major.h>
61#include <linux/mm.h>
62#include <linux/console.h>
63#include <linux/module.h>
64#include <linux/bitops.h>
Geert Uytterhoeven81e859a2006-10-09 22:27:42 +020065#include <linux/tty_flip.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67#include <asm/system.h>
68#include <asm/io.h>
69#include <asm/mvme16xhw.h>
70#include <asm/bootinfo.h>
71#include <asm/setup.h>
72
73#include <linux/types.h>
74#include <linux/kernel.h>
75
76#include <asm/uaccess.h>
77#include <linux/init.h>
78
79#define SERIAL_PARANOIA_CHECK
80#undef SERIAL_DEBUG_OPEN
81#undef SERIAL_DEBUG_THROTTLE
82#undef SERIAL_DEBUG_OTHER
83#undef SERIAL_DEBUG_IO
84#undef SERIAL_DEBUG_COUNT
85#undef SERIAL_DEBUG_DTR
86#undef CYCLOM_16Y_HACK
87#define CYCLOM_ENABLE_MONITORING
88
89#define WAKEUP_CHARS 256
90
91#define STD_COM_FLAGS (0)
92
Linus Torvalds1da177e2005-04-16 15:20:36 -070093static struct tty_driver *cy_serial_driver;
94extern int serial_console;
95static struct cyclades_port *serial_console_info = NULL;
96static unsigned int serial_console_cflag = 0;
97u_char initial_console_speed;
98
99/* Base address of cd2401 chip on mvme166/7 */
100
101#define BASE_ADDR (0xfff45000)
102#define pcc2chip ((volatile u_char *)0xfff42000)
103#define PccSCCMICR 0x1d
104#define PccSCCTICR 0x1e
105#define PccSCCRICR 0x1f
106#define PccTPIACKR 0x25
107#define PccRPIACKR 0x27
108#define PccIMLR 0x3f
109
110/* This is the per-port data structure */
111struct cyclades_port cy_port[] = {
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800112 /* CARD# */
113 {-1}, /* ttyS0 */
114 {-1}, /* ttyS1 */
115 {-1}, /* ttyS2 */
116 {-1}, /* ttyS3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117};
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800118
Tobias Klauserfe971072006-01-09 20:54:02 -0800119#define NR_PORTS ARRAY_SIZE(cy_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 * This is used to look up the divisor speeds and the timeouts
123 * We're normally limited to 15 distinct baud rates. The extra
124 * are accessed via settings in info->flags.
125 * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
126 * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
127 * HI VHI
128 */
129static int baud_table[] = {
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800130 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
131 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
132 0
133};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
135#if 0
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800136static char baud_co[] = { /* 25 MHz clock option table */
137 /* value => 00 01 02 03 04 */
138 /* divide by 8 32 128 512 2048 */
139 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
140 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
141};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800143static char baud_bpr[] = { /* 25 MHz baud rate period table */
144 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
145 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
146};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147#endif
148
149/* I think 166 brd clocks 2401 at 20MHz.... */
150
151/* These values are written directly to tcor, and >> 5 for writing to rcor */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800152static u_char baud_co[] = { /* 20 MHz clock option table */
153 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40,
154 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
155};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
157/* These values written directly to tbpr/rbpr */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800158static u_char baud_bpr[] = { /* 20 MHz baud rate period table */
159 0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81,
160 0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10
161};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800163static u_char baud_cor4[] = { /* receive threshold */
164 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
165 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07
166};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
168static void shutdown(struct cyclades_port *);
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800169static int startup(struct cyclades_port *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170static void cy_throttle(struct tty_struct *);
171static void cy_unthrottle(struct tty_struct *);
172static void config_setup(struct cyclades_port *);
173extern void console_print(const char *);
174#ifdef CYCLOM_SHOW_STATUS
175static void show_status(int);
176#endif
177
178#ifdef CONFIG_REMOTE_DEBUG
179static void debug_setup(void);
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800180void queueDebugChar(int c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181int getDebugChar(void);
182
183#define DEBUG_PORT 1
184#define DEBUG_LEN 256
185
186typedef struct {
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800187 int in;
188 int out;
189 unsigned char buf[DEBUG_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190} debugq;
191
192debugq debugiq;
193#endif
194
195/*
196 * I have my own version of udelay(), as it is needed when initialising
197 * the chip, before the delay loop has been calibrated. Should probably
198 * reference one of the vmechip2 or pccchip2 counter for an accurate
199 * delay, but this wild guess will do for now.
200 */
201
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800202void my_udelay(long us)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203{
204 u_char x;
205 volatile u_char *p = &x;
206 int i;
207
208 while (us--)
209 for (i = 100; i; i--)
210 x |= *p;
211}
212
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800213static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
214 const char *routine)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215{
216#ifdef SERIAL_PARANOIA_CHECK
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800217 if (!info) {
218 printk("Warning: null cyclades_port for (%s) in %s\n", name,
219 routine);
220 return 1;
221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800223 if ((long)info < (long)(&cy_port[0])
224 || (long)(&cy_port[NR_PORTS]) < (long)info) {
225 printk("Warning: cyclades_port out of range for (%s) in %s\n",
226 name, routine);
227 return 1;
228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800230 if (info->magic != CYCLADES_MAGIC) {
231 printk("Warning: bad magic number for serial struct (%s) in "
232 "%s\n", name, routine);
233 return 1;
234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235#endif
236 return 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800237} /* serial_paranoia_check */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
239#if 0
240/* The following diagnostic routines allow the driver to spew
241 information on the screen, even (especially!) during interrupts.
242 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800243void SP(char *data)
244{
245 unsigned long flags;
246 local_irq_save(flags);
247 console_print(data);
248 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800251char scrn[2];
252void CP(char data)
253{
254 unsigned long flags;
255 local_irq_save(flags);
256 scrn[0] = data;
257 console_print(scrn);
258 local_irq_restore(flags);
259} /* CP */
260
261void CP1(int data)
262{
263 (data < 10) ? CP(data + '0') : CP(data + 'A' - 10);
264} /* CP1 */
265void CP2(int data)
266{
267 CP1((data >> 4) & 0x0f);
268 CP1(data & 0x0f);
269} /* CP2 */
270void CP4(int data)
271{
272 CP2((data >> 8) & 0xff);
273 CP2(data & 0xff);
274} /* CP4 */
275void CP8(long data)
276{
277 CP4((data >> 16) & 0xffff);
278 CP4(data & 0xffff);
279} /* CP8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280#endif
281
282/* This routine waits up to 1000 micro-seconds for the previous
283 command to the Cirrus chip to complete and then issues the
284 new command. An error is returned if the previous command
285 didn't finish within the time limit.
286 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800287u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800289 unsigned long flags;
290 volatile int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800292 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 /* Check to see that the previous command has completed */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800294 for (i = 0; i < 100; i++) {
295 if (base_addr[CyCCR] == 0) {
296 break;
297 }
298 my_udelay(10L);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 }
300 /* if the CCR never cleared, the previous command
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800301 didn't finish within the "reasonable time" */
302 if (i == 10) {
303 local_irq_restore(flags);
304 return (-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 }
306
307 /* Issue the new command */
308 base_addr[CyCCR] = cmd;
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800309 local_irq_restore(flags);
310 return (0);
311} /* write_cy_cmd */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
313/* cy_start and cy_stop provide software output flow control as a
314 function of XON/XOFF, software CTS, and other such stuff. */
315
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800316static void cy_stop(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800318 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
319 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
320 int channel;
321 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800324 printk("cy_stop %s\n", tty->name); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325#endif
326
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800327 if (serial_paranoia_check(info, tty->name, "cy_stop"))
328 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800330 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800332 local_irq_save(flags);
333 base_addr[CyCAR] = (u_char) (channel); /* index channel */
334 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
335 local_irq_restore(flags);
336} /* cy_stop */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800338static void cy_start(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800340 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
341 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
342 int channel;
343 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800346 printk("cy_start %s\n", tty->name); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347#endif
348
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800349 if (serial_paranoia_check(info, tty->name, "cy_start"))
350 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800352 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800354 local_irq_save(flags);
355 base_addr[CyCAR] = (u_char) (channel);
356 base_addr[CyIER] |= CyTxMpty;
357 local_irq_restore(flags);
358} /* cy_start */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360/* The real interrupt service routines are called
361 whenever the card wants its hand held--chars
362 received, out buffer empty, modem change, etc.
363 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800364static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800366 struct tty_struct *tty;
367 struct cyclades_port *info;
368 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
369 unsigned char err, rfoc;
370 int channel;
371 char data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800373 /* determine the channel and change to that context */
374 channel = (u_short) (base_addr[CyLICR] >> 2);
375 info = &cy_port[channel];
376 info->last_active = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800378 if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
379 /* This is a receive timeout interrupt, ignore it */
380 base_addr[CyREOIR] = CyNOTRANS;
381 return IRQ_HANDLED;
382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800384 /* Read a byte of data if there is any - assume the error
385 * is associated with this character */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800387 if ((rfoc = base_addr[CyRFOC]) != 0)
388 data = base_addr[CyRDR];
389 else
390 data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800392 /* if there is nowhere to put the data, discard it */
393 if (info->tty == 0) {
394 base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
395 return IRQ_HANDLED;
396 } else { /* there is an open port for this data */
397 tty = info->tty;
398 if (err & info->ignore_status_mask) {
399 base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
400 return IRQ_HANDLED;
401 }
402 if (tty_buffer_request_room(tty, 1) != 0) {
403 if (err & info->read_status_mask) {
404 if (err & CyBREAK) {
405 tty_insert_flip_char(tty, data,
406 TTY_BREAK);
407 if (info->flags & ASYNC_SAK) {
408 do_SAK(tty);
409 }
410 } else if (err & CyFRAME) {
411 tty_insert_flip_char(tty, data,
412 TTY_FRAME);
413 } else if (err & CyPARITY) {
414 tty_insert_flip_char(tty, data,
415 TTY_PARITY);
416 } else if (err & CyOVERRUN) {
417 tty_insert_flip_char(tty, 0,
418 TTY_OVERRUN);
419 /*
420 If the flip buffer itself is
421 overflowing, we still loose
422 the next incoming character.
423 */
424 if (tty_buffer_request_room(tty, 1) !=
425 0) {
426 tty_insert_flip_char(tty, data,
427 TTY_FRAME);
428 }
429 /* These two conditions may imply */
430 /* a normal read should be done. */
431 /* else if(data & CyTIMEOUT) */
432 /* else if(data & CySPECHAR) */
433 } else {
434 tty_insert_flip_char(tty, 0,
435 TTY_NORMAL);
436 }
437 } else {
438 tty_insert_flip_char(tty, data, TTY_NORMAL);
439 }
440 } else {
441 /* there was a software buffer overrun
442 and nothing could be done about it!!! */
443 }
444 }
445 tty_schedule_flip(tty);
446 /* end of service */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
448 return IRQ_HANDLED;
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800449} /* cy_rxerr_interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800451static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800453 struct cyclades_port *info;
454 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
455 int channel;
456 int mdm_change;
457 int mdm_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800459 /* determine the channel and change to that context */
460 channel = (u_short) (base_addr[CyLICR] >> 2);
461 info = &cy_port[channel];
462 info->last_active = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800464 mdm_change = base_addr[CyMISR];
465 mdm_status = base_addr[CyMSVR1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800467 if (info->tty == 0) { /* nowhere to put the data, ignore it */
468 ;
469 } else {
470 if ((mdm_change & CyDCD)
471 && (info->flags & ASYNC_CHECK_CD)) {
472 if (mdm_status & CyDCD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473/* CP('!'); */
Jiri Slaby3099bbc2008-02-07 00:16:40 -0800474 wake_up_interruptible(&info->open_wait);
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800475 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476/* CP('@'); */
Jiri Slaby3099bbc2008-02-07 00:16:40 -0800477 tty_hangup(info->tty);
478 wake_up_interruptible(&info->open_wait);
479 info->flags &= ~ASYNC_NORMAL_ACTIVE;
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800480 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800482 if ((mdm_change & CyCTS)
483 && (info->flags & ASYNC_CTS_FLOW)) {
484 if (info->tty->stopped) {
485 if (mdm_status & CyCTS) {
486 /* !!! cy_start isn't used because... */
487 info->tty->stopped = 0;
488 base_addr[CyIER] |= CyTxMpty;
Jiri Slaby3099bbc2008-02-07 00:16:40 -0800489 tty_wakeup(info->tty);
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800490 }
491 } else {
492 if (!(mdm_status & CyCTS)) {
493 /* !!! cy_stop isn't used because... */
494 info->tty->stopped = 1;
495 base_addr[CyIER] &=
496 ~(CyTxMpty | CyTxRdy);
497 }
498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800500 if (mdm_status & CyDSR) {
501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800503 base_addr[CyMEOIR] = 0;
504 return IRQ_HANDLED;
505} /* cy_modem_interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800507static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800509 struct cyclades_port *info;
510 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
511 int channel;
512 int char_count, saved_cnt;
513 int outch;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800515 /* determine the channel and change to that context */
516 channel = (u_short) (base_addr[CyLICR] >> 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
518#ifdef CONFIG_REMOTE_DEBUG
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800519 if (channel == DEBUG_PORT) {
520 panic("TxInt on debug port!!!");
521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522#endif
523
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800524 info = &cy_port[channel];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800526 /* validate the port number (as configured and open) */
527 if ((channel < 0) || (NR_PORTS <= channel)) {
528 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
529 base_addr[CyTEOIR] = CyNOTRANS;
530 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800532 info->last_active = jiffies;
533 if (info->tty == 0) {
534 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800535 base_addr[CyTEOIR] = CyNOTRANS;
536 return IRQ_HANDLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800538
539 /* load the on-chip space available for outbound data */
540 saved_cnt = char_count = base_addr[CyTFTC];
541
542 if (info->x_char) { /* send special char */
543 outch = info->x_char;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 base_addr[CyTDR] = outch;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 char_count--;
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800546 info->x_char = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800549 if (info->x_break) {
550 /* The Cirrus chip requires the "Embedded Transmit
551 Commands" of start break, delay, and end break
552 sequences to be sent. The duration of the
553 break is given in TICs, which runs at HZ
554 (typically 100) and the PPR runs at 200 Hz,
555 so the delay is duration * 200/HZ, and thus a
556 break can run from 1/100 sec to about 5/4 sec.
557 Need to check these values - RGH 141095.
558 */
559 base_addr[CyTDR] = 0; /* start break */
560 base_addr[CyTDR] = 0x81;
561 base_addr[CyTDR] = 0; /* delay a bit */
562 base_addr[CyTDR] = 0x82;
563 base_addr[CyTDR] = info->x_break * 200 / HZ;
564 base_addr[CyTDR] = 0; /* terminate break */
565 base_addr[CyTDR] = 0x83;
566 char_count -= 7;
567 info->x_break = 0;
568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800570 while (char_count > 0) {
571 if (!info->xmit_cnt) {
572 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
573 break;
574 }
575 if (info->xmit_buf == 0) {
576 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
577 break;
578 }
579 if (info->tty->stopped || info->tty->hw_stopped) {
580 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
581 break;
582 }
583 /* Because the Embedded Transmit Commands have been
584 enabled, we must check to see if the escape
585 character, NULL, is being sent. If it is, we
586 must ensure that there is room for it to be
587 doubled in the output stream. Therefore we
588 no longer advance the pointer when the character
589 is fetched, but rather wait until after the check
590 for a NULL output character. (This is necessary
591 because there may not be room for the two chars
592 needed to send a NULL.
593 */
594 outch = info->xmit_buf[info->xmit_tail];
595 if (outch) {
596 info->xmit_cnt--;
597 info->xmit_tail = (info->xmit_tail + 1)
598 & (PAGE_SIZE - 1);
599 base_addr[CyTDR] = outch;
600 char_count--;
601 } else {
602 if (char_count > 1) {
603 info->xmit_cnt--;
604 info->xmit_tail = (info->xmit_tail + 1)
605 & (PAGE_SIZE - 1);
606 base_addr[CyTDR] = outch;
607 base_addr[CyTDR] = 0;
608 char_count--;
609 char_count--;
610 } else {
611 break;
612 }
613 }
614 }
615
Jiri Slaby3099bbc2008-02-07 00:16:40 -0800616 if (info->xmit_cnt < WAKEUP_CHARS)
617 tty_wakeup(info->tty);
618
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800619 base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
620 return IRQ_HANDLED;
621} /* cy_tx_interrupt */
622
623static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800625 struct tty_struct *tty;
626 struct cyclades_port *info;
627 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
628 int channel;
629 char data;
630 int char_count;
631 int save_cnt;
632 int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800634 /* determine the channel and change to that context */
635 channel = (u_short) (base_addr[CyLICR] >> 2);
636 info = &cy_port[channel];
637 info->last_active = jiffies;
638 save_cnt = char_count = base_addr[CyRFOC];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
640#ifdef CONFIG_REMOTE_DEBUG
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800641 if (channel == DEBUG_PORT) {
642 while (char_count--) {
643 data = base_addr[CyRDR];
644 queueDebugChar(data);
645 }
646 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800648 /* if there is nowhere to put the data, discard it */
649 if (info->tty == 0) {
650 while (char_count--) {
651 data = base_addr[CyRDR];
652 }
653 } else { /* there is an open port for this data */
654 tty = info->tty;
655 /* load # characters available from the chip */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657#ifdef CYCLOM_ENABLE_MONITORING
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800658 ++info->mon.int_count;
659 info->mon.char_count += char_count;
660 if (char_count > info->mon.char_max)
661 info->mon.char_max = char_count;
662 info->mon.char_last = char_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800664 len = tty_buffer_request_room(tty, char_count);
665 while (len--) {
666 data = base_addr[CyRDR];
667 tty_insert_flip_char(tty, data, TTY_NORMAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668#ifdef CYCLOM_16Y_HACK
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800669 udelay(10L);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800671 }
672 tty_schedule_flip(tty);
673 }
674 /* end of service */
675 base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
676 return IRQ_HANDLED;
677} /* cy_rx_interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679/* This is called whenever a port becomes active;
680 interrupts are enabled and DTR & RTS are turned on.
681 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800682static int startup(struct cyclades_port *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800684 unsigned long flags;
685 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
686 int channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800688 if (info->flags & ASYNC_INITIALIZED) {
689 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800691
692 if (!info->type) {
693 if (info->tty) {
694 set_bit(TTY_IO_ERROR, &info->tty->flags);
695 }
696 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800698 if (!info->xmit_buf) {
699 info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
700 if (!info->xmit_buf) {
701 return -ENOMEM;
702 }
703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800705 config_setup(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800707 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709#ifdef SERIAL_DEBUG_OPEN
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800710 printk("startup channel %d\n", channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711#endif
712
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800713 local_irq_save(flags);
714 base_addr[CyCAR] = (u_char) channel;
715 write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800717 base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 base_addr[CyMSVR1] = CyRTS;
719/* CP('S');CP('1'); */
720 base_addr[CyMSVR2] = CyDTR;
721
722#ifdef SERIAL_DEBUG_DTR
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800723 printk("cyc: %d: raising DTR\n", __LINE__);
724 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
725 base_addr[CyMSVR2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726#endif
727
728 base_addr[CyIER] |= CyRxData;
729 info->flags |= ASYNC_INITIALIZED;
730
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800731 if (info->tty) {
732 clear_bit(TTY_IO_ERROR, &info->tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 }
734 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
735
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800736 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738#ifdef SERIAL_DEBUG_OPEN
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800739 printk(" done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800741 return 0;
742} /* startup */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800744void start_xmit(struct cyclades_port *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800746 unsigned long flags;
747 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
748 int channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800750 channel = info->line;
751 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 base_addr[CyCAR] = channel;
753 base_addr[CyIER] |= CyTxMpty;
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800754 local_irq_restore(flags);
755} /* start_xmit */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756
757/*
758 * This routine shuts down a serial port; interrupts are disabled,
759 * and DTR is dropped if the hangup on close termio flag is on.
760 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800761static void shutdown(struct cyclades_port *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800763 unsigned long flags;
764 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
765 int channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800767 if (!(info->flags & ASYNC_INITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768/* CP('$'); */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800769 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 }
771
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800772 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800774#ifdef SERIAL_DEBUG_OPEN
775 printk("shutdown channel %d\n", channel);
776#endif
777
778 /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
779 SENT BEFORE DROPPING THE LINE !!! (Perhaps
780 set some flag that is read when XMTY happens.)
781 Other choices are to delay some fixed interval
782 or schedule some later processing.
783 */
784 local_irq_save(flags);
785 if (info->xmit_buf) {
786 free_page((unsigned long)info->xmit_buf);
787 info->xmit_buf = NULL;
788 }
789
790 base_addr[CyCAR] = (u_char) channel;
791 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
792 base_addr[CyMSVR1] = 0;
793/* CP('C');CP('1'); */
794 base_addr[CyMSVR2] = 0;
795#ifdef SERIAL_DEBUG_DTR
796 printk("cyc: %d: dropping DTR\n", __LINE__);
797 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
798 base_addr[CyMSVR2]);
799#endif
800 }
801 write_cy_cmd(base_addr, CyDIS_RCVR);
802 /* it may be appropriate to clear _XMIT at
803 some later date (after testing)!!! */
804
805 if (info->tty) {
806 set_bit(TTY_IO_ERROR, &info->tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 }
808 info->flags &= ~ASYNC_INITIALIZED;
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800809 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
811#ifdef SERIAL_DEBUG_OPEN
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800812 printk(" done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800814} /* shutdown */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815
816/*
817 * This routine finds or computes the various line characteristics.
818 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800819static void config_setup(struct cyclades_port *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820{
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800821 unsigned long flags;
822 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
823 int channel;
824 unsigned cflag;
825 int i;
826 unsigned char ti, need_init_chan = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800828 if (!info->tty || !info->tty->termios) {
829 return;
830 }
831 if (info->line == -1) {
832 return;
833 }
834 cflag = info->tty->termios->c_cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800836 /* baud rate */
837 i = cflag & CBAUD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838#ifdef CBAUDEX
839/* Starting with kernel 1.1.65, there is direct support for
840 higher baud rates. The following code supports those
841 changes. The conditional aspect allows this driver to be
842 used for earlier as well as later kernel versions. (The
843 mapping is slightly different from serial.c because there
844 is still the possibility of supporting 75 kbit/sec with
845 the Cyclades board.)
846 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800847 if (i & CBAUDEX) {
848 if (i == B57600)
849 i = 16;
850 else if (i == B115200)
851 i = 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852#ifdef B78600
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800853 else if (i == B78600)
854 i = 17;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800856 else
857 info->tty->termios->c_cflag &= ~CBAUDEX;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800860 if (i == 15) {
861 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
862 i += 1;
863 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
864 i += 3;
865 }
866 /* Don't ever change the speed of the console port. It will
867 * run at the speed specified in bootinfo, or at 19.2K */
868 /* Actually, it should run at whatever speed 166Bug was using */
869 /* Note info->timeout isn't used at present */
870 if (info != serial_console_info) {
871 info->tbpr = baud_bpr[i]; /* Tx BPR */
872 info->tco = baud_co[i]; /* Tx CO */
873 info->rbpr = baud_bpr[i]; /* Rx BPR */
874 info->rco = baud_co[i] >> 5; /* Rx CO */
875 if (baud_table[i] == 134) {
876 info->timeout =
877 (info->xmit_fifo_size * HZ * 30 / 269) + 2;
878 /* get it right for 134.5 baud */
879 } else if (baud_table[i]) {
880 info->timeout =
881 (info->xmit_fifo_size * HZ * 15 / baud_table[i]) +
882 2;
883 /* this needs to be propagated into the card info */
884 } else {
885 info->timeout = 0;
886 }
887 }
888 /* By tradition (is it a standard?) a baud rate of zero
889 implies the line should be/has been closed. A bit
890 later in this routine such a test is performed. */
891
892 /* byte size and parity */
893 info->cor7 = 0;
894 info->cor6 = 0;
895 info->cor5 = 0;
896 info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]); /* receive threshold */
897 /* Following two lines added 101295, RGH. */
898 /* It is obviously wrong to access CyCORx, and not info->corx here,
899 * try and remember to fix it later! */
900 channel = info->line;
901 base_addr[CyCAR] = (u_char) channel;
902 if (C_CLOCAL(info->tty)) {
903 if (base_addr[CyIER] & CyMdmCh)
904 base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */
905 /* ignore 1->0 modem transitions */
906 if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD))
907 base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD);
908 /* ignore 0->1 modem transitions */
909 if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD))
910 base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD);
911 } else {
912 if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
913 base_addr[CyIER] |= CyMdmCh; /* with modem intr */
914 /* act on 1->0 modem transitions */
915 if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) !=
916 (CyDSR | CyCTS | CyDCD))
917 base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD;
918 /* act on 0->1 modem transitions */
919 if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) !=
920 (CyDSR | CyCTS | CyDCD))
921 base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD;
922 }
923 info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
924 info->cor2 = CyETC;
925 switch (cflag & CSIZE) {
926 case CS5:
927 info->cor1 = Cy_5_BITS;
928 break;
929 case CS6:
930 info->cor1 = Cy_6_BITS;
931 break;
932 case CS7:
933 info->cor1 = Cy_7_BITS;
934 break;
935 case CS8:
936 info->cor1 = Cy_8_BITS;
937 break;
938 }
939 if (cflag & PARENB) {
940 if (cflag & PARODD) {
941 info->cor1 |= CyPARITY_O;
942 } else {
943 info->cor1 |= CyPARITY_E;
944 }
945 } else {
946 info->cor1 |= CyPARITY_NONE;
947 }
948
949 /* CTS flow control flag */
950#if 0
951 /* Don't complcate matters for now! RGH 141095 */
952 if (cflag & CRTSCTS) {
953 info->flags |= ASYNC_CTS_FLOW;
954 info->cor2 |= CyCtsAE;
955 } else {
956 info->flags &= ~ASYNC_CTS_FLOW;
957 info->cor2 &= ~CyCtsAE;
958 }
959#endif
960 if (cflag & CLOCAL)
961 info->flags &= ~ASYNC_CHECK_CD;
962 else
963 info->flags |= ASYNC_CHECK_CD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964
965 /***********************************************
966 The hardware option, CyRtsAO, presents RTS when
967 the chip has characters to send. Since most modems
968 use RTS as reverse (inbound) flow control, this
969 option is not used. If inbound flow control is
970 necessary, DTR can be programmed to provide the
971 appropriate signals for use with a non-standard
972 cable. Contact Marcio Saito for details.
973 ***********************************************/
974
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800975 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800977 local_irq_save(flags);
978 base_addr[CyCAR] = (u_char) channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 /* CyCMR set once only in mvme167_init_serial() */
981 if (base_addr[CyLICR] != channel << 2)
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800982 base_addr[CyLICR] = channel << 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 if (base_addr[CyLIVR] != 0x5c)
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800984 base_addr[CyLIVR] = 0x5c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800986 /* tx and rx baud rate */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
988 if (base_addr[CyCOR1] != info->cor1)
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800989 need_init_chan = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 if (base_addr[CyTCOR] != info->tco)
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800991 base_addr[CyTCOR] = info->tco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 if (base_addr[CyTBPR] != info->tbpr)
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800993 base_addr[CyTBPR] = info->tbpr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 if (base_addr[CyRCOR] != info->rco)
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800995 base_addr[CyRCOR] = info->rco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 if (base_addr[CyRBPR] != info->rbpr)
Jiri Slaby44bafdf2007-02-10 01:45:08 -0800997 base_addr[CyRBPR] = info->rbpr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
999 /* set line characteristics according configuration */
1000
1001 if (base_addr[CySCHR1] != START_CHAR(info->tty))
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001002 base_addr[CySCHR1] = START_CHAR(info->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001004 base_addr[CySCHR2] = STOP_CHAR(info->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 if (base_addr[CySCRL] != START_CHAR(info->tty))
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001006 base_addr[CySCRL] = START_CHAR(info->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 if (base_addr[CySCRH] != START_CHAR(info->tty))
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001008 base_addr[CySCRH] = START_CHAR(info->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 if (base_addr[CyCOR1] != info->cor1)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001010 base_addr[CyCOR1] = info->cor1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 if (base_addr[CyCOR2] != info->cor2)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001012 base_addr[CyCOR2] = info->cor2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 if (base_addr[CyCOR3] != info->cor3)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001014 base_addr[CyCOR3] = info->cor3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 if (base_addr[CyCOR4] != info->cor4)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001016 base_addr[CyCOR4] = info->cor4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 if (base_addr[CyCOR5] != info->cor5)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001018 base_addr[CyCOR5] = info->cor5;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 if (base_addr[CyCOR6] != info->cor6)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001020 base_addr[CyCOR6] = info->cor6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 if (base_addr[CyCOR7] != info->cor7)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001022 base_addr[CyCOR7] = info->cor7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
1024 if (need_init_chan)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001025 write_cy_cmd(base_addr, CyINIT_CHAN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001027 base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 /* 2ms default rx timeout */
1030 ti = info->default_timeout ? info->default_timeout : 0x02;
1031 if (base_addr[CyRTPRL] != ti)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001032 base_addr[CyRTPRL] = ti;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 if (base_addr[CyRTPRH] != 0)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001034 base_addr[CyRTPRH] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
1036 /* Set up RTS here also ????? RGH 141095 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001037 if (i == 0) { /* baud rate is zero, turn off line */
1038 if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
1039 base_addr[CyMSVR2] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040#ifdef SERIAL_DEBUG_DTR
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001041 printk("cyc: %d: dropping DTR\n", __LINE__);
1042 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1043 base_addr[CyMSVR2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001045 } else {
1046 if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
1047 base_addr[CyMSVR2] = CyDTR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048#ifdef SERIAL_DEBUG_DTR
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001049 printk("cyc: %d: raising DTR\n", __LINE__);
1050 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1051 base_addr[CyMSVR2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052#endif
1053 }
1054
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001055 if (info->tty) {
1056 clear_bit(TTY_IO_ERROR, &info->tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 }
1058
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001059 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001061} /* config_setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001063static void cy_put_char(struct tty_struct *tty, unsigned char ch)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001065 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1066 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
1068#ifdef SERIAL_DEBUG_IO
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001069 printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070#endif
1071
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001072 if (serial_paranoia_check(info, tty->name, "cy_put_char"))
1073 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001075 if (!info->xmit_buf)
1076 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001078 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 if (info->xmit_cnt >= PAGE_SIZE - 1) {
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001080 local_irq_restore(flags);
1081 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083
1084 info->xmit_buf[info->xmit_head++] = ch;
1085 info->xmit_head &= PAGE_SIZE - 1;
1086 info->xmit_cnt++;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001087 local_irq_restore(flags);
1088} /* cy_put_char */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001090static void cy_flush_chars(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001092 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1093 unsigned long flags;
1094 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1095 int channel;
1096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097#ifdef SERIAL_DEBUG_IO
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001098 printk("cy_flush_chars %s\n", tty->name); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099#endif
1100
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001101 if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
1102 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001104 if (info->xmit_cnt <= 0 || tty->stopped
1105 || tty->hw_stopped || !info->xmit_buf)
1106 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001108 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001110 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 base_addr[CyCAR] = channel;
1112 base_addr[CyIER] |= CyTxMpty;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001113 local_irq_restore(flags);
1114} /* cy_flush_chars */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
1116/* This routine gets called when tty_write has put something into
1117 the write_queue. If the port is not already transmitting stuff,
1118 start it off by enabling interrupts. The interrupt service
1119 routine will then ensure that the characters are sent. If the
1120 port is already active, there is no need to kick it.
1121 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001122static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001124 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1125 unsigned long flags;
1126 int c, total = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
1128#ifdef SERIAL_DEBUG_IO
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001129 printk("cy_write %s\n", tty->name); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130#endif
1131
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001132 if (serial_paranoia_check(info, tty->name, "cy_write")) {
1133 return 0;
1134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001136 if (!info->xmit_buf) {
1137 return 0;
1138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001140 while (1) {
1141 local_irq_save(flags);
1142 c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1143 SERIAL_XMIT_SIZE - info->xmit_head));
1144 if (c <= 0) {
1145 local_irq_restore(flags);
1146 break;
1147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001149 memcpy(info->xmit_buf + info->xmit_head, buf, c);
1150 info->xmit_head =
1151 (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
1152 info->xmit_cnt += c;
1153 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001155 buf += c;
1156 count -= c;
1157 total += c;
1158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001160 if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
1161 start_xmit(info);
1162 }
1163 return total;
1164} /* cy_write */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001166static int cy_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001168 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1169 int ret;
1170
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171#ifdef SERIAL_DEBUG_IO
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001172 printk("cy_write_room %s\n", tty->name); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173#endif
1174
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001175 if (serial_paranoia_check(info, tty->name, "cy_write_room"))
1176 return 0;
1177 ret = PAGE_SIZE - info->xmit_cnt - 1;
1178 if (ret < 0)
1179 ret = 0;
1180 return ret;
1181} /* cy_write_room */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001183static int cy_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001185 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1186
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187#ifdef SERIAL_DEBUG_IO
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001188 printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189#endif
1190
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001191 if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
1192 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001194 return info->xmit_cnt;
1195} /* cy_chars_in_buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001197static void cy_flush_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001199 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1200 unsigned long flags;
1201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202#ifdef SERIAL_DEBUG_IO
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001203 printk("cy_flush_buffer %s\n", tty->name); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204#endif
1205
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001206 if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
1207 return;
1208 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001210 local_irq_restore(flags);
1211 tty_wakeup(tty);
1212} /* cy_flush_buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
1214/* This routine is called by the upper-layer tty layer to signal
1215 that incoming characters should be throttled or that the
1216 throttle should be released.
1217 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001218static void cy_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001220 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1221 unsigned long flags;
1222 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1223 int channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
1225#ifdef SERIAL_DEBUG_THROTTLE
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001226 char buf[64];
1227
1228 printk("throttle %s: %d....\n", tty_name(tty, buf),
1229 tty->ldisc.chars_in_buffer(tty));
1230 printk("cy_throttle %s\n", tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231#endif
1232
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001233 if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
1234 return;
1235 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001237 if (I_IXOFF(tty)) {
1238 info->x_char = STOP_CHAR(tty);
1239 /* Should use the "Send Special Character" feature!!! */
1240 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001242 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001244 local_irq_save(flags);
1245 base_addr[CyCAR] = (u_char) channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 base_addr[CyMSVR1] = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001247 local_irq_restore(flags);
1248} /* cy_throttle */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001250static void cy_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001252 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1253 unsigned long flags;
1254 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1255 int channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
1257#ifdef SERIAL_DEBUG_THROTTLE
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001258 char buf[64];
1259
1260 printk("throttle %s: %d....\n", tty_name(tty, buf),
1261 tty->ldisc.chars_in_buffer(tty));
1262 printk("cy_unthrottle %s\n", tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263#endif
1264
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001265 if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
1266 return;
1267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001269 if (I_IXOFF(tty)) {
1270 info->x_char = START_CHAR(tty);
1271 /* Should use the "Send Special Character" feature!!! */
1272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001274 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001276 local_irq_save(flags);
1277 base_addr[CyCAR] = (u_char) channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 base_addr[CyMSVR1] = CyRTS;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001279 local_irq_restore(flags);
1280} /* cy_unthrottle */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
1282static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001283get_serial_info(struct cyclades_port *info,
1284 struct serial_struct __user * retinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001286 struct serial_struct tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
1288/* CP('g'); */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001289 if (!retinfo)
1290 return -EFAULT;
1291 memset(&tmp, 0, sizeof(tmp));
1292 tmp.type = info->type;
1293 tmp.line = info->line;
1294 tmp.port = info->line;
1295 tmp.irq = 0;
1296 tmp.flags = info->flags;
1297 tmp.baud_base = 0; /*!!! */
1298 tmp.close_delay = info->close_delay;
1299 tmp.custom_divisor = 0; /*!!! */
1300 tmp.hub6 = 0; /*!!! */
1301 return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
1302} /* get_serial_info */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
1304static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001305set_serial_info(struct cyclades_port *info,
1306 struct serial_struct __user * new_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001308 struct serial_struct new_serial;
1309 struct cyclades_port old_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
1311/* CP('s'); */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001312 if (!new_info)
1313 return -EFAULT;
1314 if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
1315 return -EFAULT;
1316 old_info = *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001318 if (!capable(CAP_SYS_ADMIN)) {
1319 if ((new_serial.close_delay != info->close_delay) ||
1320 ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
1321 (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
1322 return -EPERM;
1323 info->flags = ((info->flags & ~ASYNC_USR_MASK) |
1324 (new_serial.flags & ASYNC_USR_MASK));
1325 goto check_and_exit;
1326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001328 /*
1329 * OK, past this point, all the error checking has been done.
1330 * At this point, we start making changes.....
1331 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001333 info->flags = ((info->flags & ~ASYNC_FLAGS) |
1334 (new_serial.flags & ASYNC_FLAGS));
1335 info->close_delay = new_serial.close_delay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337check_and_exit:
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001338 if (info->flags & ASYNC_INITIALIZED) {
1339 config_setup(info);
1340 return 0;
1341 }
1342 return startup(info);
1343} /* set_serial_info */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001345static int cy_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001347 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1348 int channel;
1349 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1350 unsigned long flags;
1351 unsigned char status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001353 channel = info->line;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001355 local_irq_save(flags);
1356 base_addr[CyCAR] = (u_char) channel;
1357 status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
1358 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001360 return ((status & CyRTS) ? TIOCM_RTS : 0)
1361 | ((status & CyDTR) ? TIOCM_DTR : 0)
1362 | ((status & CyDCD) ? TIOCM_CAR : 0)
1363 | ((status & CyDSR) ? TIOCM_DSR : 0)
1364 | ((status & CyCTS) ? TIOCM_CTS : 0);
1365} /* cy_tiocmget */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
1367static int
1368cy_tiocmset(struct tty_struct *tty, struct file *file,
1369 unsigned int set, unsigned int clear)
1370{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001371 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1372 int channel;
1373 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1374 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001376 channel = info->line;
1377
1378 if (set & TIOCM_RTS) {
1379 local_irq_save(flags);
1380 base_addr[CyCAR] = (u_char) channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 base_addr[CyMSVR1] = CyRTS;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001382 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001384 if (set & TIOCM_DTR) {
1385 local_irq_save(flags);
1386 base_addr[CyCAR] = (u_char) channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387/* CP('S');CP('2'); */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001388 base_addr[CyMSVR2] = CyDTR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389#ifdef SERIAL_DEBUG_DTR
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001390 printk("cyc: %d: raising DTR\n", __LINE__);
1391 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1392 base_addr[CyMSVR2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001394 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 }
1396
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001397 if (clear & TIOCM_RTS) {
1398 local_irq_save(flags);
1399 base_addr[CyCAR] = (u_char) channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 base_addr[CyMSVR1] = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001401 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001403 if (clear & TIOCM_DTR) {
1404 local_irq_save(flags);
1405 base_addr[CyCAR] = (u_char) channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406/* CP('C');CP('2'); */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001407 base_addr[CyMSVR2] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408#ifdef SERIAL_DEBUG_DTR
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001409 printk("cyc: %d: dropping DTR\n", __LINE__);
1410 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1411 base_addr[CyMSVR2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001413 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 }
1415
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001416 return 0;
1417} /* set_modem_info */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001419static void send_break(struct cyclades_port *info, int duration)
1420{ /* Let the transmit ISR take care of this (since it
1421 requires stuffing characters into the output stream).
1422 */
1423 info->x_break = duration;
1424 if (!info->xmit_cnt) {
1425 start_xmit(info);
1426 }
1427} /* send_break */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
1429static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001430get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431{
1432
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001433 if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
1434 return -EFAULT;
1435 info->mon.int_count = 0;
1436 info->mon.char_count = 0;
1437 info->mon.char_max = 0;
1438 info->mon.char_last = 0;
1439 return 0;
1440}
1441
1442static int set_threshold(struct cyclades_port *info, unsigned long __user * arg)
1443{
1444 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1445 unsigned long value;
1446 int channel;
1447
1448 if (get_user(value, arg))
1449 return -EFAULT;
1450
1451 channel = info->line;
1452 info->cor4 &= ~CyREC_FIFO;
1453 info->cor4 |= value & CyREC_FIFO;
1454 base_addr[CyCOR4] = info->cor4;
1455 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456}
1457
1458static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001459get_threshold(struct cyclades_port *info, unsigned long __user * value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001461 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1462 int channel;
1463 unsigned long tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001465 channel = info->line;
1466
1467 tmp = base_addr[CyCOR4] & CyREC_FIFO;
1468 return put_user(tmp, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469}
1470
1471static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001472set_default_threshold(struct cyclades_port *info, unsigned long __user * arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001474 unsigned long value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001476 if (get_user(value, arg))
1477 return -EFAULT;
1478
1479 info->default_threshold = value & 0x0f;
1480 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481}
1482
1483static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001484get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001486 return put_user(info->default_threshold, value);
1487}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001489static int set_timeout(struct cyclades_port *info, unsigned long __user * arg)
1490{
1491 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1492 int channel;
1493 unsigned long value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001495 if (get_user(value, arg))
1496 return -EFAULT;
1497
1498 channel = info->line;
1499
1500 base_addr[CyRTPRL] = value & 0xff;
1501 base_addr[CyRTPRH] = (value >> 8) & 0xff;
1502 return 0;
1503}
1504
1505static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
1506{
1507 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1508 int channel;
1509 unsigned long tmp;
1510
1511 channel = info->line;
1512
1513 tmp = base_addr[CyRTPRL];
1514 return put_user(tmp, value);
1515}
1516
1517static int set_default_timeout(struct cyclades_port *info, unsigned long value)
1518{
1519 info->default_timeout = value & 0xff;
1520 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521}
1522
1523static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001524get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001526 return put_user(info->default_timeout, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527}
1528
1529static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001530cy_ioctl(struct tty_struct *tty, struct file *file,
1531 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001533 unsigned long val;
1534 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1535 int ret_val = 0;
1536 void __user *argp = (void __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
1538#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001539 printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540#endif
1541
Alan Cox638157b2008-04-30 00:53:22 -07001542 lock_kernel();
1543
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001544 switch (cmd) {
1545 case CYGETMON:
1546 ret_val = get_mon_info(info, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 break;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001548 case CYGETTHRESH:
1549 ret_val = get_threshold(info, argp);
1550 break;
1551 case CYSETTHRESH:
1552 ret_val = set_threshold(info, argp);
1553 break;
1554 case CYGETDEFTHRESH:
1555 ret_val = get_default_threshold(info, argp);
1556 break;
1557 case CYSETDEFTHRESH:
1558 ret_val = set_default_threshold(info, argp);
1559 break;
1560 case CYGETTIMEOUT:
1561 ret_val = get_timeout(info, argp);
1562 break;
1563 case CYSETTIMEOUT:
1564 ret_val = set_timeout(info, argp);
1565 break;
1566 case CYGETDEFTIMEOUT:
1567 ret_val = get_default_timeout(info, argp);
1568 break;
1569 case CYSETDEFTIMEOUT:
1570 ret_val = set_default_timeout(info, (unsigned long)arg);
1571 break;
1572 case TCSBRK: /* SVID version: non-zero arg --> no break */
1573 ret_val = tty_check_change(tty);
1574 if (ret_val)
1575 break;
1576 tty_wait_until_sent(tty, 0);
1577 if (!arg)
1578 send_break(info, HZ / 4); /* 1/4 second */
1579 break;
1580 case TCSBRKP: /* support for POSIX tcsendbreak() */
1581 ret_val = tty_check_change(tty);
1582 if (ret_val)
1583 break;
1584 tty_wait_until_sent(tty, 0);
1585 send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
1586 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
1588/* The following commands are incompletely implemented!!! */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001589 case TIOCGSERIAL:
1590 ret_val = get_serial_info(info, argp);
1591 break;
1592 case TIOCSSERIAL:
1593 ret_val = set_serial_info(info, argp);
1594 break;
1595 default:
1596 ret_val = -ENOIOCTLCMD;
1597 }
Alan Cox638157b2008-04-30 00:53:22 -07001598 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
1600#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001601 printk("cy_ioctl done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602#endif
1603
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001604 return ret_val;
1605} /* cy_ioctl */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001607static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001609 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
1611#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001612 printk("cy_set_termios %s\n", tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613#endif
1614
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001615 if (tty->termios->c_cflag == old_termios->c_cflag)
1616 return;
1617 config_setup(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001619 if ((old_termios->c_cflag & CRTSCTS) &&
1620 !(tty->termios->c_cflag & CRTSCTS)) {
1621 tty->stopped = 0;
1622 cy_start(tty);
1623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624#ifdef tytso_patch_94Nov25_1726
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001625 if (!(old_termios->c_cflag & CLOCAL) &&
1626 (tty->termios->c_cflag & CLOCAL))
1627 wake_up_interruptible(&info->open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001629} /* cy_set_termios */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001631static void cy_close(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001633 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
1635/* CP('C'); */
1636#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001637 printk("cy_close %s\n", tty->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638#endif
1639
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001640 if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
1641 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001643#ifdef SERIAL_DEBUG_OPEN
1644 printk("cy_close %s, count = %d\n", tty->name, info->count);
1645#endif
1646
1647 if ((tty->count == 1) && (info->count != 1)) {
1648 /*
1649 * Uh, oh. tty->count is 1, which means that the tty
1650 * structure will be freed. Info->count should always
1651 * be one in these conditions. If it's greater than
1652 * one, we've got real problems, since it means the
1653 * serial port won't be shutdown.
1654 */
1655 printk("cy_close: bad serial port count; tty->count is 1, "
1656 "info->count is %d\n", info->count);
1657 info->count = 1;
1658 }
1659#ifdef SERIAL_DEBUG_COUNT
1660 printk("cyc: %d: decrementing count to %d\n", __LINE__,
1661 info->count - 1);
1662#endif
1663 if (--info->count < 0) {
1664 printk("cy_close: bad serial port count for ttys%d: %d\n",
1665 info->line, info->count);
1666#ifdef SERIAL_DEBUG_COUNT
1667 printk("cyc: %d: setting count to 0\n", __LINE__);
1668#endif
1669 info->count = 0;
1670 }
1671 if (info->count)
1672 return;
1673 info->flags |= ASYNC_CLOSING;
1674 if (info->flags & ASYNC_INITIALIZED)
1675 tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
1676 shutdown(info);
Alan Cox978e5952008-04-30 00:53:59 -07001677 cy_flush_buffer(tty);
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001678 tty_ldisc_flush(tty);
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001679 info->tty = NULL;
1680 if (info->blocked_open) {
1681 if (info->close_delay) {
1682 msleep_interruptible(jiffies_to_msecs
1683 (info->close_delay));
1684 }
1685 wake_up_interruptible(&info->open_wait);
1686 }
1687 info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
1688 wake_up_interruptible(&info->close_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
1690#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001691 printk("cy_close done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001693} /* cy_close */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
1695/*
1696 * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
1697 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001698void cy_hangup(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001700 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1701
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001703 printk("cy_hangup %s\n", tty->name); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704#endif
1705
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001706 if (serial_paranoia_check(info, tty->name, "cy_hangup"))
1707 return;
1708
1709 shutdown(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710#if 0
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001711 info->event = 0;
1712 info->count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713#ifdef SERIAL_DEBUG_COUNT
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001714 printk("cyc: %d: setting count to 0\n", __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001716 info->tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001718 info->flags &= ~ASYNC_NORMAL_ACTIVE;
1719 wake_up_interruptible(&info->open_wait);
1720} /* cy_hangup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
1722/*
1723 * ------------------------------------------------------------
1724 * cy_open() and friends
1725 * ------------------------------------------------------------
1726 */
1727
1728static int
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001729block_til_ready(struct tty_struct *tty, struct file *filp,
1730 struct cyclades_port *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001732 DECLARE_WAITQUEUE(wait, current);
1733 unsigned long flags;
1734 int channel;
1735 int retval;
1736 volatile u_char *base_addr = (u_char *) BASE_ADDR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001738 /*
1739 * If the device is in the middle of being closed, then block
1740 * until it's done, and then try again.
1741 */
1742 if (info->flags & ASYNC_CLOSING) {
1743 interruptible_sleep_on(&info->close_wait);
1744 if (info->flags & ASYNC_HUP_NOTIFY) {
1745 return -EAGAIN;
1746 } else {
1747 return -ERESTARTSYS;
1748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001751 /*
1752 * If non-blocking mode is set, then make the check up front
1753 * and then exit.
1754 */
1755 if (filp->f_flags & O_NONBLOCK) {
1756 info->flags |= ASYNC_NORMAL_ACTIVE;
1757 return 0;
1758 }
1759
1760 /*
1761 * Block waiting for the carrier detect and the line to become
1762 * free (i.e., not in use by the callout). While we are in
1763 * this loop, info->count is dropped by one, so that
1764 * cy_close() knows when to free things. We restore it upon
1765 * exit, either normal or abnormal.
1766 */
1767 retval = 0;
1768 add_wait_queue(&info->open_wait, &wait);
1769#ifdef SERIAL_DEBUG_OPEN
1770 printk("block_til_ready before block: %s, count = %d\n",
1771 tty->name, info->count);
1772 /**/
1773#endif
1774 info->count--;
1775#ifdef SERIAL_DEBUG_COUNT
1776 printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
1777#endif
1778 info->blocked_open++;
1779
1780 channel = info->line;
1781
1782 while (1) {
1783 local_irq_save(flags);
1784 base_addr[CyCAR] = (u_char) channel;
1785 base_addr[CyMSVR1] = CyRTS;
1786/* CP('S');CP('4'); */
1787 base_addr[CyMSVR2] = CyDTR;
1788#ifdef SERIAL_DEBUG_DTR
1789 printk("cyc: %d: raising DTR\n", __LINE__);
1790 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1791 base_addr[CyMSVR2]);
1792#endif
1793 local_irq_restore(flags);
1794 set_current_state(TASK_INTERRUPTIBLE);
1795 if (tty_hung_up_p(filp)
1796 || !(info->flags & ASYNC_INITIALIZED)) {
1797 if (info->flags & ASYNC_HUP_NOTIFY) {
1798 retval = -EAGAIN;
1799 } else {
1800 retval = -ERESTARTSYS;
1801 }
1802 break;
1803 }
1804 local_irq_save(flags);
1805 base_addr[CyCAR] = (u_char) channel;
1806/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
1807 if (!(info->flags & ASYNC_CLOSING)
1808 && (C_CLOCAL(tty)
1809 || (base_addr[CyMSVR1] & CyDCD))) {
1810 local_irq_restore(flags);
1811 break;
1812 }
1813 local_irq_restore(flags);
1814 if (signal_pending(current)) {
1815 retval = -ERESTARTSYS;
1816 break;
1817 }
1818#ifdef SERIAL_DEBUG_OPEN
1819 printk("block_til_ready blocking: %s, count = %d\n",
1820 tty->name, info->count);
1821 /**/
1822#endif
1823 schedule();
1824 }
Milind Arun Choudharycc0a8fb2007-05-08 00:30:52 -07001825 __set_current_state(TASK_RUNNING);
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001826 remove_wait_queue(&info->open_wait, &wait);
1827 if (!tty_hung_up_p(filp)) {
1828 info->count++;
1829#ifdef SERIAL_DEBUG_COUNT
1830 printk("cyc: %d: incrementing count to %d\n", __LINE__,
1831 info->count);
1832#endif
1833 }
1834 info->blocked_open--;
1835#ifdef SERIAL_DEBUG_OPEN
1836 printk("block_til_ready after blocking: %s, count = %d\n",
1837 tty->name, info->count);
1838 /**/
1839#endif
1840 if (retval)
1841 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 info->flags |= ASYNC_NORMAL_ACTIVE;
1843 return 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001844} /* block_til_ready */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
1846/*
1847 * This routine is called whenever a serial port is opened. It
1848 * performs the serial-specific initialization for the tty structure.
1849 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001850int cy_open(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001852 struct cyclades_port *info;
1853 int retval, line;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854
1855/* CP('O'); */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001856 line = tty->index;
1857 if ((line < 0) || (NR_PORTS <= line)) {
1858 return -ENODEV;
1859 }
1860 info = &cy_port[line];
1861 if (info->line < 0) {
1862 return -ENODEV;
1863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864#ifdef SERIAL_DEBUG_OTHER
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001865 printk("cy_open %s\n", tty->name); /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001867 if (serial_paranoia_check(info, tty->name, "cy_open")) {
1868 return -ENODEV;
1869 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870#ifdef SERIAL_DEBUG_OPEN
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001871 printk("cy_open %s, count = %d\n", tty->name, info->count);
1872 /**/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001874 info->count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875#ifdef SERIAL_DEBUG_COUNT
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001876 printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001878 tty->driver_data = info;
1879 info->tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001881 /*
1882 * Start up serial port
1883 */
1884 retval = startup(info);
1885 if (retval) {
1886 return retval;
1887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001889 retval = block_til_ready(tty, filp, info);
1890 if (retval) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891#ifdef SERIAL_DEBUG_OPEN
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001892 printk("cy_open returning after block_til_ready with %d\n",
1893 retval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001895 return retval;
1896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897#ifdef SERIAL_DEBUG_OPEN
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001898 printk("cy_open done\n");
1899 /**/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001901 return 0;
1902} /* cy_open */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903
1904/*
1905 * ---------------------------------------------------------------------
1906 * serial167_init() and friends
1907 *
1908 * serial167_init() is called at boot-time to initialize the serial driver.
1909 * ---------------------------------------------------------------------
1910 */
1911
1912/*
1913 * This routine prints out the appropriate serial driver version
1914 * number, and identifies which options were configured into this
1915 * driver.
1916 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001917static void show_version(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001919 printk("MVME166/167 cd2401 driver\n");
1920} /* show_version */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921
1922/* initialize chips on card -- return number of valid
1923 chips (which is number of ports/4) */
1924
1925/*
1926 * This initialises the hardware to a reasonable state. It should
1927 * probe the chip first so as to copy 166-Bug setup as a default for
1928 * port 0. It initialises CMR to CyASYNC; that is never done again, so
1929 * as to limit the number of CyINIT_CHAN commands in normal running.
1930 *
1931 * ... I wonder what I should do if this fails ...
1932 */
1933
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001934void mvme167_serial_console_setup(int cflag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001936 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 int ch;
1938 u_char spd;
1939 u_char rcor, rbpr, badspeed = 0;
1940 unsigned long flags;
1941
1942 local_irq_save(flags);
1943
1944 /*
1945 * First probe channel zero of the chip, to see what speed has
1946 * been selected.
1947 */
1948
1949 base_addr[CyCAR] = 0;
1950
1951 rcor = base_addr[CyRCOR] << 5;
1952 rbpr = base_addr[CyRBPR];
1953
1954 for (spd = 0; spd < sizeof(baud_bpr); spd++)
1955 if (rbpr == baud_bpr[spd] && rcor == baud_co[spd])
1956 break;
1957 if (spd >= sizeof(baud_bpr)) {
1958 spd = 14; /* 19200 */
1959 badspeed = 1; /* Failed to identify speed */
1960 }
1961 initial_console_speed = spd;
1962
1963 /* OK, we have chosen a speed, now reset and reinitialise */
1964
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001965 my_udelay(20000L); /* Allow time for any active o/p to complete */
1966 if (base_addr[CyCCR] != 0x00) {
1967 local_irq_restore(flags);
1968 /* printk(" chip is never idle (CCR != 0)\n"); */
1969 return;
1970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001972 base_addr[CyCCR] = CyCHIP_RESET; /* Reset the chip */
1973 my_udelay(1000L);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001974
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001975 if (base_addr[CyGFRCR] == 0x00) {
1976 local_irq_restore(flags);
1977 /* printk(" chip is not responding (GFRCR stayed 0)\n"); */
1978 return;
1979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980
1981 /*
1982 * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms
1983 * tick
1984 */
1985
1986 base_addr[CyTPR] = 10;
1987
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001988 base_addr[CyPILR1] = 0x01; /* Interrupt level for modem change */
1989 base_addr[CyPILR2] = 0x02; /* Interrupt level for tx ints */
1990 base_addr[CyPILR3] = 0x03; /* Interrupt level for rx ints */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991
1992 /*
1993 * Attempt to set up all channels to something reasonable, and
1994 * bang out a INIT_CHAN command. We should then be able to limit
1995 * the ammount of fiddling we have to do in normal running.
1996 */
1997
Jiri Slaby44bafdf2007-02-10 01:45:08 -08001998 for (ch = 3; ch >= 0; ch--) {
1999 base_addr[CyCAR] = (u_char) ch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 base_addr[CyIER] = 0;
2001 base_addr[CyCMR] = CyASYNC;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002002 base_addr[CyLICR] = (u_char) ch << 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 base_addr[CyLIVR] = 0x5c;
2004 base_addr[CyTCOR] = baud_co[spd];
2005 base_addr[CyTBPR] = baud_bpr[spd];
2006 base_addr[CyRCOR] = baud_co[spd] >> 5;
2007 base_addr[CyRBPR] = baud_bpr[spd];
2008 base_addr[CySCHR1] = 'Q' & 0x1f;
2009 base_addr[CySCHR2] = 'X' & 0x1f;
2010 base_addr[CySCRL] = 0;
2011 base_addr[CySCRH] = 0;
2012 base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
2013 base_addr[CyCOR2] = 0;
2014 base_addr[CyCOR3] = Cy_1_STOP;
2015 base_addr[CyCOR4] = baud_cor4[spd];
2016 base_addr[CyCOR5] = 0;
2017 base_addr[CyCOR6] = 0;
2018 base_addr[CyCOR7] = 0;
2019 base_addr[CyRTPRL] = 2;
2020 base_addr[CyRTPRH] = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002021 base_addr[CyMSVR1] = 0;
2022 base_addr[CyMSVR2] = 0;
2023 write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 }
2025
2026 /*
2027 * Now do specials for channel zero....
2028 */
2029
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002030 base_addr[CyMSVR1] = CyRTS;
2031 base_addr[CyMSVR2] = CyDTR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 base_addr[CyIER] = CyRxData;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002033 write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
2035 local_irq_restore(flags);
2036
2037 my_udelay(20000L); /* Let it all settle down */
2038
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002039 printk("CD2401 initialised, chip is rev 0x%02x\n", base_addr[CyGFRCR]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 if (badspeed)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002041 printk
2042 (" WARNING: Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
2043 rcor >> 5, rbpr);
2044} /* serial_console_init */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
Jeff Dikeb68e31d2006-10-02 02:17:18 -07002046static const struct tty_operations cy_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 .open = cy_open,
2048 .close = cy_close,
2049 .write = cy_write,
2050 .put_char = cy_put_char,
2051 .flush_chars = cy_flush_chars,
2052 .write_room = cy_write_room,
2053 .chars_in_buffer = cy_chars_in_buffer,
2054 .flush_buffer = cy_flush_buffer,
2055 .ioctl = cy_ioctl,
2056 .throttle = cy_throttle,
2057 .unthrottle = cy_unthrottle,
2058 .set_termios = cy_set_termios,
2059 .stop = cy_stop,
2060 .start = cy_start,
2061 .hangup = cy_hangup,
2062 .tiocmget = cy_tiocmget,
2063 .tiocmset = cy_tiocmset,
2064};
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002065
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066/* The serial driver boot-time initialization code!
2067 Hardware I/O ports are mapped to character special devices on a
2068 first found, first allocated manner. That is, this code searches
2069 for Cyclom cards in the system. As each is found, it is probed
2070 to discover how many chips (and thus how many ports) are present.
2071 These ports are mapped to the tty ports 64 and upward in monotonic
2072 fashion. If an 8-port card is replaced with a 16-port card, the
2073 port mapping on a following card will shift.
2074
2075 This approach is different from what is used in the other serial
2076 device driver because the Cyclom is more properly a multiplexer,
2077 not just an aggregation of serial ports on one card.
2078
2079 If there are more cards with more ports than have been statically
2080 allocated above, a warning is printed and the extra ports are ignored.
2081 */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002082static int __init serial167_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002084 struct cyclades_port *info;
2085 int ret = 0;
2086 int good_ports = 0;
2087 int port_num = 0;
2088 int index;
2089 int DefSpeed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090#ifdef notyet
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002091 struct sigaction sa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092#endif
2093
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002094 if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401))
2095 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002097 cy_serial_driver = alloc_tty_driver(NR_PORTS);
2098 if (!cy_serial_driver)
2099 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
2101#if 0
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002102 scrn[1] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103#endif
2104
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002105 show_version();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002107 /* Has "console=0,9600n8" been used in bootinfo to change speed? */
2108 if (serial_console_cflag)
2109 DefSpeed = serial_console_cflag & 0017;
2110 else {
2111 DefSpeed = initial_console_speed;
2112 serial_console_info = &cy_port[0];
2113 serial_console_cflag = DefSpeed | CS8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114#if 0
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002115 serial_console = 64; /*callout_driver.minor_start */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002118
2119 /* Initialize the tty_driver structure */
2120
2121 cy_serial_driver->owner = THIS_MODULE;
2122 cy_serial_driver->name = "ttyS";
2123 cy_serial_driver->major = TTY_MAJOR;
2124 cy_serial_driver->minor_start = 64;
2125 cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
2126 cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
2127 cy_serial_driver->init_termios = tty_std_termios;
2128 cy_serial_driver->init_termios.c_cflag =
2129 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2130 cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
2131 tty_set_operations(cy_serial_driver, &cy_ops);
2132
2133 ret = tty_register_driver(cy_serial_driver);
2134 if (ret) {
2135 printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
2136 put_tty_driver(cy_serial_driver);
2137 return ret;
2138 }
2139
2140 port_num = 0;
2141 info = cy_port;
2142 for (index = 0; index < 1; index++) {
2143
2144 good_ports = 4;
2145
2146 if (port_num < NR_PORTS) {
2147 while (good_ports-- && port_num < NR_PORTS) {
2148 /*** initialize port ***/
2149 info->magic = CYCLADES_MAGIC;
2150 info->type = PORT_CIRRUS;
2151 info->card = index;
2152 info->line = port_num;
2153 info->flags = STD_COM_FLAGS;
2154 info->tty = NULL;
2155 info->xmit_fifo_size = 12;
2156 info->cor1 = CyPARITY_NONE | Cy_8_BITS;
2157 info->cor2 = CyETC;
2158 info->cor3 = Cy_1_STOP;
2159 info->cor4 = 0x08; /* _very_ small receive threshold */
2160 info->cor5 = 0;
2161 info->cor6 = 0;
2162 info->cor7 = 0;
2163 info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */
2164 info->tco = baud_co[DefSpeed]; /* Tx CO */
2165 info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */
2166 info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */
2167 info->close_delay = 0;
2168 info->x_char = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002169 info->count = 0;
2170#ifdef SERIAL_DEBUG_COUNT
2171 printk("cyc: %d: setting count to 0\n",
2172 __LINE__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173#endif
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002174 info->blocked_open = 0;
2175 info->default_threshold = 0;
2176 info->default_timeout = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002177 init_waitqueue_head(&info->open_wait);
2178 init_waitqueue_head(&info->close_wait);
2179 /* info->session */
2180 /* info->pgrp */
2181/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
2182 info->read_status_mask =
2183 CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY |
2184 CyFRAME | CyOVERRUN;
2185 /* info->timeout */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002187 printk("ttyS%d ", info->line);
2188 port_num++;
2189 info++;
2190 if (!(port_num & 7)) {
2191 printk("\n ");
2192 }
2193 }
2194 }
2195 printk("\n");
2196 }
2197 while (port_num < NR_PORTS) {
2198 info->line = -1;
2199 port_num++;
2200 info++;
2201 }
2202#ifdef CONFIG_REMOTE_DEBUG
2203 debug_setup();
2204#endif
2205 ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
2206 "cd2401_errors", cd2401_rxerr_interrupt);
2207 if (ret) {
2208 printk(KERN_ERR "Could't get cd2401_errors IRQ");
2209 goto cleanup_serial_driver;
2210 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002212 ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
2213 "cd2401_modem", cd2401_modem_interrupt);
2214 if (ret) {
2215 printk(KERN_ERR "Could't get cd2401_modem IRQ");
2216 goto cleanup_irq_cd2401_errors;
2217 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002219 ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
2220 "cd2401_txints", cd2401_tx_interrupt);
2221 if (ret) {
2222 printk(KERN_ERR "Could't get cd2401_txints IRQ");
2223 goto cleanup_irq_cd2401_modem;
2224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002226 ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
2227 "cd2401_rxints", cd2401_rx_interrupt);
2228 if (ret) {
2229 printk(KERN_ERR "Could't get cd2401_rxints IRQ");
2230 goto cleanup_irq_cd2401_txints;
2231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002233 /* Now we have registered the interrupt handlers, allow the interrupts */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002235 pcc2chip[PccSCCMICR] = 0x15; /* Serial ints are level 5 */
2236 pcc2chip[PccSCCTICR] = 0x15;
2237 pcc2chip[PccSCCRICR] = 0x15;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002239 pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */
2240
2241 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242cleanup_irq_cd2401_txints:
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002243 free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244cleanup_irq_cd2401_modem:
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002245 free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246cleanup_irq_cd2401_errors:
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002247 free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248cleanup_serial_driver:
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002249 if (tty_unregister_driver(cy_serial_driver))
2250 printk(KERN_ERR
2251 "Couldn't unregister MVME166/7 serial driver\n");
2252 put_tty_driver(cy_serial_driver);
2253 return ret;
2254} /* serial167_init */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255
2256module_init(serial167_init);
2257
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258#ifdef CYCLOM_SHOW_STATUS
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002259static void show_status(int line_num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002261 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2262 int channel;
2263 struct cyclades_port *info;
2264 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002266 info = &cy_port[line_num];
2267 channel = info->line;
2268 printk(" channel %d\n", channel);
2269 /**/ printk(" cy_port\n");
2270 printk(" card line flags = %d %d %x\n",
2271 info->card, info->line, info->flags);
2272 printk
2273 (" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
2274 (long)info->tty, info->read_status_mask, info->timeout,
2275 info->xmit_fifo_size);
2276 printk(" cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
2277 info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
2278 info->cor6, info->cor7);
2279 printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco,
2280 info->rbpr, info->rco);
2281 printk(" close_delay event count = %d %d %d\n", info->close_delay,
2282 info->event, info->count);
2283 printk(" x_char blocked_open = %x %x\n", info->x_char,
2284 info->blocked_open);
2285 printk(" open_wait = %lx %lx %lx\n", (long)info->open_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002287 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
2289/* Global Registers */
2290
2291 printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
2292 printk(" CyCAR %x\n", base_addr[CyCAR]);
2293 printk(" CyRISR %x\n", base_addr[CyRISR]);
2294 printk(" CyTISR %x\n", base_addr[CyTISR]);
2295 printk(" CyMISR %x\n", base_addr[CyMISR]);
2296 printk(" CyRIR %x\n", base_addr[CyRIR]);
2297 printk(" CyTIR %x\n", base_addr[CyTIR]);
2298 printk(" CyMIR %x\n", base_addr[CyMIR]);
2299 printk(" CyTPR %x\n", base_addr[CyTPR]);
2300
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002301 base_addr[CyCAR] = (u_char) channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
2303/* Virtual Registers */
2304
2305#if 0
2306 printk(" CyRIVR %x\n", base_addr[CyRIVR]);
2307 printk(" CyTIVR %x\n", base_addr[CyTIVR]);
2308 printk(" CyMIVR %x\n", base_addr[CyMIVR]);
2309 printk(" CyMISR %x\n", base_addr[CyMISR]);
2310#endif
2311
2312/* Channel Registers */
2313
2314 printk(" CyCCR %x\n", base_addr[CyCCR]);
2315 printk(" CyIER %x\n", base_addr[CyIER]);
2316 printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
2317 printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
2318 printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
2319 printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
2320 printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
2321#if 0
2322 printk(" CyCCSR %x\n", base_addr[CyCCSR]);
2323 printk(" CyRDCR %x\n", base_addr[CyRDCR]);
2324#endif
2325 printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
2326 printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
2327#if 0
2328 printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
2329 printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
2330 printk(" CySCRL %x\n", base_addr[CySCRL]);
2331 printk(" CySCRH %x\n", base_addr[CySCRH]);
2332 printk(" CyLNC %x\n", base_addr[CyLNC]);
2333 printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
2334 printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
2335#endif
2336 printk(" CyRTPRL %x\n", base_addr[CyRTPRL]);
2337 printk(" CyRTPRH %x\n", base_addr[CyRTPRH]);
2338 printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
2339 printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
2340 printk(" CyRBPR %x\n", base_addr[CyRBPR]);
2341 printk(" CyRCOR %x\n", base_addr[CyRCOR]);
2342 printk(" CyTBPR %x\n", base_addr[CyTBPR]);
2343 printk(" CyTCOR %x\n", base_addr[CyTCOR]);
2344
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002345 local_irq_restore(flags);
2346} /* show_status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347#endif
2348
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349#if 0
2350/* Dummy routine in mvme16x/config.c for now */
2351
2352/* Serial console setup. Called from linux/init/main.c */
2353
2354void console_setup(char *str, int *ints)
2355{
2356 char *s;
2357 int baud, bits, parity;
2358 int cflag = 0;
2359
2360 /* Sanity check. */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002361 if (ints[0] > 3 || ints[1] > 3)
2362 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
2364 /* Get baud, bits and parity */
2365 baud = 2400;
2366 bits = 8;
2367 parity = 'n';
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002368 if (ints[2])
2369 baud = ints[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 if ((s = strchr(str, ','))) {
2371 do {
2372 s++;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002373 } while (*s >= '0' && *s <= '9');
2374 if (*s)
2375 parity = *s++;
2376 if (*s)
2377 bits = *s - '0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 }
2379
2380 /* Now construct a cflag setting. */
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002381 switch (baud) {
2382 case 1200:
2383 cflag |= B1200;
2384 break;
2385 case 9600:
2386 cflag |= B9600;
2387 break;
2388 case 19200:
2389 cflag |= B19200;
2390 break;
2391 case 38400:
2392 cflag |= B38400;
2393 break;
2394 case 2400:
2395 default:
2396 cflag |= B2400;
2397 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002399 switch (bits) {
2400 case 7:
2401 cflag |= CS7;
2402 break;
2403 default:
2404 case 8:
2405 cflag |= CS8;
2406 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 }
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002408 switch (parity) {
2409 case 'o':
2410 case 'O':
2411 cflag |= PARODD;
2412 break;
2413 case 'e':
2414 case 'E':
2415 cflag |= PARENB;
2416 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 }
2418
2419 serial_console_info = &cy_port[ints[1]];
2420 serial_console_cflag = cflag;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002421 serial_console = ints[1] + 64; /*callout_driver.minor_start */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422}
2423#endif
2424
2425/*
2426 * The following is probably out of date for 2.1.x serial console stuff.
2427 *
2428 * The console is registered early on from arch/m68k/kernel/setup.c, and
2429 * it therefore relies on the chip being setup correctly by 166-Bug. This
2430 * seems reasonable, as the serial port has been used to invoke the system
2431 * boot. It also means that this function must not rely on any data
2432 * initialisation performed by serial167_init() etc.
2433 *
2434 * Of course, once the console has been registered, we had better ensure
2435 * that serial167_init() doesn't leave the chip non-functional.
2436 *
2437 * The console must be locked when we get here.
2438 */
2439
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002440void serial167_console_write(struct console *co, const char *str,
2441 unsigned count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002443 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 unsigned long flags;
2445 volatile u_char sink;
2446 u_char ier;
2447 int port;
2448 u_char do_lf = 0;
2449 int i = 0;
2450
2451 local_irq_save(flags);
2452
2453 /* Ensure transmitter is enabled! */
2454
2455 port = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002456 base_addr[CyCAR] = (u_char) port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 while (base_addr[CyCCR])
2458 ;
2459 base_addr[CyCCR] = CyENB_XMTR;
2460
2461 ier = base_addr[CyIER];
2462 base_addr[CyIER] = CyTxMpty;
2463
2464 while (1) {
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002465 if (pcc2chip[PccSCCTICR] & 0x20) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 /* We have a Tx int. Acknowledge it */
2467 sink = pcc2chip[PccTPIACKR];
2468 if ((base_addr[CyLICR] >> 2) == port) {
2469 if (i == count) {
2470 /* Last char of string is now output */
2471 base_addr[CyTEOIR] = CyNOTRANS;
2472 break;
2473 }
2474 if (do_lf) {
2475 base_addr[CyTDR] = '\n';
2476 str++;
2477 i++;
2478 do_lf = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002479 } else if (*str == '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 base_addr[CyTDR] = '\r';
2481 do_lf = 1;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002482 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 base_addr[CyTDR] = *str++;
2484 i++;
2485 }
2486 base_addr[CyTEOIR] = 0;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002487 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 base_addr[CyTEOIR] = CyNOTRANS;
2489 }
2490 }
2491
2492 base_addr[CyIER] = ier;
2493
2494 local_irq_restore(flags);
2495}
2496
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002497static struct tty_driver *serial167_console_device(struct console *c,
2498 int *index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499{
2500 *index = c->index;
2501 return cy_serial_driver;
2502}
2503
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504static struct console sercons = {
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002505 .name = "ttyS",
2506 .write = serial167_console_write,
2507 .device = serial167_console_device,
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002508 .flags = CON_PRINTBUFFER,
2509 .index = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510};
2511
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512static int __init serial167_console_init(void)
2513{
2514 if (vme_brdtype == VME_TYPE_MVME166 ||
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002515 vme_brdtype == VME_TYPE_MVME167 ||
2516 vme_brdtype == VME_TYPE_MVME177) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 mvme167_serial_console_setup(0);
2518 register_console(&sercons);
2519 }
2520 return 0;
2521}
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002522
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523console_initcall(serial167_console_init);
2524
2525#ifdef CONFIG_REMOTE_DEBUG
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002526void putDebugChar(int c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002528 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 unsigned long flags;
2530 volatile u_char sink;
2531 u_char ier;
2532 int port;
2533
2534 local_irq_save(flags);
2535
2536 /* Ensure transmitter is enabled! */
2537
2538 port = DEBUG_PORT;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002539 base_addr[CyCAR] = (u_char) port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 while (base_addr[CyCCR])
2541 ;
2542 base_addr[CyCCR] = CyENB_XMTR;
2543
2544 ier = base_addr[CyIER];
2545 base_addr[CyIER] = CyTxMpty;
2546
2547 while (1) {
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002548 if (pcc2chip[PccSCCTICR] & 0x20) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 /* We have a Tx int. Acknowledge it */
2550 sink = pcc2chip[PccTPIACKR];
2551 if ((base_addr[CyLICR] >> 2) == port) {
2552 base_addr[CyTDR] = c;
2553 base_addr[CyTEOIR] = 0;
2554 break;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002555 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 base_addr[CyTEOIR] = CyNOTRANS;
2557 }
2558 }
2559
2560 base_addr[CyIER] = ier;
2561
2562 local_irq_restore(flags);
2563}
2564
2565int getDebugChar()
2566{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002567 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 unsigned long flags;
2569 volatile u_char sink;
2570 u_char ier;
2571 int port;
2572 int i, c;
2573
2574 i = debugiq.out;
2575 if (i != debugiq.in) {
2576 c = debugiq.buf[i];
2577 if (++i == DEBUG_LEN)
2578 i = 0;
2579 debugiq.out = i;
2580 return c;
2581 }
2582 /* OK, nothing in queue, wait in poll loop */
2583
2584 local_irq_save(flags);
2585
2586 /* Ensure receiver is enabled! */
2587
2588 port = DEBUG_PORT;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002589 base_addr[CyCAR] = (u_char) port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590#if 0
2591 while (base_addr[CyCCR])
2592 ;
2593 base_addr[CyCCR] = CyENB_RCVR;
2594#endif
2595 ier = base_addr[CyIER];
2596 base_addr[CyIER] = CyRxData;
2597
2598 while (1) {
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002599 if (pcc2chip[PccSCCRICR] & 0x20) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 /* We have a Rx int. Acknowledge it */
2601 sink = pcc2chip[PccRPIACKR];
2602 if ((base_addr[CyLICR] >> 2) == port) {
2603 int cnt = base_addr[CyRFOC];
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002604 while (cnt-- > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 c = base_addr[CyRDR];
2606 if (c == 0)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002607 printk
2608 ("!! debug char is null (cnt=%d) !!",
2609 cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 else
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002611 queueDebugChar(c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 }
2613 base_addr[CyREOIR] = 0;
2614 i = debugiq.out;
2615 if (i == debugiq.in)
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002616 panic("Debug input queue empty!");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 c = debugiq.buf[i];
2618 if (++i == DEBUG_LEN)
2619 i = 0;
2620 debugiq.out = i;
2621 break;
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002622 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 base_addr[CyREOIR] = CyNOTRANS;
2624 }
2625 }
2626
2627 base_addr[CyIER] = ier;
2628
2629 local_irq_restore(flags);
2630
2631 return (c);
2632}
2633
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002634void queueDebugChar(int c)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635{
2636 int i;
2637
2638 i = debugiq.in;
2639 debugiq.buf[i] = c;
2640 if (++i == DEBUG_LEN)
2641 i = 0;
2642 if (i != debugiq.out)
2643 debugiq.in = i;
2644}
2645
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002646static void debug_setup()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647{
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002648 unsigned long flags;
2649 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2650 int i, cflag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002652 cflag = B19200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002654 local_irq_save(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002656 for (i = 0; i < 4; i++) {
2657 base_addr[CyCAR] = i;
2658 base_addr[CyLICR] = i << 2;
2659 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002661 debugiq.in = debugiq.out = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002663 base_addr[CyCAR] = DEBUG_PORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002665 /* baud rate */
2666 i = cflag & CBAUD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002668 base_addr[CyIER] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002670 base_addr[CyCMR] = CyASYNC;
2671 base_addr[CyLICR] = DEBUG_PORT << 2;
2672 base_addr[CyLIVR] = 0x5c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002674 /* tx and rx baud rate */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002676 base_addr[CyTCOR] = baud_co[i];
2677 base_addr[CyTBPR] = baud_bpr[i];
2678 base_addr[CyRCOR] = baud_co[i] >> 5;
2679 base_addr[CyRBPR] = baud_bpr[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002681 /* set line characteristics according configuration */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002683 base_addr[CySCHR1] = 0;
2684 base_addr[CySCHR2] = 0;
2685 base_addr[CySCRL] = 0;
2686 base_addr[CySCRH] = 0;
2687 base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
2688 base_addr[CyCOR2] = 0;
2689 base_addr[CyCOR3] = Cy_1_STOP;
2690 base_addr[CyCOR4] = baud_cor4[i];
2691 base_addr[CyCOR5] = 0;
2692 base_addr[CyCOR6] = 0;
2693 base_addr[CyCOR7] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002695 write_cy_cmd(base_addr, CyINIT_CHAN);
2696 write_cy_cmd(base_addr, CyENB_RCVR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002698 base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002700 base_addr[CyRTPRL] = 2;
2701 base_addr[CyRTPRH] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002703 base_addr[CyMSVR1] = CyRTS;
2704 base_addr[CyMSVR2] = CyDTR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002706 base_addr[CyIER] = CyRxData;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002708 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
Jiri Slaby44bafdf2007-02-10 01:45:08 -08002710} /* debug_setup */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711
2712#endif
2713
2714MODULE_LICENSE("GPL");