summaryrefslogtreecommitdiffstats
path: root/arch/mips/mips-boards/generic/printf.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-12-29 16:35:43 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-12-29 16:35:43 +0000
commitd0ed783f34132a6456fbee80ce5d121faf55fb8c (patch)
treeed7bb65b9ba2d86bafa9ba4631718717cd944d01 /arch/mips/mips-boards/generic/printf.c
parent041d5780d54608a859ac6fd0fac06ec0e670aa5b (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.c115
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);
}