debuggers.hg

view xen/drivers/char/ns16550.c @ 22906:700ac6445812

Now add KDB to the non-kdb tree
author Mukesh Rathor
date Thu Feb 03 15:42:41 2011 -0800 (2011-02-03)
parents 589d075ba295
children
line source
1 /******************************************************************************
2 * ns16550.c
3 *
4 * Driver for 16550-series UARTs. This driver is to be kept within Xen as
5 * it permits debugging of seriously-toasted machines (e.g., in situations
6 * where a device driver within a guest OS would be inaccessible).
7 *
8 * Copyright (c) 2003-2005, K A Fraser
9 */
11 #include <xen/config.h>
12 #include <xen/console.h>
13 #include <xen/init.h>
14 #include <xen/irq.h>
15 #include <xen/sched.h>
16 #include <xen/serial.h>
17 #include <xen/iocap.h>
18 #include <asm/io.h>
20 /*
21 * Configure serial port with a string:
22 * <baud>[/<clock_hz>][,DPS[,<io-base>[,<irq>[,<port-bdf>[,<bridge-bdf>]]]]].
23 * The tail of the string can be omitted if platform defaults are sufficient.
24 * If the baud rate is pre-configured, perhaps by a bootloader, then 'auto'
25 * can be specified in place of a numeric baud rate. Polled mode is specified
26 * by requesting irq 0.
27 */
28 static char __initdata opt_com1[30] = "";
29 static char __initdata opt_com2[30] = "";
30 string_param("com1", opt_com1);
31 string_param("com2", opt_com2);
33 static struct ns16550 {
34 int baud, clock_hz, data_bits, parity, stop_bits, irq;
35 unsigned long io_base; /* I/O port or memory-mapped I/O address. */
36 char *remapped_io_base; /* Remapped virtual address of mmap I/O. */
37 /* UART with IRQ line: interrupt-driven I/O. */
38 struct irqaction irqaction;
39 /* UART with no IRQ line: periodically-polled I/O. */
40 struct timer timer;
41 unsigned int timeout_ms;
42 bool_t probing, intr_works;
43 /* PCI card parameters. */
44 unsigned int pb_bdf[3]; /* pci bridge BDF */
45 unsigned int ps_bdf[3]; /* pci serial port BDF */
46 bool_t pb_bdf_enable; /* if =1, pb-bdf effective, port behind bridge */
47 bool_t ps_bdf_enable; /* if =1, ps_bdf effective, port on pci card */
48 } ns16550_com[2] = { { 0 } };
50 /* Register offsets */
51 #define RBR 0x00 /* receive buffer */
52 #define THR 0x00 /* transmit holding */
53 #define IER 0x01 /* interrupt enable */
54 #define IIR 0x02 /* interrupt identity */
55 #define FCR 0x02 /* FIFO control */
56 #define LCR 0x03 /* line control */
57 #define MCR 0x04 /* Modem control */
58 #define LSR 0x05 /* line status */
59 #define MSR 0x06 /* Modem status */
60 #define DLL 0x00 /* divisor latch (ls) (DLAB=1) */
61 #define DLM 0x01 /* divisor latch (ms) (DLAB=1) */
63 /* Interrupt Enable Register */
64 #define IER_ERDAI 0x01 /* rx data recv'd */
65 #define IER_ETHREI 0x02 /* tx reg. empty */
66 #define IER_ELSI 0x04 /* rx line status */
67 #define IER_EMSI 0x08 /* MODEM status */
69 /* Interrupt Identification Register */
70 #define IIR_NOINT 0x01 /* no interrupt pending */
71 #define IIR_IMASK 0x06 /* interrupt identity: */
72 #define IIR_LSI 0x06 /* - rx line status */
73 #define IIR_RDAI 0x04 /* - rx data recv'd */
74 #define IIR_THREI 0x02 /* - tx reg. empty */
75 #define IIR_MSI 0x00 /* - MODEM status */
77 /* FIFO Control Register */
78 #define FCR_ENABLE 0x01 /* enable FIFO */
79 #define FCR_CLRX 0x02 /* clear Rx FIFO */
80 #define FCR_CLTX 0x04 /* clear Tx FIFO */
81 #define FCR_DMA 0x10 /* enter DMA mode */
82 #define FCR_TRG1 0x00 /* Rx FIFO trig lev 1 */
83 #define FCR_TRG4 0x40 /* Rx FIFO trig lev 4 */
84 #define FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */
85 #define FCR_TRG14 0xc0 /* Rx FIFO trig lev 14 */
87 /* Line Control Register */
88 #define LCR_DLAB 0x80 /* Divisor Latch Access */
90 /* Modem Control Register */
91 #define MCR_DTR 0x01 /* Data Terminal Ready */
92 #define MCR_RTS 0x02 /* Request to Send */
93 #define MCR_OUT2 0x08 /* OUT2: interrupt mask */
94 #define MCR_LOOP 0x10 /* Enable loopback test mode */
96 /* Line Status Register */
97 #define LSR_DR 0x01 /* Data ready */
98 #define LSR_OE 0x02 /* Overrun */
99 #define LSR_PE 0x04 /* Parity error */
100 #define LSR_FE 0x08 /* Framing error */
101 #define LSR_BI 0x10 /* Break */
102 #define LSR_THRE 0x20 /* Xmit hold reg empty */
103 #define LSR_TEMT 0x40 /* Xmitter empty */
104 #define LSR_ERR 0x80 /* Error */
106 /* These parity settings can be ORed directly into the LCR. */
107 #define PARITY_NONE (0<<3)
108 #define PARITY_ODD (1<<3)
109 #define PARITY_EVEN (3<<3)
110 #define PARITY_MARK (5<<3)
111 #define PARITY_SPACE (7<<3)
113 /* Frequency of external clock source. This definition assumes PC platform. */
114 #define UART_CLOCK_HZ 1843200
116 static char ns_read_reg(struct ns16550 *uart, int reg)
117 {
118 if ( uart->remapped_io_base == NULL )
119 return inb(uart->io_base + reg);
120 return readb(uart->remapped_io_base + reg);
121 }
123 static void ns_write_reg(struct ns16550 *uart, int reg, char c)
124 {
125 if ( uart->remapped_io_base == NULL )
126 return outb(c, uart->io_base + reg);
127 writeb(c, uart->remapped_io_base + reg);
128 }
130 static void ns16550_interrupt(
131 int irq, void *dev_id, struct cpu_user_regs *regs)
132 {
133 struct serial_port *port = dev_id;
134 struct ns16550 *uart = port->uart;
136 if (uart->intr_works == 0)
137 {
138 uart->probing = 0;
139 uart->intr_works = 1;
140 stop_timer(&uart->timer);
141 }
143 while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) )
144 {
145 char lsr = ns_read_reg(uart, LSR);
146 if ( lsr & LSR_THRE )
147 serial_tx_interrupt(port, regs);
148 if ( lsr & LSR_DR )
149 serial_rx_interrupt(port, regs);
150 }
151 }
153 /* Safe: ns16550_poll() runs in softirq context so not reentrant on a given CPU. */
154 static DEFINE_PER_CPU(struct serial_port *, poll_port);
156 static void __ns16550_poll(struct cpu_user_regs *regs)
157 {
158 struct serial_port *port = this_cpu(poll_port);
159 struct ns16550 *uart = port->uart;
161 if ( uart->intr_works )
162 return; /* Interrupts work - no more polling */
164 if ( uart->probing ) {
165 uart->probing = 0;
166 if ( (ns_read_reg(uart, LSR) & 0xff) == 0xff )
167 return; /* All bits set - probably no UART present */
168 }
170 while ( ns_read_reg(uart, LSR) & LSR_DR )
171 serial_rx_interrupt(port, regs);
173 if ( ns_read_reg(uart, LSR) & LSR_THRE )
174 serial_tx_interrupt(port, regs);
176 set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms));
177 }
179 static void ns16550_poll(void *data)
180 {
181 this_cpu(poll_port) = data;
182 #ifdef run_in_exception_handler
183 run_in_exception_handler(__ns16550_poll);
184 #else
185 __ns16550_poll(guest_cpu_user_regs());
186 #endif
187 }
189 static int ns16550_tx_empty(struct serial_port *port)
190 {
191 struct ns16550 *uart = port->uart;
192 return !!(ns_read_reg(uart, LSR) & LSR_THRE);
193 }
195 static void ns16550_putc(struct serial_port *port, char c)
196 {
197 struct ns16550 *uart = port->uart;
198 ns_write_reg(uart, THR, c);
199 }
201 static int ns16550_getc(struct serial_port *port, char *pc)
202 {
203 struct ns16550 *uart = port->uart;
205 if ( !(ns_read_reg(uart, LSR) & LSR_DR) )
206 return 0;
208 *pc = ns_read_reg(uart, RBR);
209 return 1;
210 }
212 static void pci_serial_early_init(struct ns16550 *uart)
213 {
214 if ( !uart->ps_bdf_enable )
215 return;
217 if ( uart->pb_bdf_enable )
218 pci_conf_write16(uart->pb_bdf[0], uart->pb_bdf[1], uart->pb_bdf[2],
219 0x1c, (uart->io_base & 0xF000) | ((uart->io_base & 0xF000) >> 8));
221 pci_conf_write32(uart->ps_bdf[0], uart->ps_bdf[1], uart->ps_bdf[2],
222 0x10, uart->io_base | 0x1);
223 pci_conf_write16(uart->ps_bdf[0], uart->ps_bdf[1], uart->ps_bdf[2],
224 0x4, 0x1);
225 }
227 static void __devinit ns16550_init_preirq(struct serial_port *port)
228 {
229 struct ns16550 *uart = port->uart;
230 unsigned char lcr;
231 unsigned int divisor;
233 pci_serial_early_init(uart);
235 /* I/O ports are distinguished by their size (16 bits). */
236 if ( uart->io_base >= 0x10000 )
237 uart->remapped_io_base = (char *)ioremap(uart->io_base, 8);
239 lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity;
241 /* No interrupts. */
242 ns_write_reg(uart, IER, 0);
244 /* Line control and baud-rate generator. */
245 ns_write_reg(uart, LCR, lcr | LCR_DLAB);
246 if ( uart->baud != BAUD_AUTO )
247 {
248 /* Baud rate specified: program it into the divisor latch. */
249 divisor = uart->clock_hz / (uart->baud << 4);
250 ns_write_reg(uart, DLL, (char)divisor);
251 ns_write_reg(uart, DLM, (char)(divisor >> 8));
252 }
253 else
254 {
255 /* Baud rate already set: read it out from the divisor latch. */
256 divisor = ns_read_reg(uart, DLL);
257 divisor |= ns_read_reg(uart, DLM) << 8;
258 uart->baud = uart->clock_hz / (divisor << 4);
259 }
260 ns_write_reg(uart, LCR, lcr);
262 /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
263 ns_write_reg(uart, MCR, MCR_DTR | MCR_RTS);
265 /* Enable and clear the FIFOs. Set a large trigger threshold. */
266 ns_write_reg(uart, FCR, FCR_ENABLE | FCR_CLRX | FCR_CLTX | FCR_TRG14);
268 /* Check this really is a 16550+. Otherwise we have no FIFOs. */
269 if ( ((ns_read_reg(uart, IIR) & 0xc0) == 0xc0) &&
270 ((ns_read_reg(uart, FCR) & FCR_TRG14) == FCR_TRG14) )
271 port->tx_fifo_size = 16;
272 }
274 static void __devinit ns16550_init_postirq(struct serial_port *port)
275 {
276 struct ns16550 *uart = port->uart;
277 int rc, bits;
279 if ( uart->irq < 0 )
280 return;
282 serial_async_transmit(port);
284 if ( !uart->timer.function )
285 init_timer(&uart->timer, ns16550_poll, port, 0);
287 /* Calculate time to fill RX FIFO and/or empty TX FIFO for polling. */
288 bits = uart->data_bits + uart->stop_bits + !!uart->parity;
289 uart->timeout_ms = max_t(
290 unsigned int, 1, (bits * port->tx_fifo_size * 1000) / uart->baud);
292 if ( uart->irq == 0 )
293 set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms));
294 else
295 {
296 uart->irqaction.handler = ns16550_interrupt;
297 uart->irqaction.name = "ns16550";
298 uart->irqaction.dev_id = port;
299 if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
300 printk("ERROR: Failed to allocate ns16550 IRQ %d\n", uart->irq);
302 /* Master interrupt enable; also keep DTR/RTS asserted. */
303 ns_write_reg(uart, MCR, MCR_OUT2 | MCR_DTR | MCR_RTS);
305 /* Enable receive and transmit interrupts. */
306 ns_write_reg(uart, IER, IER_ERDAI | IER_ETHREI);
308 /* Do a timed write to make sure we are getting interrupts. */
309 uart->probing = 1;
310 uart->intr_works = 0;
311 ns_write_reg(uart, THR, 0xff);
312 set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms));
313 }
314 }
316 #ifdef CONFIG_X86
317 static void __init ns16550_endboot(struct serial_port *port)
318 {
319 struct ns16550 *uart = port->uart;
320 if ( ioports_deny_access(dom0, uart->io_base, uart->io_base + 7) != 0 )
321 BUG();
322 }
323 #else
324 #define ns16550_endboot NULL
325 #endif
327 static int ns16550_irq(struct serial_port *port)
328 {
329 struct ns16550 *uart = port->uart;
330 return ((uart->irq > 0) ? uart->irq : -1);
331 }
333 static struct uart_driver __read_mostly ns16550_driver = {
334 .init_preirq = ns16550_init_preirq,
335 .init_postirq = ns16550_init_postirq,
336 .endboot = ns16550_endboot,
337 .tx_empty = ns16550_tx_empty,
338 .putc = ns16550_putc,
339 .getc = ns16550_getc,
340 .irq = ns16550_irq
341 };
343 static int __init parse_parity_char(int c)
344 {
345 switch ( c )
346 {
347 case 'n':
348 return PARITY_NONE;
349 case 'o':
350 return PARITY_ODD;
351 case 'e':
352 return PARITY_EVEN;
353 case 'm':
354 return PARITY_MARK;
355 case 's':
356 return PARITY_SPACE;
357 }
358 return 0;
359 }
361 static void __init parse_pci_bdf(const char **conf, unsigned int bdf[3])
362 {
363 bdf[0] = simple_strtoul(*conf, conf, 16);
364 if ( **conf != ':' )
365 return;
366 (*conf)++;
367 bdf[1] = simple_strtoul(*conf, conf, 16);
368 if ( **conf != '.' )
369 return;
370 (*conf)++;
371 bdf[2] = simple_strtoul(*conf, conf, 16);
372 }
374 static int __init check_existence(struct ns16550 *uart)
375 {
376 unsigned char status, scratch, scratch2, scratch3;
378 /*
379 * We can't poke MMIO UARTs until they get I/O remapped later. Assume that
380 * if we're getting MMIO UARTs, the arch code knows what it's doing.
381 */
382 if ( uart->io_base >= 0x10000 )
383 return 1;
385 pci_serial_early_init(uart);
387 /*
388 * Do a simple existence test first; if we fail this,
389 * there's no point trying anything else.
390 */
391 scratch = ns_read_reg(uart, IER);
392 ns_write_reg(uart, IER, 0);
394 /*
395 * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
396 * 16C754B) allow only to modify them if an EFR bit is set.
397 */
398 scratch2 = ns_read_reg(uart, IER) & 0x0f;
399 ns_write_reg(uart, IER, 0x0F);
400 scratch3 = ns_read_reg(uart, IER) & 0x0f;
401 ns_write_reg(uart, IER, scratch);
402 if ( (scratch2 != 0) || (scratch3 != 0x0F) )
403 return 0;
405 /*
406 * Check to see if a UART is really there.
407 * Use loopback test mode.
408 */
409 ns_write_reg(uart, MCR, MCR_LOOP | 0x0A);
410 status = ns_read_reg(uart, MSR) & 0xF0;
411 return (status == 0x90);
412 }
414 #define PARSE_ERR(_f, _a...) \
415 do { \
416 printk( "ERROR: " _f "\n" , ## _a ); \
417 return; \
418 } while ( 0 )
420 static void __init ns16550_parse_port_config(
421 struct ns16550 *uart, const char *conf)
422 {
423 int baud;
425 /* No user-specified configuration? */
426 if ( (conf == NULL) || (*conf == '\0') )
427 {
428 /* Some platforms may automatically probe the UART configuartion. */
429 if ( uart->baud != 0 )
430 goto config_parsed;
431 return;
432 }
434 if ( strncmp(conf, "auto", 4) == 0 )
435 {
436 uart->baud = BAUD_AUTO;
437 conf += 4;
438 }
439 else if ( (baud = simple_strtoul(conf, &conf, 10)) != 0 )
440 uart->baud = baud;
442 if ( *conf == '/')
443 {
444 conf++;
445 uart->clock_hz = simple_strtoul(conf, &conf, 0) << 4;
446 }
448 if ( *conf != ',' )
449 goto config_parsed;
450 conf++;
452 uart->data_bits = simple_strtoul(conf, &conf, 10);
454 uart->parity = parse_parity_char(*conf);
455 conf++;
457 uart->stop_bits = simple_strtoul(conf, &conf, 10);
459 if ( *conf == ',' )
460 {
461 conf++;
462 uart->io_base = simple_strtoul(conf, &conf, 0);
464 if ( *conf == ',' )
465 {
466 conf++;
467 uart->irq = simple_strtoul(conf, &conf, 10);
468 if ( *conf == ',' )
469 {
470 conf++;
471 uart->ps_bdf_enable = 1;
472 parse_pci_bdf(&conf, &uart->ps_bdf[0]);
473 if ( *conf == ',' )
474 {
475 conf++;
476 uart->pb_bdf_enable = 1;
477 parse_pci_bdf(&conf, &uart->pb_bdf[0]);
478 }
479 }
480 }
481 }
483 config_parsed:
484 /* Sanity checks. */
485 if ( (uart->baud != BAUD_AUTO) &&
486 ((uart->baud < 1200) || (uart->baud > 115200)) )
487 PARSE_ERR("Baud rate %d outside supported range.", uart->baud);
488 if ( (uart->data_bits < 5) || (uart->data_bits > 8) )
489 PARSE_ERR("%d data bits are unsupported.", uart->data_bits);
490 if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) )
491 PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits);
492 if ( uart->io_base == 0 )
493 PARSE_ERR("I/O base address must be specified.");
494 if ( !check_existence(uart) )
495 PARSE_ERR("16550-compatible serial UART not present");
497 /* Register with generic serial driver. */
498 serial_register_uart(uart - ns16550_com, &ns16550_driver, uart);
499 }
501 void __init ns16550_init(int index, struct ns16550_defaults *defaults)
502 {
503 struct ns16550 *uart;
505 if ( (index < 0) || (index > 1) )
506 return;
508 uart = &ns16550_com[index];
510 uart->baud = (defaults->baud ? :
511 console_has((index == 0) ? "com1" : "com2")
512 ? BAUD_AUTO : 0);
513 uart->clock_hz = UART_CLOCK_HZ;
514 uart->data_bits = defaults->data_bits;
515 uart->parity = parse_parity_char(defaults->parity);
516 uart->stop_bits = defaults->stop_bits;
517 uart->irq = defaults->irq;
518 uart->io_base = defaults->io_base;
520 ns16550_parse_port_config(uart, (index == 0) ? opt_com1 : opt_com2);
521 }
523 /*
524 * Local variables:
525 * mode: C
526 * c-set-style: "BSD"
527 * c-basic-offset: 4
528 * tab-width: 4
529 * indent-tabs-mode: nil
530 * End:
531 */