[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Add support for memory-mapped ns16550 uart.
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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |