From ce51de398100c2bf093e019cb08d279978b06c21 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 10 Dec 2018 15:26:51 +0000 Subject: [PATCH] cromemco: further updates - gets us to the boot prompt The tty interfacing via IM2 mode is a bit hackish for now. Unfortunately because the emulation of the tu-art in Z80pack is currently extremely buggy we are basically forced to use IM2. Eventually we want to do IM2 properly anyway. The entire system is built around a design that has proper interrupt handling. With these changes sorted interrupts now work, and you can fail to find a root file system. Next task is getting the fdc and root fs working. --- Kernel/platform-cromemco/Makefile | 4 +- Kernel/platform-cromemco/README | 45 +++++- Kernel/platform-cromemco/cromemco.s | 225 +++++++++++++++++++++++++-- Kernel/platform-cromemco/devtty.c | 30 ++-- Kernel/platform-cromemco/fuzix.lnk | 2 + Kernel/platform-cromemco/interrupt.c | 38 +++++ Kernel/platform-cromemco/irq.h | 13 ++ Kernel/platform-cromemco/main.c | 31 +++- Kernel/platform-cromemco/rules.mk | 1 + Kernel/platform-cromemco/usermem.s | 144 +++++++++++++++++ Kernel/platform-cromemco/vector.s | 60 +++++++ 11 files changed, 548 insertions(+), 45 deletions(-) create mode 100644 Kernel/platform-cromemco/interrupt.c create mode 100644 Kernel/platform-cromemco/irq.h create mode 100644 Kernel/platform-cromemco/rules.mk create mode 100644 Kernel/platform-cromemco/usermem.s create mode 100644 Kernel/platform-cromemco/vector.s diff --git a/Kernel/platform-cromemco/Makefile b/Kernel/platform-cromemco/Makefile index c511cf83..6ca489ac 100644 --- a/Kernel/platform-cromemco/Makefile +++ b/Kernel/platform-cromemco/Makefile @@ -1,9 +1,9 @@ -CSRCS = devtty.c devfd.c +CSRCS = devtty.c devfd.c interrupt.c CSRCS += devices.c main.c ASRCS = crt0.s cromemco.s usermem.s -ASRCS += tricks.s commonmem.s +ASRCS += tricks.s commonmem.s vector.s AOBJS = $(ASRCS:.s=.rel) COBJS = $(CSRCS:.c=.rel) diff --git a/Kernel/platform-cromemco/README b/Kernel/platform-cromemco/README index 2e72ca05..975d0f15 100644 --- a/Kernel/platform-cromemco/README +++ b/Kernel/platform-cromemco/README @@ -19,9 +19,12 @@ one but there are cases we switch and borrow a bit of the other bank copy. It's easier to arrange this way anyhow. TODO -- Debug a loader (seems to work) -- An awful lot of early kernel boot debugging -- Interrupts properly (and IM2) +DONE - Debug a loader (seems to work) +IP - An awful lot of early kernel boot debugging +HACK - Interrupts properly (and IM2) + not yet doing tty interrupts nicely with buffer + and queues + @@ -47,7 +50,8 @@ The MMU settings we use are UARTs: TMS 5501 x 2 per board. These can do Z80 IM2 where the vector is -determined by A7-A5 of the IRQ (used as D7-D5 of the vector) +determined by A7-A5 of the IRQ (used as D7-D5 of the vector) or generate the +8080 RST vectors. R 0 Status @@ -201,3 +205,36 @@ W 40 Disables boot rom as a side effect W 40 bank select + +Interrupt vectors +24 uart1a parallel port +28 uart1a rda +2A uart1a tbe +34 uart1b parallel port +38 uart1b RDA +3A uart1b TBE + +(Uart0 strapped for 8080 mode for some reason) +C7 uart 0a timer 1 +CF uart 0a timer 2 +D7 FDC EOJ +DF uart 0a timer 3 +E7 uart 0a RDA +EF uart 0a TBE +F7 uart 0a timer 4 +FF uart 0a timer 5 also RTC timer + +Doc actually says + +D7-D5 = A7-A5 of port +D4 = 0 for A 1 for B +D3-1 + 000 timer 1 + 001 timer 2 + 010 !sensa + 011 timer 3 + 100 rda + 101 tbe + 110 timer4 + 111 timer5 (PI7) + diff --git a/Kernel/platform-cromemco/cromemco.s b/Kernel/platform-cromemco/cromemco.s index f598ed4c..ece53f5a 100644 --- a/Kernel/platform-cromemco/cromemco.s +++ b/Kernel/platform-cromemco/cromemco.s @@ -45,6 +45,11 @@ .globl _need_resched .globl _ssig + .globl _set_irq + .globl _spurious + .globl _irqvec + .globl interrupt_high + .globl outcharhex .globl outhl, outde, outbc .globl outnewline @@ -59,6 +64,158 @@ ; ----------------------------------------------------------------------------- .area _COMMONMEM +; +; Must be page aligned +; +_irqvec: + ; 0 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 16 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 32 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 48 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 64 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 80 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 96 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 112 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 128 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 144 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 160 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 176 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 192 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 208 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 224 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 240 + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + .word _spurious + ; 256 + .byte 0 + + _platform_reboot: _platform_monitor: jr _platform_monitor @@ -74,6 +231,15 @@ _int_disabled: .area _CODE init_early: + ret + +init_hardware: + ; set system RAM size + ld hl, #448 ; Assuming fully loaded for now + ld (_ramsize), hl + ld hl, #(448-64) ; 64K for kernel + ld (_procmem), hl + ld a,#0x81 ; Every memory writeable, read kernel out (0x40),a ; MMU set @@ -83,28 +249,20 @@ init_early: ld bc,#0x67 ldir - ; And the common across all banks - ld hl,#s__COMMONMEM - ld d,h - ld e,l - ld bc,#l__COMMONMEM - ldir - ld a,#0x01 ; bank to the kernel bank out (0x40),a - ret - -init_hardware: - ; set system RAM size - ld hl, #448 ; Assuming fully loaded for now - ld (_ramsize), hl - ld hl, #(448-64) ; 64K for kernel - ld (_procmem), hl + ld a,#0x40 ; enable interrupt mode + out (2),a + ld a,#0x70 + out (3),a ; serial 0 timer 4 tbe rda ld a, #156 ; ticks for 10Hz (9984uS per tick) out (8), a ; 10Hz timer on - im 1 ; really should use a page and im2? + ld hl,#_irqvec + ld a,h ; deal with linker limits + ld i,a + im 2 ret @@ -127,6 +285,40 @@ map_page_low: _program_vectors: ret +; +; Called when we get an unexpected vector - just ack and return +; +_spurious: ; unexpected IRQ vector - handy breakpoint + ei + reti + +; +; Set an interrupt table entry. Done in asm as we want to write it +; through to all the banks. +; +_set_irq: + pop hl + pop de + pop bc + push bc + push de + push hl + ld hl,#_irqvec + di + add hl,de + ld a,#0x81 + out (0x40),a ; write to all banks, read kernel + ld (hl),c + inc hl + ld (hl),b + ld a,#0x01 + out (0x40),a ; kernel mapping back + ld a,(_int_disabled) + or a + ret nz + ei + ret + ; outchar: Wait for UART TX idle, then print the char in A ; destroys: AF outchar: @@ -460,7 +652,6 @@ rst18: ; and leap into user space jp (hl) nop - nop rst20: ret nop nop diff --git a/Kernel/platform-cromemco/devtty.c b/Kernel/platform-cromemco/devtty.c index ffdb4bc1..e2c0eba3 100644 --- a/Kernel/platform-cromemco/devtty.c +++ b/Kernel/platform-cromemco/devtty.c @@ -4,6 +4,7 @@ #include #include #include +#include char tbuf1[TTYSIZ]; char tbuf2[TTYSIZ]; @@ -69,26 +70,19 @@ void tty_data_consumed(uint8_t minor) { } -__sfr __at 0x08 timer4; - void tty_irq(uint8_t minor) { - uint8_t r = ttybase[minor]; - uint8_t op; - while((op = in(r + 3)) != 0xFF) { - switch(op) { - case 0xE7: - /* should check in(r) for error bits */ - tty_inproc(minor, in(r + 1 )); - case 0xEF: - ttypoll &= ~(1 << minor); - wakeup(&ttydata[minor]); - case 0xF7: - if (minor == 1) { - timer_interrupt(); - timer4 = 156; - } - } + if (minor != 1) + return; /* For the moment */ + if (rx0a_int) { + uint8_t c = rx0a_char; + rx0a_int = 0; + tty_inproc(1, rx0a_char); + } + if (tx0a_int) { + tx0a_int = 0; + ttypoll &= ~(1 << 1); + wakeup(&ttydata[1]); } } diff --git a/Kernel/platform-cromemco/fuzix.lnk b/Kernel/platform-cromemco/fuzix.lnk index c1e5e7c2..bb13048f 100644 --- a/Kernel/platform-cromemco/fuzix.lnk +++ b/Kernel/platform-cromemco/fuzix.lnk @@ -7,7 +7,9 @@ platform-cromemco/crt0.rel platform-cromemco/commonmem.rel platform-cromemco/cromemco.rel +platform-cromemco/vector.rel platform-cromemco/main.rel +platform-cromemco/interrupt.rel start.rel version.rel lowlevel-z80-thunked.rel diff --git a/Kernel/platform-cromemco/interrupt.c b/Kernel/platform-cromemco/interrupt.c new file mode 100644 index 00000000..28379f6b --- /dev/null +++ b/Kernel/platform-cromemco/interrupt.c @@ -0,0 +1,38 @@ +#include +#include + +static uint8_t irqbusy(uint8_t vec) +{ + uint16_t *p = (uint16_t *)(irqvec + vec); + if (*p != (uint16_t)spurious) + return 1; + return 0; +} + +static uint8_t irqcheck(uint8_t vec) +{ + if (irqbusy(vec & 0xFE)) + return 1; + /* If it's odd and not 255 then check the vector above is also free */ + if ((vec & 1) && ++vec && irqbusy(vec)) + return 1; + return 0; +} + +int request_irq(uint8_t vec, void (*func)(uint8_t)) +{ + /* This is fun because the Cromemco has uart 0 set to use the 8080 mode + vectors which are odd numbers */ + if (irqcheck(vec)) + return -EBUSY; + set_irq(vec, func); + return 0; +} + +void free_irq(uint8_t vec) +{ + if (!irqcheck(vec)) + panic("free_irq"); + set_irq(vec, spurious); +} + diff --git a/Kernel/platform-cromemco/irq.h b/Kernel/platform-cromemco/irq.h new file mode 100644 index 00000000..1dd00c7d --- /dev/null +++ b/Kernel/platform-cromemco/irq.h @@ -0,0 +1,13 @@ +extern int request_irq(uint8_t vec, void (*func)(uint8_t)); +extern void free_irq(uint8_t vec); + +/* These have to live in common space */ +extern uint8_t irqvec[]; +extern void spurious(uint8_t vec); +extern void set_irq(uint16_t vec, void (*func)(uint8_t)); + +extern void uart0a_rx(uint8_t unused); +extern void uart0a_txdone(uint8_t unused); +extern void uart0a_timer4(uint8_t unused); + +extern uint8_t rx0a_int, tx0a_int, rx0a_char; diff --git a/Kernel/platform-cromemco/main.c b/Kernel/platform-cromemco/main.c index 38ed2563..a24f1e5d 100644 --- a/Kernel/platform-cromemco/main.c +++ b/Kernel/platform-cromemco/main.c @@ -1,6 +1,7 @@ #include #include #include +#include uaddr_t ramtop = PROGTOP; @@ -14,19 +15,41 @@ void pagemap_init(void) void platform_idle(void) { - /* halt ?? */ + __asm + halt + __endasm; } +__sfr __at 0x08 timer4; + void platform_interrupt(void) { + timer4 = 156; tty_irq(1); - tty_irq(2); - tty_irq(3); + timer_interrupt(); +// tty_irq(2); +// tty_irq(3); } -/* Nothing to do for the map of init */ +/* Get this into discard ... */ + +/* Nothing to do for the map of init but we do set our vectors up here */ void map_init(void) { + if (request_irq(0xE7, uart0a_rx) | + request_irq(0xEF, uart0a_txdone) | + request_irq(0xF7, uart0a_timer4)) + panic("irqset"); + /* We need to claim these in case we set one off as they are at odd vectors + as the base tu_uart is strapped for 8080 mode */ + if ( + request_irq(0xC7, spurious) | + request_irq(0xCF, spurious) | + request_irq(0xD7, spurious) | + request_irq(0xDF, spurious) | + request_irq(0xFF, spurious) + ) + panic("irqset2"); } uint8_t platform_param(char *p) diff --git a/Kernel/platform-cromemco/rules.mk b/Kernel/platform-cromemco/rules.mk new file mode 100644 index 00000000..c3701b05 --- /dev/null +++ b/Kernel/platform-cromemco/rules.mk @@ -0,0 +1 @@ +export BANKED=-thunked diff --git a/Kernel/platform-cromemco/usermem.s b/Kernel/platform-cromemco/usermem.s new file mode 100644 index 00000000..1682e925 --- /dev/null +++ b/Kernel/platform-cromemco/usermem.s @@ -0,0 +1,144 @@ +; +; We have a custom implementation of usermem. We really need +; to optimize ldir_to/from_user. +; + .module usermem + + .include "kernel.def" + .include "../kernel.def" + + ; exported symbols + .globl __uget + .globl __ugetc + .globl __ugetw + + .globl __uput + .globl __uputc + .globl __uputw + .globl __uzero + + .globl ldir_from_user + .globl ldir_to_user + + .area _COMMONMEM + + +uputget: + ; load DE with the byte count + ld c, 8(ix) ; byte count + ld b, 9(ix) + ld a, b + or c + ret z ; no work + ; load HL with the source address + ld l, 4(ix) ; src address + ld h, 5(ix) + ; load DE with destination address + ld e, 6(ix) + ld d, 7(ix) + ret + +__uget: + push ix + ld ix,#0 + add ix, sp + call uputget + jr z, uget_out + push de + pop ix + call ldir_from_user +uget_out: + pop ix + ld hl,#0 + ret + +__uput: + push ix + ld ix,#0 + add ix,sp + call uputget + jr z, uget_out + push de + pop ix + call ldir_to_user + jr uget_out + +; +; The kernel IRQ code will restore the bank if it interrupts this +; logic +; +__uzero: + pop de + pop hl + pop bc + push bc + push hl + push de + ld a,b + or c + ret z + ld a,(U_DATA__U_PAGE) + out (0x40),a ; user bank + ld (hl),#0 + dec bc + ld a,b + or c + jr z, uout + ld e,l + ld d,h + inc de + ldir +uout: + ld a,#1 + out (0x40),a + ret + +__ugetc: + pop bc + pop hl + push hl + push bc + ld a,(U_DATA__U_PAGE) + out (0x40),a + ld l,(hl) + ld h,#0 + jr uout + +__ugetw: + pop bc + pop hl + push hl + push bc + ld a,(U_DATA__U_PAGE) + out (0x40),a + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jr uout + +__uputc: + pop bc + pop de + pop hl + push hl + push de + push bc + ld a,(U_DATA__U_PAGE) + out (0x40),a + ld (hl),e + jr uout + +__uputw: + pop bc + pop de + pop hl + push hl + push de + push bc + ld a,(U_DATA__U_PAGE) + out (0x40),a + ld (hl),e + inc hl + ld (hl),d + jr uout diff --git a/Kernel/platform-cromemco/vector.s b/Kernel/platform-cromemco/vector.s new file mode 100644 index 00000000..67d1e60c --- /dev/null +++ b/Kernel/platform-cromemco/vector.s @@ -0,0 +1,60 @@ +; +; Interrupt handlers. These will get replaced by some proper FIFO +; logic +; + + .area _COMMONMEM + .module vector + + .globl _rx0a_char + .globl _rx0a_int + .globl _tx0a_int + .globl interrupt_high + + .globl _uart0a_rx + .globl _uart0a_txdone + .globl _uart0a_timer4 + +_uart0a_rx: ; 0xE7 + push af + push bc + push de + ld bc,#0x8140 + in d,(c) + out (c),b + in a,(1) + ld (_rx0a_char),a + ld a,#1 + ld (_rx0a_int),a + out (c),d + pop de + pop bc + pop af + ei + reti + +_uart0a_txdone: ; 0xEF + push af + push bc + push de + ld bc,#0x8140 + in d,(c) + out (c),b + ld a,#1 + ld (_tx0a_int),a + out (c),d + pop de + pop bc + pop af + ei + reti + +_uart0a_timer4: + jp interrupt_high + +_rx0a_char: + .byte 0 +_rx0a_int: + .byte 0 +_tx0a_int: + .byte 0 -- 2.34.1