ia64/linux-2.6.18-xen.hg

view drivers/serial/dz.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
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 */
27 #undef DEBUG_DZ
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>
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>
48 #define CONSOLE_LINE (3) /* for definition of struct console */
50 #include "dz.h"
52 #define DZ_INTR_DEBUG 1
54 static char *dz_name = "DECstation DZ serial driver version ";
55 static char *dz_version = "1.02";
57 struct dz_port {
58 struct uart_port port;
59 unsigned int cflag;
60 };
62 static struct dz_port dz_ports[DZ_NB_PORT];
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;
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
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 */
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 }
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 }
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 */
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;
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 }
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;
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 }
140 static void dz_stop_rx(struct uart_port *uport)
141 {
142 struct dz_port *dport = (struct dz_port *)uport;
143 unsigned long flags;
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 }
151 static void dz_enable_ms(struct uart_port *port)
152 {
153 /* nothing to do */
154 }
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 */
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;
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);
198 /* punt so we don't get duplicate characters */
199 if (!(status & DZ_DVAL))
200 goto ignore_char;
203 ch = UCHAR(status); /* grab the char */
204 flag = TTY_NORMAL;
206 #if 0
207 if (info->is_console) {
208 if (ch == 0)
209 return; /* it's a break ... */
210 }
211 #endif
213 tty = dport->port.info->tty;/* now tty points to the proper dev */
214 icount = &dport->port.icount;
216 if (!tty)
217 break;
219 icount->rx++;
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++;
230 /* check to see if we should ignore the character
231 and mask off conditions that should be ignored
232 */
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;
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);
267 if (tty)
268 tty_flip_buffer_push(tty);
269 }
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;
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 }
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++;
304 if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
305 uart_write_wakeup(&dport->port);
307 /* Are we done */
308 if (uart_circ_empty(xmit))
309 dz_stop_tx(&dport->port);
310 }
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;
323 /* if not ne modem line just return */
324 if (dport->port.line != DZ_MODEM)
325 return;
327 status = dz_in(dport, DZ_MSR);
329 /* it's easy, since DSR2 is the only bit in the register */
330 if (status)
331 dport->port.icount.dsr++;
332 }
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;
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)];
351 if (status & DZ_RDONE)
352 dz_receive_chars(dport);
354 if (status & DZ_TRDY)
355 dz_transmit_chars(dport);
357 /* FIXME: what about check modem status??? --rmk */
359 return IRQ_HANDLED;
360 }
362 /*
363 * -------------------------------------------------------------------
364 * Here ends the DZ interrupt routines.
365 * -------------------------------------------------------------------
366 */
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;
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 }
381 return mctrl;
382 }
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;
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 }
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;
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;
419 spin_lock_irqsave(&dport->port.lock, flags);
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);
426 spin_unlock_irqrestore(&dport->port.lock, flags);
428 return 0;
429 }
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 }
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);
459 /* FIXME: this appears to be obviously broken --rmk. */
460 return status ? TIOCSER_TEMT : 0;
461 }
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;
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 }
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;
486 cflag = dport->port.line;
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 }
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;
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 }
559 if (termios->c_cflag & CREAD)
560 cflag |= DZ_RXENAB;
562 spin_lock_irqsave(&dport->port.lock, flags);
564 dz_out(dport, DZ_LPR, cflag);
565 dport->cflag = cflag;
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;
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;
577 spin_unlock_irqrestore(&dport->port.lock, flags);
578 }
580 static const char *dz_type(struct uart_port *port)
581 {
582 return "DZ";
583 }
585 static void dz_release_port(struct uart_port *port)
586 {
587 /* nothing to do */
588 }
590 static int dz_request_port(struct uart_port *port)
591 {
592 return 0;
593 }
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 }
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 }
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 };
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;
640 if (!first)
641 return;
642 first = 0;
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);
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 }
662 static void dz_reset(struct dz_port *dport)
663 {
664 dz_out(dport, DZ_CSR, DZ_CLR);
666 while (dz_in(dport, DZ_CSR) & DZ_CLR);
667 /* FIXME: cpu_relax? */
669 iob();
671 /* enable scanning */
672 dz_out(dport, DZ_CSR, DZ_MSE);
673 }
675 #ifdef CONFIG_SERIAL_DZ_CONSOLE
676 static void dz_console_putchar(struct uart_port *uport, 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. */
685 spin_lock_irqsave(&dport->port.lock, flags);
687 /* spin our wheels */
688 while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--)
689 /* FIXME: cpu_relax, udelay? --rmk */
690 ;
692 /* Actually transmit the character. */
693 dz_out(dport, DZ_TDR, tmp);
695 spin_unlock_irqrestore(&dport->port.lock, flags);
696 }
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 }
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;
727 if (options)
728 uart_parse_options(options, &baud, &parity, &bits, &flow);
730 dz_reset(dport);
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 }
742 return ret;
743 }
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 };
755 void __init dz_serial_console_init(void)
756 {
757 dz_init_ports();
759 register_console(&dz_sercons);
760 }
762 #define SERIAL_DZ_CONSOLE &dz_sercons
763 #else
764 #define SERIAL_DZ_CONSOLE NULL
765 #endif /* CONFIG_SERIAL_DZ_CONSOLE */
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 };
777 int __init dz_init(void)
778 {
779 unsigned long flags;
780 int ret, i;
782 printk("%s%s\n", dz_name, dz_version);
784 dz_init_ports();
786 save_flags(flags);
787 cli();
789 #ifndef CONFIG_SERIAL_DZ_CONSOLE
790 /* reset the chip */
791 dz_reset(&dz_ports[0]);
792 #endif
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);
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");
803 ret = uart_register_driver(&dz_reg);
804 if (ret != 0)
805 return ret;
807 for (i = 0; i < DZ_NB_PORT; i++)
808 uart_add_one_port(&dz_reg, &dz_ports[i].port);
810 return ret;
811 }
813 MODULE_DESCRIPTION("DECstation DZ serial driver");
814 MODULE_LICENSE("GPL");