From be0c9f82e37d64a266cf03035810cd1b74649e83 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 25 Aug 2018 19:14:28 +0100 Subject: [PATCH] sbcv2: More UART features In particular set up the port properly rather than relying on ROMWBW. Also turn on the interrupts. --- Kernel/platform-sbcv2/devtty.c | 63 +++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/Kernel/platform-sbcv2/devtty.c b/Kernel/platform-sbcv2/devtty.c index 6ea0ef99..6ef03a7e 100644 --- a/Kernel/platform-sbcv2/devtty.c +++ b/Kernel/platform-sbcv2/devtty.c @@ -1,5 +1,10 @@ /* * We have a 16x50 UART at 0x68 and maybe a PropIO2 at A8 + * + * TODO: + * - Hardware flow control + * - Support for abuse of 16x50 as interrupt controller + * - Support for timer hack */ #include @@ -11,7 +16,15 @@ __sfr __at 0x68 uart_tx; __sfr __at 0x68 uart_rx; +__sfr __at 0x68 uart_ls; +__sfr __at 0x69 uart_ier; +__sfr __at 0x69 uart_ms; +__sfr __at 0x6A uart_fcr; +__sfr __at 0x6B uart_lcr; +__sfr __at 0x6C uart_mcr; __sfr __at 0x6D uart_lsr; +__sfr __at 0x6E uart_msr; +__sfr __at 0x6F uart_scr; static char tbuf1[TTYSIZ]; static char tbuf2[TTYSIZ]; @@ -30,7 +43,6 @@ struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */ /* Write to system console */ void kputchar(char c) { - /* Need to make console dynamic FIXME */ if (c == '\n') tty_putc(1, '\r'); tty_putc(1, c); @@ -54,9 +66,50 @@ void tty_putc(uint8_t minor, unsigned char c) prop_tty_write(c); } +static uint16_t clocks[] = { + 12, /* Not a real rate */ + 2304, + 1536, + 1047, + 857, + 768, + 384, + 192, + 96, + 48, + 24, + 12, + 6, + 3, + 2, + 1 +}; + void tty_setup(uint8_t minor) { - minor; + uint8_t d; + uint16_t w; + struct termios *t = &ttydata[minor].termios; + if (ttymap[minor] == 1) { + /* 16x50. Can actually be configured */ + d = 0x80; /* DLAB */ + d |= (t->c_cflag & CSIZE) >> 4; + if(t->c_cflag & CSTOPB) + d |= 0x04; + if (t->c_cflag & PARENB) + d |= 0x08; + if (!(t->c_cflag & PARODD)) + d |= 0x10; + uart_lcr = d; + w = clocks[t->c_cflag & CBAUD]; + uart_ls = w; + uart_ms = w >> 8; + uart_lcr = d & 0x7F; + /* FIXME: CTS/RTS support */ + d = 0x00; /* !DTR !RTS */ + uart_lcr = d; + uart_ier = 0x0D; /* We don't use tx ints */ + } } void tty_sleeping(uint8_t minor) @@ -66,7 +119,8 @@ void tty_sleeping(uint8_t minor) int tty_carrier(uint8_t minor) { - minor; + if (ttymap[minor] == 1) + return uart_msr & 0x80; return 1; } @@ -76,7 +130,8 @@ void tty_data_consumed(uint8_t minor) void tty_poll(void) { - /* Should be IRQ driven for this */ + /* Should be IRQ driven but we might not be so poll anyway if + pending. IRQs are off here so this is safe */ if (uart_lsr & 0x01) tty_inproc(ttymap[1], uart_rx); prop_tty_poll(ttymap[2]); -- 2.34.1