--- /dev/null
+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
--- /dev/null
+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.
+
+
--- /dev/null
+;
+; 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"
--- /dev/null
+#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#"
--- /dev/null
+ .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
--- /dev/null
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <tty.h>
+#include <devsys.h>
+#include <vt.h>
+#include <devide.h>
+#include <devsd.h>
+#include <blkdev.h>
+#include <devtty.h>
+
+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
+}
--- /dev/null
+#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
--- /dev/null
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include <blkdev.h>
+
+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 <rdebath@cix.compulink.co.uk>
+ * 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
+}
--- /dev/null
+-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
--- /dev/null
+; 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
--- /dev/null
+;
+; 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
--- /dev/null
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include <devinput.h>
+
+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
--- /dev/null
+/*
+ * 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
--- /dev/null
+#
+# 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
--- /dev/null
+;
+; 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
--- /dev/null
+export CPU = z80
--- /dev/null
+
+ .globl switch_bank_nosave
+
+.macro switch
+ call switch_bank_nosave
+.endm
+
+ .include "../dev/zx/tricks-big.s"
--- /dev/null
+;
+; 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"
+