tc2068: initial upload of the TC2068 support
authorAlan Cox <alan@linux.intel.com>
Tue, 27 Nov 2018 12:51:23 +0000 (12:51 +0000)
committerAlan Cox <alan@linux.intel.com>
Tue, 27 Nov 2018 12:51:23 +0000 (12:51 +0000)
This is just an initial cut - it's got lots that needs fixing (like Timex
video mode support) and it currently has some memory corruption bugs that need
nailing.

21 files changed:
Kernel/platform-tc2068/Makefile [new file with mode: 0644]
Kernel/platform-tc2068/README [new file with mode: 0644]
Kernel/platform-tc2068/commonmem.s [new file with mode: 0644]
Kernel/platform-tc2068/config.h [new file with mode: 0644]
Kernel/platform-tc2068/crt0.s [new file with mode: 0644]
Kernel/platform-tc2068/devices.c [new file with mode: 0644]
Kernel/platform-tc2068/devinput.c [new file with mode: 0644]
Kernel/platform-tc2068/devinput.h [new file with mode: 0644]
Kernel/platform-tc2068/devtty.c [new file with mode: 0644]
Kernel/platform-tc2068/devtty.h [new file with mode: 0644]
Kernel/platform-tc2068/discard.c [new file with mode: 0644]
Kernel/platform-tc2068/fuzix.lnk [new file with mode: 0644]
Kernel/platform-tc2068/kernel.def [new file with mode: 0644]
Kernel/platform-tc2068/loader-divide.s [new file with mode: 0644]
Kernel/platform-tc2068/main.c [new file with mode: 0644]
Kernel/platform-tc2068/platform_ide.h [new file with mode: 0644]
Kernel/platform-tc2068/rules.mk [new file with mode: 0644]
Kernel/platform-tc2068/target.mk [new file with mode: 0644]
Kernel/platform-tc2068/tc2068.s [new file with mode: 0644]
Kernel/platform-tc2068/tricks.s [new file with mode: 0644]
Kernel/platform-tc2068/zxvideo.s [new file with mode: 0644]

diff --git a/Kernel/platform-tc2068/Makefile b/Kernel/platform-tc2068/Makefile
new file mode 100644 (file)
index 0000000..7c03dea
--- /dev/null
@@ -0,0 +1,51 @@
+CSRCS = devtty.c devices.c main.c devinput.c
+CDSRCS = discard.c
+DSRCS = ../dev/devide.c ../dev/blkdev.c
+DDSRCS = ../dev/devide_discard.c ../dev/mbr.c
+DZSRCS = ../dev/zx/divide.c ../dev/zx/zxkeyboard.c
+DDZSRCS =
+ASRCS = crt0.s tc2068.s zxvideo.s
+ASRCS += tricks.s commonmem.s loader-divide.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 *~ 
+
+image:
+       ../tools/makedck ../fuzix.bin fuzix.dck
+       dd if=../fuzix.bin of=fuzix.load bs=32768 count=1
diff --git a/Kernel/platform-tc2068/README b/Kernel/platform-tc2068/README
new file mode 100644 (file)
index 0000000..dbaeade
--- /dev/null
@@ -0,0 +1,66 @@
+Experimental porting work for the TS2068 and TC2068 Timex spectrum like
+systems.
+
+Not yet usable (eats itself with memory corruption)
+
+----
+
+This port requires a TC2068/TS2068 system with a 64K cartridge configured
+with the low 32K RAM and high 32K ROM (or all battery backed RAM also works
+of course except maybe in the reboot case)
+
+At the moment you need a DivIDE interface and twister attached to the
+machine in order to boot it, as it will load the low 32K from the CF card
+boot area. The DivIDE needs to be set to not interfere with boot in order
+to run with a TC2068/TS2068 system without the spectrum ROM compatibility
+cartridge.
+
+Memory is laid out as follows
+
+Kernel mode
+
+0000-3FFF      Dock RAM        - common and other kernel data
+4000-7FFF      Dock RAM        - kernel data
+8000-FFFF      Dock ROM        - kernel boot and kernel code
+
+Video updating
+
+0000-3FFF      Dock RAM        - common and other kernel data
+                                 (including font and video)
+4000-7FFF      Home RAM        - screens
+8000-FFFF      Dock ROM        - kernel boot and kernel code
+
+User mode
+
+0000-3FFF      Dock RAM        - common and other kernel data
+4000-77FF      Home RAM        - screens
+7800-FFFF      Home RAM        - user space
+
+(if we kept to the 256 pixel screen we can go to a much bigger user space)
+
+
+If using with FUSE then create an hdf file for the disk, add a filesystem
+image to it and then
+       dd if=fuzix.load of=tc2068.hdf bs=1046 seek=1 conv=notrunc
+
+to place it in blocks 1+ after the partition table (in the gap left for loaders)
+
+For real media just change the offset so as not to include the 534 bytes of
+header on the hdf file.
+
+Make a copy of the media as right now it eats the disks !
+
+
+Debugging state:
+
+Looks like we may have some obscure interrupt corruption case or similar
+(we bomb weirdly late on or see a bit of random display corruption and
+fsck fails part way with corruption like results)
+
+Need to try cutting down IRQ handler. One mess was on the video display which
+suggests whatever happened occurred with the video mapped at one point (same
+char was later printed correctly)
+
+Disabling pre-empt doesn't help and fsck shows corruption in execution which
+suggests its not task switch related
+
diff --git a/Kernel/platform-tc2068/commonmem.s b/Kernel/platform-tc2068/commonmem.s
new file mode 100644 (file)
index 0000000..dc31c24
--- /dev/null
@@ -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-tc2068/config.h b/Kernel/platform-tc2068/config.h
new file mode 100644 (file)
index 0000000..54d28ab
--- /dev/null
@@ -0,0 +1,73 @@
+#define CONFIG_IDE
+#define CONFIG_LARGE_IO_DIRECT         /* 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
+
+/* Swap based one process in RAM */
+#define CONFIG_SWAP_ONLY
+#define CONFIG_SPLIT_UDATA
+#define UDATA_BLKS     1
+#define UDATA_SIZE     0x200
+#define CONFIG_DYNAMIC_BUFPOOL
+#define CONFIG_DYNAMIC_SWAP
+
+/* Custom banking */
+
+/* Banks as reported to user space */
+#define CONFIG_BANKS   1
+
+/* 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    0x7800  /* also data base */
+#define PROGLOAD    0x7800  /* also data base */
+#define PROGTOP     0xFE00  /* Top of program, below high page */
+                        /* Can probably use to FFFF FIXME */
+
+#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 SWAPBASE 0x7800
+#define SWAPTOP  0xFE00UL
+#define SWAP_SIZE 0x44
+#define MAX_SWAPS      16
+#define SWAPDEV  (swap_dev)  /* Device for swapping (dynamic). */
+
+/* We swap by hitting the user map */
+#define swap_map(x)            ((uint8_t *)(x))
diff --git a/Kernel/platform-tc2068/crt0.s b/Kernel/platform-tc2068/crt0.s
new file mode 100644 (file)
index 0000000..ab70d16
--- /dev/null
@@ -0,0 +1,117 @@
+        .module crt0
+
+       ;
+       ;       High space - read only 
+       ;
+
+        .area _CODE
+       .area _CODE2
+       ;
+       ;       Tru and keep code in the top 32K
+       ;
+
+
+       ;
+       ;       Our common lives low
+       ;
+       .area _COMMONDATA
+        .area _COMMONMEM
+       .area _CODE3
+       .area _FONT
+        .area _VIDEO           ; must end below 0x4000
+        .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 _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.def"
+
+       ;
+        ; startup code
+       ;
+       ; We loaded the rest of the kernel from disk and jumped here
+       ;
+
+        .area _CODE
+
+       .globl _start
+
+_start:
+
+        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
+        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
diff --git a/Kernel/platform-tc2068/devices.c b/Kernel/platform-tc2068/devices.c
new file mode 100644 (file)
index 0000000..90c608d
--- /dev/null
@@ -0,0 +1,45 @@
+#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
+}
diff --git a/Kernel/platform-tc2068/devinput.c b/Kernel/platform-tc2068/devinput.c
new file mode 100644 (file)
index 0000000..179e973
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *     Joysticks off the AY sound chip
+ */
+#include <kernel.h>
+#include <kdata.h>
+#include <input.h>
+#include <devinput.h>
+
+static uint8_t ay_p1_save, ay_p2_save;
+
+__sfr __at 0xF5        ay_reg;
+__sfr __banked __at 0x01F6     ay_player1;
+__sfr __banked __at 0x02F6     ay_player2;
+
+static char buf[32];
+
+static struct s_queue kqueue = {
+ buf, buf, buf, sizeof(buf), 0, sizeof(buf) / 2
+};
+
+/* Queue a character to the input device */
+void queue_input(uint8_t c)
+{
+    insq(&kqueue, c);
+    wakeup(&kqueue);
+}
+
+static uint8_t ay_encode(uint8_t r)
+{
+    uint8_t k = 0;
+    r = ~r;
+    if (r & 1)
+        k = STICK_DIGITAL_U;
+    if (r & 2)
+        k |= STICK_DIGITAL_D;
+    if (r & 4)
+        k |= STICK_DIGITAL_L;
+    if (r & 8)
+        k |= STICK_DIGITAL_R;
+    if (r & 128)
+        k |= BUTTON(0);
+    return k;
+}
+
+static uint8_t ay_js(uint8_t *slot)
+{
+    uint8_t r = ay_player1;
+    if (r == ay_p1_save)
+        return 0;
+    ay_p1_save = r;
+    *slot++ = STICK_DIGITAL;
+    *slot = ay_encode(r);
+    return 2;
+}
+
+static uint8_t ay_js2(uint8_t *slot)
+{
+    uint8_t r = ay_player2;
+    if (r == ay_p2_save)
+        return 0;
+    ay_p2_save = r;
+    *slot++ = STICK_DIGITAL | 1;
+    *slot = ay_encode(r);
+    return 2;
+}
+
+int platform_input_read(uint8_t *slot)
+{
+    uint8_t r, k;
+    if (remq(&kqueue, &r)) {
+        remq(&kqueue, &k);
+       *slot++ = KEYPRESS_CODE | r;
+       *slot = k;
+       return 2;
+    }
+
+    ay_reg = 0x0E;
+    if (ay_js(slot))
+        return 2;
+    if (ay_js2(slot))
+        return 2;
+    return 0;
+}
+
+void platform_input_wait(void)
+{
+    psleep(&kqueue);   /* We wake this on timers so it works for sticks */
+}
+
+int platform_input_write(uint8_t flag)
+{
+    flag;
+    udata.u_error = EINVAL;
+    return -1;
+}
+
+void poll_input(void)
+{
+    ay_reg=0x0E;
+    if (ay_player1 != ay_p1_save || ay_player2 != ay_p2_save)
+        wakeup(&kqueue);
+}
+        
\ No newline at end of file
diff --git a/Kernel/platform-tc2068/devinput.h b/Kernel/platform-tc2068/devinput.h
new file mode 100644 (file)
index 0000000..981f702
--- /dev/null
@@ -0,0 +1,2 @@
+extern void queue_input(uint8_t);
+extern void poll_input(void);
diff --git a/Kernel/platform-tc2068/devtty.c b/Kernel/platform-tc2068/devtty.c
new file mode 100644 (file)
index 0000000..36ac5d3
--- /dev/null
@@ -0,0 +1,148 @@
+#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>
+
+char tbuf1[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
+};
+
+tcflag_t *termios_mask[NUM_DEV_TTY + 1] = {
+       NULL,
+       console_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},
+};
+
+/* tty1 is the screen */
+
+/* Output for the system console (kprintf etc) */
+void kputchar(char c)
+{
+       if (c == '\n')
+               tty_putc(0, '\r');
+       tty_putc(0, c);
+}
+
+/* Both console and debug port are always ready */
+ttyready_t tty_writeready(uint8_t minor)
+{
+       minor;
+       return TTY_READY_NOW;
+}
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+       minor;
+       vtoutput(&c, 1);
+}
+
+int tty_carrier(uint8_t minor)
+{
+       minor;
+       return 1;
+}
+
+void tty_setup(uint8_t minor, uint8_t flags)
+{
+       minor;
+}
+
+void tty_sleeping(uint8_t minor)
+{
+       minor;
+}
+
+void tty_data_consumed(uint8_t minor)
+{
+}
+
+
+/* This is used by the vt asm code, but needs to live in the kernel */
+uint16_t cursorpos;
+
+static struct display specdisplay = {
+       0,
+       256, 192,
+       256, 192,
+       0xFF, 0xFF,
+       FMT_SPECTRUM,
+       HW_UNACCEL,
+       GFX_VBLANK|GFX_MAPPABLE|GFX_TEXT,
+       0
+};
+
+static struct videomap specmap = {
+       0,
+       0,
+       0x4000,
+       6912,
+       0,
+       0,
+       0,
+       MAP_FBMEM|MAP_FBMEM_SIMPLE
+};
+
+/*
+ *     Graphics ioctls. Very minimal for this platform. It's a single fixed
+ *     mode with direct memory mapping.
+ */
+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_MAP:
+               return uput(&specmap, ptr, sizeof(struct videomap));
+       case GFXIOC_UNMAP:
+               return 0;
+       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;
+}
diff --git a/Kernel/platform-tc2068/devtty.h b/Kernel/platform-tc2068/devtty.h
new file mode 100644 (file)
index 0000000..40a67f5
--- /dev/null
@@ -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-tc2068/discard.c b/Kernel/platform-tc2068/discard.c
new file mode 100644 (file)
index 0000000..724a24f
--- /dev/null
@@ -0,0 +1,43 @@
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include <blkdev.h>
+
+uint8_t platform_param(char *p)
+{
+       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-tc2068/fuzix.lnk b/Kernel/platform-tc2068/fuzix.lnk
new file mode 100644 (file)
index 0000000..9f25f92
--- /dev/null
@@ -0,0 +1,48 @@
+-mwxuy
+-i fuzix.ihx
+-l z80
+-b _CODE=0x8000
+-b _COMMONDATA=0x0080
+platform-tc2068/loader-divide.rel
+platform-tc2068/crt0.rel
+platform-tc2068/commonmem.rel
+platform-tc2068/tc2068.rel
+platform-tc2068/zxvideo.rel
+platform-tc2068/main.rel
+platform-tc2068/discard.rel
+start.rel
+version.rel
+lowlevel-z80.rel
+usermem_std-z80.rel
+platform-tc2068/tricks.rel
+timer.rel
+kdata.rel
+usermem.rel
+platform-tc2068/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
+simple.rel
+swap.rel
+devsys.rel
+devinput.rel
+platform-tc2068/devtty.rel
+platform-tc2068/devide.rel
+platform-tc2068/devide_discard.rel
+platform-tc2068/divide.rel
+platform-tc2068/mbr.rel
+platform-tc2068/blkdev.rel
+platform-tc2068/devinput.rel
+platform-tc2068/zxkeyboard.rel
+-e
diff --git a/Kernel/platform-tc2068/kernel.def b/Kernel/platform-tc2068/kernel.def
new file mode 100644 (file)
index 0000000..470f4d5
--- /dev/null
@@ -0,0 +1,14 @@
+; UZI mnemonics for memory addresses etc
+
+; We stick it straight after the tag
+U_DATA                      .equ 0x0080       ; (this is struct u_data from kernel.h)
+U_DATA__TOTALSIZE           .equ 0x200        ; 256+256+256 bytes.
+
+Z80_TYPE                   .equ 1
+
+PROGBASE                   .equ 0x7800
+PROGLOAD                   .equ 0x7800
+
+NBUFS                      .equ 5
+
+Z80_MMU_HOOKS              .equ 0
diff --git a/Kernel/platform-tc2068/loader-divide.s b/Kernel/platform-tc2068/loader-divide.s
new file mode 100644 (file)
index 0000000..42aed5f
--- /dev/null
@@ -0,0 +1,142 @@
+;
+;      We are run from the ROM start of the cartridge. Because this is a
+;      TS2068/TC2068 the DivIDE will have the ROM paging disabled
+;
+       .area _CODE
+
+
+       .globl _start
+
+       .globl boot
+
+;
+;      From 0x8000
+;
+;      AROS header
+
+       .byte 0x02              ; Machine code
+       .byte 0x02              ; AROS
+       .word boot              ; address to run
+       .byte 0x0f              ; page us in the top 32K please (our ROM)
+       .byte 0x01              ; autostart
+       .word 0x0021            ; reserve us no memory (yet another crappy
+                               ; 2068 bug)
+boot:
+       ; We are entered with cartridge ROM in the top 32K, system RAM in
+       ; the low 32K
+
+       di                      ; we are going to blow stuff away
+       ; Hide the screen contents
+       ld hl,#0x5800
+       ld de,#0x5801
+       ld bc,#0x02FF
+       ld (hl),#0
+       ldir
+
+       ld sp,#0x8000           ; We don't load 7E00-7FFF right now
+
+       ; Black border
+       xor a
+       out (254),a
+
+       ;
+       ;       The kernel needs cartridge RAM mapped in 0x0000-7FFF
+       ;       and cartridge ROM to 8000-FFFF
+       ;       
+       ld a,#0xFF
+       out (0xF4),a    
+
+       ;
+       ;       Ensure the master drive is selected
+       ;
+wait1:
+       in a,(191)
+       rla
+       jr c, wait1
+       ld a,#0xE0
+       out (187),a
+       nop
+wait2:
+       in a,(191)
+       and #0xC0
+       cp #0x40                ; want busy off, drdy
+       jr nz, wait2
+
+       ;
+       ; Load sectors. We shortcut stuff here because we never
+       ; load over 256 sectors
+       ;
+       ; Most stuff is in ROM already. We just need to load the
+       ; remaining chunk from 0000-3FFF and 5B00-7FFF (and it's easier
+       ; just to load through the screen)
+       ;
+       xor a                   ; LBA28 high bits
+       out (179),a
+       out (183),a
+
+       ld de,#0x3F01           ; Load 63 sectors
+                               ; from sector 1
+       ld hl,#0x0000           ; Starting address to load
+
+load_loop:
+       ld a,e
+       inc e
+       out (175),a             ; sector number to load
+       ld a,#1                 ; load one sector
+       out (171),a
+       ld a,#0x20              ; READ
+       out (191),a
+       nop
+wait3:
+       in a, (191)
+       rlca
+       jr c, wait3             ; Busy
+       bit 4,a                 ; DRQ ?
+       jr z, failed            ; Nope - bad
+       ld bc,#163              ; Data port
+       inir
+       inir
+       dec d
+       jr nz, load_loop
+
+       ; And we are done
+
+       jp _start               ; Enter entirely cartridge mapped
+failed:
+       ld a,#0x05
+       out (0xFF),a
+       di
+       halt
+
+;
+;      Zero page
+;
+       .area _PAGE0    (ABS)
+
+       .globl null_handler
+       .globl unix_syscall_entry
+       .globl interrupt_handler
+
+       .org 0
+loader:
+       jp boot
+       .ds 5
+rst_8:
+       .ds 8
+rst_10:
+       .ds 8
+rst_18:
+       .ds 8
+rst_20:
+       .ds 8
+rst_28:
+       .ds 8
+rst_30:
+       jp unix_syscall_entry
+       .ds 5
+rst_38:
+       jp interrupt_handler
+       .ds 0x66-0x3B
+nmi:   ret             ; magic...
+       retn
+
diff --git a/Kernel/platform-tc2068/main.c b/Kernel/platform-tc2068/main.c
new file mode 100644 (file)
index 0000000..6e78d21
--- /dev/null
@@ -0,0 +1,69 @@
+#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);
+}
+
+/* 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
+ */
+void platform_discard(void)
+{
+       uint16_t discard_size = 0x8000 - (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
\ No newline at end of file
diff --git a/Kernel/platform-tc2068/platform_ide.h b/Kernel/platform-tc2068/platform_ide.h
new file mode 100644 (file)
index 0000000..2141fda
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *     DivIDE interface
+ *
+ *     This is a 16bit interface with a latched data port. Each read
+ *     from A3 fetches a word then returns low then high etc. In the other
+ *     direction it latches then writes.
+ *
+ *     The latch is reset to the first state by any other port access in the
+ *     IDE space (so the command write sets it up nicely for us)
+ */
+
+#define ide_select(x)
+#define ide_deselect()
+
+#define IDE_DRIVE_COUNT        2
+
+#define IDE_REG_DATA           0xA3
+#define IDE_REG_ERROR          0xA7
+#define IDE_REG_FEATURES       0xA7
+#define IDE_REG_SEC_COUNT      0xAB
+#define IDE_REG_LBA_0          0xAF
+#define IDE_REG_LBA_1          0xB3
+#define IDE_REG_LBA_2          0xB7
+#define IDE_REG_LBA_3          0xBB
+#define IDE_REG_DEVHEAD                0xBB
+#define IDE_REG_STATUS         0xBF
+#define IDE_REG_COMMAND                0xBF
+
+#define IDE_NONSTANDARD_XFER
diff --git a/Kernel/platform-tc2068/rules.mk b/Kernel/platform-tc2068/rules.mk
new file mode 100644 (file)
index 0000000..b24847a
--- /dev/null
@@ -0,0 +1 @@
+export CROSS_CC_SYS5=--codeseg CODE3
diff --git a/Kernel/platform-tc2068/target.mk b/Kernel/platform-tc2068/target.mk
new file mode 100644 (file)
index 0000000..3bffcde
--- /dev/null
@@ -0,0 +1 @@
+export CPU = z80
diff --git a/Kernel/platform-tc2068/tc2068.s b/Kernel/platform-tc2068/tc2068.s
new file mode 100644 (file)
index 0000000..924f8a5
--- /dev/null
@@ -0,0 +1,200 @@
+;
+;    TC2068 hardware support
+;
+
+        .module zx128
+
+        ; 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_kernel_restore
+       .globl map_for_swap
+       .globl map_video
+       .globl current_map
+
+        .globl _need_resched
+       .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 (below 0x4000)
+; -----------------------------------------------------------------------------
+        .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
+        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 (above 0x8000, only accessible when the kernel is mapped)
+; -----------------------------------------------------------------------------
+        .area _CODE
+
+init_early:
+       ld a,#0xFF
+       out (0xF4),a            ; Map kernel fully
+        ret
+
+       .area _VIDEO
+
+init_hardware:
+        ; set system RAM size
+        ld hl, #80
+        ld (_ramsize), hl
+        ld hl, #(34)         ; 32K for kernel/screen/etc
+        ld (_procmem), hl
+
+        ; screen initialization
+       call _vtinit
+
+        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_process:
+        ld a, h
+        or l
+        jr z, map_kernel
+map_for_swap:
+map_process_always:
+map_process_always_di:
+       push af
+       ld a,#0x03                      ; catridge in low 16K only
+       out (0xF4),a
+       ld (current_map),a
+       pop af
+       ret
+;
+;      Save and switch to kernel
+;
+map_save_kernel:
+       push af
+        ld a, (current_map)
+        ld (map_store), a
+       pop af
+map_kernel_di:
+map_kernel:
+map_kernel_restore:
+       push af
+       ld a,#0xFF                      ; entirely from cartridge
+       ld (current_map),a
+       out (0xF4),a
+       pop af
+       ret
+
+map_video:
+       push af
+       ld a,#0xF3                      ; entirely from cartridge except video
+       ld (current_map),a
+       out (0xF4),a
+       pop af
+       ret
+
+map_restore:
+       push af
+        ld a, (map_store)
+       ld (current_map),a
+       out (0xF4),a
+       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
+       call _vtoutput
+       pop af
+       pop af
+       pop ix
+       pop hl
+       pop de
+       pop bc
+        ret
+
+       .area _COMMONDATA
+_tmpout:
+       .db 1
+
+current_map:                ; place to store current page number. Is needed
+        .db 0               ; because we have no ability to read 0xF4 port
+                            ; to detect what page is mapped currently 
+map_store:
+        .db 0
+
+_need_resched:
+        .db 0
+
diff --git a/Kernel/platform-tc2068/tricks.s b/Kernel/platform-tc2068/tricks.s
new file mode 100644 (file)
index 0000000..0113d75
--- /dev/null
@@ -0,0 +1,5 @@
+        .include "kernel.def"
+        .include "../kernel.def"
+
+       .include "../lib/z80single.s"
+
diff --git a/Kernel/platform-tc2068/zxvideo.s b/Kernel/platform-tc2068/zxvideo.s
new file mode 100644 (file)
index 0000000..ea74d6b
--- /dev/null
@@ -0,0 +1,405 @@
+;
+;        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
+       .globl map_kernel
+       .globl map_video
+
+       ; Build the video library as the only driver
+
+ZXVID_ONLY     .equ    1
+
+        .area _VIDEO
+
+;
+;       zx128 vt primitives hacked a bit
+;
+;      Will be replaced by Timex video shortly
+;
+        ; exported symbols
+        .globl zx_plot_char
+        .globl zx_scroll_down
+        .globl zx_scroll_up
+        .globl zx_cursor_on
+        .globl zx_cursor_off
+       .globl zx_cursor_disable
+        .globl zx_clear_lines
+        .globl zx_clear_across
+        .globl zx_do_beep
+       .globl _fontdata_8x8
+       .globl _curattr
+       .globl _vtattr
+
+videopos:
+        ld a,e
+        and #7
+        rrca
+        rrca
+        rrca 
+        add a,d
+        ld d,e
+        ld e,a
+        ld a,d
+        and #0x18
+        or #0x40           ; Standard screen
+        ld d,a
+       jp map_video
+
+videoattr:
+       ;                       32 x E + D into HL
+       ld a,e
+       rrca
+       rrca
+       rrca                    ; A is now 32xE with the top bits overflowed
+                               ; into the low 2 bits
+       ld l,a
+       and #3                  ; Extract the low 2 bits for the high
+       add #0x58               ; Attributes start 0x5800
+       ld h,a
+       ld a,l
+       and #0xE0               ; mask the bits that are valid
+       add d                   ; add the low 5 bits from D
+       ld l,a                  ; and done (the add can't overflow)
+       ret
+
+       .if ZXVID_ONLY
+_plot_char:
+       .endif
+zx_plot_char:
+        pop hl
+        pop de              ; D = x E = y
+        pop bc
+        push bc
+        push de
+        push hl
+
+       ld hl,(_vtattr)     ; l is vt attributes
+       push de
+       push hl             ; save attributes as inaccessible once vid mapped
+
+        call videopos
+
+        ld b, #0            ; calculating offset in font table
+        ld a, c
+       or a                ; clear carry
+        rla
+        rl b
+        rla
+        rl b
+        rla
+        rl b
+        ld c, a
+
+        ld hl, #_fontdata_8x8-32*8    ; font
+        add hl, bc          ; hl points to first byte of char data
+
+       pop bc
+       ; We do underline for now - not clear italic or bold are useful
+       ; with the font we have.
+
+        ; printing
+plot_char_loop:
+        ld a, (hl)
+        ld (de), a
+        inc hl              ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc hl              ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc hl              ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc hl              ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc hl              ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc hl              ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+        ld (de), a
+        inc hl              ; next byte of char data
+        inc d               ; next screen line
+
+        ld a, (hl)
+       bit 1,c             ; underline ?
+       jr nz, last_ul
+plot_attr:
+        ld (de), a
+
+       pop de
+       call videoattr
+       ld a,(_curattr)
+       ld (hl),a
+       jp map_kernel
+
+last_ul:
+       ld a,#0xff
+       jr plot_attr
+
+       .if ZXVID_ONLY
+_clear_lines:
+       .endif
+zx_clear_lines:
+        pop hl
+        pop de              ; E = line, D = count
+        push de
+        push hl
+       ; This way we handle 0 correctly
+       inc d
+       jr nextline
+
+clear_next_line:
+        push de
+        ld d, #0            ; from the column #0
+        ld b, d             ; b = 0
+        ld c, #32           ; clear 32 cols
+        push bc
+        push de
+        call _clear_across
+        pop hl              ; clear stack
+        pop hl
+
+        pop de
+        inc e
+nextline:
+        dec d
+        jr nz, clear_next_line
+
+        ret
+
+
+       .if ZXVID_ONLY
+_clear_across:
+       .endif
+zx_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
+       push de
+       push bc
+        call videopos       ; first pixel line of first character in DE
+        push de
+        pop hl              ; copy to hl
+        xor a
+
+        ; no boundary checks. Assuming that D + C < SCREEN_WIDTH
+
+clear_line:
+        ld b, #8            ; 8 pixel lines to clear for this char
+clear_char:
+        ld (de), a
+        inc d
+        djnz clear_char
+
+        ex de, hl
+        inc de
+        push de
+        pop hl
+
+        dec c
+        jr nz, clear_line
+       pop bc
+       pop de
+       call videoattr
+       ld a,(_curattr)
+       ld b,c
+setattr:
+       ld (hl),a
+       inc hl
+       djnz setattr
+       jp map_kernel
+
+copy_line:
+        ; HL - source, DE - destination
+
+        ; convert line coordinates to screen coordinates both for DE and HL
+        push de
+        ex de, hl
+        call videopos
+        ex de, hl
+        pop de
+        call videopos
+
+        ld c, #8
+
+copy_line_nextchar:
+        push hl
+        push de
+
+        ld b, #32
+
+copy_pixel_line:
+        ld a, (hl)
+        ld (de), a
+        inc e
+        inc l
+        djnz copy_pixel_line
+
+        pop de
+        pop hl
+        inc d
+        inc h
+        dec c
+        jr nz, copy_line_nextchar
+        ret
+
+        ; TODO: the LDIR way should be much faster
+
+       .if ZXVID_ONLY
+_scroll_down:
+       .endif
+zx_scroll_down:
+        ; set HL = (0,22), DE = (0, 23)
+        xor a
+        ld d, a
+        ld h, a
+        ld l, #22
+        ld e, #23
+        ld c, #23           ; 23 lines to move
+
+       call map_video
+
+loop_scroll_down:
+        push hl
+        push de
+        push bc
+
+        call copy_line
+
+        pop bc
+        pop de
+        pop hl
+
+        dec l
+        dec e
+        dec c
+        jr nz, loop_scroll_down
+
+       ; Attributes
+       ld hl,#0x5ADF
+       ld de,#0x5AFF
+       ld bc,#0x02E0
+       lddr
+
+        jp map_kernel
+
+
+       .if ZXVID_ONLY
+_scroll_up:
+       .endif
+zx_scroll_up:
+        ; set HL = (0,1), DE = (0, 0)
+        xor a
+        ld d, a
+        ld e, a
+        ld h, a
+        ld l, #1
+        ld c, #23           ; 23 lines to move
+
+       call map_video
+
+loop_scroll_up:
+        push hl
+        push de
+        push bc
+
+        call copy_line
+
+        pop bc
+        pop de
+        pop hl
+
+        inc l
+        inc e
+        dec c
+        jr nz, loop_scroll_up
+
+       ld hl,#0x5820
+       ld de,#0x5800
+       ld bc,#0x02E0
+       ldir
+       jp map_kernel
+
+       .if ZXVID_ONLY
+_cursor_on:
+       .endif
+zx_cursor_on:
+        pop hl
+        pop de
+        push de
+        push hl
+        ld (cursorpos), de
+
+        call videopos
+        ld a, #7
+        add a, d
+        ld d, a
+        ld a, #0xFF
+        ld (de), a
+        jp map_kernel
+       .if ZXVID_ONLY
+_cursor_disable:
+_cursor_off:
+       .endif
+zx_cursor_disable:
+zx_cursor_off:
+        ld de, (cursorpos)
+        call videopos
+        ld a, #7
+        add a, d
+        ld d, a
+        xor a
+        ld (de), a
+       jp map_kernel
+
+       .if ZXVID_ONLY
+_do_beep:
+       .endif
+zx_do_beep:
+        ret
+
+        .area _DATA
+
+cursorpos:
+        .dw 0
+
+       .area _COMMONDATA
+
+_curattr:
+       .db 7
+