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