Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
[linux-2.6] / drivers / serial / dz.c
1 /*
2  * dz.c: Serial port driver for DECStations equiped
3  *       with the DZ chipset.
4  *
5  * Copyright (C) 1998 Olivier A. D. Lebaillif
6  *
7  * Email: olivier.lebaillif@ifrsys.com
8  *
9  * [31-AUG-98] triemer
10  * Changed IRQ to use Harald's dec internals interrupts.h
11  * removed base_addr code - moving address assignment to setup.c
12  * Changed name of dz_init to rs_init to be consistent with tc code
13  * [13-NOV-98] triemer fixed code to receive characters
14  *    after patches by harald to irq code.
15  * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
16  *            field from "current" - somewhere between 2.1.121 and 2.1.131
17  Qua Jun 27 15:02:26 BRT 2001
18  * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
19  *
20  * Parts (C) 1999 David Airlie, airlied@linux.ie
21  * [07-SEP-99] Bugfixes
22  *
23  * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk>
24  * Converted to new serial core
25  */
26
27 #undef DEBUG_DZ
28
29 #include <linux/config.h>
30 #include <linux/module.h>
31 #include <linux/interrupt.h>
32 #include <linux/init.h>
33 #include <linux/console.h>
34 #include <linux/tty.h>
35 #include <linux/tty_flip.h>
36 #include <linux/serial_core.h>
37 #include <linux/serial.h>
38
39 #include <asm/bootinfo.h>
40 #include <asm/dec/interrupts.h>
41 #include <asm/dec/kn01.h>
42 #include <asm/dec/kn02.h>
43 #include <asm/dec/machtype.h>
44 #include <asm/dec/prom.h>
45 #include <asm/irq.h>
46 #include <asm/system.h>
47 #include <asm/uaccess.h>
48
49 #define CONSOLE_LINE (3)        /* for definition of struct console */
50
51 #include "dz.h"
52
53 #define DZ_INTR_DEBUG 1
54
55 static char *dz_name = "DECstation DZ serial driver version ";
56 static char *dz_version = "1.02";
57
58 struct dz_port {
59         struct uart_port        port;
60         unsigned int            cflag;
61 };
62
63 static struct dz_port dz_ports[DZ_NB_PORT];
64
65 #ifdef DEBUG_DZ
66 /*
67  * debugging code to send out chars via prom
68  */
69 static void debug_console(const char *s, int count)
70 {
71         unsigned i;
72
73         for (i = 0; i < count; i++) {
74                 if (*s == 10)
75                         prom_printf("%c", 13);
76                 prom_printf("%c", *s++);
77         }
78 }
79 #endif
80
81 /*
82  * ------------------------------------------------------------
83  * dz_in () and dz_out ()
84  *
85  * These routines are used to access the registers of the DZ
86  * chip, hiding relocation differences between implementation.
87  * ------------------------------------------------------------
88  */
89
90 static inline unsigned short dz_in(struct dz_port *dport, unsigned offset)
91 {
92         volatile unsigned short *addr =
93                 (volatile unsigned short *) (dport->port.membase + offset);
94         return *addr;
95 }
96
97 static inline void dz_out(struct dz_port *dport, unsigned offset,
98                           unsigned short value)
99 {
100         volatile unsigned short *addr =
101                 (volatile unsigned short *) (dport->port.membase + offset);
102         *addr = value;
103 }
104
105 /*
106  * ------------------------------------------------------------
107  * rs_stop () and rs_start ()
108  *
109  * These routines are called before setting or resetting
110  * tty->stopped. They enable or disable transmitter interrupts,
111  * as necessary.
112  * ------------------------------------------------------------
113  */
114
115 static void dz_stop_tx(struct uart_port *uport)
116 {
117         struct dz_port *dport = (struct dz_port *)uport;
118         unsigned short tmp, mask = 1 << dport->port.line;
119         unsigned long flags;
120
121         spin_lock_irqsave(&dport->port.lock, flags);
122         tmp = dz_in(dport, DZ_TCR);     /* read the TX flag */
123         tmp &= ~mask;                   /* clear the TX flag */
124         dz_out(dport, DZ_TCR, tmp);
125         spin_unlock_irqrestore(&dport->port.lock, flags);
126 }
127
128 static void dz_start_tx(struct uart_port *uport)
129 {
130         struct dz_port *dport = (struct dz_port *)uport;
131         unsigned short tmp, mask = 1 << dport->port.line;
132         unsigned long flags;
133
134         spin_lock_irqsave(&dport->port.lock, flags);
135         tmp = dz_in(dport, DZ_TCR);     /* read the TX flag */
136         tmp |= mask;                    /* set the TX flag */
137         dz_out(dport, DZ_TCR, tmp);
138         spin_unlock_irqrestore(&dport->port.lock, flags);
139 }
140
141 static void dz_stop_rx(struct uart_port *uport)
142 {
143         struct dz_port *dport = (struct dz_port *)uport;
144         unsigned long flags;
145
146         spin_lock_irqsave(&dport->port.lock, flags);
147         dport->cflag &= ~DZ_CREAD;
148         dz_out(dport, DZ_LPR, dport->cflag);
149         spin_unlock_irqrestore(&dport->port.lock, flags);
150 }
151
152 static void dz_enable_ms(struct uart_port *port)
153 {
154         /* nothing to do */
155 }
156
157 /*
158  * ------------------------------------------------------------
159  * Here starts the interrupt handling routines.  All of the
160  * following subroutines are declared as inline and are folded
161  * into dz_interrupt.  They were separated out for readability's
162  * sake.
163  *
164  * Note: rs_interrupt() is a "fast" interrupt, which means that it
165  * runs with interrupts turned off.  People who may want to modify
166  * rs_interrupt() should try to keep the interrupt handler as fast as
167  * possible.  After you are done making modifications, it is not a bad
168  * idea to do:
169  *
170  *      make drivers/serial/dz.s
171  *
172  * and look at the resulting assemble code in dz.s.
173  *
174  * ------------------------------------------------------------
175  */
176
177 /*
178  * ------------------------------------------------------------
179  * receive_char ()
180  *
181  * This routine deals with inputs from any lines.
182  * ------------------------------------------------------------
183  */
184 static inline void dz_receive_chars(struct dz_port *dport)
185 {
186         struct tty_struct *tty = NULL;
187         struct uart_icount *icount;
188         int ignore = 0;
189         unsigned short status, tmp;
190         unsigned char ch, flag;
191
192         /* this code is going to be a problem...
193            the call to tty_flip_buffer is going to need
194            to be rethought...
195          */
196         do {
197                 status = dz_in(dport, DZ_RBUF);
198
199                 /* punt so we don't get duplicate characters */
200                 if (!(status & DZ_DVAL))
201                         goto ignore_char;
202
203
204                 ch = UCHAR(status);     /* grab the char */
205                 flag = TTY_NORMAL;
206
207 #if 0
208                 if (info->is_console) {
209                         if (ch == 0)
210                                 return;         /* it's a break ... */
211                 }
212 #endif
213
214                 tty = dport->port.info->tty;/* now tty points to the proper dev */
215                 icount = &dport->port.icount;
216
217                 if (!tty)
218                         break;
219
220                 icount->rx++;
221
222                 /* keep track of the statistics */
223                 if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
224                         if (status & DZ_PERR)   /* parity error */
225                                 icount->parity++;
226                         else if (status & DZ_FERR)      /* frame error */
227                                 icount->frame++;
228                         if (status & DZ_OERR)   /* overrun error */
229                                 icount->overrun++;
230
231                         /*  check to see if we should ignore the character
232                            and mask off conditions that should be ignored
233                          */
234
235                         if (status & dport->port.ignore_status_mask) {
236                                 if (++ignore > 100)
237                                         break;
238                                 goto ignore_char;
239                         }
240                         /* mask off the error conditions we want to ignore */
241                         tmp = status & dport->port.read_status_mask;
242
243                         if (tmp & DZ_PERR) {
244                                 flag = TTY_PARITY;
245 #ifdef DEBUG_DZ
246                                 debug_console("PERR\n", 5);
247 #endif
248                         } else if (tmp & DZ_FERR) {
249                                 flag = TTY_FRAME;
250 #ifdef DEBUG_DZ
251                                 debug_console("FERR\n", 5);
252 #endif
253                         }
254                         if (tmp & DZ_OERR) {
255 #ifdef DEBUG_DZ
256                                 debug_console("OERR\n", 5);
257 #endif
258                                 tty_insert_flip_char(tty, ch, flag);
259                                 ch = 0;
260                                 flag = TTY_OVERRUN;
261                         }
262                 }
263                 tty_insert_flip_char(tty, ch, flag);
264               ignore_char:
265                         ;
266         } while (status & DZ_DVAL);
267
268         if (tty)
269                 tty_flip_buffer_push(tty);
270 }
271
272 /*
273  * ------------------------------------------------------------
274  * transmit_char ()
275  *
276  * This routine deals with outputs to any lines.
277  * ------------------------------------------------------------
278  */
279 static inline void dz_transmit_chars(struct dz_port *dport)
280 {
281         struct circ_buf *xmit = &dport->port.info->xmit;
282         unsigned char tmp;
283
284         if (dport->port.x_char) {       /* XON/XOFF chars */
285                 dz_out(dport, DZ_TDR, dport->port.x_char);
286                 dport->port.icount.tx++;
287                 dport->port.x_char = 0;
288                 return;
289         }
290         /* if nothing to do or stopped or hardware stopped */
291         if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
292                 dz_stop_tx(&dport->port);
293                 return;
294         }
295
296         /*
297          * if something to do ... (rember the dz has no output fifo so we go
298          * one char at a time :-<
299          */
300         tmp = xmit->buf[xmit->tail];
301         xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1);
302         dz_out(dport, DZ_TDR, tmp);
303         dport->port.icount.tx++;
304
305         if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
306                 uart_write_wakeup(&dport->port);
307
308         /* Are we done */
309         if (uart_circ_empty(xmit))
310                 dz_stop_tx(&dport->port);
311 }
312
313 /*
314  * ------------------------------------------------------------
315  * check_modem_status ()
316  *
317  * Only valid for the MODEM line duh !
318  * ------------------------------------------------------------
319  */
320 static inline void check_modem_status(struct dz_port *dport)
321 {
322         unsigned short status;
323
324         /* if not ne modem line just return */
325         if (dport->port.line != DZ_MODEM)
326                 return;
327
328         status = dz_in(dport, DZ_MSR);
329
330         /* it's easy, since DSR2 is the only bit in the register */
331         if (status)
332                 dport->port.icount.dsr++;
333 }
334
335 /*
336  * ------------------------------------------------------------
337  * dz_interrupt ()
338  *
339  * this is the main interrupt routine for the DZ chip.
340  * It deals with the multiple ports.
341  * ------------------------------------------------------------
342  */
343 static irqreturn_t dz_interrupt(int irq, void *dev, struct pt_regs *regs)
344 {
345         struct dz_port *dport;
346         unsigned short status;
347
348         /* get the reason why we just got an irq */
349         status = dz_in((struct dz_port *)dev, DZ_CSR);
350         dport = &dz_ports[LINE(status)];
351
352         if (status & DZ_RDONE)
353                 dz_receive_chars(dport);
354
355         if (status & DZ_TRDY)
356                 dz_transmit_chars(dport);
357
358         /* FIXME: what about check modem status??? --rmk */
359
360         return IRQ_HANDLED;
361 }
362
363 /*
364  * -------------------------------------------------------------------
365  * Here ends the DZ interrupt routines.
366  * -------------------------------------------------------------------
367  */
368
369 static unsigned int dz_get_mctrl(struct uart_port *uport)
370 {
371         struct dz_port *dport = (struct dz_port *)uport;
372         unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
373
374         if (dport->port.line == DZ_MODEM) {
375                 /*
376                  * CHECKME: This is a guess from the other code... --rmk
377                  */
378                 if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR)
379                         mctrl &= ~TIOCM_DSR;
380         }
381
382         return mctrl;
383 }
384
385 static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl)
386 {
387         struct dz_port *dport = (struct dz_port *)uport;
388         unsigned short tmp;
389
390         if (dport->port.line == DZ_MODEM) {
391                 tmp = dz_in(dport, DZ_TCR);
392                 if (mctrl & TIOCM_DTR)
393                         tmp &= ~DZ_MODEM_DTR;
394                 else
395                         tmp |= DZ_MODEM_DTR;
396                 dz_out(dport, DZ_TCR, tmp);
397         }
398 }
399
400 /*
401  * -------------------------------------------------------------------
402  * startup ()
403  *
404  * various initialization tasks
405  * -------------------------------------------------------------------
406  */
407 static int dz_startup(struct uart_port *uport)
408 {
409         struct dz_port *dport = (struct dz_port *)uport;
410         unsigned long flags;
411         unsigned short tmp;
412
413         /* The dz lines for the mouse/keyboard must be
414          * opened using their respective drivers.
415          */
416         if ((dport->port.line == DZ_KEYBOARD) ||
417             (dport->port.line == DZ_MOUSE))
418                 return -ENODEV;
419
420         spin_lock_irqsave(&dport->port.lock, flags);
421
422         /* enable the interrupt and the scanning */
423         tmp = dz_in(dport, DZ_CSR);
424         tmp |= DZ_RIE | DZ_TIE | DZ_MSE;
425         dz_out(dport, DZ_CSR, tmp);
426
427         spin_unlock_irqrestore(&dport->port.lock, flags);
428
429         return 0;
430 }
431
432 /*
433  * -------------------------------------------------------------------
434  * shutdown ()
435  *
436  * This routine will shutdown a serial port; interrupts are disabled, and
437  * DTR is dropped if the hangup on close termio flag is on.
438  * -------------------------------------------------------------------
439  */
440 static void dz_shutdown(struct uart_port *uport)
441 {
442         dz_stop_tx(uport);
443 }
444
445 /*
446  * get_lsr_info - get line status register info
447  *
448  * Purpose: Let user call ioctl() to get info when the UART physically
449  *          is emptied.  On bus types like RS485, the transmitter must
450  *          release the bus after transmitting. This must be done when
451  *          the transmit shift register is empty, not be done when the
452  *          transmit holding register is empty.  This functionality
453  *          allows an RS485 driver to be written in user space.
454  */
455 static unsigned int dz_tx_empty(struct uart_port *uport)
456 {
457         struct dz_port *dport = (struct dz_port *)uport;
458         unsigned short status = dz_in(dport, DZ_LPR);
459
460         /* FIXME: this appears to be obviously broken --rmk. */
461         return status ? TIOCSER_TEMT : 0;
462 }
463
464 static void dz_break_ctl(struct uart_port *uport, int break_state)
465 {
466         struct dz_port *dport = (struct dz_port *)uport;
467         unsigned long flags;
468         unsigned short tmp, mask = 1 << uport->line;
469
470         spin_lock_irqsave(&uport->lock, flags);
471         tmp = dz_in(dport, DZ_TCR);
472         if (break_state)
473                 tmp |= mask;
474         else
475                 tmp &= ~mask;
476         dz_out(dport, DZ_TCR, tmp);
477         spin_unlock_irqrestore(&uport->lock, flags);
478 }
479
480 static void dz_set_termios(struct uart_port *uport, struct termios *termios,
481                            struct termios *old_termios)
482 {
483         struct dz_port *dport = (struct dz_port *)uport;
484         unsigned long flags;
485         unsigned int cflag, baud;
486
487         cflag = dport->port.line;
488
489         switch (termios->c_cflag & CSIZE) {
490         case CS5:
491                 cflag |= DZ_CS5;
492                 break;
493         case CS6:
494                 cflag |= DZ_CS6;
495                 break;
496         case CS7:
497                 cflag |= DZ_CS7;
498                 break;
499         case CS8:
500         default:
501                 cflag |= DZ_CS8;
502         }
503
504         if (termios->c_cflag & CSTOPB)
505                 cflag |= DZ_CSTOPB;
506         if (termios->c_cflag & PARENB)
507                 cflag |= DZ_PARENB;
508         if (termios->c_cflag & PARODD)
509                 cflag |= DZ_PARODD;
510
511         baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);
512         switch (baud) {
513         case 50:
514                 cflag |= DZ_B50;
515                 break;
516         case 75:
517                 cflag |= DZ_B75;
518                 break;
519         case 110:
520                 cflag |= DZ_B110;
521                 break;
522         case 134:
523                 cflag |= DZ_B134;
524                 break;
525         case 150:
526                 cflag |= DZ_B150;
527                 break;
528         case 300:
529                 cflag |= DZ_B300;
530                 break;
531         case 600:
532                 cflag |= DZ_B600;
533                 break;
534         case 1200:
535                 cflag |= DZ_B1200;
536                 break;
537         case 1800:
538                 cflag |= DZ_B1800;
539                 break;
540         case 2000:
541                 cflag |= DZ_B2000;
542                 break;
543         case 2400:
544                 cflag |= DZ_B2400;
545                 break;
546         case 3600:
547                 cflag |= DZ_B3600;
548                 break;
549         case 4800:
550                 cflag |= DZ_B4800;
551                 break;
552         case 7200:
553                 cflag |= DZ_B7200;
554                 break;
555         case 9600:
556         default:
557                 cflag |= DZ_B9600;
558         }
559
560         if (termios->c_cflag & CREAD)
561                 cflag |= DZ_RXENAB;
562
563         spin_lock_irqsave(&dport->port.lock, flags);
564
565         dz_out(dport, DZ_LPR, cflag);
566         dport->cflag = cflag;
567
568         /* setup accept flag */
569         dport->port.read_status_mask = DZ_OERR;
570         if (termios->c_iflag & INPCK)
571                 dport->port.read_status_mask |= DZ_FERR | DZ_PERR;
572
573         /* characters to ignore */
574         uport->ignore_status_mask = 0;
575         if (termios->c_iflag & IGNPAR)
576                 dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;
577
578         spin_unlock_irqrestore(&dport->port.lock, flags);
579 }
580
581 static const char *dz_type(struct uart_port *port)
582 {
583         return "DZ";
584 }
585
586 static void dz_release_port(struct uart_port *port)
587 {
588         /* nothing to do */
589 }
590
591 static int dz_request_port(struct uart_port *port)
592 {
593         return 0;
594 }
595
596 static void dz_config_port(struct uart_port *port, int flags)
597 {
598         if (flags & UART_CONFIG_TYPE)
599                 port->type = PORT_DZ;
600 }
601
602 /*
603  * verify the new serial_struct (for TIOCSSERIAL).
604  */
605 static int dz_verify_port(struct uart_port *port, struct serial_struct *ser)
606 {
607         int ret = 0;
608         if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ)
609                 ret = -EINVAL;
610         if (ser->irq != port->irq)
611                 ret = -EINVAL;
612         return ret;
613 }
614
615 static struct uart_ops dz_ops = {
616         .tx_empty       = dz_tx_empty,
617         .get_mctrl      = dz_get_mctrl,
618         .set_mctrl      = dz_set_mctrl,
619         .stop_tx        = dz_stop_tx,
620         .start_tx       = dz_start_tx,
621         .stop_rx        = dz_stop_rx,
622         .enable_ms      = dz_enable_ms,
623         .break_ctl      = dz_break_ctl,
624         .startup        = dz_startup,
625         .shutdown       = dz_shutdown,
626         .set_termios    = dz_set_termios,
627         .type           = dz_type,
628         .release_port   = dz_release_port,
629         .request_port   = dz_request_port,
630         .config_port    = dz_config_port,
631         .verify_port    = dz_verify_port,
632 };
633
634 static void __init dz_init_ports(void)
635 {
636         static int first = 1;
637         struct dz_port *dport;
638         unsigned long base;
639         int i;
640
641         if (!first)
642                 return;
643         first = 0;
644
645         if (mips_machtype == MACH_DS23100 ||
646             mips_machtype == MACH_DS5100)
647                 base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_DZ11);
648         else
649                 base = CKSEG1ADDR(KN02_SLOT_BASE + KN02_DZ11);
650
651         for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {
652                 spin_lock_init(&dport->port.lock);
653                 dport->port.membase     = (char *) base;
654                 dport->port.iotype      = UPIO_PORT;
655                 dport->port.irq         = dec_interrupt[DEC_IRQ_DZ11];
656                 dport->port.line        = i;
657                 dport->port.fifosize    = 1;
658                 dport->port.ops         = &dz_ops;
659                 dport->port.flags       = UPF_BOOT_AUTOCONF;
660         }
661 }
662
663 static void dz_reset(struct dz_port *dport)
664 {
665         dz_out(dport, DZ_CSR, DZ_CLR);
666
667         while (dz_in(dport, DZ_CSR) & DZ_CLR);
668                 /* FIXME: cpu_relax? */
669
670         iob();
671
672         /* enable scanning */
673         dz_out(dport, DZ_CSR, DZ_MSE);
674 }
675
676 #ifdef CONFIG_SERIAL_DZ_CONSOLE
677 static void dz_console_put_char(struct dz_port *dport, unsigned char ch)
678 {
679         unsigned long flags;
680         int loops = 2500;
681         unsigned short tmp = ch;
682         /* this code sends stuff out to serial device - spinning its
683            wheels and waiting. */
684
685         spin_lock_irqsave(&dport->port.lock, flags);
686
687         /* spin our wheels */
688         while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--)
689                 /* FIXME: cpu_relax, udelay? --rmk */
690                 ;
691
692         /* Actually transmit the character. */
693         dz_out(dport, DZ_TDR, tmp);
694
695         spin_unlock_irqrestore(&dport->port.lock, flags);
696 }
697 /*
698  * -------------------------------------------------------------------
699  * dz_console_print ()
700  *
701  * dz_console_print is registered for printk.
702  * The console must be locked when we get here.
703  * -------------------------------------------------------------------
704  */
705 static void dz_console_print(struct console *cons,
706                              const char *str,
707                              unsigned int count)
708 {
709         struct dz_port *dport = &dz_ports[CONSOLE_LINE];
710 #ifdef DEBUG_DZ
711         prom_printf((char *) str);
712 #endif
713         while (count--) {
714                 if (*str == '\n')
715                         dz_console_put_char(dport, '\r');
716                 dz_console_put_char(dport, *str++);
717         }
718 }
719
720 static int __init dz_console_setup(struct console *co, char *options)
721 {
722         struct dz_port *dport = &dz_ports[CONSOLE_LINE];
723         int baud = 9600;
724         int bits = 8;
725         int parity = 'n';
726         int flow = 'n';
727         int ret;
728         unsigned short mask, tmp;
729
730         if (options)
731                 uart_parse_options(options, &baud, &parity, &bits, &flow);
732
733         dz_reset(dport);
734
735         ret = uart_set_options(&dport->port, co, baud, parity, bits, flow);
736         if (ret == 0) {
737                 mask = 1 << dport->port.line;
738                 tmp = dz_in(dport, DZ_TCR);     /* read the TX flag */
739                 if (!(tmp & mask)) {
740                         tmp |= mask;            /* set the TX flag */
741                         dz_out(dport, DZ_TCR, tmp);
742                 }
743         }
744
745         return ret;
746 }
747
748 static struct console dz_sercons =
749 {
750         .name   = "ttyS",
751         .write  = dz_console_print,
752         .device = uart_console_device,
753         .setup  = dz_console_setup,
754         .flags  = CON_CONSDEV | CON_PRINTBUFFER,
755         .index  = CONSOLE_LINE,
756 };
757
758 void __init dz_serial_console_init(void)
759 {
760         dz_init_ports();
761
762         register_console(&dz_sercons);
763 }
764
765 #define SERIAL_DZ_CONSOLE       &dz_sercons
766 #else
767 #define SERIAL_DZ_CONSOLE       NULL
768 #endif /* CONFIG_SERIAL_DZ_CONSOLE */
769
770 static struct uart_driver dz_reg = {
771         .owner                  = THIS_MODULE,
772         .driver_name            = "serial",
773 #ifdef CONFIG_DEVFS
774         .dev_name               = "tts/%d",
775 #else
776         .dev_name               = "ttyS%d",
777 #endif
778         .major                  = TTY_MAJOR,
779         .minor                  = 64,
780         .nr                     = DZ_NB_PORT,
781         .cons                   = SERIAL_DZ_CONSOLE,
782 };
783
784 int __init dz_init(void)
785 {
786         unsigned long flags;
787         int ret, i;
788
789         printk("%s%s\n", dz_name, dz_version);
790
791         dz_init_ports();
792
793         save_flags(flags);
794         cli();
795
796 #ifndef CONFIG_SERIAL_DZ_CONSOLE
797         /* reset the chip */
798         dz_reset(&dz_ports[0]);
799 #endif
800
801         /* order matters here... the trick is that flags
802            is updated... in request_irq - to immediatedly obliterate
803            it is unwise. */
804         restore_flags(flags);
805
806         if (request_irq(dz_ports[0].port.irq, dz_interrupt,
807                         SA_INTERRUPT, "DZ", &dz_ports[0]))
808                 panic("Unable to register DZ interrupt");
809
810         ret = uart_register_driver(&dz_reg);
811         if (ret != 0)
812                 return ret;
813
814         for (i = 0; i < DZ_NB_PORT; i++)
815                 uart_add_one_port(&dz_reg, &dz_ports[i].port);
816
817         return ret;
818 }
819
820 MODULE_DESCRIPTION("DECstation DZ serial driver");
821 MODULE_LICENSE("GPL");