From: Sergey Kiselev Date: Thu, 12 Mar 2015 04:58:39 +0000 (-0700) Subject: zeta-v2: adopt UART code from P112, implement tty_setup X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=17c20a26e359309c9b6e06e16d4689d5755ae931;p=FUZIX.git zeta-v2: adopt UART code from P112, implement tty_setup --- diff --git a/Kernel/platform-zeta-v2/devtty.c b/Kernel/platform-zeta-v2/devtty.c index f9ac01be..25232940 100644 --- a/Kernel/platform-zeta-v2/devtty.c +++ b/Kernel/platform-zeta-v2/devtty.c @@ -13,33 +13,95 @@ char tbufp[TTYSIZ]; #endif struct s_queue ttyinq[NUM_DEV_TTY+1] = { /* ttyinq[0] is never used */ - { NULL, NULL, NULL, 0, 0, 0 }, - { tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ/2 }, + {NULL, NULL, NULL, 0, 0, 0}, + {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ/2}, #ifdef CONFIG_PPP - { tbufp, tbufp, tbufp, TTYSIZ, 0, TTYSIZ/2 }, + {tbufp, tbufp, tbufp, TTYSIZ, 0, TTYSIZ/2}, #endif }; -/* FIXME: implement */ +uint16_t divisor_table[16] = { + 0, UART_CLOCK / 16 / 50, UART_CLOCK / 16 / 75, UART_CLOCK / 16 / 110, + UART_CLOCK / 16 / 134, UART_CLOCK / 16 / 150, UART_CLOCK / 16 / 300, + UART_CLOCK / 16 / 600, UART_CLOCK / 16 / 1200, UART_CLOCK / 16 / 2400, + UART_CLOCK / 16 / 4800, UART_CLOCK / 16 / 9600, + UART_CLOCK / 16 / 19200, UART_CLOCK / 16 / 38400, + UART_CLOCK / 16 / 57600, UART_CLOCK / 16 / 115200 +}; + void tty_setup(uint8_t minor) { - minor; + uint16_t b; + uint8_t lcr = 0; + if (minor == 1) { + b = ttydata[minor].termios.c_cflag & CBAUD; + if (b > 0 && b < 16) { + UART0_LCR = 0x80; /* LCR = DLAB ON */ + UART0_DLL = divisor_table[b] & 0xFF; + UART0_DLH = divisor_table[b] >> 8; + } + /* word length 5(00), 6(01), 7(10), or 8(11) */ + lcr = (ttydata[minor].termios.c_cflag & CSIZE) >> 4; + /* stop bits 1(0), or 2(1) */ + lcr |= (ttydata[minor].termios.c_cflag & CSTOPB) >> 4; + /* parity disable(0), or enable(1) */ + lcr |= (ttydata[minor].termios.c_cflag & PARENB) >> 5; + /* parity odd(0), or even(1) */ + lcr |= ((ttydata[minor].termios.c_cflag & PARODD) ^ PARODD) >> 5; + UART0_LCR = lcr; + UART0_MCR = 0x03; /* DTR = ON, RTS = ON */ + } } -/* FIXME: implement (although /DCD is hardwired to GND) */ int tty_carrier(uint8_t minor) { - minor; - return 1; + uint8_t c; + if (minor == 1) { + c = UART0_MSR; + return (c & 0x80) ? 1 : 0; /* test DCD */ + } + return 1; } -void tty_interrupt(void) +void tty_pollirq_uart0(void) { - uint8_t reg = UART0_LSR; - if (reg & 0x01) { - /* data available */ - reg = UART0_RBR; - tty_inproc(1, reg); + uint8_t iir, msr, lsr; + while (true) { + iir = UART0_IIR; + lsr = UART0_LSR; + /* IRR bits + * 3 2 1 0 + * ------- + * x x x 1 no interrupt pending + * 0 1 1 0 6 LSR changed -- read the LSR + * 0 1 0 0 4 receive FIFO >= threshold + * 1 1 0 0 C received data sat in FIFO for a while + * 0 0 1 0 2 transmit holding register empty + * 0 0 0 0 0 MSR changed -- read the MSR + */ + switch (iir & 0x0F) { + case 0x0: /* MSR changed */ + case 0x2: /* transmit register empty */ + msr = UART0_MSR; + if ((msr & 0x10) && (lsr & 0x20)){ + /* CTS high, transmit reg empty */ + tty_outproc(1); + } + /* fall through */ + case 0x6: /* LSR changed */ + /* we already read the LSR register so int has cleared */ + UART0_IER = 0x01; /* enable only receive interrupts */ + break; + case 0x4: /* receive (FIFO >= threshold) */ + case 0xC: /* receive (timeout waiting for FIFO to fill) */ + while (lsr & 0x01) { /* Data ready */ + tty_inproc(1, UART0_RBR); + lsr = UART0_LSR; + } + break; + default: + return; + } } } @@ -65,15 +127,22 @@ void tty_putc(uint8_t minor, unsigned char c) void tty_sleeping(uint8_t minor) { - minor; + if (minor == 1) { + UART0_IER = 0x0B; /* enable all but LSR interrupt */ + } } ttyready_t tty_writeready(uint8_t minor) { - uint8_t reg; + uint8_t c; if (minor == 1) { - reg = UART0_LSR; - return (reg & 0x20) ? TTY_READY_NOW : TTY_READY_SOON; + c = UART0_MSR; + if ((c & 0x10) == 0) /* CTS not asserted? */ + return TTY_READY_LATER; + c = UART0_LSR; + if (c & 0x20) /* THRE? */ + return TTY_READY_NOW; + return TTY_READY_SOON; } return TTY_READY_NOW; } diff --git a/Kernel/platform-zeta-v2/devtty.h b/Kernel/platform-zeta-v2/devtty.h index 242631e9..709b94e4 100644 --- a/Kernel/platform-zeta-v2/devtty.h +++ b/Kernel/platform-zeta-v2/devtty.h @@ -1,7 +1,9 @@ #ifndef __DEVTTY_DOT_H__ #define __DEVTTY_DOT_H__ + +#define UART_CLOCK 1843200UL void tty_putc(uint8_t minor, unsigned char c); -void tty_interrupt(void); +void tty_pollirq_uart0(void); #ifdef CONFIG_PPP void tty_poll_ppp(void); diff --git a/Kernel/platform-zeta-v2/kernel.def b/Kernel/platform-zeta-v2/kernel.def index ae762f1b..cacebb28 100644 --- a/Kernel/platform-zeta-v2/kernel.def +++ b/Kernel/platform-zeta-v2/kernel.def @@ -12,7 +12,7 @@ PROGLOAD .equ 0x0100 ; Zeta SBC V2 mnemonics for I/O ports etc -CONSOLE_RATE .equ 38400 +CONSOLE_RATE .equ 9600 CPU_CLOCK_KHZ .equ 20000 diff --git a/Kernel/platform-zeta-v2/main.c b/Kernel/platform-zeta-v2/main.c index 2bd56896..73afac06 100644 --- a/Kernel/platform-zeta-v2/main.c +++ b/Kernel/platform-zeta-v2/main.c @@ -4,7 +4,7 @@ #include #include "config.h" #ifdef CONFIG_FLOPPY -#include "devfd.h" +#include #endif extern unsigned char irqvector; @@ -31,7 +31,7 @@ void platform_interrupt(void) timer_interrupt(); return; case 2: - tty_interrupt(); + tty_pollirq_uart0(); return; default: return; diff --git a/Kernel/platform-zeta-v2/zeta-v2.s b/Kernel/platform-zeta-v2/zeta-v2.s index 8ebd8db8..0b6113b7 100644 --- a/Kernel/platform-zeta-v2/zeta-v2.s +++ b/Kernel/platform-zeta-v2/zeta-v2.s @@ -63,12 +63,12 @@ init_hardware: out (UART0_DLL),a ; set low byte of divisor ld a,#CONSOLE_DIVISOR_HIGH ; baud rate divisor - high byte out (UART0_DLH),a ; set high byte of divisor - ld a,#3 ; value for LCR and MCR + ld a,#0x03 ; value for LCR and MCR out (UART0_LCR),a ; 8 bit data, 1 stop, no parity out (UART0_MCR),a ; DTR ON, RTS ON - ld a,#6 ; disable and reset FIFOs - out (UART0_FCR),a - ld a,#1 ; enable receive data available + ld a,#0x07 ; enable and clear FIFOs + out (UART0_FCR),a ; interrupt theshold 1 byte + ld a,#0x01 ; enable receive data available out (UART0_IER),a ; interrupt ; initialize CTC ld a,#0x47 ; counter mode, disable interrupts