From f1cec5f1c7ba844266d20c8163ed1f19dc9f9562 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 2 Oct 2018 12:44:34 +0100 Subject: [PATCH] rc2014-tiny: add all the tty setup support --- Kernel/platform-rc2014-tiny/devtty.c | 150 +++++++++++++++++++++++++-- Kernel/platform-rc2014-tiny/rc2014.h | 2 + Kernel/platform-rc2014-tiny/rc2014.s | 14 +++ 3 files changed, 155 insertions(+), 11 deletions(-) diff --git a/Kernel/platform-rc2014-tiny/devtty.c b/Kernel/platform-rc2014-tiny/devtty.c index b5ff0f67..e73e2c62 100644 --- a/Kernel/platform-rc2014-tiny/devtty.c +++ b/Kernel/platform-rc2014-tiny/devtty.c @@ -17,46 +17,171 @@ struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */ {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}, }; +static tcflag_t uart0_mask[4] = { + _ISYS, + _OSYS, + CSIZE|CSTOPB|PARENB|PARODD|_CSYS, + _LSYS +}; + +static tcflag_t uart1_mask[4] = { + _ISYS, + /* FIXME: break */ + _OSYS, + /* FIXME CTS/RTS */ + CSIZE|CBAUD|CSTOPB|PARENB|PARODD|_CSYS, + _LSYS, +}; + +tcflag_t *termios_mask[NUM_DEV_TTY + 1] = { + NULL, + uart0_mask, + uart1_mask +}; + +uint8_t sio_r[] = { + 0x03, 0xC1, + 0x04, 0xC4, + 0x05, 0xEA +}; + +static void sio2_setup(uint8_t minor, uint8_t flags) +{ + struct termios *t = &ttydata[minor].termios; + uint8_t r; + /* Set bits per character */ + sio_r[1] = 0x01 | ((t->c_cflag & CSIZE) << 2); + r = 0xC4; + if (t->c_cflag & CSTOPB) + r |= 0x08; + if (t->c_cflag & PARENB) + r |= 0x01; + if (t->c_cflag & PARODD) + r |= 0x02; + sio_r[3] = r; + sio_r[5] = 0x8A | ((t->c_cflag & CSIZE) << 1); +} + void tty_setup(uint8_t minor, uint8_t flags) { - if (minor == 1) { + if (ser_type == 1) { + sio2_setup(minor, flags); + sio2_otir(SIO0_BASE + 2 * minor); + /* We need to do CTS/RTS support and baud setting on channel 2 + yet */ + } + if (ser_type == 2) { + struct termios *t = &ttydata[1].termios; + uint8_t r = t->c_cflag & CSIZE; + /* No CS5/CS6 CS7 must have parity enabled */ + if (r <= CS7) { + t->c_cflag &= ~CSIZE; + t->c_cflag |= CS7|PARENB; + } + /* No CS8 parity and 2 stop bits */ + if (r == CS8 && (t->c_cflag & PARENB)) + t->c_cflag &= ~CSTOPB; + /* There is no obvious logic to this */ + switch(t->c_cflag & (CSIZE|PARENB|PARODD|CSTOPB)) { + case CS7|PARENB: + r = 0xEB; + break; + case CS7|PARENB|PARODD: + r = 0xEF; + break; + case CS7|PARENB|CSTOPB: + r = 0xE3; + case CS7|PARENB|PARODD|CSTOPB: + r = 0xE7; + case CS8|CSTOPB: + r = 0xF3; + break; + case CS8: + r = 0xF7; + break; + case CS8|PARENB: + r = 0xFB; + break; + case CS8|PARENB|PARODD: + r = 0xFF; + break; + } + ACIA_C = r; } } int tty_carrier(uint8_t minor) { -// uint8_t c; - if (minor == 1) { -// c = UART0_MSR; -// return (c & 0x80) ? 1 : 0; /* test DCD */ - } - return 1; + uint8_t c; + if (ser_type == 1) { + if (minor == 1) { + SIOA_C = 0; + c = SIOA_C; + } else { + SIOB_C = 0; + c = SIOB_C; + } + if (c & 0x8) + return 1; + return 0; + } else /* ACIA isn't wired for carrier on any board */ + return 1; } void tty_pollirq_sio(void) { + static uint8_t old_ca, old_cb; uint8_t ca, cb; + uint8_t progress; + + /* Check for an interrupt */ + SIOA_C = 0; + if (!(SIOA_C & 2)) + return; /* FIXME: need to process error/event interrupts as we can get spurious characters or lines on an unused SIO floating */ do { + progress = 0; SIOA_C = 0; // read register 0 ca = SIOA_C; - if (ca & 1) + /* Input pending */ + if ((ca & 1) && !fullq(&ttyinq[1])) { + progress = 1; tty_inproc(1, SIOA_D); + } + /* Break */ + if (ca & 2) + SIOA_C = 2 << 5; + /* Output pending */ if (ca & 4) { tty_outproc(1); SIOA_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending } + /* Carrier changed */ + if ((ca ^ old_ca) & 8) { + if (ca & 8) + tty_carrier_raise(1); + else + tty_carrier_drop(1); + } SIOB_C = 0; // read register 0 cb = SIOB_C; - if (cb & 1) + if ((cb & 1) && !fullq(&ttyinq[2])) { tty_inproc(2, SIOB_D); + progress = 1; + } if (cb & 4) { tty_outproc(2); SIOB_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending } - } while((ca | cb) & 1); + if ((cb ^ old_cb) & 8) { + if (cb & 8) + tty_carrier_raise(2); + else + tty_carrier_drop(2); + } + } while(progress); } void tty_pollirq_acia(void) @@ -95,7 +220,10 @@ void tty_sleeping(uint8_t minor) interrupts as we do this. Really we want to switch to irq driven tx ints on this platform I think. Need to time it and see - An asm common level tty driver might be a better idea */ + An asm common level tty driver might be a better idea + + Need to review this we should be ok as the IRQ handler always leaves + us pointing at RR0 */ ttyready_t tty_writeready(uint8_t minor) { irqflags_t irq; diff --git a/Kernel/platform-rc2014-tiny/rc2014.h b/Kernel/platform-rc2014-tiny/rc2014.h index 2cf84045..d7cb6242 100644 --- a/Kernel/platform-rc2014-tiny/rc2014.h +++ b/Kernel/platform-rc2014-tiny/rc2014.h @@ -18,4 +18,6 @@ __sfr __at (SIO0_BASE + 3) SIOB_D; __sfr __at (ACIA_BASE + 0) ACIA_C; __sfr __at (ACIA_BASE + 1) ACIA_D; +extern void sio2_otir(uint8_t port) __z88dk_fastcall; + #endif diff --git a/Kernel/platform-rc2014-tiny/rc2014.s b/Kernel/platform-rc2014-tiny/rc2014.s index 50182d4e..9ff12734 100644 --- a/Kernel/platform-rc2014-tiny/rc2014.s +++ b/Kernel/platform-rc2014-tiny/rc2014.s @@ -357,6 +357,20 @@ map_save_kernel: pop af ret +; +; A little SIO helper +; + .globl _sio_r + .globl _sio2_otir + +_sio2_otir: + ld b,#0x06 + ld c,l + ld hl,#_sio_r + otir + ret + + ;========================================================================= ; Basic console I/O ;========================================================================= -- 2.34.1