From 5a816781976fd7c28c13992413de3ac8d338e511 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 6 Mar 2019 00:36:41 +0000 Subject: [PATCH] scorpion: Initial scorpion support (Scorpion 256) --- Kernel/platform-scorpion/Makefile | 77 ++++ Kernel/platform-scorpion/README | 127 ++++++ Kernel/platform-scorpion/base-image.trd | Bin 0 -> 9216 bytes Kernel/platform-scorpion/commonmem.s | 8 + Kernel/platform-scorpion/config.h | 78 ++++ Kernel/platform-scorpion/crt0.s | 114 ++++++ Kernel/platform-scorpion/devices.c | 45 +++ Kernel/platform-scorpion/devtty.h | 19 + Kernel/platform-scorpion/discard.c | 108 ++++++ Kernel/platform-scorpion/fuzix.lnk | 54 +++ Kernel/platform-scorpion/kernel.def | 17 + Kernel/platform-scorpion/loader.s | 58 +++ Kernel/platform-scorpion/main.c | 82 ++++ Kernel/platform-scorpion/platform_ide.h | 30 ++ Kernel/platform-scorpion/rules.mk | 19 + Kernel/platform-scorpion/scorpion.s | 494 ++++++++++++++++++++++++ Kernel/platform-scorpion/target.mk | 1 + Kernel/platform-scorpion/tricks.s | 8 + Kernel/platform-scorpion/zxvideo.s | 28 ++ 19 files changed, 1367 insertions(+) create mode 100644 Kernel/platform-scorpion/Makefile create mode 100644 Kernel/platform-scorpion/README create mode 100644 Kernel/platform-scorpion/base-image.trd create mode 100644 Kernel/platform-scorpion/commonmem.s create mode 100644 Kernel/platform-scorpion/config.h create mode 100644 Kernel/platform-scorpion/crt0.s create mode 100644 Kernel/platform-scorpion/devices.c create mode 100644 Kernel/platform-scorpion/devtty.h create mode 100644 Kernel/platform-scorpion/discard.c create mode 100644 Kernel/platform-scorpion/fuzix.lnk create mode 100644 Kernel/platform-scorpion/kernel.def create mode 100644 Kernel/platform-scorpion/loader.s create mode 100644 Kernel/platform-scorpion/main.c create mode 100644 Kernel/platform-scorpion/platform_ide.h create mode 100644 Kernel/platform-scorpion/rules.mk create mode 100644 Kernel/platform-scorpion/scorpion.s create mode 100644 Kernel/platform-scorpion/target.mk create mode 100644 Kernel/platform-scorpion/tricks.s create mode 100644 Kernel/platform-scorpion/zxvideo.s diff --git a/Kernel/platform-scorpion/Makefile b/Kernel/platform-scorpion/Makefile new file mode 100644 index 00000000..8c8d483f --- /dev/null +++ b/Kernel/platform-scorpion/Makefile @@ -0,0 +1,77 @@ +CSRCS = devices.c main.c +CDSRCS = discard.c +DSRCS = ../dev/devide.c ../dev/devsd.c ../dev/blkdev.c +DDSRCS = ../dev/devide_discard.c ../dev/devsd_discard.c ../dev/mbr.c +DZSRCS = ../dev/zx/nemoide.c ../dev/zx/zxmmc.c ../dev/zx/zxkeyboard.c +DZSRCS += ../dev/zx/devinput.c ../dev/zx/bankbig.c ../dev/zx/zxtty.c +DDZSRCS = +ASRCS = crt0.s scorpion.s zxvideo.s +ASRCS += tricks.s commonmem.s + +COBJS = $(CSRCS:.c=.rel) +CDOBJS = $(CDSRCS:.c=.rel) +AOBJS = $(ASRCS:.s=.rel) +DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS)) +DDOBJS = $(patsubst ../dev/%.c,%.rel, $(DDSRCS)) +DZOBJS = $(patsubst ../dev/zx/%.c,%.rel, $(DZSRCS)) +DDZOBJS = $(patsubst ../dev/zx/%.c,%.rel, $(DDZSRCS)) +OBJS = $(COBJS) $(CDOBJS) $(AOBJS) $(DOBJS) $(DDOBJS) $(DZOBJS) $(DDZOBJS) + +CROSS_CCOPTS += -I../dev/ -I../dev/zx/ + +CROSS_CC_SEG3 = --codeseg CODE3 + +all: $(OBJS) + +$(COBJS): %.rel: %.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG3) -c $< + +$(CDOBJS): %.rel: %.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< + +$(DOBJS): %.rel: ../dev/%.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG3) -c $< + +$(DDOBJS): %.rel: ../dev/%.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< + +$(DZOBJS): %.rel: ../dev/zx/%.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG3) -c $< + +$(DDZOBJS): %.rel: ../dev/zx/%.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< + +$(AOBJS): %.rel: %.s + $(CROSS_AS) $(ASOPTS) $< + +clean: + rm -f $(OBJS) *.lst *.asm *.sym *.rst *.rel core *~ + rm -f block? loader.bin loader.tmp loader.ihx fuzix.trd + +loader.bin: loader.s + sdasz80 -o loader.s + sdldz80 -i loader.rel + makebin -s 32768 loader.ihx loader.tmp + dd if=loader.tmp bs=2048 skip=15 count=1 conv=sync of=loader.bin + +image: loader.bin + # Low 16K (will end up in bank 0 0000-3FFF) + dd if=../common.bin bs=16384 conv=sync skip=0 count=1 of=block0 + # Bank 1 (C000-FFFF) + dd if=../bank1.bin bs=16384 conv=sync skip=3 count=1 of=block1 + # Bank 2 (8000-BFFF) + dd if=../common.bin bs=16384 conv=sync skip=2 count=1 of=block2 + # Bank 6 (C000-FFFF) + dd if=../bank2.bin bs=16384 conv=sync skip=3 count=1 of=block3 + # Bank 7 (C000-FFFF) + dd if=../bank3.bin bs=16384 conv=sync skip=3 count=1 of=block4 + + cp base-image.trd fuzix.trd + # Insert 4K loader + ../tools/trdify fuzix.trd BOOT0 loader.bin + # Kernel image + ../tools/trdify fuzix.trd BLOCK0 block0 + ../tools/trdify fuzix.trd BLOCK1 block1 + ../tools/trdify fuzix.trd BLOCK2 block2 + ../tools/trdify fuzix.trd BLOCK3 block3 + ../tools/trdify fuzix.trd BLOCK4 block4 diff --git a/Kernel/platform-scorpion/README b/Kernel/platform-scorpion/README new file mode 100644 index 00000000..2086d9d4 --- /dev/null +++ b/Kernel/platform-scorpion/README @@ -0,0 +1,127 @@ +Development tree for Scorpion Spectrum style machines. + +Currently this supports the Scorpion 256 but using NemoIDE not SMUC. The other +compatible systems ought to work but we don't yet detect the extra memory on +them. The similar ZX Profi won't yet work. + +Supporting the bigger/slightly different boxes needs three things +1. Loader changes for the ZX Profi +2. Changes to bank numbering/allocation by platfomr type and size +3. Detection of memory size +4. Detection of (or loader reporting of) machine type + +TODO +- SMUC IDE +- Support both SMUC and NemoIDE in one build ? +- Add the other machines + +These systems use a pair of I/O ports 7FFD as with the Spectrum 128K and 1FFD +which confusingly works nothing like the 1FFD on +2A/+3 systems + +On the Scorpion 7FFD works exactly like the Spectrum 128K and indeed a 128K +spectrum port will work out of the box (although you'd want SMUC IDE adding). + +The 1FFD port supplies all the extras + +Scorpion 256 (and Kay 256) +0: disable ROM (RAM0 is mapped over 0000-3FFF) +1: selects service shadow ROM +4: banking bit 3 (0-2 are taken from 7FFD) + +Kay 1024 + +7: banking bit 4 +7FFD bit 7: banking bit 5 + +Pentagon 1024 v 1.xx + +0: disable ROM +1: protected mode (1FFD and 7FFD bit 7 locked to TR-DOS) * +3: Upper bit of ROM select (lower bit is 7FFD bit 4) +4: banking bit 3 +5: lock 1FFD and bit 7 of 7FFD (128K compat enable) * +7: banking bit 4 + +(*) latched until next boot + +and as with the Kay 7FFD bit7 is banking bit 5 + +The 1024K expansion to the Scorpion differs from the Kay to be awkward + +1FFD +6: banking bit 4 +7: banking bit 5 + +And the ZX Profi uses DFFD instead of 1FFD and drives the upper bits +differently. + +DFFD +0-2: banking bits 3-5 +3: paging at C000, or if set at 4000 +4: 0000-3FFF is RAM0 +5: 0: 1F/3F/5F/7F are i8255A + 1: 1F/3F/5F/7F are FDC + + + +---- +These machines all have the same basic problem, there is a 16K window at +C000-FFFF which is pageable but no bigger pageable range. + +We run with the following mapping + +0000-3FFF IRQ vectors, common, const, commondata etc +4000-5FFF Spectrum screen memory and system variables +6000-7FFF Free for now +8000-83FF Needed to create the exec of init +8400-BFFF _DISCARD area - blown away when we exec init + (tons of room in this space) +C000-FFFF + 0: 0000-3FFF (Kernel data/common) + 1: Kernel CODE (fairly full) + 2: Mapped at 0x8000-0xBFFF (holds current process copy) + 3: User process + 4: User process + 5: Mapped at 0x4000-0x7FFF (Screen, spare) + 6: Kernel CODE2 (fairly full) + 7: CODE3, Video (lots of room) + +User processes live in 3/4 and 8+. We have copy stuff back and forth +to page 2 due to the memory manager liits. + +To Do: +- Debug the rest +- Write SMUC driver code +- Work out what we need to do for Pentagon v Scorpion etc +- Floppy driver +- Optimizations for switching (runticks expiry on non-preempt case + should we clear runticks - pro it gets us better perf, anti it reduces + responsiveness. +- Parent first support + + +- Why does ls /bin lose the lowest pixel row of the 'yes' command ? + (Seems we lose the bottom line of the left most char - off by one bug + in zxvid ?) +- 6 or 5bit wide fonts (42, 51 column) +- Optimize zxvid - especially scrolling +- Move vtborder to common +- See if we can in fact keep 6000-7FFF clear. If so we can look at + ldir switching another 8K up and down to give 40K program sizes + which would be a big improvement. Would need us to allocate 2.5 + banks per process however so need some allocator changes + +Floppy disk interfaces are problematic. The standard Betadisk interface locks +the I/O ports to its ROM being active, which sucks. Fortunately it appears +there is a mildy insane stunt we can pull. We can use the ROM to query itself +to find the address of the out (c),a present in all Beta ROM images. + +We can then do a ROP attack on the ROM in order to make it do the "right" +out (c),a in it in order to do a bank switch with RAM at 0000-3FFF and catch +the next instruction. Providing we remain in the RAM below 4000 it'll leave +the card selected. + +Does mean we need to patch our kernel to grab the next instruction, and then +put it back all under di but it does look doable. + + diff --git a/Kernel/platform-scorpion/base-image.trd b/Kernel/platform-scorpion/base-image.trd new file mode 100644 index 0000000000000000000000000000000000000000..0545ac2946896bee6d6ee509b2646961d6c17ffa GIT binary patch literal 9216 zcmeI$K}*7590u@bt!z^!Mk>{$#A`@1)0Q|Bg&-;%VG%Vv2+`3?R0j{c^ac6^cJ0zv z5I=yYphF$2Lm(X^A!^RpUFae_|I7P6|LuJ@ewU56-e{c1ohoV2AV4TpDpk$NWn4j$ z1fjHBDepLqGTJB>Sfu@X)h~oUi0#dn=@XHfJFfcP=Epypa2E_TR@(V zN@r3C82sh91#BH0Zy!1H|9%$tqW}dcKmiJji-13f_;*@cPi+K&pGznRFW{@4%4FS+ zXdw5V`%Jj!0*QOYz5|>igM?zcA5mwt|8jlU9xTi{Tfu;0D~;OZs1Q#RP5nXK!;1+F z=H0-n*$upzYUJ794fM>gGd|Ag(BTuOt)||wI#zXQ#b_CQ>!gs}thf69o5g(1C)}zZ z@}U|vI@WUXG!67Z3S?ZzLa}}ILKSCGKz`J>rP3Q&Lo I6c{IgU+k(_v;Y7A literal 0 HcmV?d00001 diff --git a/Kernel/platform-scorpion/commonmem.s b/Kernel/platform-scorpion/commonmem.s new file mode 100644 index 00000000..dc31c24e --- /dev/null +++ b/Kernel/platform-scorpion/commonmem.s @@ -0,0 +1,8 @@ +; +; Multiple app sizes and the fact the kernel and apps share the same banks +; means we need to put this somewhere low +; + .module commonmem + .area _COMMONDATA + + .include "../cpu-z80/std-commonmem.s" diff --git a/Kernel/platform-scorpion/config.h b/Kernel/platform-scorpion/config.h new file mode 100644 index 00000000..41063b23 --- /dev/null +++ b/Kernel/platform-scorpion/config.h @@ -0,0 +1,78 @@ +#define CONFIG_IDE +#define CONFIG_SD +#define SD_DRIVE_COUNT 2 +#define CONFIG_LARGE_IO_DIRECT(x) 1 /* We support direct to user I/O */ + +/* Enable to make ^Z dump the inode table for debug */ +#undef CONFIG_IDUMP +/* Enable to make ^A drop back into the monitor */ +#undef CONFIG_MONITOR +/* Profil syscall support (not yet complete) */ +#define CONFIG_PROFIL +/* Multiple processes in memory at once */ +#define CONFIG_MULTI +/* Single tasking */ +#undef CONFIG_SINGLETASK +/* CP/M emulation */ +#undef CONFIG_CPM_EMU + +/* Input layer support */ +#define CONFIG_INPUT +#define CONFIG_INPUT_GRABMAX 3 +/* Video terminal, not a serial tty */ +#define CONFIG_VT +/* Keyboard contains non-ascii symbols */ +#define CONFIG_UNIKEY +#define CONFIG_FONT8X8 +#define CONFIG_FONT8X8SMALL + +#define CONFIG_DYNAMIC_BUFPOOL +#define CONFIG_DYNAMIC_SWAP + +/* Tell the spectrum devtty layer where graphics is mapped */ +#define CONFIG_GFXBASE 0x4000 +/* Custom banking */ + +/* A 1MB machine has 64 blocks and the kernel plus system pages eat + 0,1,2,5,6,7 */ +#define MAX_MAPS 58 +#define MAP_SIZE 0x8000U + +/* Banks as reported to user space */ +#define CONFIG_BANKS 2 + +/* Vt definitions */ +#define VT_WIDTH 32 +#define VT_HEIGHT 24 +#define VT_RIGHT 31 +#define VT_BOTTOM 23 + +#define TICKSPERSEC 50 /* Ticks per second */ +#define PROGBASE 0x8000 /* also data base */ +#define PROGLOAD 0x8000 /* also data base */ +#define PROGTOP 0xFE00 /* Top of program, base of U_DATA copy */ +#define PROC_SIZE 32 /* Memory needed per process */ +#define MAXTICKS 10 /* As our task switch is so expensive */ + +#define BOOT_TTY (513) /* Set this to default device for stdio, stderr */ + /* In this case, the default is the first TTY device */ + +/* We need a tidier way to do this from the loader */ +#define CMDLINE NULL /* Location of root dev name */ + +/* Device parameters */ +#define NUM_DEV_TTY 1 + +#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ +#define NBUFS 5 /* Number of block buffers */ +#define NMOUNTS 4 /* Number of mounts at a time */ +#define MAX_BLKDEV 4 /* 2 IDE drives, 2 SD drive */ + +#define SWAP_SIZE 0x40 +#define MAX_SWAPS 16 +#define SWAPDEV (swap_dev) /* Device for swapping (dynamic). */ + +/* All our pages get mapped into the top 16K bank for swapping use */ +#define swap_map(x) ((uint8_t *)(x|0xC000)) + +#define BOOTDEVICENAMES "hd#,fd#" diff --git a/Kernel/platform-scorpion/crt0.s b/Kernel/platform-scorpion/crt0.s new file mode 100644 index 00000000..33caf7b0 --- /dev/null +++ b/Kernel/platform-scorpion/crt0.s @@ -0,0 +1,114 @@ + .module crt0 + ; + ; Our common lives low + ; + .area _COMMONDATA + .area _COMMONMEM + .area _CONST + .area _STUBS + .area _INITIALIZED + ; + ; Beyond this point we just zero. + ; + .area _DATA + .area _BSEG + .area _BSS + .area _HEAP + .area _GSINIT + .area _GSFINAL + ; + ; Finally the buffers so they can expand + ; + .area _BUFFERS + ; + ; All our code is banked at 0xC000 + ; + .area _CODE1 + .area _CODE2 + ; We start this bank with FONT so that we have it aligned + .area _FONT + .area _CODE3 + .area _VIDEO + + ; Discard is dumped in at 0x8000 and will be blown away later. + .area _DISCARD + ; Somewhere to throw it out of the way + .area _INITIALIZER + + ; imported symbols + .globl _fuzix_main + .globl init_early + .globl init_hardware + .globl l__BUFFERS + .globl s__BUFFERS + .globl l__DATA + .globl s__DATA + .globl kstack_top + + .globl unix_syscall_entry + .globl nmi_handler + .globl interrupt_handler + + .include "kernel.def" + .include "../kernel-z80.def" + + .area _CODE1 + ; startup code + ; + ; Entered from the bootstrap with 0-3FFF mapped and loaded as + ; RAM bank 0 + ; + di + + ; We need to wipe the BSS but the rest of the job is done. + + ld hl, #s__DATA + ld de, #s__DATA+1 + ld bc, #l__DATA-1 + ld (hl), #0 + ldir + ld hl, #s__BUFFERS + ld de, #s__BUFFERS+1 + ld bc, #l__BUFFERS-1 + ld (hl), #0 + ldir + + ld sp, #kstack_top + + ; Configure memory map + push af + call init_early + pop af + + ; Hardware setup + push af + call init_hardware + pop af + + ; Call the C main routine + push af + call _fuzix_main + pop af + + ; main shouldn't return, but if it does... + di +stop: halt + jr stop + + .area _COMMONDATA + + .area _STUBS +stubs: + .ds 540 + + .area _BUFFERS +; +; Buffers (we use asm to set this up as we need them in a special segment +; so we can recover the discard memory into the buffer pool +; + + .globl _bufpool + .area _BUFFERS + +_bufpool: + .ds BUFSIZE * NBUFS diff --git a/Kernel/platform-scorpion/devices.c b/Kernel/platform-scorpion/devices.c new file mode 100644 index 00000000..90c608d1 --- /dev/null +++ b/Kernel/platform-scorpion/devices.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct devsw dev_tab[] = /* The device driver switch table */ +{ + /* 0: /dev/hd Hard disc block devices */ + { blkdev_open, no_close, blkdev_read, blkdev_write, blkdev_ioctl }, + /* 1: /dev/fd Floppy disc block devices: nope */ + { no_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 2: /dev/tty TTY devices */ + { tty_open, tty_close, tty_read, tty_write, gfx_ioctl }, + /* 3: /dev/lpr Printer devices */ + { no_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 4: /dev/mem etc System devices (one offs) */ + { no_open, no_close, sys_read, sys_write, sys_ioctl }, + /* 5: Pack to 7 with nxio if adding private devices and start at 8 */ +}; + +bool validdev(uint16_t dev) +{ + /* This is a bit uglier than needed but the right hand side is + a constant this way */ + if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) - 1) + return false; + else + return true; +} + +void device_init(void) +{ +#ifdef CONFIG_IDE + devide_init(); +#endif +#ifdef CONFIG_SD + devsd_init(); +#endif +} diff --git a/Kernel/platform-scorpion/devtty.h b/Kernel/platform-scorpion/devtty.h new file mode 100644 index 00000000..40a67f5c --- /dev/null +++ b/Kernel/platform-scorpion/devtty.h @@ -0,0 +1,19 @@ +#ifndef __DEVTTY_DOT_H__ +#define __DEVTTY_DOT_H__ + +void tty_pollirq(void); +static void keydecode(void); + +#define KEY_ROWS 8 +#define KEY_COLS 5 +extern uint8_t keymap[8]; +extern uint8_t keyboard[8][5]; +extern uint8_t shiftkeyboard[8][5]; + +extern uint8_t timer_wait; + +extern int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr); + +extern uint8_t vtborder; + +#endif diff --git a/Kernel/platform-scorpion/discard.c b/Kernel/platform-scorpion/discard.c new file mode 100644 index 00000000..bf0596fa --- /dev/null +++ b/Kernel/platform-scorpion/discard.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include + +extern uint8_t fuller, kempston, kmouse, kempston_mbmask; + +void pagemap_init(void) +{ + uint8_t i; + uint8_t r; + + pagemap_add(3); + pagemap_add(4); + + /* This is good to 512K on the Pentagon 1024/Kay 1024. We will need + to rethink stuff for the upper 512K if we ever care */ + /* Bits 2-0 are written to 7FFD with the right ROM info */ + /* Bits 7-4 are written to 1FFD with the right ROM disable etc */ + + /* FIXME: for now hardcode 256K */ + for (i = 8; i < 16; i++) { + uint8_t r = i & 7; + if (i & 8) + r |= 0x10; /* bank bit 3 */ + if (i & 16) + r |= 0x80; + /* Scorpion 1024K mod only + if (i & 32) + r |= 0x40; + */ + pagemap_add(r); + } +} + +/* string.c + * Copyright (C) 1995,1996 Robert de Bath + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ +static int strcmp(const char *d, const char *s) +{ + register char *s1 = (char *) d, *s2 = (char *) s, c1, c2; + + while ((c1 = *s1++) == (c2 = *s2++) && c1); + return c1 - c2; +} + +uint8_t platform_param(char *p) +{ + if (strcmp(p, "kempston") == 0) { + kempston = 1; + return 1; + } + if (strcmp(p, "kmouse") == 0) { + kmouse = 1; + return 1; + } + if (strcmp(p, "fuller") == 0) { + fuller = 1; + return 1; + } + if (strcmp(p, "kmouse3") == 0) { + kmouse = 1; + kempston_mbmask = 7; + return 1; + } + if (strcmp(p, "kmturbo") == 0) { + /* For now rely on the turbo detect - may want to change this */ + kmouse = 1; + return 1; + } + return 0; +} + +/* Nothing to do for the map of init */ +void map_init(void) +{ +} + +void platform_copyright(void) +{ +} + +/* + * This function is called for partitioned devices if a partition is found + * and marked as swap type. The first one found will be used as swap. We + * only support one swap device. + */ +void platform_swap_found(uint8_t letter, uint8_t m) +{ + blkdev_t *blk = blk_op.blkdev; + uint16_t n; + if (swap_dev != 0xFFFF) + return; + letter -= 'a'; + kputs("(swap) "); + swap_dev = letter << 4 | m; + n = blk->lba_count[m - 1] / SWAP_SIZE; + if (n > MAX_SWAPS) + n = MAX_SWAPS; +#ifdef SWAPDEV + while (n) + swapmap_init(n--); +#endif +} diff --git a/Kernel/platform-scorpion/fuzix.lnk b/Kernel/platform-scorpion/fuzix.lnk new file mode 100644 index 00000000..0482d761 --- /dev/null +++ b/Kernel/platform-scorpion/fuzix.lnk @@ -0,0 +1,54 @@ +-mwxuy +-r +-i fuzix.ihx +-b _COMMONDATA=0x0100 +-b _CODE1=0xC000 +-b _CODE2=0xC000 +-b _FONT=0xC000 +-b _DISCARD=0x8400 +-l z80 +platform-scorpion/crt0.rel +platform-scorpion/commonmem.rel +platform-scorpion/scorpion.rel +platform-scorpion/zxvideo.rel +platform-scorpion/main.rel +platform-scorpion/discard.rel +start.rel +version.rel +lowlevel-z80-banked.rel +usermem_std-z80-banked.rel +platform-scorpion/tricks.rel +timer.rel +kdata.rel +usermem.rel +platform-scorpion/devices.rel +devio.rel +filesys.rel +process.rel +inode.rel +syscall_exec16.rel +syscall_fs.rel +syscall_fs2.rel +syscall_fs3.rel +syscall_proc.rel +syscall_other.rel +tty.rel +vt.rel +font8x8.rel +mm.rel +platform-scorpion/bankbig.rel +swap.rel +devsys.rel +devinput.rel +platform-scorpion/zxtty.rel +platform-scorpion/devide.rel +platform-scorpion/devide_discard.rel +platform-scorpion/devsd.rel +platform-scorpion/devsd_discard.rel +platform-scorpion/nemoide.rel +platform-scorpion/zxmmc.rel +platform-scorpion/mbr.rel +platform-scorpion/blkdev.rel +platform-scorpion/devinput.rel +platform-scorpion/zxkeyboard.rel +-e diff --git a/Kernel/platform-scorpion/kernel.def b/Kernel/platform-scorpion/kernel.def new file mode 100644 index 00000000..dd1699a3 --- /dev/null +++ b/Kernel/platform-scorpion/kernel.def @@ -0,0 +1,17 @@ +; UZI mnemonics for memory addresses etc + +; We stick it straight after the tag +U_DATA__TOTALSIZE .equ 0x200 ; 256+256 bytes @0x0100 + +U_DATA_STASH .equ 0xFE00 ; FE00-FFFF + +Z80_TYPE .equ 1 + +PROGBASE .equ 0x8000 +PROGLOAD .equ 0x8000 + +NBUFS .equ 5 + +BANK_BITS .equ 0x10 ; Spectrum ROM select + ; Doesn't really matter! +BANK2_BITS .equ 0x01 ; ROM paged out diff --git a/Kernel/platform-scorpion/loader.s b/Kernel/platform-scorpion/loader.s new file mode 100644 index 00000000..eea29f75 --- /dev/null +++ b/Kernel/platform-scorpion/loader.s @@ -0,0 +1,58 @@ +; +; Load our kernel image via TRDOS +; +; The disk holds files of the format code{n} where n is the bank to +; place it in. TRDOS is asked to load the lot and then we launch +; + + .module loader + .area CODE(ABS) + .org 0x7800 + +start: + ld sp,#start + xor a + ld de,#0x0109 + call trdos ; bank 0 (will appear at 0x0000) + inc a + ld de,#0x0509 + call trdos ; bank 1 (high bank CODE1) + inc a + ld de,#0x0909 + call trdos ; bank 2 (0x8000-0xBFFF bank) + ld a,#6 + ld de,#0x0D09 + call trdos ; bank 6 (high bank CODE2) + inc a + ld de,#0x1109 + call trdos ; bank 7 (high bank CODE3) + + di + ; Turn off low ROM + ld bc,#0x1ffd + ld a,#0x01 + out (c),a + ; The kernel is loaded into 1,6,7 + ; The low memory is loaded into bank 0 + ; The 8000-BFFF range is loaded by the loader + ; The 4000-7FFF range is zero + + ; Switch ROM for bank 0 + ld a,#0x01 + ld bc,#0x7ffd + out (c),a + ; FIXME - where is best to start up + jp 0xC000 + +trdos: + ; Switch bank + push af + ld bc,#0x7ffd + out (254),a + or #0x10 + out (c),a + ld hl,#0xC000 + ld bc,#0x4005 + call 15635 + pop af + ret diff --git a/Kernel/platform-scorpion/main.c b/Kernel/platform-scorpion/main.c new file mode 100644 index 00000000..8b9869a3 --- /dev/null +++ b/Kernel/platform-scorpion/main.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include + +uint16_t ramtop = PROGTOP; +uint16_t swap_dev = 0xFFFF; + +/* On idle we spin checking for the terminals. Gives us more responsiveness + for the polled ports */ +void platform_idle(void) +{ + /* We don't want an idle poll and IRQ driven tty poll at the same moment */ + __asm + halt + __endasm; +} + +uint8_t timer_wait; + +void platform_interrupt(void) +{ + tty_pollirq(); + timer_interrupt(); + poll_input(); + if (timer_wait) + wakeup(&timer_interrupt); +} + +/* + * So that we don't suck in a library routine we can't use from + * the runtime + */ + +int strlen(const char *p) +{ + int len = 0; + while(*p++) + len++; + return len; +} + +/* This points to the last buffer in the disk buffers. There must be at least + four buffers to avoid deadlocks. */ +struct blkbuf *bufpool_end = bufpool + NBUFS; + +/* + * We pack discard into the memory image is if it were just normal + * code but place it at the end after the buffers. When we finish up + * booting we turn everything from the buffer pool to the start of + * user space into buffers. + * + * We don't touch discard. Discard is just turned into user space. + */ +void platform_discard(void) +{ + uint16_t discard_size = 0x4000 - (uint16_t)bufpool_end; + bufptr bp = bufpool_end; + + discard_size /= sizeof(struct blkbuf); + + kprintf("%d buffers added\n", discard_size); + + bufpool_end += discard_size; + + memset( bp, 0, discard_size * sizeof(struct blkbuf) ); + + for( bp = bufpool + NBUFS; bp < bufpool_end; ++bp ){ + bp->bf_dev = NO_DEVICE; + bp->bf_busy = BF_FREE; + } +} + +#ifndef SWAPDEV +/* Adding dummy swapper since it is referenced by tricks.s */ +void swapper(ptptr p) +{ + p; +} +#endif diff --git a/Kernel/platform-scorpion/platform_ide.h b/Kernel/platform-scorpion/platform_ide.h new file mode 100644 index 00000000..e20ab5ad --- /dev/null +++ b/Kernel/platform-scorpion/platform_ide.h @@ -0,0 +1,30 @@ +/* + * NemoIDE interface + * + * This is a 16bit interface with a latched data port. + * + * The latch means we have to work from two ports which is ugly but + * at least it's not using the high bits of the address. + */ + +#define ide_select(x) +#define ide_deselect() + +#define IDE_DRIVE_COUNT 2 + +#define IDE_REG_DATA 0x10 +#define IDE_REG_DATA_LATCH 0x11 +#define IDE_REG_ERROR 0x30 +#define IDE_REG_FEATURES 0x30 +#define IDE_REG_SEC_COUNT 0x50 +#define IDE_REG_LBA_0 0x70 +#define IDE_REG_LBA_1 0x90 +#define IDE_REG_LBA_2 0xB0 +#define IDE_REG_LBA_3 0xD0 +#define IDE_REG_DEVHEAD 0xD0 +#define IDE_REG_STATUS 0xF0 +#define IDE_REG_COMMAND 0xF0 + +#define IDE_REG_CONTROL 0xC8 + +#define IDE_NONSTANDARD_XFER diff --git a/Kernel/platform-scorpion/rules.mk b/Kernel/platform-scorpion/rules.mk new file mode 100644 index 00000000..c0539a62 --- /dev/null +++ b/Kernel/platform-scorpion/rules.mk @@ -0,0 +1,19 @@ +# +# ZX128 uses banked kernel images +# +CROSS_CCOPTS += --external-banker + +CFLAGS += -Idev/zx/ +# +# Tell the core code we are using the banked helpers +# +export BANKED=-banked +# +export CROSS_CC_SEG1=--codeseg CODE2 +export CROSS_CC_SEG3=--codeseg CODE1 +export CROSS_CC_SEG4=--codeseg CODE1 +export CROSS_CC_SYS1=--codeseg CODE1 +export CROSS_CC_SYS2=--codeseg CODE1 +export CROSS_CC_SYS3=--codeseg CODE1 +export CROSS_CC_SYS4=--codeseg CODE3 +export CROSS_CC_SYS5=--codeseg CODE3 diff --git a/Kernel/platform-scorpion/scorpion.s b/Kernel/platform-scorpion/scorpion.s new file mode 100644 index 00000000..1888dce8 --- /dev/null +++ b/Kernel/platform-scorpion/scorpion.s @@ -0,0 +1,494 @@ +; +; Pentagon hardware support +; + + .module pentagon + + ; exported symbols + .globl init_early + .globl init_hardware + .globl _program_vectors + .globl platform_interrupt_all + .globl interrupt_handler + .globl unix_syscall_entry + .globl null_handler + + .globl map_kernel + .globl map_process_always + .globl map_process + .globl map_kernel_di + .globl map_process_always_di + .globl map_save_kernel + .globl map_restore + .globl map_process_save + .globl map_kernel_restore + .globl map_for_swap + .globl current_map + .globl switch_bank + .globl switch_bank_nosave + + .globl _need_resched + .globl _int_disabled + .globl _udata + + ; exported debugging tools + .globl _platform_monitor + .globl _platform_reboot + .globl outchar + + ; imported symbols + .globl _ramsize + .globl _procmem + + .globl _vtoutput + .globl _vtinit + + .globl outcharhex + .globl outhl, outde, outbc + .globl outnewline + .globl outstring + .globl outstringhex + + .globl null_handler + .globl nmi_handler + .globl unix_syscall_entry + .globl interrupt_handler + + ; banking support + .globl __bank_0_1 + .globl __bank_0_2 + .globl __bank_0_3 + .globl __bank_1_2 + .globl __bank_1_3 + .globl __bank_2_1 + .globl __bank_2_3 + .globl __bank_3_1 + .globl __bank_3_2 + + .globl __stub_0_1 + .globl __stub_0_2 + .globl __stub_0_3 + .globl __stub_1_2 + .globl __stub_1_3 + .globl __stub_2_1 + .globl __stub_2_3 + .globl __stub_3_1 + .globl __stub_3_2 + + .include "kernel.def" + .include "../kernel-z80.def" + +; ----------------------------------------------------------------------------- +; COMMON MEMORY BANK (below 0xC000) +; ----------------------------------------------------------------------------- + .area _COMMONMEM + +_platform_monitor: + ; + ; Not so much a monitor as wait for space + ; + ld a, #0x7F + in a, (0xFE) + rra + jr c, _platform_monitor + +_platform_reboot: + di + im 1 + ld bc, #0xeff7 + xor a + out (c),a ; turn off RAM in low 16K + ld bc, #0x7ffd + xor a ; 128K ROM, initial banks, low screen + out (c), a + rst 0 ; Into the ROM + +platform_interrupt_all: + ret + + .area _COMMONDATA + +_int_disabled: + .db 1 + + +; ----------------------------------------------------------------------------- +; KERNEL MEMORY BANK (above 0xC000, only accessible when the kernel is mapped) +; ----------------------------------------------------------------------------- + .area _CODE1 + +; +; The memory banker will deal with the map setting +; +init_early: + xor a + out (0xFE),a + ret + + .area _VIDEO + +init_hardware: + ; set system RAM size + ; FIXME: probe this and map accordingly in discard.c + ld hl, #256 + ld (_ramsize), hl + ; We lose the following to the system + ; 0: low 16K of kernel + ; 1: first kernel bank at C000 + ; 2: 4000-7FFF (screen and buffers) + ; 5: 8000-BFFF (working 16K copy) + ; 6: second kernel bank at C000 + ; 7: third kernel bank at C000 + ; + ; We might be able to squash things up and get 6 or 7 back + ; but as we work in pairs it's not actually that interesting. OTOH + ; getting 6000-7FFF back might be for program sizes. + ; + ld hl, #(256 - 96) + ld (_procmem), hl + + ld a,#0xC3 + ld (0x00),a + ld (0x30),a + ld (0x38),a + ld (0x66),a + ld hl,#null_handler + ld (0x01),hl + ld hl,#unix_syscall_entry + ld (0x31),hl + ld hl,#interrupt_handler + ld (0x39),hl + ld hl,#nmi_handler + ld (0x67),hl + ; screen initialization + push af + call _vtinit + pop af + + ret + +;------------------------------------------------------------------------------ +; COMMON MEMORY PROCEDURES FOLLOW + + .area _COMMONMEM + +_program_vectors: + ret + + ; Swap helper. Map the page in A into the address space such + ; that swap_map() gave the correct pointer to use. Undone by + ; a map_kernel_{restore} +map_for_swap: + ; bank switching procedure. On entrance: + ; A - bank number to set + push af + ld a, (current_map) + ld (ksave_map), a + pop af + ; Then fall through to set the bank up + +switch_bank: + ; Write the store first, that way any interrupt will restore + ; the new bank and our out will just be a no-op + ld (current_map), a +switch_bank_nosave: + push af + push bc + ld bc, #0x7ffd + push af + or #BANK_BITS + and #0x1F ; bits 2/1/0 + bank bit + out (c), a + pop af + and #0xF0 + or #BANK2_BITS ; ROM out + ld b,#0x1f + out (c),a + pop bc + pop af + ret + + +map_process: + ld a, h + or l + jr z, map_kernel_nosavea + push af + inc hl + inc hl + ld a, (hl) + dec hl + dec hl + call switch_bank + pop af + ret + +; +; We always save here so that existing code works until we have a +; clear usage of save/restore forms across the kernel +; +map_process_save: +map_process_always: +map_process_always_di: + push af + ld a, (current_map) + ld (ksave_map), a + ld a, (_udata + U_DATA__U_PAGE2) + call switch_bank + pop af + ret + +; +; Save and switch to kernel +; +map_save_kernel: + push af + ld a, (current_map) + ld (map_store), a + pop af +; +; This may look odd. However the kernel is banked so any +; invocation of kernel code in fact runs common code and the +; common code will bank in the right kernel bits for us when it calls +; out of common into banked code. We do a restore to handle all the +; callers who do map_process_always/map_kernel pairs. Probably we +; should have some global change to map_process_save/map_kernel_restore +; +map_kernel_di: +map_kernel: +map_kernel_nosavea: ; to avoid double reg A saving +map_kernel_restore: + push af + ld a, (ksave_map) + call switch_bank + pop af + ret + + +map_restore: + push af + ld a, (map_store) + call switch_bank + pop af + ret + +; +; We have no easy serial debug output instead just breakpoint this +; address when debugging. +; +outchar: + ld (_tmpout), a + push bc + push de + push hl + push ix + ld hl, #1 + push hl + ld hl, #_tmpout + push hl + push af + call _vtoutput + pop af + pop af + pop af + pop ix + pop hl + pop de + pop bc + ret + +_tmpout: + .db 1 + +current_map: ; place to store current page number. Is needed + .db 0 ; because we have no ability to read 7ffd port + ; to detect what page is mapped currently +map_store: + .db 0 + +ksave_map: + .db 0 + +_need_resched: + .db 0 + +; +; Banking helpers +; +; Logical Physical +; 0 COMMON (0x4000) +; 1 0 +; 2 1 +; 3 7 +; +; +__bank_0_1: + ld a,#1 ; switch to physical bank 1 (logical 1) +bankina0: + ; + ; Get the target address first, otherwise we will change + ; bank and read it from the wrong spot! + ; + pop hl ; Return address (points to true function address) + ld e, (hl) ; DE = function to call + inc hl + ld d, (hl) + inc hl + push hl ; Restore corrected return pointer + ld bc, (current_map) ; get current bank into B + call switch_bank ; Move to new bank + ; figure out which bank to map on the return path + ld a, c + dec a + jr z, __retmap1 + cp #5 + jr z, __retmap2 + jr __retmap3 + +callhl: jp (hl) + +__bank_0_2: + ld a, #6 ; logical 2 -> physical 6 + jr bankina0 +__bank_0_3: + ld a, #7 ; logical 3 -> physical 7 + jr bankina0 + +__bank_1_2: + ld a, #6 +bankina1: + pop hl ; Return address (points to true function address) + ld e, (hl) ; DE = function to call + inc hl + ld d, (hl) + inc hl + push hl ; Restore corrected return pointer + call switch_bank ; Move to new bank +__retmap1: + ex de, hl + call callhl ; call the function + ld a,#1 ; return to bank 1 (physical 1) + jp switch_bank +__bank_1_3: + ld a, #7 + jr bankina1 + +__bank_2_1: + ld a,#1 +bankina2: + pop hl ; Return address (points to true function address) + ld e, (hl) ; DE = function to call + inc hl + ld d, (hl) + inc hl + push hl ; Restore corrected return pointer + call switch_bank ; Move to new bank +__retmap2: + ex de, hl + call callhl ; call the function + ld a, #6 ; return to bank 2 + jp switch_bank +__bank_2_3: + ld a, #7 + jr bankina2 + +__bank_3_1: + ld a, #1 +bankina3: + pop hl ; Return address (points to true function address) + ld e, (hl) ; DE = function to call + inc hl + ld d, (hl) + inc hl + push hl ; Restore corrected return pointer + call switch_bank ; Move to new bank +__retmap3: + ex de, hl + call callhl ; call the function + ld a, #7 ; return to bank 0 + jp switch_bank + +__bank_3_2: + ld a, #6 + jr bankina3 + +; +; Stubs need some stack munging and use DE +; + +__stub_0_1: + ld a,#1 +__stub_0_a: + pop hl ; the return + ex (sp), hl ; write it over the discard + ld bc, (current_map) + call switch_bank + ld a, c + dec a + jr z, __stub_1_ret + cp #5 ; bank 6 + jr z, __stub_2_ret + jr __stub_3_ret ; bank 7 +__stub_0_2: + ld a, #6 + jr __stub_0_a +__stub_0_3: + ld a, #7 + jr __stub_0_a + +__stub_1_2: + ld a, #6 +__stub_1_a: + pop hl ; the return + ex (sp), hl ; write it over the discard + call switch_bank +__stub_1_ret: + ex de, hl + call callhl + ld a,#1 + call switch_bank + pop de + push de ; dummy the caller will discard + push de ; FIXME don't we need to use BC and can't we get + ret ; rid of all non 0_x stubs ? +__stub_1_3: + ld a, #7 + jr __stub_1_a + +__stub_2_1: + ld a,#1 +__stub_2_a: + pop hl ; the return + ex (sp), hl ; write it over the discad + call switch_bank +__stub_2_ret: + ex de, hl ; DE is our target + call callhl + ld a,#6 + call switch_bank + pop de + push de ; dummy the caller will discard + push de + ret +__stub_2_3: + ld a, #7 + jr __stub_2_a + +__stub_3_1: + ld a,#1 +__stub_3_a: + pop hl ; the return + ex (sp), hl ; write it over the discad + call switch_bank +__stub_3_ret: + ex de, hl + call callhl + ld a,#7 + call switch_bank + pop de + push de ; dummy the caller will discard + push de + ret +__stub_3_2: + ld a, #6 + jr __stub_3_a diff --git a/Kernel/platform-scorpion/target.mk b/Kernel/platform-scorpion/target.mk new file mode 100644 index 00000000..3bffcde0 --- /dev/null +++ b/Kernel/platform-scorpion/target.mk @@ -0,0 +1 @@ +export CPU = z80 diff --git a/Kernel/platform-scorpion/tricks.s b/Kernel/platform-scorpion/tricks.s new file mode 100644 index 00000000..1289126c --- /dev/null +++ b/Kernel/platform-scorpion/tricks.s @@ -0,0 +1,8 @@ + + .globl switch_bank_nosave + +.macro switch + call switch_bank_nosave +.endm + + .include "../dev/zx/tricks-big.s" diff --git a/Kernel/platform-scorpion/zxvideo.s b/Kernel/platform-scorpion/zxvideo.s new file mode 100644 index 00000000..950cb76c --- /dev/null +++ b/Kernel/platform-scorpion/zxvideo.s @@ -0,0 +1,28 @@ +; +; zx128 vt primitives +; + + .module zxvideo + + ; exported symbols + .globl _plot_char + .globl _scroll_down + .globl _scroll_up + .globl _cursor_on + .globl _cursor_off + .globl _cursor_disable + .globl _clear_lines + .globl _clear_across + .globl _do_beep + .globl _fontdata_8x8 + .globl _curattr + .globl _vtattr + + ; Build the video library as the only driver + +ZXVID_ONLY .equ 1 + + .area _VIDEO + + .include "../dev/zx/video-banked.s" + -- 2.34.1