From 9703899a941e2a937dd7db885e324deb607e1c95 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Jun 2005 09:49:28 +0000 Subject: bitkeeper revision 1.1660 (42a027a8dd_EUm7b7XhKL_lNM4H_Rg) Add support for memory-mapped ns16550 uart. Signed-off-by: Keir Fraser --- xen/arch/x86/dmi_scan.c | 1 - xen/drivers/char/ns16550.c | 71 +++++++++++++++++++++++++++------------------- xen/include/asm-x86/io.h | 9 ++++++ 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/xen/arch/x86/dmi_scan.c b/xen/arch/x86/dmi_scan.c index 3bb1820c66..74a487aade 100644 --- a/xen/arch/x86/dmi_scan.c +++ b/xen/arch/x86/dmi_scan.c @@ -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 --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index 89e64497e2..3a58e34767 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -21,11 +21,13 @@ string_param("com1", opt_com1); 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 @@ static struct ns16550 { #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 @@ static void ns16550_putc(struct serial_port *port, char c) { 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 @@ static void ns16550_init_preirq(struct serial_port *port) 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 @@ static void ns16550_init_postirq(struct serial_port *port) 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 @@ static void ns16550_parse_port_config(struct ns16550 *uart, char *conf) 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 --git a/xen/include/asm-x86/io.h b/xen/include/asm-x86/io.h index 2d92fc9234..2b733e4e86 100644 --- a/xen/include/asm-x86/io.h +++ b/xen/include/asm-x86/io.h @@ -54,6 +54,15 @@ static inline void * phys_to_virt(unsigned long address) #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 -- cgit v1.2.3