ChangeSet 1.1660, 2005/06/03 10:49:28+01:00, kaf24@xxxxxxxxxxxxxxxxxxxx
Add support for memory-mapped ns16550 uart.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
arch/x86/dmi_scan.c | 1
drivers/char/ns16550.c | 73 ++++++++++++++++++++++++++++---------------------
include/asm-x86/io.h | 9 ++++++
3 files changed, 52 insertions(+), 31 deletions(-)
diff -Nru a/xen/arch/x86/dmi_scan.c b/xen/arch/x86/dmi_scan.c
--- a/xen/arch/x86/dmi_scan.c 2005-06-03 06:01:48 -04:00
+++ b/xen/arch/x86/dmi_scan.c 2005-06-03 06:01:48 -04:00
@@ -12,7 +12,6 @@
#define bt_ioremap(b,l) ((u8 *)__acpi_map_table(b,l))
#define bt_iounmap(b,l) ((void)0)
-#define ioremap(b,l) (__va(b))
#define memcpy_fromio memcpy
#define alloc_bootmem(l) xmalloc_bytes(l)
diff -Nru a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c 2005-06-03 06:01:48 -04:00
+++ b/xen/drivers/char/ns16550.c 2005-06-03 06:01:48 -04:00
@@ -21,11 +21,13 @@
string_param("com2", opt_com2);
static struct ns16550 {
- int baud, data_bits, parity, stop_bits, io_base, irq;
+ int baud, data_bits, parity, stop_bits, irq;
+ unsigned long io_base; /* I/O port or memory-mapped I/O address. */
+ char *remapped_io_base; /* Remapped virtual address of mmap I/O. */
struct irqaction irqaction;
} ns16550_com[2] = {
- { 0, 0, 0, 0, 0x3f8, 4 },
- { 0, 0, 0, 0, 0x2f8, 3 }
+ { 0, 0, 0, 0, 4, 0x3f8 },
+ { 0, 0, 0, 0, 3, 0x2f8 }
};
/* Register offsets */
@@ -82,6 +84,20 @@
#define PARITY_MARK (5<<3)
#define PARITY_SPACE (7<<3)
+static char ns_read_reg(struct ns16550 *uart, int reg)
+{
+ if ( uart->remapped_io_base == NULL )
+ return inb(uart->io_base + reg);
+ return readb(uart->remapped_io_base + reg);
+}
+
+static void ns_write_reg(struct ns16550 *uart, int reg, char c)
+{
+ if ( uart->remapped_io_base == NULL )
+ return outb(c, uart->io_base + reg);
+ writeb(c, uart->remapped_io_base + reg);
+}
+
static void ns16550_interrupt(
int irq, void *dev_id, struct cpu_user_regs *regs)
{
@@ -92,20 +108,20 @@
{
struct ns16550 *uart = port->uart;
- while ( !(inb(uart->io_base + LSR) & LSR_THRE) )
+ while ( !(ns_read_reg(uart, LSR) & LSR_THRE) )
cpu_relax();
- outb(c, uart->io_base + THR);
+ ns_write_reg(uart, THR, c);
}
static int ns16550_getc(struct serial_port *port, char *pc)
{
struct ns16550 *uart = port->uart;
- if ( !(inb(uart->io_base + LSR) & LSR_DR) )
+ if ( !(ns_read_reg(uart, LSR) & LSR_DR) )
return 0;
- *pc = inb(uart->io_base + RBR);
+ *pc = ns_read_reg(uart, RBR);
return 1;
}
@@ -114,22 +130,26 @@
struct ns16550 *uart = port->uart;
unsigned char lcr;
+ /* I/O ports are distinguished by their size (16 bits). */
+ if ( uart->io_base >= 0x10000 )
+ uart->remapped_io_base = (char *)ioremap(uart->io_base, 8);
+
lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity;
/* No interrupts. */
- outb(0, uart->io_base + IER);
+ ns_write_reg(uart, IER, 0);
/* Line control and baud-rate generator. */
- outb(lcr | LCR_DLAB, uart->io_base + LCR);
- outb(115200/uart->baud, uart->io_base + DLL); /* baud lo */
- outb(0, uart->io_base + DLM); /* baud hi */
- outb(lcr, uart->io_base + LCR); /* parity, data, stop */
+ ns_write_reg(uart, LCR, lcr | LCR_DLAB);
+ ns_write_reg(uart, DLL, 115200/uart->baud); /* baud lo */
+ ns_write_reg(uart, DLM, 0); /* baud hi */
+ ns_write_reg(uart, LCR, lcr); /* parity, data, stop */
/* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */
- outb(MCR_DTR | MCR_RTS, uart->io_base + MCR);
+ ns_write_reg(uart, MCR, MCR_DTR | MCR_RTS);
/* Enable and clear the FIFOs. Set a large trigger threshold. */
- outb(FCR_ENABLE | FCR_CLRX | FCR_CLTX | FCR_TRG14, uart->io_base + FCR);
+ ns_write_reg(uart, FCR, FCR_ENABLE | FCR_CLRX | FCR_CLTX | FCR_TRG14);
}
static void ns16550_init_postirq(struct serial_port *port)
@@ -144,13 +164,13 @@
printk("ERROR: Failed to allocate na16550 IRQ %d\n", uart->irq);
/* For sanity, clear the receive FIFO. */
- outb(FCR_ENABLE | FCR_CLRX | FCR_TRG14, uart->io_base + FCR);
+ ns_write_reg(uart, FCR, FCR_ENABLE | FCR_CLRX | FCR_TRG14);
/* Master interrupt enable; also keep DTR/RTS asserted. */
- outb(MCR_OUT2 | MCR_DTR | MCR_RTS, uart->io_base + MCR);
+ ns_write_reg(uart, MCR, MCR_OUT2 | MCR_DTR | MCR_RTS);
/* Enable receive interrupts. */
- outb(IER_ERDAI, uart->io_base + IER);
+ ns_write_reg(uart, IER, IER_ERDAI);
}
#ifdef CONFIG_X86
@@ -227,20 +247,13 @@
if ( *conf == ',' )
{
conf++;
-
uart->io_base = simple_strtol(conf, &conf, 0);
- if ( (uart->io_base <= 0x0000) || (uart->io_base > 0xfff0) )
- PARSE_ERR("I/O port base 0x%x is outside the supported range.",
- uart->io_base);
-
- if ( *conf != ',' )
- PARSE_ERR("Missing IRQ specifier.");
-
- conf++;
-
- uart->irq = simple_strtol(conf, &conf, 10);
- if ( (uart->irq <= 0) || (uart->irq >= 32) )
- PARSE_ERR("IRQ %d is outside the supported range.", uart->irq);
+
+ if ( *conf == ',' )
+ {
+ conf++;
+ uart->irq = simple_strtol(conf, &conf, 10);
+ }
}
serial_register_uart(uart - ns16550_com, &ns16550_driver, uart);
diff -Nru a/xen/include/asm-x86/io.h b/xen/include/asm-x86/io.h
--- a/xen/include/asm-x86/io.h 2005-06-03 06:01:48 -04:00
+++ b/xen/include/asm-x86/io.h 2005-06-03 06:01:48 -04:00
@@ -54,6 +54,15 @@
#define page_to_pfn(_page) ((unsigned long)((_page) - frame_table))
#define page_to_virt(_page) phys_to_virt(page_to_phys(_page))
+/* We don't need real ioremap() on Xen/x86. */
+#define ioremap(x,l) (__va(x))
+
+#define readb(x) (*(volatile char *)(x))
+#define readw(x) (*(volatile short *)(x))
+#define readl(x) (*(volatile int *)(x))
+#define writeb(d,x) (*(volatile char *)(x) = (d))
+#define writew(d,x) (*(volatile short *)(x) = (d))
+#define writel(d,x) (*(volatile int *)(x) = (d))
/*
* IO bus memory addresses are also 1:1 with the physical address
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|