From: Alan Cox Date: Sun, 27 Jan 2019 16:23:46 +0000 (+0000) Subject: rc2014-sbc64: Further serial work X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=d10d92fc86f6e0b657194e3fb0808a411a4f8c87;p=FUZIX.git rc2014-sbc64: Further serial work - Fix SIO probing - Support second SIO card at 0x84 - Tidy up SIO code in general SIO isn't yet working --- diff --git a/Kernel/platform-rc2014-sbc64/config.h b/Kernel/platform-rc2014-sbc64/config.h index 39660528..dfa894cb 100644 --- a/Kernel/platform-rc2014-sbc64/config.h +++ b/Kernel/platform-rc2014-sbc64/config.h @@ -61,7 +61,7 @@ extern unsigned int swap_dev; #define CONFIG_IDE /* Device parameters */ -#define NUM_DEV_TTY 3 +#define NUM_DEV_TTY 5 /* UART0 as the console */ #define BOOT_TTY (512 + 1) diff --git a/Kernel/platform-rc2014-sbc64/devtty.c b/Kernel/platform-rc2014-sbc64/devtty.c index 33070d8e..17ba40d1 100644 --- a/Kernel/platform-rc2014-sbc64/devtty.c +++ b/Kernel/platform-rc2014-sbc64/devtty.c @@ -12,6 +12,8 @@ __sfr __at 0xf9 cpld_data; static char tbuf1[TTYSIZ]; static char tbuf2[TTYSIZ]; static char tbuf3[TTYSIZ]; +static char tbuf4[TTYSIZ]; +static char tbuf5[TTYSIZ]; static uint8_t sleeping; @@ -20,6 +22,8 @@ struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */ {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2}, {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}, {tbuf3, tbuf3, tbuf3, TTYSIZ, 0, TTYSIZ / 2}, + {tbuf4, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}, + {tbuf5, tbuf3, tbuf3, TTYSIZ, 0, TTYSIZ / 2}, }; static tcflag_t uart0_mask[4] = { @@ -49,7 +53,9 @@ tcflag_t *termios_mask[NUM_DEV_TTY + 1] = { NULL, uart0_mask, uart1_mask, - uart2_mask + uart2_mask, + uart1_mask, + uart1_mask }; uint8_t sio_r[] = { @@ -122,35 +128,37 @@ void tty_setup(uint8_t minor, uint8_t flags) return; sio2_setup(minor, flags); sio2_otir(SIO0_BASE + 2 * (minor - 2)); - /* We need to do CTS/RTS support and baud setting on channel 2 - yet */ + /* We need to do CTS/RTS support on channel 2 yet */ } void tty_resume(void) { tty_setup(1, 0); - tty_setup(2, 0); - tty_setup(3, 0); + if (sio_present) { + tty_setup(2, 0); + tty_setup(3, 0); + } + if (sio1_present) { + tty_setup(4, 0); + tty_setup(5, 0); + } } int tty_carrier(uint8_t minor) { uint8_t c; + uint8_t port; if (minor == 1) return 1; - else if (minor == 2) { - SIOA_C = 0; - c = SIOA_C; - } else { - SIOB_C = 0; - c = SIOB_C; - } - if (c & 0x8) + port = SIOA_C + 2 * (minor - 2); + out(port, 0); + c = in(port); + if (c & 0x08) return 1; return 0; } -void tty_pollirq_sio(void) +void tty_pollirq_sio0(void) { static uint8_t old_ca, old_cb; uint8_t ca, cb; @@ -168,42 +176,100 @@ void tty_pollirq_sio(void) SIOA_C = 0; // read register 0 ca = SIOA_C; /* Input pending */ - if ((ca & 1) && !fullq(&ttyinq[1])) { + if ((ca & 1) && !fullq(&ttyinq[2])) { progress = 1; - tty_inproc(1, SIOA_D); + tty_inproc(2, SIOA_D); } /* Break */ if (ca & 2) SIOA_C = 2 << 5; /* Output pending */ - if ((ca & 4) && (sleeping & 2)) { - tty_outproc(1); - sleeping &= ~2; + if ((ca & 4) && (sleeping & 4)) { + tty_outproc(2); + sleeping &= ~4; 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); + tty_carrier_raise(2); else - tty_carrier_drop(1); + tty_carrier_drop(2); } SIOB_C = 0; // read register 0 cb = SIOB_C; - if ((cb & 1) && !fullq(&ttyinq[2])) { - tty_inproc(2, SIOB_D); + if ((cb & 1) && !fullq(&ttyinq[3])) { + tty_inproc(3, SIOB_D); progress = 1; } - if ((cb & 4) && (sleeping & 4)) { - tty_outproc(2); - sleeping &= ~4; + if ((cb & 4) && (sleeping & 16)) { + tty_outproc(3); + sleeping &= ~16; SIOB_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending } if ((cb ^ old_cb) & 8) { if (cb & 8) - tty_carrier_raise(2); + tty_carrier_raise(3); else - tty_carrier_drop(2); + tty_carrier_drop(3); + } + } while(progress); +} + +void tty_pollirq_sio1(void) +{ + static uint8_t old_ca, old_cb; + uint8_t ca, cb; + uint8_t progress; + + /* Check for an interrupt */ + SIOC_C = 0; + if (!(SIOC_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; + SIOC_C = 0; // read register 0 + ca = SIOC_C; + /* Input pending */ + if ((ca & 1) && !fullq(&ttyinq[4])) { + progress = 1; + tty_inproc(4, SIOC_D); + } + /* Break */ + if (ca & 2) + SIOC_C = 2 << 5; + /* Output pending */ + if ((ca & 4) && (sleeping & 16)) { + tty_outproc(4); + sleeping &= ~16; + SIOC_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending + } + /* Carrier changed */ + if ((ca ^ old_ca) & 8) { + if (ca & 8) + tty_carrier_raise(4); + else + tty_carrier_drop(4); + } + SIOD_C = 0; // read register 0 + cb = SIOD_C; + if ((cb & 1) && !fullq(&ttyinq[2])) { + tty_inproc(5, SIOD_D); + progress = 1; + } + if ((cb & 4) && (sleeping & 32)) { + tty_outproc(5); + sleeping &= ~32; + SIOD_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending + } + if ((cb ^ old_cb) & 8) { + if (cb & 8) + tty_carrier_raise(5); + else + tty_carrier_drop(5); } } while(progress); } @@ -224,10 +290,8 @@ void tty_putc(uint8_t minor, unsigned char c) cpld_bitbang(c); irqrestore(irq); } - if (minor == 2) - SIOA_D = c; - else if (minor == 2) - SIOB_D = c; + else + out(SIOA_D + 2 * (minor - 2), c); } /* We will need this for SIO once we implement flow control signals */ @@ -248,28 +312,19 @@ ttyready_t tty_writeready(uint8_t minor) { irqflags_t irq; uint8_t c; - + uint8_t port; /* Bitbanged so trick the kernel into yielding when appropriate */ if (minor == 1) return need_reschedule() ? TTY_READY_SOON: TTY_READY_NOW; irq = di(); - if (minor == 2) { - SIOA_C = 0; /* read register 0 */ - c = SIOA_C; - irqrestore(irq); - if (c & 0x04) /* THRE? */ - return TTY_READY_NOW; - return TTY_READY_SOON; - } else if (minor == 3) { - SIOB_C = 0; /* read register 0 */ - c = SIOB_C; - irqrestore(irq); - if (c & 0x04) /* THRE? */ - return TTY_READY_NOW; - return TTY_READY_SOON; - } + + port = SIOA_C + 2 * (minor - 2); + out(port, 0); + c = in(port); irqrestore(irq); - return TTY_READY_NOW; + if (c & 0x04) /* THRE? */ + return TTY_READY_NOW; + return TTY_READY_SOON; } void tty_data_consumed(uint8_t minor) @@ -288,7 +343,11 @@ void kputchar(char c) int rctty_open(uint8_t minor, uint16_t flag) { - if (minor > 1 && !sio_present) { + if ((minor == 2 || minor == 3) && !sio_present) { + udata.u_error = ENODEV; + return -1; + } + if ((minor == 4 || minor == 5) && !sio1_present) { udata.u_error = ENODEV; return -1; } diff --git a/Kernel/platform-rc2014-sbc64/devtty.h b/Kernel/platform-rc2014-sbc64/devtty.h index fd42a603..beb41ef8 100644 --- a/Kernel/platform-rc2014-sbc64/devtty.h +++ b/Kernel/platform-rc2014-sbc64/devtty.h @@ -2,7 +2,8 @@ #define __DEVTTY_DOT_H__ void tty_putc(uint8_t minor, unsigned char c); -void tty_pollirq_sio(void); +void tty_pollirq_sio0(void); +void tty_pollirq_sio1(void); void tty_poll_cpld(void); int rctty_open(uint8_t minor, uint16_t flag); diff --git a/Kernel/platform-rc2014-sbc64/discard.c b/Kernel/platform-rc2014-sbc64/discard.c index 5d998f24..2cfda54e 100644 --- a/Kernel/platform-rc2014-sbc64/discard.c +++ b/Kernel/platform-rc2014-sbc64/discard.c @@ -18,8 +18,12 @@ void pagemap_init(void) pagemap_add(0x12); pagemap_add(0x10); + if (sio_present) + kputs("Z80 SIO detected at 0x80.\n"); + if (sio1_present) + kputs("Z80 SIO detected at 0x84.\n"); if (ctc_present) - kputs("Z80 CTC detected.\n"); + kputs("Z80 CTC detected at 0x88.\n"); } /* diff --git a/Kernel/platform-rc2014-sbc64/main.c b/Kernel/platform-rc2014-sbc64/main.c index 376d3f7d..92940a80 100644 --- a/Kernel/platform-rc2014-sbc64/main.c +++ b/Kernel/platform-rc2014-sbc64/main.c @@ -14,6 +14,7 @@ uint16_t swap_dev = 0xFFFF; uint16_t ramtop = 0x7E00; uint8_t ctc_present; uint8_t sio_present; +uint8_t sio1_present; void platform_discard(void) { @@ -66,7 +67,9 @@ void platform_interrupt(void) tty_poll_cpld(); if (sio_present) - tty_pollirq_sio(); + tty_pollirq_sio0(); + if (sio1_present) + tty_pollirq_sio1(); if (ctc_present) { uint8_t n = 255 - CTC_CH3; CTC_CH3 = 0x47; diff --git a/Kernel/platform-rc2014-sbc64/rc2014.h b/Kernel/platform-rc2014-sbc64/rc2014.h index b98a7846..b07cf2ef 100644 --- a/Kernel/platform-rc2014-sbc64/rc2014.h +++ b/Kernel/platform-rc2014-sbc64/rc2014.h @@ -12,6 +12,12 @@ __sfr __at (SIO0_BASE + 1) SIOA_D; __sfr __at (SIO0_BASE + 2) SIOB_C; __sfr __at (SIO0_BASE + 3) SIOB_D; +#define SIO1_BASE 0x84 +__sfr __at (SIO1_BASE + 0) SIOC_C; +__sfr __at (SIO1_BASE + 1) SIOC_D; +__sfr __at (SIO1_BASE + 2) SIOD_C; +__sfr __at (SIO1_BASE + 3) SIOD_D; + __sfr __at 0x88 CTC_CH0; __sfr __at 0x89 CTC_CH1; __sfr __at 0x8A CTC_CH2; @@ -22,5 +28,6 @@ extern void cpld_bitbang(uint8_t c) __z88dk_fastcall; extern uint8_t ctc_present; extern uint8_t sio_present; +extern uint8_t sio1_present; #endif diff --git a/Kernel/platform-rc2014-sbc64/rc2014.s b/Kernel/platform-rc2014-sbc64/rc2014.s index b1047949..a1afbad6 100644 --- a/Kernel/platform-rc2014-sbc64/rc2014.s +++ b/Kernel/platform-rc2014-sbc64/rc2014.s @@ -35,6 +35,8 @@ .globl nmi_handler .globl _suspend .globl _ctc_present + .globl _sio_present + .globl _sio1_present .globl _tty_resume .globl _ide_resume @@ -56,10 +58,16 @@ RTS_LOW .EQU 0xEA ; Base address of SIO/2 chip 0x80 ; For the Scott Baker SIO card adjust the order to match rc2014.h + SIOA_C .EQU 0x80 -SIOA_D .EQU SIOA_D+1 -SIOB_C .EQU SIOA_D+2 -SIOB_D .EQU SIOA_D+3 +SIOA_D .EQU SIOA_C+1 +SIOB_C .EQU SIOA_C+2 +SIOB_D .EQU SIOA_C+3 + +SIOC_C .EQU 0x84 +SIOC_D .EQU SIOC_C+1 +SIOD_C .EQU SIOC_C+2 +SIOD_D .EQU SIOC_C+3 ;========================================================================= ; Buffers @@ -86,8 +94,67 @@ init_hardware: call program_kvectors + ; Look for an SIO using the ROMWBW algorithm + + xor a + ld c,#SIOA_C + out (c),a ; RR0 + in b,(c) ; Save RR0 value + inc a + out (c),a ; RR1 + in a,(c) + cp b ; Same from both reads - not an SIO + + jr z, no_sio0 + + ; Repeat the check on SIO B + + xor a + ld c,#SIOB_C + out (c),a ; RR0 + in b,(c) ; Save RR0 value + inc a + out (c),a ; RR1 + in a,(c) + cp b ; Same from both reads - not an SIO + + jr z, no_sio0 + + ld a,#0x01 + ld (_sio_present),a + +no_sio0: + + xor a + ld c,#SIOC_C + out (c),a ; RR0 + in b,(c) ; Save RR0 value + inc a + out (c),a ; RR1 + in a,(c) + cp b ; Same from both reads - not an SIO + + jr z, no_sio1 + + ; Repeat the check on SIO B + + xor a + ld c,#SIOD_C + out (c),a ; RR0 + in b,(c) ; Save RR0 value + inc a + out (c),a ; RR1 + in a,(c) + cp b ; Same from both reads - not an SIO + + jr z, no_sio1 + + ld a,#0x01 + ld (_sio1_present),a + +no_sio1: + resume_hardware: - ; FIXME: autodetect SIO and check for second SIO ld hl,#sio_setup ld bc,#0xA00 + SIOA_C ; 10 bytes to SIOA_C @@ -95,6 +162,12 @@ resume_hardware: ld hl,#sio_setup ld bc,#0x0A00 + SIOB_C ; and to SIOB_C otir + ld hl,#sio_setup + ld bc,#0xA00 + SIOC_C ; 10 bytes to SIOA_C + otir + ld hl,#sio_setup + ld bc,#0x0A00 + SIOD_C ; and to SIOB_C + otir serial_up: ; ---------------------------------------------------------------------