drivers/char/ds1286.c: use time_before, time_before_eq, etc
[linux-2.6-block.git] / drivers / char / serial167.c
CommitLineData
1da177e4
LT
1/*
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
1da177e4
LT
47#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>
81e859ac 65#include <linux/tty_flip.h>
1da177e4
LT
66
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
1da177e4
LT
93static 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[] = {
44bafdf3
JS
112 /* CARD# */
113 {-1}, /* ttyS0 */
114 {-1}, /* ttyS1 */
115 {-1}, /* ttyS2 */
116 {-1}, /* ttyS3 */
1da177e4 117};
44bafdf3 118
fe971071 119#define NR_PORTS ARRAY_SIZE(cy_port)
1da177e4 120
1da177e4
LT
121/*
122 * 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[] = {
44bafdf3
JS
130 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
131 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
132 0
133};
1da177e4
LT
134
135#if 0
44bafdf3
JS
136static 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};
1da177e4 142
44bafdf3
JS
143static 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};
1da177e4
LT
147#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 */
44bafdf3
JS
152static 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};
1da177e4
LT
156
157/* These values written directly to tbpr/rbpr */
44bafdf3
JS
158static 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};
1da177e4 162
44bafdf3
JS
163static 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};
1da177e4
LT
167
168static void shutdown(struct cyclades_port *);
44bafdf3 169static int startup(struct cyclades_port *);
1da177e4
LT
170static 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);
44bafdf3 180void queueDebugChar(int c);
1da177e4
LT
181int getDebugChar(void);
182
183#define DEBUG_PORT 1
184#define DEBUG_LEN 256
185
186typedef struct {
44bafdf3
JS
187 int in;
188 int out;
189 unsigned char buf[DEBUG_LEN];
1da177e4
LT
190} 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
44bafdf3 202void my_udelay(long us)
1da177e4
LT
203{
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
44bafdf3
JS
213static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
214 const char *routine)
1da177e4
LT
215{
216#ifdef SERIAL_PARANOIA_CHECK
44bafdf3
JS
217 if (!info) {
218 printk("Warning: null cyclades_port for (%s) in %s\n", name,
219 routine);
220 return 1;
221 }
222
223 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 }
229
230 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 }
1da177e4
LT
235#endif
236 return 0;
44bafdf3 237} /* serial_paranoia_check */
1da177e4
LT
238
239#if 0
240/* The following diagnostic routines allow the driver to spew
241 information on the screen, even (especially!) during interrupts.
242 */
44bafdf3
JS
243void SP(char *data)
244{
245 unsigned long flags;
246 local_irq_save(flags);
247 console_print(data);
248 local_irq_restore(flags);
1da177e4 249}
44bafdf3 250
1da177e4 251char scrn[2];
44bafdf3
JS
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 */
1da177e4 260
44bafdf3
JS
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 */
1da177e4
LT
280#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 */
44bafdf3 287u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
1da177e4 288{
44bafdf3
JS
289 unsigned long flags;
290 volatile int i;
1da177e4 291
44bafdf3 292 local_irq_save(flags);
1da177e4 293 /* Check to see that the previous command has completed */
44bafdf3
JS
294 for (i = 0; i < 100; i++) {
295 if (base_addr[CyCCR] == 0) {
296 break;
297 }
298 my_udelay(10L);
1da177e4
LT
299 }
300 /* if the CCR never cleared, the previous command
44bafdf3
JS
301 didn't finish within the "reasonable time" */
302 if (i == 10) {
303 local_irq_restore(flags);
304 return (-1);
1da177e4
LT
305 }
306
307 /* Issue the new command */
308 base_addr[CyCCR] = cmd;
44bafdf3
JS
309 local_irq_restore(flags);
310 return (0);
311} /* write_cy_cmd */
1da177e4
LT
312
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
44bafdf3 316static void cy_stop(struct tty_struct *tty)
1da177e4 317{
44bafdf3
JS
318 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;
1da177e4
LT
322
323#ifdef SERIAL_DEBUG_OTHER
44bafdf3 324 printk("cy_stop %s\n", tty->name); /* */
1da177e4
LT
325#endif
326
44bafdf3
JS
327 if (serial_paranoia_check(info, tty->name, "cy_stop"))
328 return;
1da177e4 329
44bafdf3 330 channel = info->line;
1da177e4 331
44bafdf3
JS
332 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 */
1da177e4 337
44bafdf3 338static void cy_start(struct tty_struct *tty)
1da177e4 339{
44bafdf3
JS
340 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;
1da177e4
LT
344
345#ifdef SERIAL_DEBUG_OTHER
44bafdf3 346 printk("cy_start %s\n", tty->name); /* */
1da177e4
LT
347#endif
348
44bafdf3
JS
349 if (serial_paranoia_check(info, tty->name, "cy_start"))
350 return;
1da177e4 351
44bafdf3 352 channel = info->line;
1da177e4 353
44bafdf3
JS
354 local_irq_save(flags);
355 base_addr[CyCAR] = (u_char) (channel);
356 base_addr[CyIER] |= CyTxMpty;
357 local_irq_restore(flags);
358} /* cy_start */
1da177e4 359
1da177e4
LT
360/* 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 */
44bafdf3 364static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
1da177e4 365{
44bafdf3
JS
366 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;
372
373 /* 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;
377
378 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 }
1da177e4 383
44bafdf3
JS
384 /* Read a byte of data if there is any - assume the error
385 * is associated with this character */
1da177e4 386
44bafdf3
JS
387 if ((rfoc = base_addr[CyRFOC]) != 0)
388 data = base_addr[CyRDR];
389 else
390 data = 0;
391
392 /* 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 */
1da177e4
LT
447 base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
448 return IRQ_HANDLED;
44bafdf3
JS
449} /* cy_rxerr_interrupt */
450
451static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
1da177e4 452{
44bafdf3
JS
453 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;
458
459 /* 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;
463
464 mdm_change = base_addr[CyMISR];
465 mdm_status = base_addr[CyMSVR1];
466
467 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) {
1da177e4 473/* CP('!'); */
3099bbc5 474 wake_up_interruptible(&info->open_wait);
44bafdf3 475 } else {
1da177e4 476/* CP('@'); */
3099bbc5
JS
477 tty_hangup(info->tty);
478 wake_up_interruptible(&info->open_wait);
479 info->flags &= ~ASYNC_NORMAL_ACTIVE;
44bafdf3 480 }
1da177e4 481 }
44bafdf3
JS
482 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;
3099bbc5 489 tty_wakeup(info->tty);
44bafdf3
JS
490 }
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 }
499 }
500 if (mdm_status & CyDSR) {
1da177e4 501 }
1da177e4 502 }
44bafdf3
JS
503 base_addr[CyMEOIR] = 0;
504 return IRQ_HANDLED;
505} /* cy_modem_interrupt */
1da177e4 506
44bafdf3 507static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
1da177e4 508{
44bafdf3
JS
509 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;
1da177e4 514
44bafdf3
JS
515 /* determine the channel and change to that context */
516 channel = (u_short) (base_addr[CyLICR] >> 2);
1da177e4
LT
517
518#ifdef CONFIG_REMOTE_DEBUG
44bafdf3
JS
519 if (channel == DEBUG_PORT) {
520 panic("TxInt on debug port!!!");
521 }
1da177e4
LT
522#endif
523
44bafdf3 524 info = &cy_port[channel];
1da177e4 525
44bafdf3
JS
526 /* 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;
531 }
532 info->last_active = jiffies;
533 if (info->tty == 0) {
534 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
44bafdf3
JS
535 base_addr[CyTEOIR] = CyNOTRANS;
536 return IRQ_HANDLED;
537 }
538
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;
1da177e4 544 base_addr[CyTDR] = outch;
1da177e4 545 char_count--;
44bafdf3 546 info->x_char = 0;
1da177e4 547 }
1da177e4 548
44bafdf3
JS
549 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 }
569
570 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
3099bbc5
JS
616 if (info->xmit_cnt < WAKEUP_CHARS)
617 tty_wakeup(info->tty);
618
44bafdf3
JS
619 base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
620 return IRQ_HANDLED;
621} /* cy_tx_interrupt */
1da177e4 622
44bafdf3 623static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
1da177e4 624{
44bafdf3
JS
625 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;
633
634 /* 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];
1da177e4
LT
639
640#ifdef CONFIG_REMOTE_DEBUG
44bafdf3
JS
641 if (channel == DEBUG_PORT) {
642 while (char_count--) {
643 data = base_addr[CyRDR];
644 queueDebugChar(data);
645 }
646 } else
1da177e4 647#endif
44bafdf3
JS
648 /* 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 */
1da177e4
LT
656
657#ifdef CYCLOM_ENABLE_MONITORING
44bafdf3
JS
658 ++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;
663#endif
664 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);
1da177e4 668#ifdef CYCLOM_16Y_HACK
44bafdf3 669 udelay(10L);
1da177e4 670#endif
44bafdf3
JS
671 }
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 */
1da177e4 678
1da177e4
LT
679/* This is called whenever a port becomes active;
680 interrupts are enabled and DTR & RTS are turned on.
681 */
44bafdf3 682static int startup(struct cyclades_port *info)
1da177e4 683{
44bafdf3
JS
684 unsigned long flags;
685 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
686 int channel;
1da177e4 687
44bafdf3
JS
688 if (info->flags & ASYNC_INITIALIZED) {
689 return 0;
690 }
1da177e4 691
44bafdf3
JS
692 if (!info->type) {
693 if (info->tty) {
694 set_bit(TTY_IO_ERROR, &info->tty->flags);
695 }
696 return 0;
1da177e4 697 }
44bafdf3
JS
698 if (!info->xmit_buf) {
699 info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
700 if (!info->xmit_buf) {
701 return -ENOMEM;
702 }
1da177e4 703 }
1da177e4 704
44bafdf3 705 config_setup(info);
1da177e4 706
44bafdf3 707 channel = info->line;
1da177e4
LT
708
709#ifdef SERIAL_DEBUG_OPEN
44bafdf3 710 printk("startup channel %d\n", channel);
1da177e4
LT
711#endif
712
44bafdf3
JS
713 local_irq_save(flags);
714 base_addr[CyCAR] = (u_char) channel;
715 write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
1da177e4 716
44bafdf3 717 base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */
1da177e4
LT
718 base_addr[CyMSVR1] = CyRTS;
719/* CP('S');CP('1'); */
720 base_addr[CyMSVR2] = CyDTR;
721
722#ifdef SERIAL_DEBUG_DTR
44bafdf3
JS
723 printk("cyc: %d: raising DTR\n", __LINE__);
724 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
725 base_addr[CyMSVR2]);
1da177e4
LT
726#endif
727
728 base_addr[CyIER] |= CyRxData;
729 info->flags |= ASYNC_INITIALIZED;
730
44bafdf3
JS
731 if (info->tty) {
732 clear_bit(TTY_IO_ERROR, &info->tty->flags);
1da177e4
LT
733 }
734 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
735
44bafdf3 736 local_irq_restore(flags);
1da177e4
LT
737
738#ifdef SERIAL_DEBUG_OPEN
44bafdf3 739 printk(" done\n");
1da177e4 740#endif
44bafdf3
JS
741 return 0;
742} /* startup */
1da177e4 743
44bafdf3 744void start_xmit(struct cyclades_port *info)
1da177e4 745{
44bafdf3
JS
746 unsigned long flags;
747 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
748 int channel;
1da177e4 749
44bafdf3
JS
750 channel = info->line;
751 local_irq_save(flags);
1da177e4
LT
752 base_addr[CyCAR] = channel;
753 base_addr[CyIER] |= CyTxMpty;
44bafdf3
JS
754 local_irq_restore(flags);
755} /* start_xmit */
1da177e4
LT
756
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 */
44bafdf3 761static void shutdown(struct cyclades_port *info)
1da177e4 762{
44bafdf3
JS
763 unsigned long flags;
764 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
765 int channel;
1da177e4 766
44bafdf3 767 if (!(info->flags & ASYNC_INITIALIZED)) {
1da177e4 768/* CP('$'); */
44bafdf3
JS
769 return;
770 }
1da177e4 771
44bafdf3 772 channel = info->line;
1da177e4
LT
773
774#ifdef SERIAL_DEBUG_OPEN
44bafdf3 775 printk("shutdown channel %d\n", channel);
1da177e4
LT
776#endif
777
44bafdf3
JS
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;
1da177e4
LT
788 }
789
44bafdf3 790 base_addr[CyCAR] = (u_char) channel;
1da177e4 791 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
44bafdf3 792 base_addr[CyMSVR1] = 0;
1da177e4 793/* CP('C');CP('1'); */
44bafdf3 794 base_addr[CyMSVR2] = 0;
1da177e4 795#ifdef SERIAL_DEBUG_DTR
44bafdf3
JS
796 printk("cyc: %d: dropping DTR\n", __LINE__);
797 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
798 base_addr[CyMSVR2]);
1da177e4 799#endif
44bafdf3
JS
800 }
801 write_cy_cmd(base_addr, CyDIS_RCVR);
802 /* it may be appropriate to clear _XMIT at
803 some later date (after testing)!!! */
1da177e4 804
44bafdf3
JS
805 if (info->tty) {
806 set_bit(TTY_IO_ERROR, &info->tty->flags);
1da177e4
LT
807 }
808 info->flags &= ~ASYNC_INITIALIZED;
44bafdf3 809 local_irq_restore(flags);
1da177e4
LT
810
811#ifdef SERIAL_DEBUG_OPEN
44bafdf3 812 printk(" done\n");
1da177e4 813#endif
44bafdf3 814} /* shutdown */
1da177e4
LT
815
816/*
817 * This routine finds or computes the various line characteristics.
818 */
44bafdf3 819static void config_setup(struct cyclades_port *info)
1da177e4 820{
44bafdf3
JS
821 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;
827
828 if (!info->tty || !info->tty->termios) {
829 return;
830 }
831 if (info->line == -1) {
832 return;
833 }
834 cflag = info->tty->termios->c_cflag;
835
836 /* baud rate */
837 i = cflag & CBAUD;
1da177e4
LT
838#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 */
44bafdf3
JS
847 if (i & CBAUDEX) {
848 if (i == B57600)
849 i = 16;
850 else if (i == B115200)
851 i = 18;
1da177e4 852#ifdef B78600
44bafdf3
JS
853 else if (i == B78600)
854 i = 17;
1da177e4 855#endif
44bafdf3
JS
856 else
857 info->tty->termios->c_cflag &= ~CBAUDEX;
858 }
859#endif
860 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);
1da177e4 911 } else {
44bafdf3
JS
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 */
1da177e4 950#if 0
44bafdf3
JS
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;
1da177e4
LT
964
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
44bafdf3 975 channel = info->line;
1da177e4 976
44bafdf3
JS
977 local_irq_save(flags);
978 base_addr[CyCAR] = (u_char) channel;
1da177e4
LT
979
980 /* CyCMR set once only in mvme167_init_serial() */
981 if (base_addr[CyLICR] != channel << 2)
44bafdf3 982 base_addr[CyLICR] = channel << 2;
1da177e4 983 if (base_addr[CyLIVR] != 0x5c)
44bafdf3 984 base_addr[CyLIVR] = 0x5c;
1da177e4 985
44bafdf3 986 /* tx and rx baud rate */
1da177e4
LT
987
988 if (base_addr[CyCOR1] != info->cor1)
44bafdf3 989 need_init_chan = 1;
1da177e4 990 if (base_addr[CyTCOR] != info->tco)
44bafdf3 991 base_addr[CyTCOR] = info->tco;
1da177e4 992 if (base_addr[CyTBPR] != info->tbpr)
44bafdf3 993 base_addr[CyTBPR] = info->tbpr;
1da177e4 994 if (base_addr[CyRCOR] != info->rco)
44bafdf3 995 base_addr[CyRCOR] = info->rco;
1da177e4 996 if (base_addr[CyRBPR] != info->rbpr)
44bafdf3 997 base_addr[CyRBPR] = info->rbpr;
1da177e4
LT
998
999 /* set line characteristics according configuration */
1000
1001 if (base_addr[CySCHR1] != START_CHAR(info->tty))
44bafdf3 1002 base_addr[CySCHR1] = START_CHAR(info->tty);
1da177e4 1003 if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
44bafdf3 1004 base_addr[CySCHR2] = STOP_CHAR(info->tty);
1da177e4 1005 if (base_addr[CySCRL] != START_CHAR(info->tty))
44bafdf3 1006 base_addr[CySCRL] = START_CHAR(info->tty);
1da177e4 1007 if (base_addr[CySCRH] != START_CHAR(info->tty))
44bafdf3 1008 base_addr[CySCRH] = START_CHAR(info->tty);
1da177e4 1009 if (base_addr[CyCOR1] != info->cor1)
44bafdf3 1010 base_addr[CyCOR1] = info->cor1;
1da177e4 1011 if (base_addr[CyCOR2] != info->cor2)
44bafdf3 1012 base_addr[CyCOR2] = info->cor2;
1da177e4 1013 if (base_addr[CyCOR3] != info->cor3)
44bafdf3 1014 base_addr[CyCOR3] = info->cor3;
1da177e4 1015 if (base_addr[CyCOR4] != info->cor4)
44bafdf3 1016 base_addr[CyCOR4] = info->cor4;
1da177e4 1017 if (base_addr[CyCOR5] != info->cor5)
44bafdf3 1018 base_addr[CyCOR5] = info->cor5;
1da177e4 1019 if (base_addr[CyCOR6] != info->cor6)
44bafdf3 1020 base_addr[CyCOR6] = info->cor6;
1da177e4 1021 if (base_addr[CyCOR7] != info->cor7)
44bafdf3 1022 base_addr[CyCOR7] = info->cor7;
1da177e4
LT
1023
1024 if (need_init_chan)
44bafdf3 1025 write_cy_cmd(base_addr, CyINIT_CHAN);
1da177e4 1026
44bafdf3 1027 base_addr[CyCAR] = (u_char) channel; /* !!! Is this needed? */
1da177e4
LT
1028
1029 /* 2ms default rx timeout */
1030 ti = info->default_timeout ? info->default_timeout : 0x02;
1031 if (base_addr[CyRTPRL] != ti)
44bafdf3 1032 base_addr[CyRTPRL] = ti;
1da177e4 1033 if (base_addr[CyRTPRH] != 0)
44bafdf3 1034 base_addr[CyRTPRH] = 0;
1da177e4
LT
1035
1036 /* Set up RTS here also ????? RGH 141095 */
44bafdf3
JS
1037 if (i == 0) { /* baud rate is zero, turn off line */
1038 if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
1039 base_addr[CyMSVR2] = 0;
1da177e4 1040#ifdef SERIAL_DEBUG_DTR
44bafdf3
JS
1041 printk("cyc: %d: dropping DTR\n", __LINE__);
1042 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1043 base_addr[CyMSVR2]);
1da177e4 1044#endif
44bafdf3
JS
1045 } else {
1046 if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
1047 base_addr[CyMSVR2] = CyDTR;
1da177e4 1048#ifdef SERIAL_DEBUG_DTR
44bafdf3
JS
1049 printk("cyc: %d: raising DTR\n", __LINE__);
1050 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1051 base_addr[CyMSVR2]);
1da177e4
LT
1052#endif
1053 }
1054
44bafdf3
JS
1055 if (info->tty) {
1056 clear_bit(TTY_IO_ERROR, &info->tty->flags);
1da177e4
LT
1057 }
1058
44bafdf3 1059 local_irq_restore(flags);
1da177e4 1060
44bafdf3 1061} /* config_setup */
1da177e4 1062
44bafdf3 1063static void cy_put_char(struct tty_struct *tty, unsigned char ch)
1da177e4 1064{
44bafdf3
JS
1065 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1066 unsigned long flags;
1da177e4
LT
1067
1068#ifdef SERIAL_DEBUG_IO
44bafdf3 1069 printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
1da177e4
LT
1070#endif
1071
44bafdf3
JS
1072 if (serial_paranoia_check(info, tty->name, "cy_put_char"))
1073 return;
1da177e4 1074
44bafdf3
JS
1075 if (!info->xmit_buf)
1076 return;
1da177e4 1077
44bafdf3 1078 local_irq_save(flags);
1da177e4 1079 if (info->xmit_cnt >= PAGE_SIZE - 1) {
44bafdf3
JS
1080 local_irq_restore(flags);
1081 return;
1da177e4
LT
1082 }
1083
1084 info->xmit_buf[info->xmit_head++] = ch;
1085 info->xmit_head &= PAGE_SIZE - 1;
1086 info->xmit_cnt++;
44bafdf3
JS
1087 local_irq_restore(flags);
1088} /* cy_put_char */
1da177e4 1089
44bafdf3 1090static void cy_flush_chars(struct tty_struct *tty)
1da177e4 1091{
44bafdf3
JS
1092 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
1da177e4 1097#ifdef SERIAL_DEBUG_IO
44bafdf3 1098 printk("cy_flush_chars %s\n", tty->name); /* */
1da177e4
LT
1099#endif
1100
44bafdf3
JS
1101 if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
1102 return;
1da177e4 1103
44bafdf3
JS
1104 if (info->xmit_cnt <= 0 || tty->stopped
1105 || tty->hw_stopped || !info->xmit_buf)
1106 return;
1da177e4 1107
44bafdf3 1108 channel = info->line;
1da177e4 1109
44bafdf3 1110 local_irq_save(flags);
1da177e4
LT
1111 base_addr[CyCAR] = channel;
1112 base_addr[CyIER] |= CyTxMpty;
44bafdf3
JS
1113 local_irq_restore(flags);
1114} /* cy_flush_chars */
1da177e4
LT
1115
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 */
44bafdf3 1122static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
1da177e4 1123{
44bafdf3
JS
1124 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1125 unsigned long flags;
1126 int c, total = 0;
1da177e4
LT
1127
1128#ifdef SERIAL_DEBUG_IO
44bafdf3 1129 printk("cy_write %s\n", tty->name); /* */
1da177e4
LT
1130#endif
1131
44bafdf3
JS
1132 if (serial_paranoia_check(info, tty->name, "cy_write")) {
1133 return 0;
1134 }
1da177e4 1135
44bafdf3
JS
1136 if (!info->xmit_buf) {
1137 return 0;
1138 }
1da177e4 1139
44bafdf3
JS
1140 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 }
1148
1149 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);
1154
1155 buf += c;
1156 count -= c;
1157 total += c;
1158 }
1159
1160 if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
1161 start_xmit(info);
1162 }
1163 return total;
1164} /* cy_write */
1165
1166static int cy_write_room(struct tty_struct *tty)
1da177e4 1167{
44bafdf3
JS
1168 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1169 int ret;
1170
1da177e4 1171#ifdef SERIAL_DEBUG_IO
44bafdf3 1172 printk("cy_write_room %s\n", tty->name); /* */
1da177e4
LT
1173#endif
1174
44bafdf3
JS
1175 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 */
1da177e4 1182
44bafdf3 1183static int cy_chars_in_buffer(struct tty_struct *tty)
1da177e4 1184{
44bafdf3
JS
1185 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1186
1da177e4 1187#ifdef SERIAL_DEBUG_IO
44bafdf3 1188 printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */
1da177e4
LT
1189#endif
1190
44bafdf3
JS
1191 if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
1192 return 0;
1da177e4 1193
44bafdf3
JS
1194 return info->xmit_cnt;
1195} /* cy_chars_in_buffer */
1da177e4 1196
44bafdf3 1197static void cy_flush_buffer(struct tty_struct *tty)
1da177e4 1198{
44bafdf3
JS
1199 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1200 unsigned long flags;
1201
1da177e4 1202#ifdef SERIAL_DEBUG_IO
44bafdf3 1203 printk("cy_flush_buffer %s\n", tty->name); /* */
1da177e4
LT
1204#endif
1205
44bafdf3
JS
1206 if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
1207 return;
1208 local_irq_save(flags);
1da177e4 1209 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
44bafdf3
JS
1210 local_irq_restore(flags);
1211 tty_wakeup(tty);
1212} /* cy_flush_buffer */
1da177e4
LT
1213
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 */
44bafdf3 1218static void cy_throttle(struct tty_struct *tty)
1da177e4 1219{
44bafdf3
JS
1220 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;
1da177e4
LT
1224
1225#ifdef SERIAL_DEBUG_THROTTLE
44bafdf3
JS
1226 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);
1da177e4
LT
1231#endif
1232
44bafdf3
JS
1233 if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
1234 return;
1235 }
1da177e4 1236
44bafdf3
JS
1237 if (I_IXOFF(tty)) {
1238 info->x_char = STOP_CHAR(tty);
1239 /* Should use the "Send Special Character" feature!!! */
1240 }
1da177e4 1241
44bafdf3 1242 channel = info->line;
1da177e4 1243
44bafdf3
JS
1244 local_irq_save(flags);
1245 base_addr[CyCAR] = (u_char) channel;
1da177e4 1246 base_addr[CyMSVR1] = 0;
44bafdf3
JS
1247 local_irq_restore(flags);
1248} /* cy_throttle */
1da177e4 1249
44bafdf3 1250static void cy_unthrottle(struct tty_struct *tty)
1da177e4 1251{
44bafdf3
JS
1252 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;
1da177e4
LT
1256
1257#ifdef SERIAL_DEBUG_THROTTLE
44bafdf3
JS
1258 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);
1da177e4
LT
1263#endif
1264
44bafdf3
JS
1265 if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
1266 return;
1267 }
1da177e4 1268
44bafdf3
JS
1269 if (I_IXOFF(tty)) {
1270 info->x_char = START_CHAR(tty);
1271 /* Should use the "Send Special Character" feature!!! */
1272 }
1da177e4 1273
44bafdf3 1274 channel = info->line;
1da177e4 1275
44bafdf3
JS
1276 local_irq_save(flags);
1277 base_addr[CyCAR] = (u_char) channel;
1da177e4 1278 base_addr[CyMSVR1] = CyRTS;
44bafdf3
JS
1279 local_irq_restore(flags);
1280} /* cy_unthrottle */
1da177e4
LT
1281
1282static int
44bafdf3
JS
1283get_serial_info(struct cyclades_port *info,
1284 struct serial_struct __user * retinfo)
1da177e4 1285{
44bafdf3 1286 struct serial_struct tmp;
1da177e4
LT
1287
1288/* CP('g'); */
44bafdf3
JS
1289 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 */
1da177e4
LT
1303
1304static int
44bafdf3
JS
1305set_serial_info(struct cyclades_port *info,
1306 struct serial_struct __user * new_info)
1da177e4 1307{
44bafdf3
JS
1308 struct serial_struct new_serial;
1309 struct cyclades_port old_info;
1da177e4
LT
1310
1311/* CP('s'); */
44bafdf3
JS
1312 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;
1317
1318 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 }
1da177e4 1327
44bafdf3
JS
1328 /*
1329 * OK, past this point, all the error checking has been done.
1330 * At this point, we start making changes.....
1331 */
1da177e4 1332
44bafdf3
JS
1333 info->flags = ((info->flags & ~ASYNC_FLAGS) |
1334 (new_serial.flags & ASYNC_FLAGS));
1335 info->close_delay = new_serial.close_delay;
1da177e4 1336
44bafdf3
JS
1337check_and_exit:
1338 if (info->flags & ASYNC_INITIALIZED) {
1339 config_setup(info);
1340 return 0;
1341 }
1342 return startup(info);
1343} /* set_serial_info */
1da177e4 1344
44bafdf3
JS
1345static int cy_tiocmget(struct tty_struct *tty, struct file *file)
1346{
1347 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;
1da177e4 1352
44bafdf3 1353 channel = info->line;
1da177e4 1354
44bafdf3
JS
1355 local_irq_save(flags);
1356 base_addr[CyCAR] = (u_char) channel;
1357 status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
1358 local_irq_restore(flags);
1da177e4 1359
44bafdf3
JS
1360 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 */
1da177e4
LT
1366
1367static int
1368cy_tiocmset(struct tty_struct *tty, struct file *file,
1369 unsigned int set, unsigned int clear)
1370{
44bafdf3
JS
1371 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;
1375
1376 channel = info->line;
1377
1378 if (set & TIOCM_RTS) {
1379 local_irq_save(flags);
1380 base_addr[CyCAR] = (u_char) channel;
1da177e4 1381 base_addr[CyMSVR1] = CyRTS;
44bafdf3 1382 local_irq_restore(flags);
1da177e4 1383 }
44bafdf3
JS
1384 if (set & TIOCM_DTR) {
1385 local_irq_save(flags);
1386 base_addr[CyCAR] = (u_char) channel;
1da177e4 1387/* CP('S');CP('2'); */
44bafdf3 1388 base_addr[CyMSVR2] = CyDTR;
1da177e4 1389#ifdef SERIAL_DEBUG_DTR
44bafdf3
JS
1390 printk("cyc: %d: raising DTR\n", __LINE__);
1391 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1392 base_addr[CyMSVR2]);
1da177e4 1393#endif
44bafdf3 1394 local_irq_restore(flags);
1da177e4
LT
1395 }
1396
44bafdf3
JS
1397 if (clear & TIOCM_RTS) {
1398 local_irq_save(flags);
1399 base_addr[CyCAR] = (u_char) channel;
1da177e4 1400 base_addr[CyMSVR1] = 0;
44bafdf3 1401 local_irq_restore(flags);
1da177e4 1402 }
44bafdf3
JS
1403 if (clear & TIOCM_DTR) {
1404 local_irq_save(flags);
1405 base_addr[CyCAR] = (u_char) channel;
1da177e4 1406/* CP('C');CP('2'); */
44bafdf3 1407 base_addr[CyMSVR2] = 0;
1da177e4 1408#ifdef SERIAL_DEBUG_DTR
44bafdf3
JS
1409 printk("cyc: %d: dropping DTR\n", __LINE__);
1410 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1411 base_addr[CyMSVR2]);
1da177e4 1412#endif
44bafdf3 1413 local_irq_restore(flags);
1da177e4
LT
1414 }
1415
44bafdf3
JS
1416 return 0;
1417} /* set_modem_info */
1418
1419static 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 */
1da177e4
LT
1428
1429static int
44bafdf3 1430get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
1da177e4
LT
1431{
1432
44bafdf3
JS
1433 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;
1da177e4
LT
1440}
1441
44bafdf3 1442static int set_threshold(struct cyclades_port *info, unsigned long __user * arg)
1da177e4 1443{
44bafdf3
JS
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;
1da177e4
LT
1456}
1457
1458static int
44bafdf3 1459get_threshold(struct cyclades_port *info, unsigned long __user * value)
1da177e4 1460{
44bafdf3
JS
1461 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1462 int channel;
1463 unsigned long tmp;
1464
1465 channel = info->line;
1466
1467 tmp = base_addr[CyCOR4] & CyREC_FIFO;
1468 return put_user(tmp, value);
1da177e4
LT
1469}
1470
1471static int
44bafdf3 1472set_default_threshold(struct cyclades_port *info, unsigned long __user * arg)
1da177e4 1473{
44bafdf3 1474 unsigned long value;
1da177e4 1475
44bafdf3
JS
1476 if (get_user(value, arg))
1477 return -EFAULT;
1da177e4 1478
44bafdf3
JS
1479 info->default_threshold = value & 0x0f;
1480 return 0;
1da177e4
LT
1481}
1482
1483static int
44bafdf3 1484get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
1da177e4 1485{
44bafdf3 1486 return put_user(info->default_threshold, value);
1da177e4
LT
1487}
1488
44bafdf3 1489static int set_timeout(struct cyclades_port *info, unsigned long __user * arg)
1da177e4 1490{
44bafdf3
JS
1491 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1492 int channel;
1493 unsigned long value;
1494
1495 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;
1da177e4
LT
1503}
1504
44bafdf3 1505static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
1da177e4 1506{
44bafdf3
JS
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);
1da177e4
LT
1515}
1516
44bafdf3 1517static int set_default_timeout(struct cyclades_port *info, unsigned long value)
1da177e4 1518{
44bafdf3
JS
1519 info->default_timeout = value & 0xff;
1520 return 0;
1da177e4
LT
1521}
1522
1523static int
44bafdf3 1524get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
1da177e4 1525{
44bafdf3 1526 return put_user(info->default_timeout, value);
1da177e4
LT
1527}
1528
1529static int
44bafdf3
JS
1530cy_ioctl(struct tty_struct *tty, struct file *file,
1531 unsigned int cmd, unsigned long arg)
1da177e4 1532{
44bafdf3
JS
1533 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;
1da177e4
LT
1537
1538#ifdef SERIAL_DEBUG_OTHER
44bafdf3
JS
1539 printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
1540#endif
1541
638157bc
AC
1542 lock_kernel();
1543
44bafdf3
JS
1544 switch (cmd) {
1545 case CYGETMON:
1546 ret_val = get_mon_info(info, argp);
1547 break;
1548 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);
1da177e4 1586 break;
1da177e4
LT
1587
1588/* The following commands are incompletely implemented!!! */
44bafdf3
JS
1589 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 }
638157bc 1598 unlock_kernel();
1da177e4
LT
1599
1600#ifdef SERIAL_DEBUG_OTHER
44bafdf3 1601 printk("cy_ioctl done\n");
1da177e4
LT
1602#endif
1603
44bafdf3
JS
1604 return ret_val;
1605} /* cy_ioctl */
1da177e4 1606
44bafdf3 1607static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
1da177e4 1608{
44bafdf3 1609 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1da177e4
LT
1610
1611#ifdef SERIAL_DEBUG_OTHER
44bafdf3 1612 printk("cy_set_termios %s\n", tty->name);
1da177e4
LT
1613#endif
1614
44bafdf3
JS
1615 if (tty->termios->c_cflag == old_termios->c_cflag)
1616 return;
1617 config_setup(info);
1da177e4 1618
44bafdf3
JS
1619 if ((old_termios->c_cflag & CRTSCTS) &&
1620 !(tty->termios->c_cflag & CRTSCTS)) {
1621 tty->stopped = 0;
1622 cy_start(tty);
1623 }
1da177e4 1624#ifdef tytso_patch_94Nov25_1726
44bafdf3
JS
1625 if (!(old_termios->c_cflag & CLOCAL) &&
1626 (tty->termios->c_cflag & CLOCAL))
1627 wake_up_interruptible(&info->open_wait);
1da177e4 1628#endif
44bafdf3 1629} /* cy_set_termios */
1da177e4 1630
44bafdf3 1631static void cy_close(struct tty_struct *tty, struct file *filp)
1da177e4 1632{
44bafdf3 1633 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1da177e4
LT
1634
1635/* CP('C'); */
1636#ifdef SERIAL_DEBUG_OTHER
44bafdf3 1637 printk("cy_close %s\n", tty->name);
1da177e4
LT
1638#endif
1639
44bafdf3
JS
1640 if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
1641 return;
1642 }
1da177e4 1643#ifdef SERIAL_DEBUG_OPEN
44bafdf3
JS
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 }
1da177e4 1659#ifdef SERIAL_DEBUG_COUNT
44bafdf3
JS
1660 printk("cyc: %d: decrementing count to %d\n", __LINE__,
1661 info->count - 1);
1da177e4 1662#endif
44bafdf3
JS
1663 if (--info->count < 0) {
1664 printk("cy_close: bad serial port count for ttys%d: %d\n",
1665 info->line, info->count);
1da177e4 1666#ifdef SERIAL_DEBUG_COUNT
44bafdf3 1667 printk("cyc: %d: setting count to 0\n", __LINE__);
1da177e4 1668#endif
44bafdf3 1669 info->count = 0;
1da177e4 1670 }
44bafdf3
JS
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);
1677 if (tty->driver->flush_buffer)
1678 tty->driver->flush_buffer(tty);
1679 tty_ldisc_flush(tty);
44bafdf3
JS
1680 info->tty = NULL;
1681 if (info->blocked_open) {
1682 if (info->close_delay) {
1683 msleep_interruptible(jiffies_to_msecs
1684 (info->close_delay));
1685 }
1686 wake_up_interruptible(&info->open_wait);
1687 }
1688 info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
1689 wake_up_interruptible(&info->close_wait);
1da177e4
LT
1690
1691#ifdef SERIAL_DEBUG_OTHER
44bafdf3 1692 printk("cy_close done\n");
1da177e4 1693#endif
44bafdf3 1694} /* cy_close */
1da177e4
LT
1695
1696/*
1697 * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
1698 */
44bafdf3 1699void cy_hangup(struct tty_struct *tty)
1da177e4 1700{
44bafdf3
JS
1701 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1702
1da177e4 1703#ifdef SERIAL_DEBUG_OTHER
44bafdf3 1704 printk("cy_hangup %s\n", tty->name); /* */
1da177e4
LT
1705#endif
1706
44bafdf3
JS
1707 if (serial_paranoia_check(info, tty->name, "cy_hangup"))
1708 return;
1709
1710 shutdown(info);
1da177e4 1711#if 0
44bafdf3
JS
1712 info->event = 0;
1713 info->count = 0;
1da177e4 1714#ifdef SERIAL_DEBUG_COUNT
44bafdf3 1715 printk("cyc: %d: setting count to 0\n", __LINE__);
1da177e4 1716#endif
44bafdf3 1717 info->tty = 0;
1da177e4 1718#endif
44bafdf3
JS
1719 info->flags &= ~ASYNC_NORMAL_ACTIVE;
1720 wake_up_interruptible(&info->open_wait);
1721} /* cy_hangup */
1da177e4
LT
1722
1723/*
1724 * ------------------------------------------------------------
1725 * cy_open() and friends
1726 * ------------------------------------------------------------
1727 */
1728
1729static int
44bafdf3
JS
1730block_til_ready(struct tty_struct *tty, struct file *filp,
1731 struct cyclades_port *info)
1da177e4 1732{
44bafdf3
JS
1733 DECLARE_WAITQUEUE(wait, current);
1734 unsigned long flags;
1735 int channel;
1736 int retval;
1737 volatile u_char *base_addr = (u_char *) BASE_ADDR;
1738
1739 /*
1740 * If the device is in the middle of being closed, then block
1741 * until it's done, and then try again.
1742 */
1743 if (info->flags & ASYNC_CLOSING) {
1744 interruptible_sleep_on(&info->close_wait);
1745 if (info->flags & ASYNC_HUP_NOTIFY) {
1746 return -EAGAIN;
1747 } else {
1748 return -ERESTARTSYS;
1749 }
1750 }
1751
1752 /*
1753 * If non-blocking mode is set, then make the check up front
1754 * and then exit.
1755 */
1756 if (filp->f_flags & O_NONBLOCK) {
1757 info->flags |= ASYNC_NORMAL_ACTIVE;
1758 return 0;
1759 }
1760
1761 /*
1762 * Block waiting for the carrier detect and the line to become
1763 * free (i.e., not in use by the callout). While we are in
1764 * this loop, info->count is dropped by one, so that
1765 * cy_close() knows when to free things. We restore it upon
1766 * exit, either normal or abnormal.
1767 */
1768 retval = 0;
1769 add_wait_queue(&info->open_wait, &wait);
1da177e4 1770#ifdef SERIAL_DEBUG_OPEN
44bafdf3
JS
1771 printk("block_til_ready before block: %s, count = %d\n",
1772 tty->name, info->count);
1773 /**/
1da177e4 1774#endif
44bafdf3 1775 info->count--;
1da177e4 1776#ifdef SERIAL_DEBUG_COUNT
44bafdf3 1777 printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
1da177e4 1778#endif
44bafdf3 1779 info->blocked_open++;
1da177e4 1780
44bafdf3 1781 channel = info->line;
1da177e4 1782
44bafdf3
JS
1783 while (1) {
1784 local_irq_save(flags);
1785 base_addr[CyCAR] = (u_char) channel;
1786 base_addr[CyMSVR1] = CyRTS;
1da177e4 1787/* CP('S');CP('4'); */
44bafdf3 1788 base_addr[CyMSVR2] = CyDTR;
1da177e4 1789#ifdef SERIAL_DEBUG_DTR
44bafdf3
JS
1790 printk("cyc: %d: raising DTR\n", __LINE__);
1791 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1792 base_addr[CyMSVR2]);
1793#endif
1794 local_irq_restore(flags);
1795 set_current_state(TASK_INTERRUPTIBLE);
1796 if (tty_hung_up_p(filp)
1797 || !(info->flags & ASYNC_INITIALIZED)) {
1798 if (info->flags & ASYNC_HUP_NOTIFY) {
1799 retval = -EAGAIN;
1800 } else {
1801 retval = -ERESTARTSYS;
1802 }
1803 break;
1804 }
1805 local_irq_save(flags);
1806 base_addr[CyCAR] = (u_char) channel;
1da177e4 1807/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
44bafdf3
JS
1808 if (!(info->flags & ASYNC_CLOSING)
1809 && (C_CLOCAL(tty)
1810 || (base_addr[CyMSVR1] & CyDCD))) {
1811 local_irq_restore(flags);
1812 break;
1813 }
1814 local_irq_restore(flags);
1815 if (signal_pending(current)) {
1816 retval = -ERESTARTSYS;
1817 break;
1818 }
1da177e4 1819#ifdef SERIAL_DEBUG_OPEN
44bafdf3
JS
1820 printk("block_til_ready blocking: %s, count = %d\n",
1821 tty->name, info->count);
1822 /**/
1823#endif
1824 schedule();
1825 }
cc0a8fbb 1826 __set_current_state(TASK_RUNNING);
44bafdf3
JS
1827 remove_wait_queue(&info->open_wait, &wait);
1828 if (!tty_hung_up_p(filp)) {
1829 info->count++;
1da177e4 1830#ifdef SERIAL_DEBUG_COUNT
44bafdf3
JS
1831 printk("cyc: %d: incrementing count to %d\n", __LINE__,
1832 info->count);
1da177e4 1833#endif
44bafdf3
JS
1834 }
1835 info->blocked_open--;
1da177e4 1836#ifdef SERIAL_DEBUG_OPEN
44bafdf3
JS
1837 printk("block_til_ready after blocking: %s, count = %d\n",
1838 tty->name, info->count);
1839 /**/
1da177e4 1840#endif
44bafdf3
JS
1841 if (retval)
1842 return retval;
1843 info->flags |= ASYNC_NORMAL_ACTIVE;
1844 return 0;
1845} /* block_til_ready */
1da177e4
LT
1846
1847/*
1848 * This routine is called whenever a serial port is opened. It
1849 * performs the serial-specific initialization for the tty structure.
1850 */
44bafdf3 1851int cy_open(struct tty_struct *tty, struct file *filp)
1da177e4 1852{
44bafdf3
JS
1853 struct cyclades_port *info;
1854 int retval, line;
1da177e4
LT
1855
1856/* CP('O'); */
44bafdf3
JS
1857 line = tty->index;
1858 if ((line < 0) || (NR_PORTS <= line)) {
1859 return -ENODEV;
1860 }
1861 info = &cy_port[line];
1862 if (info->line < 0) {
1863 return -ENODEV;
1864 }
1da177e4 1865#ifdef SERIAL_DEBUG_OTHER
44bafdf3 1866 printk("cy_open %s\n", tty->name); /* */
1da177e4 1867#endif
44bafdf3
JS
1868 if (serial_paranoia_check(info, tty->name, "cy_open")) {
1869 return -ENODEV;
1870 }
1da177e4 1871#ifdef SERIAL_DEBUG_OPEN
44bafdf3
JS
1872 printk("cy_open %s, count = %d\n", tty->name, info->count);
1873 /**/
1da177e4 1874#endif
44bafdf3 1875 info->count++;
1da177e4 1876#ifdef SERIAL_DEBUG_COUNT
44bafdf3 1877 printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
1da177e4 1878#endif
44bafdf3
JS
1879 tty->driver_data = info;
1880 info->tty = tty;
1da177e4 1881
44bafdf3
JS
1882 /*
1883 * Start up serial port
1884 */
1885 retval = startup(info);
1886 if (retval) {
1887 return retval;
1888 }
1da177e4 1889
44bafdf3
JS
1890 retval = block_til_ready(tty, filp, info);
1891 if (retval) {
1da177e4 1892#ifdef SERIAL_DEBUG_OPEN
44bafdf3
JS
1893 printk("cy_open returning after block_til_ready with %d\n",
1894 retval);
1da177e4 1895#endif
44bafdf3
JS
1896 return retval;
1897 }
1da177e4 1898#ifdef SERIAL_DEBUG_OPEN
44bafdf3
JS
1899 printk("cy_open done\n");
1900 /**/
1da177e4 1901#endif
44bafdf3
JS
1902 return 0;
1903} /* cy_open */
1da177e4
LT
1904
1905/*
1906 * ---------------------------------------------------------------------
1907 * serial167_init() and friends
1908 *
1909 * serial167_init() is called at boot-time to initialize the serial driver.
1910 * ---------------------------------------------------------------------
1911 */
1912
1913/*
1914 * This routine prints out the appropriate serial driver version
1915 * number, and identifies which options were configured into this
1916 * driver.
1917 */
44bafdf3 1918static void show_version(void)
1da177e4 1919{
44bafdf3
JS
1920 printk("MVME166/167 cd2401 driver\n");
1921} /* show_version */
1da177e4
LT
1922
1923/* initialize chips on card -- return number of valid
1924 chips (which is number of ports/4) */
1925
1926/*
1927 * This initialises the hardware to a reasonable state. It should
1928 * probe the chip first so as to copy 166-Bug setup as a default for
1929 * port 0. It initialises CMR to CyASYNC; that is never done again, so
1930 * as to limit the number of CyINIT_CHAN commands in normal running.
1931 *
1932 * ... I wonder what I should do if this fails ...
1933 */
1934
44bafdf3 1935void mvme167_serial_console_setup(int cflag)
1da177e4 1936{
44bafdf3 1937 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1da177e4
LT
1938 int ch;
1939 u_char spd;
1940 u_char rcor, rbpr, badspeed = 0;
1941 unsigned long flags;
1942
1943 local_irq_save(flags);
1944
1945 /*
1946 * First probe channel zero of the chip, to see what speed has
1947 * been selected.
1948 */
1949
1950 base_addr[CyCAR] = 0;
1951
1952 rcor = base_addr[CyRCOR] << 5;
1953 rbpr = base_addr[CyRBPR];
1954
1955 for (spd = 0; spd < sizeof(baud_bpr); spd++)
1956 if (rbpr == baud_bpr[spd] && rcor == baud_co[spd])
1957 break;
1958 if (spd >= sizeof(baud_bpr)) {
1959 spd = 14; /* 19200 */
1960 badspeed = 1; /* Failed to identify speed */
1961 }
1962 initial_console_speed = spd;
1963
1964 /* OK, we have chosen a speed, now reset and reinitialise */
1965
44bafdf3
JS
1966 my_udelay(20000L); /* Allow time for any active o/p to complete */
1967 if (base_addr[CyCCR] != 0x00) {
1968 local_irq_restore(flags);
1969 /* printk(" chip is never idle (CCR != 0)\n"); */
1970 return;
1971 }
1da177e4 1972
44bafdf3
JS
1973 base_addr[CyCCR] = CyCHIP_RESET; /* Reset the chip */
1974 my_udelay(1000L);
1da177e4 1975
44bafdf3
JS
1976 if (base_addr[CyGFRCR] == 0x00) {
1977 local_irq_restore(flags);
1978 /* printk(" chip is not responding (GFRCR stayed 0)\n"); */
1979 return;
1980 }
1da177e4
LT
1981
1982 /*
1983 * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms
1984 * tick
1985 */
1986
1987 base_addr[CyTPR] = 10;
1988
44bafdf3
JS
1989 base_addr[CyPILR1] = 0x01; /* Interrupt level for modem change */
1990 base_addr[CyPILR2] = 0x02; /* Interrupt level for tx ints */
1991 base_addr[CyPILR3] = 0x03; /* Interrupt level for rx ints */
1da177e4
LT
1992
1993 /*
1994 * Attempt to set up all channels to something reasonable, and
1995 * bang out a INIT_CHAN command. We should then be able to limit
1996 * the ammount of fiddling we have to do in normal running.
1997 */
1998
44bafdf3
JS
1999 for (ch = 3; ch >= 0; ch--) {
2000 base_addr[CyCAR] = (u_char) ch;
1da177e4
LT
2001 base_addr[CyIER] = 0;
2002 base_addr[CyCMR] = CyASYNC;
44bafdf3 2003 base_addr[CyLICR] = (u_char) ch << 2;
1da177e4
LT
2004 base_addr[CyLIVR] = 0x5c;
2005 base_addr[CyTCOR] = baud_co[spd];
2006 base_addr[CyTBPR] = baud_bpr[spd];
2007 base_addr[CyRCOR] = baud_co[spd] >> 5;
2008 base_addr[CyRBPR] = baud_bpr[spd];
2009 base_addr[CySCHR1] = 'Q' & 0x1f;
2010 base_addr[CySCHR2] = 'X' & 0x1f;
2011 base_addr[CySCRL] = 0;
2012 base_addr[CySCRH] = 0;
2013 base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
2014 base_addr[CyCOR2] = 0;
2015 base_addr[CyCOR3] = Cy_1_STOP;
2016 base_addr[CyCOR4] = baud_cor4[spd];
2017 base_addr[CyCOR5] = 0;
2018 base_addr[CyCOR6] = 0;
2019 base_addr[CyCOR7] = 0;
2020 base_addr[CyRTPRL] = 2;
2021 base_addr[CyRTPRH] = 0;
44bafdf3
JS
2022 base_addr[CyMSVR1] = 0;
2023 base_addr[CyMSVR2] = 0;
2024 write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR);
1da177e4
LT
2025 }
2026
2027 /*
2028 * Now do specials for channel zero....
2029 */
2030
44bafdf3
JS
2031 base_addr[CyMSVR1] = CyRTS;
2032 base_addr[CyMSVR2] = CyDTR;
1da177e4 2033 base_addr[CyIER] = CyRxData;
44bafdf3 2034 write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
1da177e4
LT
2035
2036 local_irq_restore(flags);
2037
2038 my_udelay(20000L); /* Let it all settle down */
2039
44bafdf3 2040 printk("CD2401 initialised, chip is rev 0x%02x\n", base_addr[CyGFRCR]);
1da177e4 2041 if (badspeed)
44bafdf3
JS
2042 printk
2043 (" WARNING: Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
2044 rcor >> 5, rbpr);
2045} /* serial_console_init */
1da177e4 2046
b68e31d0 2047static const struct tty_operations cy_ops = {
1da177e4
LT
2048 .open = cy_open,
2049 .close = cy_close,
2050 .write = cy_write,
2051 .put_char = cy_put_char,
2052 .flush_chars = cy_flush_chars,
2053 .write_room = cy_write_room,
2054 .chars_in_buffer = cy_chars_in_buffer,
2055 .flush_buffer = cy_flush_buffer,
2056 .ioctl = cy_ioctl,
2057 .throttle = cy_throttle,
2058 .unthrottle = cy_unthrottle,
2059 .set_termios = cy_set_termios,
2060 .stop = cy_stop,
2061 .start = cy_start,
2062 .hangup = cy_hangup,
2063 .tiocmget = cy_tiocmget,
2064 .tiocmset = cy_tiocmset,
2065};
44bafdf3 2066
1da177e4
LT
2067/* The serial driver boot-time initialization code!
2068 Hardware I/O ports are mapped to character special devices on a
2069 first found, first allocated manner. That is, this code searches
2070 for Cyclom cards in the system. As each is found, it is probed
2071 to discover how many chips (and thus how many ports) are present.
2072 These ports are mapped to the tty ports 64 and upward in monotonic
2073 fashion. If an 8-port card is replaced with a 16-port card, the
2074 port mapping on a following card will shift.
2075
2076 This approach is different from what is used in the other serial
2077 device driver because the Cyclom is more properly a multiplexer,
2078 not just an aggregation of serial ports on one card.
2079
2080 If there are more cards with more ports than have been statically
2081 allocated above, a warning is printed and the extra ports are ignored.
2082 */
44bafdf3 2083static int __init serial167_init(void)
1da177e4 2084{
44bafdf3
JS
2085 struct cyclades_port *info;
2086 int ret = 0;
2087 int good_ports = 0;
2088 int port_num = 0;
2089 int index;
2090 int DefSpeed;
1da177e4 2091#ifdef notyet
44bafdf3 2092 struct sigaction sa;
1da177e4
LT
2093#endif
2094
44bafdf3
JS
2095 if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401))
2096 return 0;
1da177e4 2097
44bafdf3
JS
2098 cy_serial_driver = alloc_tty_driver(NR_PORTS);
2099 if (!cy_serial_driver)
2100 return -ENOMEM;
1da177e4
LT
2101
2102#if 0
44bafdf3 2103 scrn[1] = '\0';
1da177e4
LT
2104#endif
2105
44bafdf3 2106 show_version();
1da177e4 2107
44bafdf3
JS
2108 /* Has "console=0,9600n8" been used in bootinfo to change speed? */
2109 if (serial_console_cflag)
2110 DefSpeed = serial_console_cflag & 0017;
2111 else {
2112 DefSpeed = initial_console_speed;
2113 serial_console_info = &cy_port[0];
2114 serial_console_cflag = DefSpeed | CS8;
1da177e4 2115#if 0
44bafdf3
JS
2116 serial_console = 64; /*callout_driver.minor_start */
2117#endif
2118 }
1da177e4 2119
44bafdf3 2120 /* Initialize the tty_driver structure */
1da177e4 2121
44bafdf3
JS
2122 cy_serial_driver->owner = THIS_MODULE;
2123 cy_serial_driver->name = "ttyS";
2124 cy_serial_driver->major = TTY_MAJOR;
2125 cy_serial_driver->minor_start = 64;
2126 cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
2127 cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
2128 cy_serial_driver->init_termios = tty_std_termios;
2129 cy_serial_driver->init_termios.c_cflag =
2130 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2131 cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
2132 tty_set_operations(cy_serial_driver, &cy_ops);
2133
2134 ret = tty_register_driver(cy_serial_driver);
2135 if (ret) {
2136 printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
2137 put_tty_driver(cy_serial_driver);
2138 return ret;
2139 }
1da177e4 2140
44bafdf3
JS
2141 port_num = 0;
2142 info = cy_port;
2143 for (index = 0; index < 1; index++) {
1da177e4 2144
44bafdf3
JS
2145 good_ports = 4;
2146
2147 if (port_num < NR_PORTS) {
2148 while (good_ports-- && port_num < NR_PORTS) {
1da177e4 2149 /*** initialize port ***/
44bafdf3
JS
2150 info->magic = CYCLADES_MAGIC;
2151 info->type = PORT_CIRRUS;
2152 info->card = index;
2153 info->line = port_num;
2154 info->flags = STD_COM_FLAGS;
2155 info->tty = NULL;
2156 info->xmit_fifo_size = 12;
2157 info->cor1 = CyPARITY_NONE | Cy_8_BITS;
2158 info->cor2 = CyETC;
2159 info->cor3 = Cy_1_STOP;
2160 info->cor4 = 0x08; /* _very_ small receive threshold */
2161 info->cor5 = 0;
2162 info->cor6 = 0;
2163 info->cor7 = 0;
2164 info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */
2165 info->tco = baud_co[DefSpeed]; /* Tx CO */
2166 info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */
2167 info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */
2168 info->close_delay = 0;
2169 info->x_char = 0;
44bafdf3 2170 info->count = 0;
1da177e4 2171#ifdef SERIAL_DEBUG_COUNT
44bafdf3
JS
2172 printk("cyc: %d: setting count to 0\n",
2173 __LINE__);
2174#endif
2175 info->blocked_open = 0;
2176 info->default_threshold = 0;
2177 info->default_timeout = 0;
44bafdf3
JS
2178 init_waitqueue_head(&info->open_wait);
2179 init_waitqueue_head(&info->close_wait);
2180 /* info->session */
2181 /* info->pgrp */
1da177e4 2182/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
44bafdf3
JS
2183 info->read_status_mask =
2184 CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY |
2185 CyFRAME | CyOVERRUN;
2186 /* info->timeout */
2187
2188 printk("ttyS%d ", info->line);
2189 port_num++;
2190 info++;
2191 if (!(port_num & 7)) {
2192 printk("\n ");
2193 }
2194 }
1da177e4 2195 }
44bafdf3
JS
2196 printk("\n");
2197 }
2198 while (port_num < NR_PORTS) {
2199 info->line = -1;
2200 port_num++;
2201 info++;
2202 }
1da177e4 2203#ifdef CONFIG_REMOTE_DEBUG
44bafdf3
JS
2204 debug_setup();
2205#endif
2206 ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
2207 "cd2401_errors", cd2401_rxerr_interrupt);
2208 if (ret) {
2209 printk(KERN_ERR "Could't get cd2401_errors IRQ");
2210 goto cleanup_serial_driver;
2211 }
2212
2213 ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
2214 "cd2401_modem", cd2401_modem_interrupt);
2215 if (ret) {
2216 printk(KERN_ERR "Could't get cd2401_modem IRQ");
2217 goto cleanup_irq_cd2401_errors;
2218 }
2219
2220 ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
2221 "cd2401_txints", cd2401_tx_interrupt);
2222 if (ret) {
2223 printk(KERN_ERR "Could't get cd2401_txints IRQ");
2224 goto cleanup_irq_cd2401_modem;
2225 }
2226
2227 ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
2228 "cd2401_rxints", cd2401_rx_interrupt);
2229 if (ret) {
2230 printk(KERN_ERR "Could't get cd2401_rxints IRQ");
2231 goto cleanup_irq_cd2401_txints;
2232 }
2233
2234 /* Now we have registered the interrupt handlers, allow the interrupts */
2235
2236 pcc2chip[PccSCCMICR] = 0x15; /* Serial ints are level 5 */
2237 pcc2chip[PccSCCTICR] = 0x15;
2238 pcc2chip[PccSCCRICR] = 0x15;
2239
2240 pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */
2241
2242 return 0;
1da177e4 2243cleanup_irq_cd2401_txints:
44bafdf3 2244 free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
1da177e4 2245cleanup_irq_cd2401_modem:
44bafdf3 2246 free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
1da177e4 2247cleanup_irq_cd2401_errors:
44bafdf3 2248 free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
1da177e4 2249cleanup_serial_driver:
44bafdf3
JS
2250 if (tty_unregister_driver(cy_serial_driver))
2251 printk(KERN_ERR
2252 "Couldn't unregister MVME166/7 serial driver\n");
2253 put_tty_driver(cy_serial_driver);
2254 return ret;
2255} /* serial167_init */
1da177e4
LT
2256
2257module_init(serial167_init);
2258
1da177e4 2259#ifdef CYCLOM_SHOW_STATUS
44bafdf3 2260static void show_status(int line_num)
1da177e4 2261{
44bafdf3
JS
2262 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2263 int channel;
2264 struct cyclades_port *info;
2265 unsigned long flags;
2266
2267 info = &cy_port[line_num];
2268 channel = info->line;
2269 printk(" channel %d\n", channel);
2270 /**/ printk(" cy_port\n");
2271 printk(" card line flags = %d %d %x\n",
2272 info->card, info->line, info->flags);
2273 printk
2274 (" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
2275 (long)info->tty, info->read_status_mask, info->timeout,
2276 info->xmit_fifo_size);
2277 printk(" cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
2278 info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
2279 info->cor6, info->cor7);
2280 printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco,
2281 info->rbpr, info->rco);
2282 printk(" close_delay event count = %d %d %d\n", info->close_delay,
2283 info->event, info->count);
2284 printk(" x_char blocked_open = %x %x\n", info->x_char,
2285 info->blocked_open);
2286 printk(" open_wait = %lx %lx %lx\n", (long)info->open_wait);
2287
2288 local_irq_save(flags);
1da177e4
LT
2289
2290/* Global Registers */
2291
2292 printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
2293 printk(" CyCAR %x\n", base_addr[CyCAR]);
2294 printk(" CyRISR %x\n", base_addr[CyRISR]);
2295 printk(" CyTISR %x\n", base_addr[CyTISR]);
2296 printk(" CyMISR %x\n", base_addr[CyMISR]);
2297 printk(" CyRIR %x\n", base_addr[CyRIR]);
2298 printk(" CyTIR %x\n", base_addr[CyTIR]);
2299 printk(" CyMIR %x\n", base_addr[CyMIR]);
2300 printk(" CyTPR %x\n", base_addr[CyTPR]);
2301
44bafdf3 2302 base_addr[CyCAR] = (u_char) channel;
1da177e4
LT
2303
2304/* Virtual Registers */
2305
2306#if 0
2307 printk(" CyRIVR %x\n", base_addr[CyRIVR]);
2308 printk(" CyTIVR %x\n", base_addr[CyTIVR]);
2309 printk(" CyMIVR %x\n", base_addr[CyMIVR]);
2310 printk(" CyMISR %x\n", base_addr[CyMISR]);
2311#endif
2312
2313/* Channel Registers */
2314
2315 printk(" CyCCR %x\n", base_addr[CyCCR]);
2316 printk(" CyIER %x\n", base_addr[CyIER]);
2317 printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
2318 printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
2319 printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
2320 printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
2321 printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
2322#if 0
2323 printk(" CyCCSR %x\n", base_addr[CyCCSR]);
2324 printk(" CyRDCR %x\n", base_addr[CyRDCR]);
2325#endif
2326 printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
2327 printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
2328#if 0
2329 printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
2330 printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
2331 printk(" CySCRL %x\n", base_addr[CySCRL]);
2332 printk(" CySCRH %x\n", base_addr[CySCRH]);
2333 printk(" CyLNC %x\n", base_addr[CyLNC]);
2334 printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
2335 printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
2336#endif
2337 printk(" CyRTPRL %x\n", base_addr[CyRTPRL]);
2338 printk(" CyRTPRH %x\n", base_addr[CyRTPRH]);
2339 printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
2340 printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
2341 printk(" CyRBPR %x\n", base_addr[CyRBPR]);
2342 printk(" CyRCOR %x\n", base_addr[CyRCOR]);
2343 printk(" CyTBPR %x\n", base_addr[CyTBPR]);
2344 printk(" CyTCOR %x\n", base_addr[CyTCOR]);
2345
44bafdf3
JS
2346 local_irq_restore(flags);
2347} /* show_status */
1da177e4
LT
2348#endif
2349
1da177e4
LT
2350#if 0
2351/* Dummy routine in mvme16x/config.c for now */
2352
2353/* Serial console setup. Called from linux/init/main.c */
2354
2355void console_setup(char *str, int *ints)
2356{
2357 char *s;
2358 int baud, bits, parity;
2359 int cflag = 0;
2360
2361 /* Sanity check. */
44bafdf3
JS
2362 if (ints[0] > 3 || ints[1] > 3)
2363 return;
1da177e4
LT
2364
2365 /* Get baud, bits and parity */
2366 baud = 2400;
2367 bits = 8;
2368 parity = 'n';
44bafdf3
JS
2369 if (ints[2])
2370 baud = ints[2];
1da177e4
LT
2371 if ((s = strchr(str, ','))) {
2372 do {
2373 s++;
44bafdf3
JS
2374 } while (*s >= '0' && *s <= '9');
2375 if (*s)
2376 parity = *s++;
2377 if (*s)
2378 bits = *s - '0';
1da177e4
LT
2379 }
2380
2381 /* Now construct a cflag setting. */
44bafdf3
JS
2382 switch (baud) {
2383 case 1200:
2384 cflag |= B1200;
2385 break;
2386 case 9600:
2387 cflag |= B9600;
2388 break;
2389 case 19200:
2390 cflag |= B19200;
2391 break;
2392 case 38400:
2393 cflag |= B38400;
2394 break;
2395 case 2400:
2396 default:
2397 cflag |= B2400;
2398 break;
1da177e4 2399 }
44bafdf3
JS
2400 switch (bits) {
2401 case 7:
2402 cflag |= CS7;
2403 break;
2404 default:
2405 case 8:
2406 cflag |= CS8;
2407 break;
1da177e4 2408 }
44bafdf3
JS
2409 switch (parity) {
2410 case 'o':
2411 case 'O':
2412 cflag |= PARODD;
2413 break;
2414 case 'e':
2415 case 'E':
2416 cflag |= PARENB;
2417 break;
1da177e4
LT
2418 }
2419
2420 serial_console_info = &cy_port[ints[1]];
2421 serial_console_cflag = cflag;
44bafdf3 2422 serial_console = ints[1] + 64; /*callout_driver.minor_start */
1da177e4
LT
2423}
2424#endif
2425
2426/*
2427 * The following is probably out of date for 2.1.x serial console stuff.
2428 *
2429 * The console is registered early on from arch/m68k/kernel/setup.c, and
2430 * it therefore relies on the chip being setup correctly by 166-Bug. This
2431 * seems reasonable, as the serial port has been used to invoke the system
2432 * boot. It also means that this function must not rely on any data
2433 * initialisation performed by serial167_init() etc.
2434 *
2435 * Of course, once the console has been registered, we had better ensure
2436 * that serial167_init() doesn't leave the chip non-functional.
2437 *
2438 * The console must be locked when we get here.
2439 */
2440
44bafdf3
JS
2441void serial167_console_write(struct console *co, const char *str,
2442 unsigned count)
1da177e4 2443{
44bafdf3 2444 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1da177e4
LT
2445 unsigned long flags;
2446 volatile u_char sink;
2447 u_char ier;
2448 int port;
2449 u_char do_lf = 0;
2450 int i = 0;
2451
2452 local_irq_save(flags);
2453
2454 /* Ensure transmitter is enabled! */
2455
2456 port = 0;
44bafdf3 2457 base_addr[CyCAR] = (u_char) port;
1da177e4
LT
2458 while (base_addr[CyCCR])
2459 ;
2460 base_addr[CyCCR] = CyENB_XMTR;
2461
2462 ier = base_addr[CyIER];
2463 base_addr[CyIER] = CyTxMpty;
2464
2465 while (1) {
44bafdf3 2466 if (pcc2chip[PccSCCTICR] & 0x20) {
1da177e4
LT
2467 /* We have a Tx int. Acknowledge it */
2468 sink = pcc2chip[PccTPIACKR];
2469 if ((base_addr[CyLICR] >> 2) == port) {
2470 if (i == count) {
2471 /* Last char of string is now output */
2472 base_addr[CyTEOIR] = CyNOTRANS;
2473 break;
2474 }
2475 if (do_lf) {
2476 base_addr[CyTDR] = '\n';
2477 str++;
2478 i++;
2479 do_lf = 0;
44bafdf3 2480 } else if (*str == '\n') {
1da177e4
LT
2481 base_addr[CyTDR] = '\r';
2482 do_lf = 1;
44bafdf3 2483 } else {
1da177e4
LT
2484 base_addr[CyTDR] = *str++;
2485 i++;
2486 }
2487 base_addr[CyTEOIR] = 0;
44bafdf3 2488 } else
1da177e4
LT
2489 base_addr[CyTEOIR] = CyNOTRANS;
2490 }
2491 }
2492
2493 base_addr[CyIER] = ier;
2494
2495 local_irq_restore(flags);
2496}
2497
44bafdf3
JS
2498static struct tty_driver *serial167_console_device(struct console *c,
2499 int *index)
1da177e4
LT
2500{
2501 *index = c->index;
2502 return cy_serial_driver;
2503}
2504
1da177e4 2505static struct console sercons = {
44bafdf3
JS
2506 .name = "ttyS",
2507 .write = serial167_console_write,
2508 .device = serial167_console_device,
44bafdf3
JS
2509 .flags = CON_PRINTBUFFER,
2510 .index = -1,
1da177e4
LT
2511};
2512
1da177e4
LT
2513static int __init serial167_console_init(void)
2514{
2515 if (vme_brdtype == VME_TYPE_MVME166 ||
44bafdf3
JS
2516 vme_brdtype == VME_TYPE_MVME167 ||
2517 vme_brdtype == VME_TYPE_MVME177) {
1da177e4
LT
2518 mvme167_serial_console_setup(0);
2519 register_console(&sercons);
2520 }
2521 return 0;
2522}
44bafdf3 2523
1da177e4
LT
2524console_initcall(serial167_console_init);
2525
2526#ifdef CONFIG_REMOTE_DEBUG
44bafdf3 2527void putDebugChar(int c)
1da177e4 2528{
44bafdf3 2529 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1da177e4
LT
2530 unsigned long flags;
2531 volatile u_char sink;
2532 u_char ier;
2533 int port;
2534
2535 local_irq_save(flags);
2536
2537 /* Ensure transmitter is enabled! */
2538
2539 port = DEBUG_PORT;
44bafdf3 2540 base_addr[CyCAR] = (u_char) port;
1da177e4
LT
2541 while (base_addr[CyCCR])
2542 ;
2543 base_addr[CyCCR] = CyENB_XMTR;
2544
2545 ier = base_addr[CyIER];
2546 base_addr[CyIER] = CyTxMpty;
2547
2548 while (1) {
44bafdf3 2549 if (pcc2chip[PccSCCTICR] & 0x20) {
1da177e4
LT
2550 /* We have a Tx int. Acknowledge it */
2551 sink = pcc2chip[PccTPIACKR];
2552 if ((base_addr[CyLICR] >> 2) == port) {
2553 base_addr[CyTDR] = c;
2554 base_addr[CyTEOIR] = 0;
2555 break;
44bafdf3 2556 } else
1da177e4
LT
2557 base_addr[CyTEOIR] = CyNOTRANS;
2558 }
2559 }
2560
2561 base_addr[CyIER] = ier;
2562
2563 local_irq_restore(flags);
2564}
2565
2566int getDebugChar()
2567{
44bafdf3 2568 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1da177e4
LT
2569 unsigned long flags;
2570 volatile u_char sink;
2571 u_char ier;
2572 int port;
2573 int i, c;
2574
2575 i = debugiq.out;
2576 if (i != debugiq.in) {
2577 c = debugiq.buf[i];
2578 if (++i == DEBUG_LEN)
2579 i = 0;
2580 debugiq.out = i;
2581 return c;
2582 }
2583 /* OK, nothing in queue, wait in poll loop */
2584
2585 local_irq_save(flags);
2586
2587 /* Ensure receiver is enabled! */
2588
2589 port = DEBUG_PORT;
44bafdf3 2590 base_addr[CyCAR] = (u_char) port;
1da177e4
LT
2591#if 0
2592 while (base_addr[CyCCR])
2593 ;
2594 base_addr[CyCCR] = CyENB_RCVR;
2595#endif
2596 ier = base_addr[CyIER];
2597 base_addr[CyIER] = CyRxData;
2598
2599 while (1) {
44bafdf3 2600 if (pcc2chip[PccSCCRICR] & 0x20) {
1da177e4
LT
2601 /* We have a Rx int. Acknowledge it */
2602 sink = pcc2chip[PccRPIACKR];
2603 if ((base_addr[CyLICR] >> 2) == port) {
2604 int cnt = base_addr[CyRFOC];
44bafdf3 2605 while (cnt-- > 0) {
1da177e4
LT
2606 c = base_addr[CyRDR];
2607 if (c == 0)
44bafdf3
JS
2608 printk
2609 ("!! debug char is null (cnt=%d) !!",
2610 cnt);
1da177e4 2611 else
44bafdf3 2612 queueDebugChar(c);
1da177e4
LT
2613 }
2614 base_addr[CyREOIR] = 0;
2615 i = debugiq.out;
2616 if (i == debugiq.in)
44bafdf3 2617 panic("Debug input queue empty!");
1da177e4
LT
2618 c = debugiq.buf[i];
2619 if (++i == DEBUG_LEN)
2620 i = 0;
2621 debugiq.out = i;
2622 break;
44bafdf3 2623 } else
1da177e4
LT
2624 base_addr[CyREOIR] = CyNOTRANS;
2625 }
2626 }
2627
2628 base_addr[CyIER] = ier;
2629
2630 local_irq_restore(flags);
2631
2632 return (c);
2633}
2634
44bafdf3 2635void queueDebugChar(int c)
1da177e4
LT
2636{
2637 int i;
2638
2639 i = debugiq.in;
2640 debugiq.buf[i] = c;
2641 if (++i == DEBUG_LEN)
2642 i = 0;
2643 if (i != debugiq.out)
2644 debugiq.in = i;
2645}
2646
44bafdf3 2647static void debug_setup()
1da177e4 2648{
44bafdf3
JS
2649 unsigned long flags;
2650 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2651 int i, cflag;
1da177e4 2652
44bafdf3 2653 cflag = B19200;
1da177e4 2654
44bafdf3 2655 local_irq_save(flags);
1da177e4 2656
44bafdf3
JS
2657 for (i = 0; i < 4; i++) {
2658 base_addr[CyCAR] = i;
2659 base_addr[CyLICR] = i << 2;
2660 }
1da177e4 2661
44bafdf3 2662 debugiq.in = debugiq.out = 0;
1da177e4 2663
44bafdf3 2664 base_addr[CyCAR] = DEBUG_PORT;
1da177e4 2665
44bafdf3
JS
2666 /* baud rate */
2667 i = cflag & CBAUD;
1da177e4 2668
44bafdf3 2669 base_addr[CyIER] = 0;
1da177e4 2670
44bafdf3
JS
2671 base_addr[CyCMR] = CyASYNC;
2672 base_addr[CyLICR] = DEBUG_PORT << 2;
2673 base_addr[CyLIVR] = 0x5c;
1da177e4 2674
44bafdf3 2675 /* tx and rx baud rate */
1da177e4 2676
44bafdf3
JS
2677 base_addr[CyTCOR] = baud_co[i];
2678 base_addr[CyTBPR] = baud_bpr[i];
2679 base_addr[CyRCOR] = baud_co[i] >> 5;
2680 base_addr[CyRBPR] = baud_bpr[i];
1da177e4 2681
44bafdf3 2682 /* set line characteristics according configuration */
1da177e4 2683
44bafdf3
JS
2684 base_addr[CySCHR1] = 0;
2685 base_addr[CySCHR2] = 0;
2686 base_addr[CySCRL] = 0;
2687 base_addr[CySCRH] = 0;
2688 base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
2689 base_addr[CyCOR2] = 0;
2690 base_addr[CyCOR3] = Cy_1_STOP;
2691 base_addr[CyCOR4] = baud_cor4[i];
2692 base_addr[CyCOR5] = 0;
2693 base_addr[CyCOR6] = 0;
2694 base_addr[CyCOR7] = 0;
1da177e4 2695
44bafdf3
JS
2696 write_cy_cmd(base_addr, CyINIT_CHAN);
2697 write_cy_cmd(base_addr, CyENB_RCVR);
1da177e4 2698
44bafdf3 2699 base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */
1da177e4 2700
44bafdf3
JS
2701 base_addr[CyRTPRL] = 2;
2702 base_addr[CyRTPRH] = 0;
1da177e4 2703
44bafdf3
JS
2704 base_addr[CyMSVR1] = CyRTS;
2705 base_addr[CyMSVR2] = CyDTR;
1da177e4 2706
44bafdf3 2707 base_addr[CyIER] = CyRxData;
1da177e4 2708
44bafdf3 2709 local_irq_restore(flags);
1da177e4 2710
44bafdf3 2711} /* debug_setup */
1da177e4
LT
2712
2713#endif
2714
2715MODULE_LICENSE("GPL");