--- /dev/null
+ASRCS = crt0.s zxevo.s video.s
+ASRCS += tricks.s commonmem.s
+CSRCS = devtty.c 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/evommc.c ../dev/zx/zxkeyboard.c ../dev/zx/devinput.c
+DDZSRCS =
+NSRCS = ../dev/net/net_native.c
+
+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))
+NOBJS = $(patsubst ../dev/net/%.c,%.rel, $(NSRCS))
+
+OBJS = $(COBJS) $(CDOBJS) $(AOBJS) $(DOBJS) $(DDOBJS) $(DZOBJS) $(DDZOBJS) $(NOBJS)
+
+CROSS_CCOPTS += -I../dev/ -I../dev/zx/ -I../dev/net/
+
+all: $(OBJS)
+
+$(COBJS): %.rel: %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(CDOBJS): %.rel: %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
+$(DOBJS): %.rel: ../dev/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(DDOBJS): %.rel: ../dev/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
+$(DZOBJS): %.rel: ../dev/zx/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(DDZOBJS): %.rel: ../dev/zx/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
+$(NOBJS): %.rel: ../dev/net/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(AOBJS): %.rel: %.s
+ $(CROSS_AS) $(ASOPTS) $<
+
+clean:
+ rm -f $(OBJS) *.lst *.asm *.sym *.rst *.rel core *~
+ rm -f FUZIX FUZIX.BIN load-esx.ihx load-esx.tmp
+
+image:
+ # Build an esxdos friendly setup
+ sdasz80 -o load-esx.s
+ sdldz80 -i load-esx.rel
+ makebin -s 8704 load-esx.ihx load-esx.tmp
+ # Generate the image file we need
+ dd if=load-esx.tmp of=FUZIX bs=8192 skip=1
+
+ dd if=/dev/zero bs=256 count=1 >FUZIX.BIN
+ cat ../fuzix.bin >>FUZIX.BIN
--- /dev/null
+First draft only
+
+ZX Evolution (baseconf)
+
+I/O Mapping
+
+The ZX Evolution has two oddities here. Firstly it inherits a lot of the
+ZX Spectrum 16bit wide port decode hacks. Secondly it has a shadow and non
+shadow mode and some ports are present only in one mode.
+
+- Implementation rule for Fuzix, you must have DI on for shadow mode. Also
+ standard sys functions may turn shadow off if used (notably mapping)
+
+Memory
+
+512K ROM, 4MB RAM.
+
+
+Memory Map:
+
+0000-BFFF: Kernel
+C000-FFFF: Kernel/Common (we stick to 48K apps to get a bigger kernel)
+
+0000-BFFF: User
+C000-FFFF: Kernel/Common
+
+We will need to push disk buffers into their own bank and we have banks for
+video as well. But we have 4MB so who cares. Reworking the port for bigger
+user apps can occur later
+
+More interesting question: would we be better off using bankfixed or thunked ?
+
+
+TODO
+- Figure out how the boot logic works
+- Write a boot loader
+- Correct the set up code to set turbo and video etc right
+- Look at the other bits of port BF and how to use without getting in a mess
+- xx77 is even worse
+- Go through and sort out shadow v non shadow
+- Set up the IDE and SD ports and code
+- Add external buffer support to devsd
+- External buffers
+- Graphics modes setting and mapping
+- UDG and font loads
+- Floppy driver including adding external buffer support
+- RTC
+- PS/2 config and keyboard control ?
+- What to do with all that RAM ?
+- Video mapping into user space - do we support a top at 0x7FFF and direct
+ video map choice ?
+- Longer term look at memory options - thunked might be worth it to get big
+ user processes
--- /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
+/* 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) */
+#undef CONFIG_PROFIL
+/* Multiple processes in memory at once */
+#define CONFIG_MULTI
+/* Single tasking */
+#undef CONFIG_SINGLETASK
+
+/* Select a banked memory set up */
+#define CONFIG_BANK16 /* 16K pages */
+#define MAX_MAPS 255 /* 4MB FIXME cut this down by reserved pages */
+/* How many banks do we have in our address space */
+#define CONFIG_BANKS 4 /* 8 x 8K will fix when do paging */
+
+/* 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
+/* Vt definitions */
+#define VT_WIDTH 64
+#define VT_HEIGHT 24
+#define VT_RIGHT 63
+#define VT_BOTTOM 23
+
+
+/*
+ * Define the program loading area (needs to match kernel.def)
+ */
+#define PROGBASE 0x0000 /* Base of user */
+#define PROGLOAD 0x0100 /* Load and run here */
+#define PROGTOP 0xC000 /* Top of program, base of U_DATA */
+#define PROC_SIZE 48 /* Memory needed per process */
+
+/*
+ * Definitions for swapping - we don't need swap!
+ */
+
+/* What is the maximum number of /dev/hd devices we have. In theory right now
+ it's actually 3 - the two HD and the SD interface */
+#define MAX_BLKDEV 3
+/* SD card, single card only */
+#define CONFIG_SD
+#define SD_DRIVE_COUNT 1
+#define CONFIG_IDE
+
+#define BOOTDEVICENAMES "hd#"
+
+/* We will resize the buffers available after boot. This is the normal setting */
+#define CONFIG_DYNAMIC_BUFPOOL
+/* Larger transfers (including process execution) should go directly not via
+ the buffer cache. For all small (eg bit) systems this is the right setting
+ as it avoids polluting the small cache with data when it needs to be full
+ of directory and inode information */
+#define CONFIG_LARGE_IO_DIRECT(x) 1
+
+/* Specify this if there is a real time clock capable of reporting seconds. It
+ will be used to lock the kernel time better to reality. Other details like
+ Y2K support, or even supporting dates as well don't matter */
+ /* FIXME: there is one but its weird! */
+#undef CONFIG_RTC
+/* Specify that there is a full real time clock that can supply the date and
+ time to the system. */
+#undef CONFIG_RTC_FULL
+
+/*
+ * How fast does the clock tick (if present), or how many times a second do
+ * we simulate if not. For a machine without video 10 is a good number. If
+ * you have video you probably want whatever vertical sync/blank interrupt
+ * rate the machine has. For many systems it's whatever the hardware gives
+ * you.
+ *
+ * Note that this needs to be divisible by 10 and at least 10. If your clock
+ * is a bit slower you may need to fudge things somewhat so that the kernel
+ * gets 10 timer interrupt calls per second.
+ */
+#define TICKSPERSEC 50 /* Ticks per second */
+
+/* Core networking support */
+#define CONFIG_NET
+/* Or native (eg SLIP) */
+#define CONFIG_NET_NATIVE
+
+/*
+ * The device (major/minor) for the console and boot up tty attached to
+ * init at start up. 512 is the major 2, so all the tty devices are
+ * 512 + n where n is the tty.
+ */
+#define BOOT_TTY (512 + 1) /* Set this to default device for stdio, stderr */
+ /* In this case, the default is the first TTY device */
+/*
+ * If you have a mechanism to pass in a root device configuration then
+ * this holds the address of the buffer (eg a CP/M command line or similar).
+ * If the configuration is fixed then this can be a string holding the
+ * configuration. NULL means 'prompt the user'.
+ */
+#define CMDLINE NULL /* Location of root dev name */
+
+/* Device parameters */
+#define NUM_DEV_TTY 2 /* How many tty devices does the platform support */
+#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */
+#define NBUFS 5 /* Number of block buffers. Must be 4+ and must match
+ kernel.def */
+#define NMOUNTS 4 /* Number of mounts at a time */
+
+/* This can optionally be set to force a default baud rate, eg if the system
+ console should match a firmware set rate */
+#define TTY_INIT_BAUD B115200 /* Console is 'fast' */
--- /dev/null
+ .module crt0
+
+ .area _CODE
+ .area _CODE2
+ .area _CODE3
+ .area _VIDEO
+ .area _INITIALIZED
+ .area _HOME
+ .area _CONST
+
+ ;
+ ; 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
+ .area _INITIALIZER
+
+ .area _DISCARD
+ ; Somewhere to throw it out of the way
+
+
+ ; Our common is mapped high
+ .area _COMMONDATA
+ .area _COMMONMEM
+ .area _FONT
+
+
+
+ ; 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.def"
+
+ ;
+ ; startup code. Runs from 0x100. The kernel is mapped into pages
+ ; 16-23 and 16-22 are currently mapped. Stack is not valid on entry
+ ; and interrupts are off.
+ ;
+
+ .area _CODE
+
+ .globl _start
+
+_start:
+ ; Map in the top page (it couldn't be mapped by the loader as the
+ ; loader is living in it)
+ ld a,#0x57 ; MMU E000-FFFF
+ ld bc,#0x243B
+ out (c),a
+ ld a,#23 ; Top kernel page
+ inc b
+ out (c),a
+
+ ; 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
+ call init_early
+
+ ; Hardware setup
+ call init_hardware
+
+ ; Call the C main routine
+ call _fuzix_main
+
+ ; main shouldn't return, but if it does...
+ di
+stop: halt
+ jr stop
+
+ .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 <blkdev.h>
+#include <devide.h>
+#include <devsd.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 */
+ /* FIXME: we need to add the fd eventually */
+ { 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
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <devtty.h>
+#include <keycode.h>
+#include <vt.h>
+#include <tty.h>
+#include <graphics.h>
+#include <input.h>
+#include <devinput.h>
+
+static char tbuf1[TTYSIZ];
+static char tbuf2[TTYSIZ];
+
+uint8_t vtattr_cap = VTA_INVERSE|VTA_FLASH|VTA_UNDERLINE;
+extern uint8_t curattr;
+
+static tcflag_t console_mask[4] = {
+ _ISYS,
+ _OSYS,
+ _CSYS,
+ _LSYS
+};
+
+static tcflag_t serial_mask[4] = {
+ _ISYS,
+ _OSYS,
+ CSIZE|CBAUD|CSTOPB|PARENB|PARODD|_CSYS,
+ _LSYS
+};
+
+tcflag_t *termios_mask[NUM_DEV_TTY + 1] = {
+ NULL,
+ console_mask,
+ serial_mask,
+};
+
+struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */
+ {NULL, NULL, NULL, 0, 0, 0},
+ {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2},
+ {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2},
+};
+
+/* tty1 is the screen, tty2 is a 16x50 clone */
+
+__sfr __banked __at 0xF8EF uart_rx;
+__sfr __banked __at 0xF8EF uart_tx;
+__sfr __banked __at 0xF8EF uart_ls;
+__sfr __banked __at 0xF9EF uart_ier;
+__sfr __banked __at 0xF9EF uart_ms;
+__sfr __banked __at 0xFAEF uart_fcr;
+__sfr __banked __at 0xFBEF uart_lcr;
+__sfr __banked __at 0xFCEF uart_mcr;
+__sfr __banked __at 0xFDEF uart_lsr;
+__sfr __banked __at 0xFEEF uart_msr;
+__sfr __banked __at 0xFFEF uart_scr;
+
+
+/* Output for the system console (kprintf etc) */
+void kputchar(char c)
+{
+ if (c == '\n')
+ tty_putc(0, '\r');
+ tty_putc(0, c);
+}
+
+ttyready_t tty_writeready(uint8_t minor)
+{
+ if (minor == 1)
+ return TTY_READY_NOW;
+ if (uart_lsr & 0x20)
+ return TTY_READY_NOW;
+ return TTY_READY_SOON;
+}
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+ if (minor == 1)
+ vtoutput(&c, 1);
+ else
+ uart_tx = c;
+}
+
+void tty_polluart(void)
+{
+ uint8_t msr;
+
+ while (uart_lsr & 0x01)
+ tty_inproc(2, uart_rx);
+ msr = uart_msr;
+ /* DCD changed - tell the kernel so it can hangup or open ports */
+ if (msr & 0x08) {
+ if (msr & 0x80)
+ tty_carrier_raise(2);
+ else
+ tty_carrier_drop(2);
+ }
+ /* TODO: CTS/RTS */
+}
+
+int tty_carrier(uint8_t minor)
+{
+ if (minor == 2)
+ return uart_msr & 0x80;
+ return 1;
+}
+
+/*
+ * 16x50 conversion betwen a Bxxxx speed rate (see tty.h) and the values
+ * to stuff into the chip.
+ *
+ * FIXME: update for this board
+ */
+static uint16_t clocks[] = {
+ 12, /* Not a real rate */
+ 2304,
+ 1536,
+ 1047,
+ 857,
+ 768,
+ 384,
+ 192,
+ 96,
+ 48,
+ 24,
+ 12,
+ 6,
+ 3,
+ 2,
+ 1
+};
+
+/*
+ * This function is called whenever the terminal interface is opened
+ * or the settings changed. It is responsible for making the requested
+ * changes to the port if possible. Strictly speaking it should write
+ * back anything that cannot be implemented to the state it selected.
+ *
+ * That needs tidying up in many platforms and we also need a proper way
+ * to say 'this port is fixed config' before making it so.
+ */
+void tty_setup(uint8_t minor, uint8_t flags)
+{
+ uint8_t d;
+ uint16_t w;
+
+ if (minor == 1)
+ return;
+
+ /* 16x50. Can actually be configured */
+ d = 0x80; /* DLAB (so we can write the speed) */
+ d |= (ttydata[2].termios.c_cflag & CSIZE) >> 4;
+ if(ttydata[2].termios.c_cflag & CSTOPB)
+ d |= 0x04;
+ if (ttydata[2].termios.c_cflag & PARENB)
+ d |= 0x08;
+ if (!(ttydata[2].termios.c_cflag & PARODD))
+ d |= 0x10;
+ uart_lcr = d;
+ w = clocks[ttydata[2].termios.c_cflag & CBAUD];
+ uart_ls = w;
+ uart_ms = w >> 8;
+ uart_lcr = d & 0x7F;
+ /* FIXME: CTS/RTS support */
+ d = 0x03; /* DTR RTS */
+ uart_mcr = d;
+ uart_ier = 0x0D; /* We don't use tx ints */
+}
+
+void tty_sleeping(uint8_t minor)
+{
+ used(minor);
+}
+
+void tty_data_consumed(uint8_t minor)
+{
+ used(minor);
+}
+
+/* This gfx stuff needs a major revisit for all the modes */
+
+/* This is used by the vt asm code, but needs to live in the kernel */
+uint16_t cursorpos;
+
+/* For now we only support 64 char mode - we should add the mode setting
+ logic and other modes FIXME */
+static struct display specdisplay = {
+ 0,
+ 512, 192,
+ 512, 192,
+ 0xFF, 0xFF,
+ FMT_TIMEX64,
+ HW_UNACCEL,
+ GFX_VBLANK|GFX_MAPPABLE|GFX_TEXT,
+ 0
+};
+
+/*
+ * Graphics ioctls. Not yet updated to reflect TBBlue at all
+ */
+int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr)
+{
+ if (minor != 1 || arg >> 8 != 0x03)
+ return vt_ioctl(minor, arg, ptr);
+ switch(arg) {
+ case GFXIOC_GETINFO:
+ return uput(&specdisplay, ptr, sizeof(struct display));
+ case GFXIOC_WAITVB:
+ /* Our system clock is vblank */
+ timer_wait++;
+ psleep(&timer_interrupt);
+ timer_wait--;
+ chksigs();
+ if (udata.u_cursig) {
+ udata.u_error = EINTR;
+ return -1;
+ }
+ return 0;
+ }
+ return -1;
+}
+
+void vtattr_notify(void)
+{
+ /* Attribute byte fixups: not hard as the colours map directly
+ to the spectrum ones */
+ if (vtattr & VTA_INVERSE)
+ curattr = ((vtink & 7) << 3) | (vtpaper & 7);
+ else
+ curattr = (vtink & 7) | ((vtpaper & 7) << 3);
+ if (vtattr & VTA_FLASH)
+ curattr |= 0x80;
+ /* How to map the bright bit - we go by either */
+ if ((vtink | vtpaper) & 0x10)
+ curattr |= 0x40;
+}
--- /dev/null
+#ifndef __DEVTTY_DOT_H__
+#define __DEVTTY_DOT_H__
+
+void tty_pollirq(void);
+static void keydecode(void);
+
+extern void tty_polluart(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 kempston, kmouse, kempston_mbmask;
+
+uint8_t platform_param(char *p)
+{
+ return 0;
+}
+
+/* Nothing to do for the map of init */
+void map_init(void)
+{
+}
+
+void pagemap_init(void)
+{
+ uint8_t i;
+ /* We have 256 pages 0-255 but we need to work with the complement */
+ /* In addition certain pages are magic
+ 5 / 2 / 0 are the classic spectrum pages
+ 0-7 are the 128K spectrum pages
+ then above that the compat ones for Pentagon etc
+
+ This effectively means we need to consider special:
+ page 5/7 for the Spectrum video modes
+ page 4/6 for 256x192 16 colour
+ page 1/5 for 640x200 and 320x200 mode
+ page 1/3/5/7 for ATM text mode without it being packed
+ In one page mode it ends up in page 8 or 10 !
+
+ So we do
+ 0 / 1 / 2 / 3 Kernel
+ 4-8 Video
+ 9 Buffers (eventually)
+ 10 Video alt
+ 11 Init
+
+ We could in theory reduce it a bit by shuffling the buffers
+ around on a video change
+
+ We have 4MB, we actually can't use even 1MB with 16 processes!
+
+ Might want to move the kernel a bit so we can run a ZX spectrum
+ as a process ?
+
+ */
+ for (i = 12; i < 255; i++) {
+ pagemap_add(~i);
+ i++;
+ }
+ /* Common for init */
+ pagemap_add(~10);
+}
+
+void platform_copyright(void)
+{
+ /* We always have the kempston interfaces present */
+ kempston = 1;
+ kmouse = 1;
+ kempston_mbmask = 7;
+ /* FIXME: do we need to tweak dev/zx/devinput to allow us to force
+ 'turbo' features or make mbmask tell us - the Evo has 3 buttons
+ and wheel on 4-7 */
+}
+
--- /dev/null
+-mwxuy
+-i fuzix.ihx
+-l z80
+-b _CODE=0x0100
+-b _COMMONDATA=0xF200
+-b _DISCARD=0xE200
+platform-zxevo/crt0.rel
+platform-zxevo/commonmem.rel
+platform-zxevo/zxevo.rel
+platform-zxevo/video.rel
+platform-zxevo/main.rel
+platform-zxevo/discard.rel
+start.rel
+version.rel
+lowlevel-z80.rel
+usermem_std-z80.rel
+platform-zxevo/tricks.rel
+timer.rel
+kdata.rel
+usermem.rel
+platform-zxevo/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
+syscall_net.rel
+tty.rel
+vt.rel
+font8x8.rel
+mm.rel
+bank16k.rel
+swap.rel
+devsys.rel
+devinput.rel
+platform-zxevo/devtty.rel
+platform-zxevo/devide.rel
+platform-zxevo/devide_discard.rel
+platform-zxevo/devsd.rel
+platform-zxevo/devsd_discard.rel
+platform-zxevo/evommc.rel
+platform-zxevo/mbr.rel
+platform-zxevo/blkdev.rel
+platform-zxevo/devinput.rel
+platform-zxevo/zxkeyboard.rel
+platform-zxevo/net_native.rel
+-e
--- /dev/null
+U_DATA .equ 0xF000 ; (this is struct u_data from kernel.h)
+U_DATA__TOTALSIZE .equ 0x200 ; 256+256 bytes.
+
+Z80_TYPE .equ 1
+
+PROGBASE .equ 0x0000
+PROGLOAD .equ 0x0100
+
+NBUFS .equ 5
+
+Z80_MMU_HOOKS .equ 0
--- /dev/null
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include <devinput.h>
+
+/* 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();
+ tty_polluart();
+ timer_interrupt();
+ poll_input();
+ if (timer_wait)
+ wakeup(&timer_interrupt);
+}
+
+/* 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.
+ *
+ * Discard gets turned into buffers or user space
+ */
+void platform_discard(void)
+{
+ uint16_t discard_size = 0xE000 - (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;
+ }
+}
+
+/* Adding dummy swapper since it is referenced by tricks.s */
+void swapper(ptptr p)
+{
+ p;
+}
--- /dev/null
+/*
+ * ZX Evolution. Sort of a NEMO IDE but has extra magic so you don't
+ * have to play with two ports and sometimes byteswap but can just inir
+ * and otir.
+ */
+
+#define ide_select(x)
+#define ide_deselect()
+
+#define IDE_DRIVE_COUNT 2
+
+#define IDE_REG_DATA 0x10
+#define IDE_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_ALTSTATUS 0xC8
+#define IDE_REG_CONTROL 0xC8
+
--- /dev/null
+export CPU = z80
--- /dev/null
+ .module tricks
+
+ .globl _ptab_alloc
+ .globl _makeproc
+ .globl _chksigs
+ .globl _getproc
+ .globl _platform_monitor
+ .globl trap_illegal
+ .globl _platform_switchout
+ .globl _switchin
+ .globl _doexec
+ .globl _dofork
+ .globl _runticks
+ .globl unix_syscall_entry
+ .globl interrupt_handler
+ .globl map_kernel
+ .globl _ramtop
+ .globl _need_resched
+ .globl _int_disabled
+ .globl _udata
+
+ ; imported debug symbols
+ .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex
+
+ .include "kernel.def"
+ .include "../kernel.def"
+
+ .area _COMMONMEM
+
+; ramtop must be in common for single process swapping cases
+; and its a constant for the others from before init forks so it'll be fine
+; here
+_ramtop:
+ .dw 0
+_need_resched:
+ .db 0
+
+; Switchout switches out the current process, finds another that is READY,
+; possibly the same process, and switches it in. When a process is
+; restarted after calling switchout, it thinks it has just returned
+; from switchout().
+;
+; This function can have no arguments or auto variables.
+_platform_switchout:
+ ; save machine state
+
+ ld hl, #0 ; return code set here is ignored, but _switchin can
+ ; return from either _switchout OR _dofork, so they must both write
+ ; U_DATA__U_SP with the following on the stack:
+ push hl ; return code
+ push ix
+ push iy
+ ld (U_DATA__U_SP), sp ; this is where the SP is restored in _switchin
+
+ ; find another process to run (may select this one again)
+ call _getproc
+
+ push hl
+ call _switchin
+
+ ; we should never get here
+ call _platform_monitor
+
+badswitchmsg: .ascii "_switchin: FAIL"
+ .db 13, 10, 0
+
+_switchin:
+ di
+ pop bc ; return address
+ pop de ; new process pointer
+
+ ld hl, #P_TAB__P_PAGE_OFFSET+3 ; Common
+ add hl, de ; process ptr
+
+ ld a,#0x01
+ out (0xBF),a ; Shadow on
+
+ ld a, (hl)
+ ld bc,#0xF7F7
+ out (c), a ; *CAUTION* our stack just left the building
+
+ xor a
+ out (0xBF),a ; Shadow off
+
+ ; carry clear from xor
+
+ ; ------- No stack -------
+ ; check u_data->u_ptab matches what we wanted
+ ld hl, (U_DATA__U_PTAB) ; u_data->u_ptab
+ sbc hl, de ; subtract, result will be zero if DE==IX
+ jr nz, switchinfail
+
+ ; wants optimising up a bit
+ ld hl, #P_TAB__P_STATUS_OFFSET
+ add hl, de
+ ld (hl), #P_RUNNING
+
+ ; runticks = 0
+ ld hl, #0
+ ld (_runticks), hl
+
+ ; restore machine state -- note we may be returning from either
+ ; _switchout or _dofork
+ ld sp, (U_DATA__U_SP)
+
+ ; ---- New task stack ----
+
+ pop iy
+ pop ix
+ pop hl ; return code
+
+ ; enable interrupts, if the ISR isn't already running
+ ld a, (U_DATA__U_ININTERRUPT)
+ ld (_int_disabled),a
+ or a
+ ret nz ; in ISR, leave interrupts off
+ ei
+ ret ; return with interrupts on
+
+switchinfail:
+ call outhl
+ ld hl, #badswitchmsg
+ call outstring
+ ; something went wrong and we didn't switch in what we asked for
+ jp _platform_monitor
+
+fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry
+
+;
+; Called from _fork. We are in a syscall, the uarea is live as the
+; parent uarea. The kernel is the mapped object.
+;
+_dofork:
+ ; always disconnect the vehicle battery before performing maintenance
+ di ; should already be the case ... belt and braces.
+
+ pop de ; return address
+ pop hl ; new process p_tab*
+ push hl
+ push de
+
+ ld (fork_proc_ptr), hl
+
+ ; prepare return value in parent process -- HL = p->p_pid;
+ ld de, #P_TAB__P_PID_OFFSET
+ add hl, de
+ ld a, (hl)
+ inc hl
+ ld h, (hl)
+ ld l, a
+
+ ; Save the stack pointer and critical registers.
+ ; When this process (the parent) is switched back in, it will be as if
+ ; it returns with the value of the child's pid.
+ push hl ; HL still has p->p_pid from above, the return value in the parent
+ push ix
+ push iy
+
+ ; save kernel stack pointer -- when it comes back in the parent we'll be in
+ ; _switchin which will immediately return (appearing to be _dofork()
+ ; returning) and with HL (ie return code) containing the child PID.
+ ; Hurray.
+ ld (U_DATA__U_SP), sp
+
+ ; now we're in a safe state for _switchin to return in the parent
+ ; process.
+
+ ; --------- we switch stack copies in this call -----------
+ call fork_copy ; copy 0x000 to udata.u_top and the
+ ; uarea and return on the childs
+ ; common
+ ; We are now in the kernel child context
+
+ ; now the copy operation is complete we can get rid of the stuff
+ ; _switchin will be expecting from our copy of the stack.
+ pop bc
+ pop bc
+ pop bc
+
+ ; The child makes its own new process table entry, etc.
+ ld hl, #_udata
+ push hl
+ ld hl, (fork_proc_ptr)
+ push hl
+ call _makeproc
+ pop bc
+ pop bc
+
+ ; any calls to map process will now map the childs memory
+
+ ; runticks = 0;
+ ld hl, #0
+ ld (_runticks), hl
+ ; in the child process, fork() returns zero.
+ ;
+ ; And we exit, with the kernel mapped, the child now being deemed
+ ; to be the live uarea. The parent is frozen in time and space as
+ ; if it had done a switchout().
+ ret
+
+fork_copy:
+ ld hl, (U_DATA__U_TOP)
+ ld de, #0x0fff
+ add hl, de ; + 0x1000 (-1 for the rounding to follow)
+ ld a, h
+ rlca
+ rlca ; get just the number of banks in the bottom
+ ; bits
+ and #3
+ inc a ; and round up to the next bank
+ ld b, a
+ ; we need to copy the relevant chunks
+ ld hl, (fork_proc_ptr)
+ ld de, #P_TAB__P_PAGE_OFFSET
+ add hl, de
+ ; hl now points into the child pages
+ ld de, #U_DATA__U_PAGE
+ ; and de is the parent
+
+fork_next:
+ ; These two must in the loop for the moment as map_kernel in the
+ ; loop undoes it
+ ld a,#0x01
+ out (0xBF),a ; Shadow on
+ ld a,(hl)
+ exx
+ ld bc,#0x37F7
+ out (c), a ; 0x4000 map the child
+ exx
+ ld c, a
+ inc hl
+ ld a, (de)
+ exx
+ ld bc,#0x77F7
+ out (c), a ; 0x8000 map the parent
+ exx
+ inc de
+ exx
+ ld hl, #0x8000 ; copy the bank
+ ld de, #0x4000
+ ld bc, #0x4000 ; we copy the whole bank, we could optimise
+ ; further
+ ldir
+ exx
+ ; FIXME: get the process tables lower (eg data first ?)
+ call map_kernel ; put the maps back so we can look in p_tab
+ djnz fork_next
+ jp map_kernel
--- /dev/null
+;
+; ZX Evolution Text Mode
+;
+; Not particularly sane
+;
+; 80 column but split so
+; 0x01C0 holds 40 chars then a gap (left of each pair)
+; 0x11C0 holds the same for the right pairs
+; 0x21C0 is the attributes of the *right* pairs
+; 0x31C0 is the attributes of the left pairs
+;
+; And the attributes are
+;
+; bits 7/5/4/3 = pixel colour
+; bits 6/2/1/0 = background colour
+;
+; Lower font is ascii, upper font is russian but font can be
+; changed providing you jump through some weird hoops
+;
+
+ ; 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
+
+ ; imports
+
+ .globl map_video
+ .globl map_kernel
+;
+; Y * 64 + X / 2
+; Base is then 0x1C0 (left) 0x11C0 (right)
+;
+videopos:
+ ld a,e ; Get Y (0 - 24)
+ ld e,d ; X
+ rl e ; So it shifts back as we want
+ rra
+ srl e
+ rra ; In effect Y x 64 +
+ srl e ; A,E is now the 16bit offset
+ ; Y * 64 + x / 2
+ ld d,a
+ jr nc, left
+ set 4,d ; right
+left:
+ ld hl,#0x01c0
+ add hl,de
+ ld a,h
+ xor #0x30
+ ld d,a ; attributes
+ ld e,l ;
+ ret
+
+_plot_char:
+ pop hl
+ pop de ; D = x E = y
+ pop bc
+ push bc
+ push de
+ push hl
+
+ call map_video
+ call videopos
+ ld (hl), a
+ ld a,(_curattr)
+ ld (de), a
+ jp map_kernel
+
+_clear_lines:
+ pop hl
+ pop de ; E = line, D = count
+ push de
+ push hl
+ ; This way we handle 0 correctly
+ inc d
+ ld c,d
+ ld d,#0
+ call videopos
+ ld a,(_curattr)
+ call map_video
+ jr nextline
+
+clear_next_line:
+ ld b,#80
+clear_line_loop:
+ ld (hl),#' '
+ inc hl
+ ld (de),a
+ inc de
+ djnz clear_line_loop
+nextline:
+ dec c
+ jr nz, clear_next_line
+ jp map_kernel
+
+_clear_across:
+ pop hl
+ pop de ; DE = coords
+ pop bc ; C = count
+ push bc
+ push de
+ push hl
+ ld a,c
+ or a
+ ret z ; No work to do - bail out
+ call videopos
+ ld a,(_curattr)
+ ld b,c
+ call map_video
+clear_loop:
+ ld (hl),#' '
+ inc hl
+ ld (de),a
+ inc de
+ djnz clear_loop
+ jp map_kernel
+
+_scroll_down:
+ call map_video
+ ld hl,#0x07BF
+ ld de,#0x07FF
+ ld bc,#1600-64
+ lddr
+ ld hl,#0x17BF
+ ld de,#0x17FF
+ ld bc,#1600-64
+ lddr
+ ld hl,#0x27BF
+ ld de,#0x27FF
+ ld bc,#1600-64
+ ldir
+ ld hl,#0x37BF
+ ld de,#0x37FF
+ ld bc,#1600-64
+ ldir
+ jp map_kernel
+
+_scroll_up:
+ call map_video
+ ld hl,#0x01E0
+ ld de,#0x01C0
+ ld bc,#1600-64
+ ldir
+ ld hl,#0x11E0
+ ld de,#0x11C0
+ ld bc,#1600-64
+ ldir
+ ld hl,#0x21E0
+ ld de,#0x21C0
+ ld bc,#1600-64
+ ldir
+ ld hl,#0x31E0
+ ld de,#0x31C0
+ ld bc,#1600-64
+ ldir
+ jp map_kernel
+
+_cursor_on:
+ pop hl
+ pop de
+ push de
+ push hl
+ ld (cursorpos), de
+_cursor_disable:
+_cursor_off:
+ ld de,(cursorpos)
+ call videopos
+ call map_video
+ ld a,(de)
+ xor #0x3F
+ ld (de),a
+ jp map_kernel
+
+_do_beep:
+ ret
+
+ .area _DATA
+
+cursorpos:
+ .dw 0
+
+ .area _COMMONMEM
+_curattr:
+ .db 7
--- /dev/null
+;
+; ZX Evolution hardware support
+;
+
+ .module zxevo
+
+ ; 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 nmi_handler
+
+ .globl map_buffers
+ .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_kernel_restore
+ .globl map_video
+ .globl current_map
+
+ .globl _int_disabled
+ .globl _vtborder
+
+ ; 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
+
+ .include "kernel.def"
+ .include "../kernel.def"
+
+; -----------------------------------------------------------------------------
+; COMMON MEMORY BANK (above 0xE000)
+; -----------------------------------------------------------------------------
+ .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
+ ; FIXME: put back 48K ROM
+ rst 0 ; back into our booter
+
+platform_interrupt_all:
+ ret
+
+ .area _COMMONDATA
+
+_int_disabled:
+ .db 1
+
+_vtborder: ; needs to be common
+ .db 0
+
+
+; -----------------------------------------------------------------------------
+; KERNEL CODE BANK (below 0xC000, only accessible when the kernel is mapped)
+; -----------------------------------------------------------------------------
+ .area _CODE
+
+init_early:
+ ret
+
+ .area _DISCARD
+
+init_hardware:
+ ; set system RAM size
+ ld hl, #4096
+ ld (_ramsize), hl
+ ld hl, #512 ; FIXME: TBD
+ ld (_procmem), hl
+
+ ; Set up video etc
+
+ ; EFE7 bit 0 0 bit 5 0
+ ; xx77 bit 3: 1 = 14Mhz
+ ; xx77 bits 2-0: 111 ATM video
+
+ ld a,#0x01
+ out (0xBF),a ; Shadow on
+
+ ld bc,#0x0177 ; MMU on, hold off, res off
+ ld a,#0x0F ; 14MHz, 80x25 text mode
+ out (c),a
+
+ ld bc,#0xFFBF
+ ld a,#0x00 ; FIXME: correct value
+ out (c),a ; Video and turbo set
+
+ xor a
+ out (c),a ; Shadow back off
+
+ ; EFE7 is shadow off !
+ ld bc,#0xEFE7
+
+ ld a,#0x80 ; turbo, pentagon, video 80x25
+ ; no RAM0 override
+ out (c),a
+
+
+ ; screen initialization
+ call _vtinit
+
+ ret
+
+;------------------------------------------------------------------------------
+; COMMON MEMORY PROCEDURES FOLLOW
+
+ .area _COMMONMEM
+
+_program_vectors:
+ pop de
+ pop hl
+ push hl
+ push de
+ call map_process
+
+ ; write zeroes across all vectors
+ ld hl, #0
+ ld de, #1
+ ld bc, #0x007f ; program first 0x80 bytes only
+ ld (hl), #0x00
+ ldir
+
+ ; now install the interrupt vector at 0x0038
+ ld a, #0xC3 ; JP instruction
+ ld (0x0038), a
+ ld hl, #interrupt_handler
+ ld (0x0039), hl
+
+ ; set restart vector for FUZIX system calls
+ ld (0x0030), a ; (rst 30h is unix function call vector)
+ ld hl, #unix_syscall_entry
+ ld (0x0031), hl
+
+ ld (0x0000), a
+ ld hl, #null_handler ; to Our Trap Handler
+ ld (0x0001), hl
+
+ ld (0x0066), a ; Set vector for NMI
+ ld hl, #nmi_handler
+ ld (0x0067), hl
+
+ jr map_kernel
+
+map_process:
+ ld a, h
+ or l
+ jr z, map_kernel
+map_process_always:
+map_process_always_di:
+ push af
+ push bc
+ push hl
+ ld hl,(U_DATA__U_PAGE)
+map_write_hl:
+ ld (current_map),hl
+ ;
+ ; The map is stored with page number complements
+ ;
+ ld a,#0x01
+ out (0xBF),a ; Shadow on
+ ld bc,#0x37F7
+ outi
+ ld b,#0x77
+ outi
+ ld b,#0xB7
+ outi
+ xor a
+ out (0xBF),a ; Shadow on
+ pop hl
+ pop bc
+ pop af
+ ret
+
+;
+; Save and switch to kernel
+;
+map_save_kernel:
+ push hl
+ ld hl, (current_map)
+ ld (map_store), hl
+ pop hl
+map_kernel_di:
+map_kernel:
+map_buffers:
+map_kernel_restore:
+ push af
+ push bc
+ push hl
+ ld hl, #kernel_map
+ jr map_write_hl
+
+map_video:
+ push af
+ push bc
+ push hl
+ ld hl, #video_map
+ jr map_write_hl
+
+map_restore:
+ push af
+ push bc
+ push hl
+ ld hl, (map_store)
+ jr map_write_hl
+
+;
+; Debug output
+;
+outchar:
+ push bc
+outcw:
+ ld c,#0xFDEF
+ in a,(c)
+ and #0x20
+ jr z, outcw
+ ld b,#0xF8
+ out (c),a
+ pop bc
+ ret
+
+ .area _COMMONDATA
+_tmpout:
+ .db 1
+
+current_map: ; place to store current page pointer
+ .dw 0
+map_store: ; and the saved one
+ .dw 0
+
+ ; TODO FIXME
+kernel_map:
+ .db 0, 1, 2, 3
+video_map:
+ .db 0, 1, 8, 3