diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-12-29 16:35:43 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-12-29 16:35:43 +0000 |
commit | d0ed783f34132a6456fbee80ce5d121faf55fb8c (patch) | |
tree | ed7bb65b9ba2d86bafa9ba4631718717cd944d01 /arch/mips/mips-boards/generic/printf.c | |
parent | 041d5780d54608a859ac6fd0fac06ec0e670aa5b (diff) |
Bunch more patches from MIPS.
Diffstat (limited to 'arch/mips/mips-boards/generic/printf.c')
-rw-r--r-- | arch/mips/mips-boards/generic/printf.c | 115 |
1 files changed, 100 insertions, 15 deletions
diff --git a/arch/mips/mips-boards/generic/printf.c b/arch/mips/mips-boards/generic/printf.c index 3c21ae8bf..4f3f6e845 100644 --- a/arch/mips/mips-boards/generic/printf.c +++ b/arch/mips/mips-boards/generic/printf.c @@ -25,31 +25,116 @@ #include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> -#include <asm/addrspace.h> -#include <asm/mips-boards/generic.h> +#include <linux/serialP.h> +#include <linux/serial_reg.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/serial.h> -static char ppbuf[1024]; -void (*prom_print_str)(unsigned int out, char *s, int len); +#ifdef CONFIG_MIPS_ATLAS +/* + * Atlas registers are memory mapped on 64-bit aligned boundaries and + * only word access are allowed. + * When reading the UART 8 bit registers only the LSB are valid. + */ +unsigned int atlas_serial_in(struct async_struct *info, int offset) +{ + return (*(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) & 0xff); +} + +void atlas_serial_out(struct async_struct *info, int offset, int value) +{ + *(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) = value; +} + +#define serial_in atlas_serial_in +#define serial_out atlas_serial_out + +#else +static unsigned int serial_in(struct async_struct *info, int offset) +{ + return inb(info->port + offset); +} -void __init setup_prom_printf(void) +static void serial_out(struct async_struct *info, int offset, + int value) { - prom_print_str = (void *)*(unsigned int *)YAMON_PROM_PRINT_ADDR; + outb(value, info->port + offset); } +#endif + +static struct serial_state rs_table[] = { + SERIAL_PORT_DFNS /* Defined in serial.h */ +}; + +/* + * Hooks to fake "prom" console I/O before devices + * are fully initialized. + */ +static struct async_struct prom_port_info = {0}; + +void __init setup_prom_printf(int tty_no) { + struct serial_state *ser = &rs_table[tty_no]; + + prom_port_info.state = ser; + prom_port_info.magic = SERIAL_MAGIC; + prom_port_info.port = ser->port; + prom_port_info.flags = ser->flags; + + /* No setup of UART - assume YAMON left in sane state */ +} + +int putPromChar(char c) +{ + if (!prom_port_info.state) { /* need to init device first */ + return 0; + } + + while ((serial_in(&prom_port_info, UART_LSR) & UART_LSR_THRE) == 0) + ; + + serial_out(&prom_port_info, UART_TX, c); + + return 1; +} + +char getPromChar(void) +{ + if (!prom_port_info.state) { /* need to init device first */ + return 0; + } + + while (!(serial_in(&prom_port_info, UART_LSR) & 1)) + ; + + return(serial_in(&prom_port_info, UART_RX)); +} + +static char buf[1024]; void __init prom_printf(char *fmt, ...) { - va_list args; - int len; + va_list args; + int l; + char *p, *buf_end; + long flags; + + int putPromChar(char); - va_start(args, fmt); - vsprintf(ppbuf, fmt, args); - len = strlen(ppbuf); + /* Low level, brute force, not SMP safe... */ + save_and_cli(flags); + va_start(args, fmt); + l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */ + va_end(args); - prom_print_str(0, ppbuf, len); + buf_end = buf + l; - va_end(args); - return; - + for (p = buf; p < buf_end; p++) { + /* Crude cr/nl handling is better than none */ + if(*p == '\n')putPromChar('\r'); + putPromChar(*p); + } + restore_flags(flags); } |