Add new dragon-nx32 port
authorTormod Volden <debian.tormod@gmail.com>
Mon, 6 Apr 2015 09:32:57 +0000 (11:32 +0200)
committerAlan Cox <alan@linux.intel.com>
Mon, 6 Apr 2015 10:36:41 +0000 (11:36 +0100)
For Dragon 32 or 64 with an external banked memory
cartridge.

Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
29 files changed:
Kernel/platform-dragon-nx32/Makefile [new file with mode: 0644]
Kernel/platform-dragon-nx32/README [new file with mode: 0644]
Kernel/platform-dragon-nx32/commonmem.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/config.h [new file with mode: 0644]
Kernel/platform-dragon-nx32/crt0.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/devdw.c [new file with mode: 0644]
Kernel/platform-dragon-nx32/devdw.h [new file with mode: 0644]
Kernel/platform-dragon-nx32/devfd.c [new file with mode: 0644]
Kernel/platform-dragon-nx32/devfd.h [new file with mode: 0644]
Kernel/platform-dragon-nx32/device.h [new file with mode: 0644]
Kernel/platform-dragon-nx32/devices.c [new file with mode: 0644]
Kernel/platform-dragon-nx32/devlpr.c [new file with mode: 0644]
Kernel/platform-dragon-nx32/devlpr.h [new file with mode: 0644]
Kernel/platform-dragon-nx32/devtty.c [new file with mode: 0644]
Kernel/platform-dragon-nx32/devtty.h [new file with mode: 0644]
Kernel/platform-dragon-nx32/dragon.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/drivewire.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/dw.def [new file with mode: 0644]
Kernel/platform-dragon-nx32/dwread.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/dwwrite.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/floppy.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/fuzix.link [new file with mode: 0644]
Kernel/platform-dragon-nx32/kernel.def [new file with mode: 0644]
Kernel/platform-dragon-nx32/libc.c [new file with mode: 0644]
Kernel/platform-dragon-nx32/main.c [new file with mode: 0644]
Kernel/platform-dragon-nx32/mem-nx32.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/target.mk [new file with mode: 0644]
Kernel/platform-dragon-nx32/tricks.s [new file with mode: 0644]
Kernel/platform-dragon-nx32/usermem_sam.s [new file with mode: 0644]

diff --git a/Kernel/platform-dragon-nx32/Makefile b/Kernel/platform-dragon-nx32/Makefile
new file mode 100644 (file)
index 0000000..422c63b
--- /dev/null
@@ -0,0 +1,35 @@
+
+CSRCS = devlpr.c devtty.c devfd.c devdw.c
+CSRCS += devices.c main.c libc.c
+
+ASRCS = crt0.s dragon.s mem-nx32.s
+ASRCS += tricks.s commonmem.s usermem_sam.s floppy.s drivewire.s
+
+COBJS = $(CSRCS:.c=$(BINEXT))
+AOBJS = $(ASRCS:.s=$(BINEXT))
+OBJS  = $(COBJS) $(AOBJS)
+
+JUNK = $(CSRCS:.c=.o) $(ASRCS:.s=.o)
+
+all: $(OBJS)
+
+$(COBJS): %$(BINEXT): %.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG2) -c $<
+
+$(AOBJS): %$(BINEXT): %.s
+       $(CROSS_AS) $(ASOPTS) $< -o $*.o
+
+clean:
+       rm -f $(OBJS) $(JUNK)
+
+image:
+       $(CROSS_LD) -o ../fuzix.bin --map=../fuzix.map --script=fuzix.link \
+       crt0.o commonmem.o usermem_sam.o \
+       dragon.o mem-nx32.o ../bankfixed.o \
+       ../start.o ../version.o ../lowlevel-6809.o \
+       tricks.o main.o ../timer.o ../kdata.o devfd.o floppy.o devices.o \
+       drivewire.o devdw.o \
+       ../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
+       ../syscall_proc.o ../syscall_other.o ../mm.o \
+       ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o ../syscall_exec16.o \
+       devlpr.o devtty.o libc.o ../vt.o
diff --git a/Kernel/platform-dragon-nx32/README b/Kernel/platform-dragon-nx32/README
new file mode 100644 (file)
index 0000000..2a7d258
--- /dev/null
@@ -0,0 +1,19 @@
+Dragon (32 or 64) + external memory cartridge
+
+This port is for running FUZIX on real Dragons using an external
+memory cartridge which is being prototyped.
+
+The cartridge can have from 2 to 256 banks of 32KB each. It will
+map the active bank at 0x8000-0xFEFF and use the EXMEM (SLENB) signal to
+hide the internal ROMs. Writing the bank number to FFBF selects the
+bank and activates the cartridge. Writing to FFBE deactivates the
+cartridge. It is only active if the SAM is in map type 0.
+
+The port reserves the internal RAM at 0-0x7FFF plus bank 0 for the kernel.
+
+The port can use DriveWire to mount a root filesystem, and is
+able to execute init. syscalls and fork have not been tested.
+Swapping out to disk does not work yet.
+
+There is not much 6809 userspace work done.
+
diff --git a/Kernel/platform-dragon-nx32/commonmem.s b/Kernel/platform-dragon-nx32/commonmem.s
new file mode 100644 (file)
index 0000000..335764d
--- /dev/null
@@ -0,0 +1,23 @@
+;
+        .module commonmem
+
+        ; exported symbols
+        .globl _ub
+        .globl _udata
+        .globl kstack_top
+        .globl istack_top
+        .globl istack_switched_sp
+
+        .area .udata
+
+_ub:    ; first 512 bytes: starts with struct u_block, with the kernel stack working down from above
+_udata:
+kstack_base:
+       zmb 512
+kstack_top:
+
+        ; next 256 bytes: 254 byte interrupt stack, then 2 byte saved stack pointer
+istack_base:
+       zmb 254
+istack_top:
+istack_switched_sp: .dw 0
diff --git a/Kernel/platform-dragon-nx32/config.h b/Kernel/platform-dragon-nx32/config.h
new file mode 100644 (file)
index 0000000..77233a4
--- /dev/null
@@ -0,0 +1,56 @@
+/* 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 - for now while we get it booting */
+#undef CONFIG_SINGLETASK
+/* Pure swap */
+#undef CONFIG_SWAP_ONLY
+/* Banked Kernel: need to fix GCC first */
+#define CONFIG_BANK_FIXED
+#define MAX_MAPS 4
+#define MAP_SIZE 0x7C00U
+#define CONFIG_BANKS   1
+/* And swapping */
+#undef SWAPDEV
+
+/* Video terminal, not a serial tty */
+#define CONFIG_VT
+/* Simple text mode */
+#define CONFIG_VT_SIMPLE
+/* Vt definitions */
+#define VT_BASE                (uint8_t *)0x0400       /* Default video text mode base */
+#define VT_WIDTH       32
+#define VT_HEIGHT      16
+#define VT_RIGHT       31
+#define VT_BOTTOM      15
+#define VT_INITIAL_LINE        4
+
+extern unsigned char vt_mangle_6847(unsigned char c);
+#define VT_MAP_CHAR(x) vt_mangle_6847(x)
+
+#define TICKSPERSEC 50   /* Ticks per second */
+/* FIXME: This will move once we put the display in the kernel bank and
+   sort the banker out */
+#define PROGBASE    0x8000  /* also data base */
+#define PROGLOAD    0x8000  /* also data base */
+#define PROGTOP     0xFC00  /* Top of program */
+
+#define BOOT_TTY (512 + 1)   /* Set this to default device for stdio, stderr */
+                          /* In this case, the default is the first TTY device */
+                            /* Temp FIXME set to serial port for debug ease */
+
+/* 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 2
+#define NDEVS    2        /* Devices 0..NDEVS-1 are capable of being mounted */
+                          /*  (add new mountable devices to beginning area.) */
+#define TTYDEV   BOOT_TTY /* Device used by kernel for messages, panics */
+#define NBUFS    6       /* Number of block buffers */
+#define NMOUNTS         2        /* Number of mounts at a time */
diff --git a/Kernel/platform-dragon-nx32/crt0.s b/Kernel/platform-dragon-nx32/crt0.s
new file mode 100644 (file)
index 0000000..0197903
--- /dev/null
@@ -0,0 +1,35 @@
+               ; exported
+               .globl start
+
+               ; imported symbols
+               .globl _fuzix_main
+               .globl init_early
+               .globl init_hardware
+               .globl kstack_top
+
+               ; startup code
+               .area .start
+
+start:
+               ; text may be in memory bank 0
+               jsr map_kernel
+               jmp main
+
+               .area .text
+
+main:          orcc #0x10              ; interrupts definitely off
+               lds #kstack_top
+
+               ldx #__sectionbase_.bss__
+               ldy #__sectionlen_.bss__
+               clra
+bss_wipe:      sta ,x+
+               leay -1,y
+               bne bss_wipe
+
+               jsr init_early
+               jsr init_hardware
+               jsr _fuzix_main
+               orcc #0x10
+stop:          bra stop
+
diff --git a/Kernel/platform-dragon-nx32/devdw.c b/Kernel/platform-dragon-nx32/devdw.c
new file mode 100644 (file)
index 0000000..ae3fc91
--- /dev/null
@@ -0,0 +1,89 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devdw.h>
+
+#define MAX_DW 4       /* can be 255 */
+
+#define DW_READ                0
+#define DW_WRITE       1
+
+static uint8_t dw_tab[MAX_DW];
+
+/*
+ *     Block device glue for DriveWire
+ *
+ *     DriveWire uses 256 byte sector transfers
+ */
+
+static int dw_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
+{
+    blkno_t block;
+    uint16_t dptr;
+    int ct = 0;
+    int tries;
+    uint8_t err;
+    uint8_t *driveptr = dw_tab + minor;
+    uint8_t cmd[5];
+
+    if(rawflag)
+        goto bad2;
+
+    dptr = (uint16_t)udata.u_buf->bf_data;
+    block = udata.u_buf->bf_blk;
+
+//    kprintf("Issue command: drive %d\n", minor);
+    /* maybe mimicking floppy driver more than needed? */
+    cmd[0] = is_read ? DW_READ : DW_WRITE;
+    cmd[1] = block >> 7;       /* 2 sectors per block */
+    cmd[2] = (block << 1) & 0xFF;
+    cmd[3] = dptr >> 8;
+    cmd[4] = dptr & 0xFF;
+    *driveptr = minor; /* pass minor (drive number) through here for now */
+        
+    while (ct < 2) {
+        for (tries = 0; tries < 4 ; tries++) {
+            // kprintf("dw_operation on block %d ct %d\n", block, ct);
+            err = dw_operation(cmd, driveptr);
+            if (err == 0)
+                break;
+            if (tries > 1)
+                dw_reset(driveptr);
+        }
+        /* FIXME: should we try the other half and then bail out ? */
+        if (tries == 3)
+            goto bad;
+        cmd[3]++;      /* Move on 256 bytes in the buffer */
+        cmd[2]++;      /* Next sector for 2nd block */
+        ct++;
+    }
+    return 1;
+bad:
+    kprintf("dw%d: error %x\n", minor, err);
+bad2:
+    udata.u_error = EIO;
+    return -1;
+}
+
+/* FIXME: for bit-banger transport (not Becker) we should set up
+   the PIA at some point too */
+
+int dw_open(uint8_t minor, uint16_t flag)
+{
+    if(minor >= MAX_DW) {
+        udata.u_error = ENODEV;
+        return -1;
+    }
+    return 0;
+}
+
+int dw_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+    return dw_transfer(minor, true, rawflag);
+}
+
+int dw_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+    return dw_transfer(minor, false, rawflag);
+}
+
diff --git a/Kernel/platform-dragon-nx32/devdw.h b/Kernel/platform-dragon-nx32/devdw.h
new file mode 100644 (file)
index 0000000..d7b9358
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __DEVDW_DOT_H__
+#define __DEVDW_DOT_H__
+
+/* public interface */
+int dw_read(uint8_t minor, uint8_t rawflag, uint8_t flag);
+int dw_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
+int dw_open(uint8_t minor, uint16_t flag);
+
+/* low level interface */
+uint8_t dw_reset(uint8_t *drive);
+uint8_t dw_operation(uint8_t *cmd, uint8_t *drive);
+
+#endif /* __DEVDW_DOT_H__ */
+
diff --git a/Kernel/platform-dragon-nx32/devfd.c b/Kernel/platform-dragon-nx32/devfd.c
new file mode 100644 (file)
index 0000000..c4754a5
--- /dev/null
@@ -0,0 +1,124 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devfd.h>
+
+#define MAX_FD 4
+
+#define OPDIR_NONE     0
+#define OPDIR_READ     1
+#define OPDIR_WRITE    2
+
+#define FD_READ                0x88    /* 2797 needs 0x88, 1797 needs 0x80 */
+#define FD_WRITE       0xA8    /* Likewise A8 v A0 */
+
+static uint8_t motorct;
+static uint8_t fd_selected = 0xFF;
+static uint8_t fd_tab[MAX_FD];
+
+static void fd_motor_busy(void)
+{
+    motorct++;
+}
+
+static void fd_motor_idle(void)
+{
+    motorct--;
+    // if (motorct == 0) ... start timer */
+}
+
+static void fd_motor_timeout(void)
+{
+    fd_selected = 0xff;
+    fd_motor_off();
+}
+
+/*
+ *     We only support normal block I/O because otherwise we'd need
+ *     bounce buffers - which would make it just as pointless!
+ *
+ *     The Dragon and COCO have 18 x 256 byte sectors per track. We
+ *     use them in pairs. We assume an even sectors per track. This is fine
+ *     for our usage but would break for single density media.
+ */
+
+/* static uint8_t selmap[4] = { 0x01, 0x02, 0x04, 0x40 }; - COCO */
+static uint8_t selmap[4] = {0x00, 0x01, 0x02, 0x03 };
+
+static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
+{
+    blkno_t block;
+    uint16_t dptr;
+    int ct = 0;
+    int tries;
+    uint8_t err;
+    uint8_t *driveptr = fd_tab + minor;
+    uint8_t cmd[6];
+
+    if(rawflag)
+        goto bad2;
+
+    fd_motor_busy();           /* Touch the motor timer first so we don't
+                                   go and turn it off as we are doing this */
+    if (fd_selected != minor) {
+        uint8_t err = fd_motor_on(selmap[minor]);
+        if (err)
+            goto bad;
+    }
+
+    dptr = (uint16_t)udata.u_buf->bf_data;
+    block = udata.u_buf->bf_blk;
+
+//    kprintf("Issue command: drive %d\n", minor);
+    cmd[0] = is_read ? FD_READ : FD_WRITE;
+    cmd[1] = block / 9;                /* 2 sectors per block */
+    cmd[2] = ((block % 9) << 1) + 1;   /*eww.. */
+    cmd[3] = is_read ? OPDIR_READ: OPDIR_WRITE;
+    cmd[4] = dptr >> 8;
+    cmd[5] = dptr & 0xFF;
+        
+    while (ct < 2) {
+        for (tries = 0; tries < 4 ; tries++) {
+            err = fd_operation(cmd, driveptr);
+            if (err == 0)
+                break;
+            if (tries > 1)
+                fd_reset(driveptr);
+        }
+        /* FIXME: should we try the other half and then bale out ? */
+        if (tries == 3)
+            goto bad;
+        cmd[4]++;      /* Move on 256 bytes in the buffer */
+        cmd[2]++;      /* Next sector for 2nd block */
+        ct++;
+    }
+    fd_motor_idle();
+    return 1;
+bad:
+    kprintf("fd%d: error %x\n", minor, err);
+bad2:
+    fd_motor_idle();
+    udata.u_error = EIO;
+    return -1;
+
+}
+
+int fd_open(uint8_t minor, uint16_t flag)
+{
+    if(minor >= MAX_FD) {
+        udata.u_error = ENODEV;
+        return -1;
+    }
+    return 0;
+}
+
+int fd_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+    return fd_transfer(minor, true, rawflag);
+}
+
+int fd_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+    return fd_transfer(minor, false, rawflag);
+}
+
diff --git a/Kernel/platform-dragon-nx32/devfd.h b/Kernel/platform-dragon-nx32/devfd.h
new file mode 100644 (file)
index 0000000..e5224ac
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __DEVFD_DOT_H__
+#define __DEVFD_DOT_H__
+
+/* public interface */
+int fd_read(uint8_t minor, uint8_t rawflag, uint8_t flag);
+int fd_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
+int fd_open(uint8_t minor, uint16_t flag);
+
+/* low level interface */
+uint8_t fd_reset(uint8_t *drive);
+uint8_t fd_operation(uint8_t *cmd, uint8_t *drive);
+uint8_t fd_motor_on(uint8_t drive);
+uint8_t fd_motor_off(void);
+
+#endif /* __DEVFD_DOT_H__ */
+
diff --git a/Kernel/platform-dragon-nx32/device.h b/Kernel/platform-dragon-nx32/device.h
new file mode 100644 (file)
index 0000000..6f4c1e2
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __DEVICE_DOT_H__
+#define __DEVICE_DOT_H__
+
+extern void mod_control(uint8_t set, uint8_t clr);
+
+#endif /* __DEVICE_DOT_H__ */
diff --git a/Kernel/platform-dragon-nx32/devices.c b/Kernel/platform-dragon-nx32/devices.c
new file mode 100644 (file)
index 0000000..a188243
--- /dev/null
@@ -0,0 +1,45 @@
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <devfd.h>
+#include <devdw.h>
+#include <devsys.h>
+#include <devlpr.h>
+#include <tty.h>
+#include <vt.h>
+
+struct devsw dev_tab[] =  /* The device driver switch table */
+{
+// minor    open         close        read      write       ioctl
+// -----------------------------------------------------------------
+  /* 0: /dev/fd                Floppy disc block devices  */
+  {  fd_open,     no_close,    fd_read,   fd_write,   no_ioctl },
+  /* 1: /dev/hd                Hard disc block devices (absent) */
+  {  nxio_open,     no_close,    no_rdwr,   no_rdwr,   no_ioctl },
+  /* 2: /dev/tty       TTY devices */
+  {  tty_open,     tty_close,   tty_read,  tty_write,  vt_ioctl },
+  /* 3: /dev/lpr       Printer devices */
+  {  lpr_open,     lpr_close,   no_rdwr,   lpr_write,  no_ioctl  },
+  /* 4: /dev/mem etc   System devices (one offs) */
+  {  no_open,      no_close,    sys_read, sys_write, sys_ioctl  },
+  /* Pack to 7 with nxio if adding private devices and start at 8 */
+  {  nxio_open,     no_close,    no_rdwr,   no_rdwr,   no_ioctl },
+  {  nxio_open,     no_close,    no_rdwr,   no_rdwr,   no_ioctl },
+  {  nxio_open,     no_close,    no_rdwr,   no_rdwr,   no_ioctl },
+  /* 8: /dev/dw                DriveWire remote disk images */
+  {  dw_open,      no_close,    dw_read,   dw_write,  no_ioctl },
+};
+
+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) + 255)
+       return false;
+    else
+        return true;
+}
+void device_init(void)
+{
+}
+
diff --git a/Kernel/platform-dragon-nx32/devlpr.c b/Kernel/platform-dragon-nx32/devlpr.c
new file mode 100644 (file)
index 0000000..a011085
--- /dev/null
@@ -0,0 +1,54 @@
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <device.h>
+#include <devlpr.h>
+
+/* random test places */
+uint8_t *lpstat = (uint8_t *)0xFF00;
+uint8_t *lpdata = (uint8_t *)0xFF01;
+
+int lpr_open(uint8_t minor, uint16_t flag)
+{
+       minor;
+       flag;                   // shut up compiler
+       return 0;
+}
+
+int lpr_close(uint8_t minor)
+{
+       minor;                  // shut up compiler
+       return 0;
+}
+
+int lpr_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+       int c = udata.u_count;
+       char *p = udata.u_base;
+       uint16_t ct;
+
+       minor;
+       rawflag;
+       flag;                   // shut up compiler
+
+       while (c-- > 0) {
+               ct = 0;
+
+               /* Try and balance polling and sleeping */
+               while (*lpstat & 2) {
+                       ct++;
+                       if (ct == 10000) {
+                               udata.u_ptab->p_timeout = 3;
+                               if (psleep_flags(NULL, flag)) {
+                                       if (udata.u_count)
+                                               udata.u_error = 0;
+                                       return udata.u_count;
+                               }
+                               ct = 0;
+                       }
+               }
+               /* Data */
+               *lpdata = ugetc(p++);
+       }
+       return udata.u_count;
+}
diff --git a/Kernel/platform-dragon-nx32/devlpr.h b/Kernel/platform-dragon-nx32/devlpr.h
new file mode 100644 (file)
index 0000000..7765c18
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __DEVLPR_DOT_H__
+#define __DEVLPR_DOT_H__
+
+int lpr_open(uint8_t minor, uint16_t flag);
+int lpr_close(uint8_t minor);
+int lpr_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
+
+#endif
diff --git a/Kernel/platform-dragon-nx32/devtty.c b/Kernel/platform-dragon-nx32/devtty.c
new file mode 100644 (file)
index 0000000..9419151
--- /dev/null
@@ -0,0 +1,194 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <devtty.h>
+#include <device.h>
+#include <vt.h>
+#include <tty.h>
+
+#undef  DEBUG                  /* UNdefine to delete debug code sequences */
+
+uint8_t *uart_data = (uint8_t *)0xFF04;        /* ACIA data */
+uint8_t *uart_status = (uint8_t *)0xFF05;      /* ACIA status */
+uint8_t *uart_command = (uint8_t *)0xFF06;     /* ACIA command */
+uint8_t *uart_control = (uint8_t *)0xFF07;     /* ACIA control */
+
+char tbuf1[TTYSIZ];
+char tbuf2[TTYSIZ];
+
+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 the serial port */
+
+/* Output for the system console (kprintf etc) */
+void kputchar(char c)
+{
+       if (c == '\n')
+               tty_putc(1, '\r');
+       tty_putc(1, c);
+}
+
+ttyready_t tty_writeready(uint8_t minor)
+{
+       uint8_t c;
+       if (minor == 1)
+               return TTY_READY_NOW;
+       c = *uart_status;
+       return (c & 16) ? TTY_READY_NOW : TTY_READY_SOON; /* TX DATA empty */
+}
+
+/* For DragonPlus we should perhaps support both monitors 8) */
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+       if (minor == 1) {
+               vtoutput(&c, 1);
+       } else
+               *uart_data = c; /* Data */
+}
+
+void tty_sleeping(uint8_t minor)
+{
+    used(minor);
+}
+
+void tty_setup(uint8_t minor)
+{
+       if (minor == 2) {
+               /* FIXME: do proper mode setting */
+               *uart_command = 0x01;   /* DTR high, IRQ enabled, TX irq disabled 8N1 */
+               *uart_control = 0x1E;   /* 9600 baud */
+       }
+}
+
+int tty_carrier(uint8_t minor)
+{
+       /* The serial DCD is status bit 5 but not wired */
+       return 1;
+}
+
+void tty_interrupt(void)
+{
+       uint8_t r = *uart_status;
+       if (r & 0x8) {
+               r = *uart_data;
+               tty_inproc(2,r);
+       }       
+}
+
+uint8_t keymap[8];
+static uint8_t keyin[8];
+static uint8_t keybyte, keybit;
+static uint8_t newkey;
+static int keysdown = 0;
+static uint8_t shiftmask[8] = {
+       0, 0x40, 0, 0, 0, 0, 0, 0x40
+};
+
+static uint8_t rbit[8] = {
+       0xFE,
+       0xFD,
+       0xFB,
+       0xF7,
+       0xEF,
+       0xDF,
+       0xBF,
+       0x7F,
+};
+
+/* Row inputs: multiplexed with the joystick */
+static volatile uint8_t *pia_row = (uint8_t *)0xFF00;
+/* Columns for scanning: multiplexed with the printer port */
+static volatile uint8_t *pia_col = (uint8_t *)0xFF02;
+/* Control */
+static volatile uint8_t *pia_ctrl = (uint8_t *)0xFF03;
+
+static void keyproc(void)
+{
+       int i;
+       uint8_t key;
+
+       for (i = 0; i < 8; i++) {
+               /* We do the scan in software on the Dragon */
+               *pia_col = rbit[i];
+               keyin[i] = ~*pia_row;
+               key = keyin[i] ^ keymap[i];
+               if (key) {
+                       int n;
+                       int m = 1;
+                       for (n = 0; n < 7; n++) {
+                               if ((key & m) && (keymap[i] & m)) {
+                                       if (!(shiftmask[i] & m))
+                                               keysdown--;
+                               }
+                               if ((key & m) && !(keymap[i] & m)) {
+                                       if (!(shiftmask[i] & m))
+                                               keysdown++;
+                                       keybyte = i;
+                                       keybit = n;
+                                       newkey = 1;
+                               }
+                               m += m;
+                       }
+               }
+               keymap[i] = keyin[i];
+       }
+}
+
+uint8_t keyboard[8][7] = {
+       { '0', '8', '@', 'h', 'p', 'x', 10 },
+       { '1', '9', 'a', 'i', 'q', 'y', 0 /* clear - used as ctrl*/ },
+       { '2', ':', 'b', 'j', 'r', 'z', 27 /* break (used for esc) */ },
+       { '3', ';', 'c', 'k', 's', '^' /* up */, 0 /* NC */ },
+       { '4', ',', 'd', 'l', 't', '|' /* down */, 0 /* NC */ },
+       { '5', '-', 'e', 'm', 'u', 8 /* left */, 0 /* NC */ },
+       { '6', '.', 'f', 'n', 'v', '\t' /* right */, 0 /* NC */ },
+       { '7', '/', 'g', 'o', 'w', ' ', 0 /* shift */ },
+};
+
+uint8_t shiftkeyboard[8][7] = {
+       { '_', '(', '\\', 'H', 'P', 'X', 10 },
+       { '!', ')', 'A', 'I', 'Q', 'Y', 0 /* clear */ },
+       { '"', '*', 'B', 'J', 'R', 'Z', 3 /* break */ },
+       { '#', '+', 'C', 'K', 'S', '[' /* up */, 0 /* NC */ },
+       { '$', '<', 'D', 'L', 'T', ']' /* down */, 0 /* NC */ },
+       { '%', '=', 'E', 'M', 'U', '{' /* left */, 0 /* NC */ },
+       { '&', '>', 'F', 'N', 'V', '}' /* right */, 0 /* NC */ },
+       { '\'', '?', 'G', 'O', 'W', ' ', 0 /* shift */ },
+};
+
+static void keydecode(void)
+{
+       uint8_t c;
+
+       if (keymap[7] & 64)     /* shift */
+               c = shiftkeyboard[keybyte][keybit];
+       else
+               c = keyboard[keybyte][keybit];
+       if (keymap[1] & 64) {   /* control */
+               if (c > 31 && c < 96)
+                       c &= 31;
+       }
+       tty_inproc(1, c);
+}
+
+void platform_interrupt(void)
+{
+       uint8_t i = *pia_ctrl;
+       if (i & 0x80) {
+               *pia_col;
+               newkey = 0;
+               keyproc();
+               if (keysdown < 3 && newkey)
+                       keydecode();
+               timer_interrupt();
+       }
+}
+
+/* This is used by the vt asm code, but needs to live at the top of the kernel */
+uint16_t cursorpos;
diff --git a/Kernel/platform-dragon-nx32/devtty.h b/Kernel/platform-dragon-nx32/devtty.h
new file mode 100644 (file)
index 0000000..14c28c3
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __DEVTTY_DOT_H__
+#define __DEVTTY_DOT_H__
+
+#define KEY_ROWS 8
+#define KEY_COLS 7
+extern uint8_t keymap[8];
+extern uint8_t keyboard[8][7];
+extern uint8_t shiftkeyboard[8][7];
+
+#endif
diff --git a/Kernel/platform-dragon-nx32/dragon.s b/Kernel/platform-dragon-nx32/dragon.s
new file mode 100644 (file)
index 0000000..4f1462e
--- /dev/null
@@ -0,0 +1,131 @@
+       ;
+       ; common Dragon platform
+       ;
+
+               .module dragon
+
+               ; exported
+
+               ; imported
+               .globl unix_syscall_entry
+               .globl fd_nmi_handler
+               .globl size_ram
+
+               ; exported debugging tools
+               .globl _trap_monitor
+               .globl outchar
+               .globl _di
+               .globl _ei
+               .globl _irqrestore
+
+            include "kernel.def"
+            include "../kernel09.def"
+
+
+               .area .vectors
+       ;
+       ;       At 0x100 as required by the Dragon ROM
+       ;
+                   jmp badswi_handler                  ; 0x100
+                   jmp badswi_handler                  ; 0x103
+                   jmp unix_syscall_entry              ; 0x106
+                   jmp fd_nmi_handler                  ; 0x109
+                   jmp interrupt_handler               ; 0x10C
+                   jmp firq_handler                    ; 0x10F
+
+
+       .area .text
+init_early:
+       rts
+init_hardware:
+       jsr size_ram
+       ; Turn on PIA  CB1 (50Hz interrupt)
+       lda 0xFF03
+       ora #1
+       sta 0xFF03
+       rts
+
+
+; old p6809.s stuff below
+
+            ; exported symbols
+            .globl init_early
+            .globl init_hardware
+            .globl _program_vectors
+           .globl _kernel_flag
+
+
+            ; imported symbols
+            .globl _ramsize
+            .globl _procmem
+            .globl unix_syscall_entry
+           .globl fd_nmi_handler
+
+            .area .common
+
+trapmsg:    .ascii "Trapdoor: SP="
+            .db 0
+trapmsg2:   .ascii ", PC="
+            .db 0
+tm_user_sp: .dw 0
+
+_trap_reboot:
+_trap_monitor:
+           cwai #0
+           bra _trap_monitor
+
+
+_di:
+           tfr cc,b            ; return the old irq state
+           orcc #0x10
+           rts
+_ei:
+           andcc #0xef
+           rts
+
+_irqrestore:                   ; B holds the data
+           tfr b,cc
+           rts
+
+            .area .text
+
+
+;
+;------------------------------------------------------------------------------
+; COMMON MEMORY PROCEDURES FOLLOW
+
+
+            .area .common
+
+;
+;      In the Dragon nx32 case our vectors live in a fixed block
+;      and is not banked out.
+;
+_program_vectors:
+           rts
+
+;
+;      FIXME:
+;
+firq_handler:
+badswi_handler:
+           rti
+
+; outchar: Simple writing to video memory
+
+outchar:
+           pshs x
+           ldx traceptr
+           cmpa #0x60
+            blo lc
+           suba #0x20
+lc          anda #0x3F
+           sta ,x+
+           stx traceptr
+           puls x,pc
+
+           .area .data
+
+_kernel_flag: .db 1
+traceptr:
+          .dw 0x0400
diff --git a/Kernel/platform-dragon-nx32/drivewire.s b/Kernel/platform-dragon-nx32/drivewire.s
new file mode 100644 (file)
index 0000000..babebeb
--- /dev/null
@@ -0,0 +1,139 @@
+;
+; DriveWire sector routines
+;
+; Copyright 2015 Tormod Volden
+; Copyright 2008 Boisy G. Pitre
+; Distributed under the GNU General Public License, version 2 or later.
+;
+
+       ; exported
+       .globl _dw_operation
+       .globl _dw_reset
+
+       .area .text
+
+_dw_reset:
+       ; maybe reinitalise PIA here?
+       ; and send DW_INIT request to server?
+       rts
+
+_dw_operation:
+       pshs y
+       ; get parameters from C, X points to cmd packet
+       ldy 4,s         ; driveptr
+       lda ,y          ; for now, contains minor = drive number directly
+       ldb ,x          ; write flag
+       ; buffer location into Y
+       ldy 3,x
+       ; sector number into X
+       ldx 1,x
+       tstb
+       bne @write
+       jsr dw_read_sector
+       bra @done
+@write  jsr dw_write_sector
+@done  bcs @err
+       bne @err
+       ldx #0
+@ret   puls y,pc
+@err   ldx #0xFFFF
+       bra @ret
+
+; Write a sector to the DriveWire server
+; Drive number in A, sector number in X, buffer location in Y
+; Sets carry or non-zero flags on error
+dw_write_sector:
+       ; header: OP, drive = A, LSN 23-16 = 0, LSN 15-8 and LSN 7-0 = X
+       clrb
+       pshs a,b,x
+       ldb #OP_WRITE
+       pshs b
+       ; send header
+       tfr s,x
+       pshs y          ; save buffer location
+       ldy #5
+       jsr DWWrite
+       ; send payload
+       ldx ,s
+       ldy #256
+       jsr DWWrite
+       ; calculate checksum of payload, backwards
+       exg x,y         ; Y is zero after DWWrite
+@sum   ldb ,-y
+       abx
+       cmpy ,s         ; buffer location start
+       bne @sum
+       stx ,s          ; checksum to send
+       tfr s,x
+       ldy #2
+       jsr DWWrite
+       ; get status byte from server into following byte
+       ldy #1
+       clra            ; clear carry bit for BECKER variant
+       jsr DWRead
+       leas 7,s
+       bcs @ret
+       bne @ret
+       ldb -5,s        ; received status byte (zero is success)
+@ret   rts
+
+;
+; Based on "DoRead" by Boisy G. Pitre from DWDOS hosted on toolshed.sf.net 
+; Read a sector from the DriveWire server
+; Drive number in A, 16-bit sector in X, buffer location in Y
+; Sets carry or non-zero flags on error
+
+dw_read_sector:
+         ; header: OP, drive = A, LSN 23-16 = 0, LSN 15-8 and LSN 7-0 = X
+         clrb
+         pshs  d,x,y
+         lda   #OP_READEX
+ReRead   pshs  a
+         leax  ,s
+        ldy   #$0005
+        lbsr  DWWrite
+        puls  a
+        ldx   4,s                      get read buffer pointer
+        ldy   #256                     read 256 bytes
+        ldd   #133*1                   1 second timeout
+        bsr   DWRead
+         bcs   ReadEx
+         bne   ReadEx
+; Send 2 byte checksum
+        pshs  y
+        leax  ,s
+        ldy   #2
+        lbsr  DWWrite
+        ldy   #1
+        ldd   #133*1
+        bsr   DWRead
+        leas  2,s
+        bcs   ReadEx
+        bne   ReadEx
+; Check received status byte
+        lda   ,s
+        beq   ReadEx
+        cmpa  #E_CRC
+        bne   ReadErr
+        lda   #OP_REREADEX
+        clr   ,s
+        bra   ReRead  
+ReadErr  comb                  ; set carry bit
+ReadEx  puls  d,x,y,pc
+
+; Used by DWRead and DWWrite
+IntMasks equ   $50
+NOINTMASK equ  1
+
+; Hardcode these for now so that we can use below files unmodified
+H6309    equ 0
+BECKER   equ 1
+ARDUINO  equ 0
+JMCPBCK  equ 0
+BAUD38400 equ 0
+
+; These files are copied almost as-is from HDB-DOS
+         include "dw.def"
+         include "dwread.s"
+         include "dwwrite.s"
+
diff --git a/Kernel/platform-dragon-nx32/dw.def b/Kernel/platform-dragon-nx32/dw.def
new file mode 100644 (file)
index 0000000..677f4c7
--- /dev/null
@@ -0,0 +1,70 @@
+********************************************************************
+*
+* Copied from HDB-DOS from toolshed.sf.net
+*
+* dwdefs - DriveWire Definitions File
+*
+* $Id: dwdefs.d,v 1.10 2010/02/21 06:24:47 aaronwolfe Exp $
+*
+* Ed.    Comments                                       Who YY/MM/DD
+* ------------------------------------------------------------------
+*   1    Started                                        BGP 03/04/03
+*   2    Added DWGLOBS area                             BGP 09/12/27
+
+         nam   dwdefs
+         ttl   DriveWire Definitions File
+
+* Addresses
+BBOUT       equ    $FF20
+BBIN        equ    $FF22
+
+* Opcodes
+OP_NOP      equ    $00         No-Op
+OP_RESET1   equ    $FE         Server Reset
+OP_RESET2   equ    $FF         Server Reset
+OP_RESET3   equ    $F8         Server Reset
+OP_DWINIT      equ        'Z           DriveWire dw3 init/OS9 boot
+OP_TIME     equ    '#          Current time requested
+OP_INIT     equ    'I          Init routine called
+OP_READ     equ    'R          Read one sector
+OP_REREAD   equ    'r          Re-read one sector
+OP_READEX   equ    'R+128      Read one sector
+OP_REREADEX equ    'r+128      Re-read one sector
+OP_WRITE    equ    'W          Write one sector
+OP_REWRIT   equ    'w          Re-write one sector
+OP_GETSTA   equ    'G          GetStat routine called
+OP_SETSTA   equ    'S          SetStat routine called
+OP_TERM     equ    'T          Term routine called
+OP_SERINIT  equ    'E
+OP_SERTERM  equ    'E+128
+
+* Printer opcodes
+OP_PRINT    equ    'P          Print byte to the print buffer
+OP_PRINTFLUSH equ  'F          Flush the server print buffer
+
+* Serial opcodes
+OP_SERREAD equ 'C
+OP_SERREADM equ 'c
+OP_SERWRITE equ 'C+128
+OP_SERGETSTAT equ 'D
+OP_SERSETSTAT equ 'D+128
+
+* for dw vfm
+OP_VFM equ 'V+128
+
+* WireBug opcodes (Server-initiated)
+OP_WIREBUG_MODE  equ   'B
+* WireBug opcodes (Server-initiated)
+OP_WIREBUG_READREGS   equ  'R  Read the CoCo's registers
+OP_WIREBUG_WRITEREGS  equ  'r  Write the CoCo's registers
+OP_WIREBUG_READMEM    equ  'M  Read the CoCo's memory
+OP_WIREBUG_WRITEMEM   equ  'm  Write the CoCo's memory
+OP_WIREBUG_GO         equ  'G  Tell CoCo to get out of WireBug mode and continue execution
+
+* VPort opcodes (CoCo-initiated)
+OP_VPORT_READ         equ  'V
+OP_VPORT_WRITE        equ  'v
+
+* Error definitions
+E_CRC      equ   $F3            Same as NitrOS-9 E$CRC
+
diff --git a/Kernel/platform-dragon-nx32/dwread.s b/Kernel/platform-dragon-nx32/dwread.s
new file mode 100644 (file)
index 0000000..1b4c587
--- /dev/null
@@ -0,0 +1,341 @@
+*******************************************************
+*
+* Copied from HDB-DOS from toolshed.sf.net
+* The original code is public domain
+*
+* DWRead
+*    Receive a response from the DriveWire server.
+*    Times out if serial port goes idle for more than 1.4 (0.7) seconds.
+*    Serial data format:  1-8-N-1
+*    4/12/2009 by Darren Atkinson
+*
+* Entry:
+*    X  = starting address where data is to be stored
+*    Y  = number of bytes expected
+*
+* Exit:
+*    CC = carry set on framing error, Z set if all bytes received
+*    X  = starting address of data received
+*    Y  = checksum
+*    U is preserved.  All accumulators are clobbered
+*
+
+          IFNE ARDUINO
+* Note: this is an optimistic routine. It presumes that the server will always be there, and
+* has NO timeout fallback. It is also very short and quick.
+DWRead    clra                          ; clear Carry (no framing error)
+          pshs   u,x,cc              ; preserve registers
+          leau   ,x
+          ldx    #$0000
+loop@     tst    $FF51                  ; check for CA1 bit (1=Arduino has byte ready)
+          bpl    loop@                  ; loop if not set
+          ldb    $FF50                  ; clear CA1 bit in status register
+          stb    ,u+                    ; save off acquired byte
+          abx                           ; update checksum
+          leay   ,-y
+          bne    loop@
+
+          leay      ,x                  ; return checksum in Y
+          puls      cc,x,u,pc        ; restore registers and return
+
+          ELSE
+
+          IFNE JMCPBCK
+* NOTE: There is no timeout currently on here...
+DWRead    clra                          ; clear Carry (no framing error)
+          deca                          ; clear Z flag, A = timeout msb ($ff)
+          tfr       cc,b
+          pshs      u,x,dp,b,a          ; preserve registers, push timeout msb
+          leau   ,x
+          ldx    #$0000
+          IFEQ   NOINTMASK
+          orcc   #IntMasks
+          ENDC
+loop@     ldb    $FF4C
+          bitb   #$02
+          beq    loop@
+          ldb    $FF44
+          stb    ,u+
+          abx
+          leay   ,-y
+          bne    loop@
+
+          tfr    x,y
+          ldb    #0
+          lda    #3
+          leas      1,s                 ; remove timeout msb from stack
+          inca                          ; A = status to be returned in C and Z
+          ora       ,s                  ; place status information into the..
+          sta       ,s                  ; ..C and Z bits of the preserved CC
+          leay      ,x                  ; return checksum in Y
+          puls      cc,dp,x,u,pc        ; restore registers and return
+          ELSE
+          IFNE BECKER
+          IFNDEF BCKSTAT
+BCKSTAT   equ   $FF41
+          ENDC
+          IFNDEF BCKPORT
+BCKPORT   equ   $FF42
+          ENDC
+* NOTE: There is no timeout currently on here...
+DWRead    clra                          ; clear Carry (no framing error)
+          deca                          ; clear Z flag, A = timeout msb ($ff)
+          tfr       cc,b
+          pshs      u,x,dp,b,a          ; preserve registers, push timeout msb
+          leau   ,x
+          ldx    #$0000
+          IFEQ   NOINTMASK
+          orcc   #IntMasks
+          ENDC
+loop@     ldb    BCKSTAT
+          bitb   #$02
+          beq    loop@
+          ldb    BCKPORT
+          stb    ,u+
+          abx
+          leay   ,-y
+          bne    loop@
+          tfr    x,y
+          ldb    #0
+          lda    #3
+timeout   leas      1,s                 ; remove timeout msb from stack
+          inca                          ; A = status to be returned in C and Z
+          ora       ,s                  ; place status information into the..
+          sta       ,s                  ; ..C and Z bits of the preserved CC
+          leay      ,x                  ; return checksum in Y
+          puls      cc,dp,x,u,pc        ; restore registers and return
+          ENDC
+          ENDC
+          ENDC
+
+          IFEQ BECKER+JMCPBCK+ARDUINO
+          IFNE BAUD38400
+*******************************************************
+* 38400 bps using 6809 code and timimg
+*******************************************************
+
+DWRead    clra                          ; clear Carry (no framing error)
+          deca                          ; clear Z flag, A = timeout msb ($ff)
+          tfr       cc,b
+          pshs      u,x,dp,b,a          ; preserve registers, push timeout msb
+          IFEQ      NOINTMASK
+          orcc      #IntMasks           ; mask interrupts
+          ENDC
+          tfr       a,dp                ; set direct page to $FFxx
+          setdp     $ff
+          leau      ,x                  ; U = storage ptr
+          ldx       #0                  ; initialize checksum
+          adda      #2                  ; A = $01 (serial in mask), set Carry
+
+* Wait for a start bit or timeout
+rx0010    bcc       rxExit              ; exit if timeout expired
+          ldb       #$ff                ; init timeout lsb
+rx0020    bita      <BBIN               ; check for start bit
+          beq       rxByte              ; branch if start bit detected
+          subb      #1                  ; decrement timeout lsb
+          bita      <BBIN
+          beq       rxByte
+          bcc       rx0020              ; loop until timeout lsb rolls under
+          bita      <BBIN
+          beq       rxByte
+          addb      ,s                  ; B = timeout msb - 1
+          bita      <BBIN
+          beq       rxByte
+          stb       ,s                  ; store decremented timeout msb
+          bita      <BBIN
+          bne       rx0010              ; loop if still no start bit
+
+* Read a byte
+rxByte    leay      ,-y                 ; decrement request count
+          ldd       #$ff80              ; A = timeout msb, B = shift counter
+          sta       ,s                  ; reset timeout msb for next byte
+rx0030    exg       a,a
+          nop
+          lda       <BBIN               ; read data bit
+          lsra                          ; shift into carry
+          rorb                          ; rotate into byte accumulator
+          lda       #$01                ; prep stop bit mask
+          bcc       rx0030              ; loop until all 8 bits read
+
+          stb       ,u+                 ; store received byte to memory
+          abx                           ; update checksum
+          ldb       #$ff                ; set timeout lsb for next byte
+          anda      <BBIN               ; read stop bit
+          beq       rxExit              ; exit if framing error
+          leay      ,y                  ; test request count
+          bne       rx0020              ; loop if another byte wanted
+          lda       #$03                ; setup to return SUCCESS
+
+* Clean up, set status and return
+rxExit    leas      1,s                 ; remove timeout msb from stack
+          inca                          ; A = status to be returned in C and Z
+          ora       ,s                  ; place status information into the..
+          sta       ,s                  ; ..C and Z bits of the preserved CC
+          leay      ,x                  ; return checksum in Y
+          puls      cc,dp,x,u,pc        ; restore registers and return
+          setdp     $00
+
+
+          ELSE
+          IFNE H6309
+*******************************************************
+* 57600 (115200) bps using 6309 native mode
+*******************************************************
+
+DWRead    clrb                          ; clear Carry (no framing error)
+          decb                          ; clear Z flag, B = $FF
+          pshs      u,x,dp,cc           ; preserve registers
+          IFEQ      NOINTMASK
+          orcc      #IntMasks           ; mask interrupts
+          ENDC
+*         ldmd      #1                  ; requires 6309 native mode
+          tfr       b,dp                ; set direct page to $FFxx
+          setdp     $ff
+          leay      -1,y                ; adjust request count
+          leau      ,x                  ; U = storage ptr
+          tfr       0,x                 ; initialize checksum
+          lda       #$01                ; A = serial in mask
+          bra       rx0030              ; go wait for start bit
+
+* Read a byte
+rxByte    sexw                          ; 4 cycle delay
+          ldw       #$006a              ; shift counter and timing flags
+          clra                          ; clear carry so next will branch
+rx0010    bcc       rx0020              ; branch if even bit number (15 cycles)
+          nop                           ; extra (16th) cycle
+rx0020    lda       <BBIN               ; read bit
+          lsra                          ; move bit into carry
+          rorb                          ; rotate bit into byte accumulator
+          lda       #0                  ; prep A for 8th data bit
+          lsrw                          ; bump shift count, timing bit to carry
+          bne       rx0010              ; loop until 7th data bit has been read
+          incw                          ; W = 1 for subtraction from Y
+          inca                          ; A = 1 for reading bit 7
+          anda      <BBIN               ; read bit 7
+          lsra                          ; move bit 7 into carry, A = 0
+          rorb                          ; byte is now complete
+          stb       ,u+                 ; store received byte to memory
+          abx                           ; update checksum
+          subr      w,y                 ; decrement request count
+          inca                          ; A = 1 for reading stop bit
+          anda      <BBIN               ; read stop bit
+          bls       rxExit              ; exit if completed or framing error
+
+* Wait for a start bit or timeout
+rx0030    clrw                          ; initialize timeout counter
+rx0040    bita      <BBIN               ; check for start bit
+          beq       rxByte              ; branch if start bit detected
+          addw      #1                  ; bump timeout counter
+          bita      <BBIN
+          beq       rxByte
+          bcc       rx0040              ; loop until timeout rolls over
+          lda       #$03                ; setup to return TIMEOUT status
+
+* Clean up, set status and return
+rxExit    beq       rx0050              ; branch if framing error
+          eora      #$02                ; toggle SUCCESS flag
+rx0050    inca                          ; A = status to be returned in C and Z
+          ora       ,s                  ; place status information into the..
+          sta       ,s                  ; ..C and Z bits of the preserved CC
+          leay      ,x                  ; return checksum in Y
+          puls      cc,dp,x,u,pc        ; restore registers and return
+          setdp     $00
+
+
+          ELSE
+*******************************************************
+* 57600 (115200) bps using 6809 code and timimg
+*******************************************************
+
+DWRead    clra                          ; clear Carry (no framing error)
+          deca                          ; clear Z flag, A = timeout msb ($ff)
+          tfr       cc,b
+          pshs      u,x,dp,b,a          ; preserve registers, push timeout msb
+          IFEQ      NOINTMASK
+          orcc      #IntMasks           ; mask interrupts
+          ENDC
+          tfr       a,dp                ; set direct page to $FFxx
+          ;setdp     $ff
+          leau      ,x                  ; U = storage ptr
+          ldx       #0                  ; initialize checksum
+          lda       #$01                ; A = serial in mask
+          bra       rx0030              ; go wait for start bit
+
+* Read a byte
+rxByte    leau      1,u                 ; bump storage ptr
+          leay      ,-y                 ; decrement request count
+          lda       <BBIN               ; read bit 0
+          lsra                          ; move bit 0 into Carry
+          ldd       #$ff20              ; A = timeout msb, B = shift counter
+          sta       ,s                  ; reset timeout msb for next byte
+          rorb                          ; rotate bit 0 into byte accumulator
+rx0010    lda       <BBIN               ; read bit (d1, d3, d5)
+          lsra
+          rorb
+          bita      1,s                 ; 5 cycle delay
+          bcs       rx0020              ; exit loop after reading bit 5
+          lda       <BBIN               ; read bit (d2, d4)
+          lsra
+          rorb
+          leau      ,u
+          bra       rx0010
+
+rx0020    lda       <BBIN               ; read bit 6
+          lsra
+          rorb
+          leay      ,y                  ; test request count
+          beq       rx0050              ; branch if final byte of request
+          lda       <BBIN               ; read bit 7
+          lsra
+          rorb                          ; byte is now complete
+          stb       -1,u                ; store received byte to memory
+          abx                           ; update checksum
+          lda       <BBIN               ; read stop bit
+          anda      #$01                ; mask out other bits
+          beq       rxExit              ; exit if framing error
+
+* Wait for a start bit or timeout
+rx0030    bita      <BBIN               ; check for start bit
+          beq       rxByte              ; branch if start bit detected
+          bita      <BBIN               ; again
+          beq       rxByte
+          ldb       #$ff                ; init timeout lsb
+rx0040    bita      <BBIN
+          beq       rxByte
+          subb      #1                  ; decrement timeout lsb
+          bita      <BBIN
+          beq       rxByte
+          bcc       rx0040              ; loop until timeout lsb rolls under
+          bita      <BBIN
+          beq       rxByte
+          addb      ,s                  ; B = timeout msb - 1
+          bita      <BBIN
+          beq       rxByte
+          stb       ,s                  ; store decremented timeout msb
+          bita      <BBIN
+          beq       rxByte
+          bcs       rx0030              ; loop if timeout hasn't expired
+          bra       rxExit              ; exit due to timeout
+
+rx0050    lda       <BBIN               ; read bit 7 of final byte
+          lsra
+          rorb                          ; byte is now complete
+          stb       -1,u                ; store received byte to memory
+          abx                           ; calculate final checksum
+          lda       <BBIN               ; read stop bit
+          anda      #$01                ; mask out other bits
+          ora       #$02                ; return SUCCESS if no framing error
+
+* Clean up, set status and return
+rxExit    leas      1,s                 ; remove timeout msb from stack
+          inca                          ; A = status to be returned in C and Z
+          ora       ,s                  ; place status information into the..
+          sta       ,s                  ; ..C and Z bits of the preserved CC
+          leay      ,x                  ; return checksum in Y
+          puls      cc,dp,x,u,pc        ; restore registers and return
+          ;setdp     $00
+
+          ENDC
+          ENDC
+          ENDC
+
diff --git a/Kernel/platform-dragon-nx32/dwwrite.s b/Kernel/platform-dragon-nx32/dwwrite.s
new file mode 100644 (file)
index 0000000..d262968
--- /dev/null
@@ -0,0 +1,196 @@
+*******************************************************
+*
+* Copied from HDB-DOS from toolshed.sf.net
+* The original code is public domain
+*
+* DWWrite
+*    Send a packet to the DriveWire server.
+*    Serial data format:  1-8-N-1
+*    4/12/2009 by Darren Atkinson
+*
+* Entry:
+*    X  = starting address of data to send
+*    Y  = number of bytes to send
+*
+* Exit:
+*    X  = address of last byte sent + 1
+*    Y  = 0
+*    All others preserved
+*
+
+
+          IFNE ARDUINO
+DWWrite   pshs      a                  ; preserve registers
+txByte
+          lda       ,x+                ; get byte from buffer
+          sta       $FF52              ; put it to PIA
+loop@     tst       $FF53              ; check status register
+          bpl       loop@              ; until CB1 is set by Arduino, continue looping
+          tst       $FF52              ; clear CB1 in status register
+          leay      -1,y                ; decrement byte counter
+          bne       txByte              ; loop if more to send
+
+          puls      a,pc                ; restore registers and return
+
+          ELSE
+
+          IFNE JMCPBCK
+DWWrite   pshs      d,cc              ; preserve registers
+          IFEQ      NOINTMASK
+          orcc      #IntMasks           ; mask interrupts
+          ENDC
+txByte
+          lda       ,x+
+          sta       $FF44
+          leay      -1,y                ; decrement byte counter
+          bne       txByte              ; loop if more to send
+
+          puls      cc,d,pc           ; restore registers and return
+
+          ELSE
+          IFNE BECKER
+          IFNDEF BCKPORT
+BCKPORT   equ   $FF42
+          ENDC
+DWWrite   pshs      d,cc              ; preserve registers
+          IFEQ      NOINTMASK
+          orcc      #IntMasks           ; mask interrupts
+          ENDC
+;          ldu       #BBOUT              ; point U to bit banger out register
+;          lda       3,u                 ; read PIA 1-B control register
+;          anda      #$f7                ; clear sound enable bit
+;          sta       3,u                 ; disable sound output
+;          fcb       $8c                 ; skip next instruction
+
+txByte
+          lda       ,x+
+          sta       BCKPORT
+          leay      -1,y                ; decrement byte counter
+          bne       txByte              ; loop if more to send
+
+          puls      cc,d,pc           ; restore registers and return
+          ENDC
+          ENDC
+          ENDC
+
+          IFEQ BECKER+JMCPBCK+ARDUINO
+          IFNE BAUD38400
+*******************************************************
+* 38400 bps using 6809 code and timimg
+*******************************************************
+
+DWWrite   pshs      u,d,cc              ; preserve registers
+          IFEQ      NOINTMASK
+          orcc      #IntMasks           ; mask interrupts
+          ENDC
+          ldu       #BBOUT              ; point U to bit banger out register
+          lda       3,u                 ; read PIA 1-B control register
+          anda      #$f7                ; clear sound enable bit
+          sta       3,u                 ; disable sound output
+          fcb       $8c                 ; skip next instruction
+
+txByte    stb       ,--u                ; send stop bit
+          leau      ,u+
+          lda       #8                  ; counter for start bit and 7 data bits
+          ldb       ,x+                 ; get a byte to transmit
+          lslb                          ; left rotate the byte two positions..
+          rolb                          ; ..placing a zero (start bit) in bit 1
+tx0010    stb       ,u++                ; send bit
+          tst       ,--u
+          rorb                          ; move next bit into position
+          deca                          ; decrement loop counter
+          bne       tx0010              ; loop until 7th data bit has been sent
+          leau      ,u
+          stb       ,u                  ; send bit 7
+          lda       ,u++
+          ldb       #$02                ; value for stop bit (MARK)
+          leay      -1,y                ; decrement byte counter
+          bne       txByte              ; loop if more to send
+
+          stb       ,--u                ; leave bit banger output at MARK
+          puls      cc,d,u,pc           ; restore registers and return
+
+          ELSE
+
+          IFNE H6309
+*******************************************************
+* 57600 (115200) bps using 6309 native mode
+*******************************************************
+
+DWWrite   pshs      u,d,cc              ; preserve registers
+          IFEQ      NOINTMASK
+          orcc      #IntMasks           ; mask interrupts
+          ENDC
+*         ldmd      #1                  ; requires 6309 native mode
+          ldu       #BBOUT+1            ; point U to bit banger out register +1
+          aim       #$f7,2,u            ; disable sound output
+          lda       #8                  ; counter for start bit and 7 data bits
+          fcb       $8c                 ; skip next instruction
+
+txByte    stb       -1,u                ; send stop bit
+tx0010    ldb       ,x+                 ; get a byte to transmit
+          lslb                          ; left rotate the byte two positions..
+          rolb                          ; ..placing a zero (start bit) in bit 1
+          bra       tx0030
+
+tx0020    bita      #1                  ; even or odd bit number ?
+          beq       tx0040              ; branch if even (15 cycles)
+tx0030    nop                           ; extra (16th) cycle
+tx0040    stb       -1,u                ; send bit
+          rorb                          ; move next bit into position
+          deca                          ; decrement loop counter
+          bne       tx0020              ; loop until 7th data bit has been sent
+          leau      ,u+
+          stb       -1,u                ; send bit 7
+          ldd       #$0802              ; A = loop counter, B = MARK value
+          leay      -1,y                ; decrement byte counter
+          bne       txByte              ; loop if more to send
+
+          stb       -1,u                ; final stop bit
+          puls      cc,d,u,pc           ; restore registers and return
+
+          ELSE
+*******************************************************
+* 57600 (115200) bps using 6809 code and timimg
+*******************************************************
+
+DWWrite   pshs      dp,d,cc             ; preserve registers
+          IFEQ      NOINTMASK
+          orcc      #IntMasks           ; mask interrupts
+          ENDC
+          ldd       #$04ff              ; A = loop counter, B = $ff
+          tfr       b,dp                ; set direct page to $FFxx
+          ;setdp     $ff
+          ldb       <$ff23              ; read PIA 1-B control register
+          andb      #$f7                ; clear sound enable bit
+          stb       <$ff23              ; disable sound output
+          fcb       $8c                 ; skip next instruction
+
+txByte    stb       <BBOUT              ; send stop bit
+          ldb       ,x+                 ; get a byte to transmit
+          nop
+          lslb                          ; left rotate the byte two positions..
+          rolb                          ; ..placing a zero (start bit) in bit 1
+tx0020    stb       <BBOUT              ; send bit (start bit, d1, d3, d5)
+          rorb                          ; move next bit into position
+          exg       a,a
+          nop
+          stb       <BBOUT              ; send bit (d0, d2, d4, d6)
+          rorb                          ; move next bit into position
+          leau      ,u
+          deca                          ; decrement loop counter
+          bne       tx0020              ; loop until 7th data bit has been sent
+
+          stb       <BBOUT              ; send bit 7
+          ldd       #$0402              ; A = loop counter, B = MARK value
+          leay      ,-y                 ; decrement byte counter
+          bne       txByte              ; loop if more to send
+
+          stb       <BBOUT              ; leave bit banger output at MARK
+          puls      cc,d,dp,pc          ; restore registers and return
+          ;setdp     $00
+
+          ENDC
+          ENDC
+          ENDC
+
diff --git a/Kernel/platform-dragon-nx32/floppy.s b/Kernel/platform-dragon-nx32/floppy.s
new file mode 100644 (file)
index 0000000..b039889
--- /dev/null
@@ -0,0 +1,399 @@
+;
+;      Core floppy routines for the Dragon
+;
+
+       .globl  fd_nmi_handler
+       .globl  nmi_handler
+
+       .globl _fd_reset
+       .globl _fd_operation
+       .globl _fd_motor_on
+       .globl _fd_motor_off
+;
+;      MMIO for the floppy controller
+;
+;      For a Dragon cartridge
+;
+FDCCTRL        EQU     0xFF48
+;
+;      0-1: drive select
+;      2: motor on
+;      3: density
+;      4: precomp
+;      5: nmi mode
+;
+FDCREG EQU     0xFF40
+FDCTRK EQU     0xFF41
+FDCSEC EQU     0xFF42
+FDCDATA        EQU     0xFF43
+
+;
+;      Structures we use
+;
+;
+;      Per disk structure to hold device state
+;
+TRKCOPY        EQU     0
+
+;
+;      Command issue
+;
+CMD    EQU     0
+TRACK  EQU     1
+SECTOR EQU     2
+DIRECT EQU     3               ; 0 = read 2 = write 1 = status
+DATA   EQU     4
+
+       .area   .text
+;
+;      NMI handling for the floppy drive
+;
+fd_nmi_handler:
+       lda     FDCREG
+       ldy     nmivector
+       sty     10,s            ; overwrite the return PC
+       ldy     #nmi_handler
+       sty     nmivector       ; unexpected NMI trap
+       rti
+
+;
+;      Snooze to give the drive controller time to think
+;
+disknap:
+       ldx     #8750           ; assuming 0.9MHz
+disknapw:
+       leax    -1,x
+       bne     disknapw
+       rts
+
+;
+;      Wait for the drive controller to become ready
+;
+waitdisk:
+       ldx     #0              ; wait timer
+waitdisk_l:
+       leax    -1,x
+       beq     forceint        ; try forcing an interrupt
+       lda     <FDCREG
+       bita    #0x01
+       bne     waitdisk_l
+       rts                     ; done, idle EQ true
+forceint:                      ; no response, bigger stick
+       lda     #0xD0           ; reset
+       sta     <FDCREG
+       nop
+       exg     a,a
+       exg     a,a
+       lda     <FDCREG         ; read to reset int status
+       ; ?? what to do next ??
+       lda     #0xff           ; force NEQ
+       rts
+
+;      Set up the disk. On entry y points to our per drive data and
+;      x points to the command block
+;
+fdsetup:
+       lda     TRKCOPY,y
+       sta     <FDCTRK         ; reset track register
+       pshs    x,y
+       cmpa    TRACK,x         ; target track
+;
+;      FIXME: what have we screwed up here so this always branches ???
+;
+;      beq     fdiosetup
+
+       sta     <FDCTRK         ; target
+       ;
+       ;       So we can verify
+       ;
+       lda     SECTOR,x
+       sta     <FDCSEC
+       ;
+       ;       Need to seek the disk
+       ;
+       lda     #0x14
+       sta     <FDCREG         ; seek
+       nop
+       exg     a,a
+       exg     a,a
+       jsr     waitdisk
+       bne     setuptimeout
+       jsr     disknap
+       anda    #0x18           ; error bits
+       beq     fdiosetup
+       ; seek failed, not good
+setuptimeout:                  ; NE = bad
+       puls    x,y
+       ldb     <FDCTRK         ; we have no idea where we are
+       stb     TRKCOPY,y       ; so remember what the drive reported
+       rts
+;
+;      Head in the right place
+;
+fdiosetup:
+       puls    x,y
+       lda     TRACK,x
+       sta     TRKCOPY,y       ; remember we arrived
+       ldb     fdcctrl
+       andb    #0xEF           ; precomp
+       cmpa    #22
+       blo     noprecomp
+       orb     #0x10
+noprecomp:
+       orb     #0x20           ; NMI/halt on
+       stb     <FDCCTRL                ; precomp configured
+       lda     SECTOR,x
+       sta     <FDCSEC
+       lda     <FDCREG         ; clear any pending int
+       lda     CMD,x           ; command to issue
+       ldy     #fdxferdone
+       sty     nmivector       ; so our NMI handler will clean up
+       ldy     #0              ; timeout handling
+       orcc    #0x50           ; irqs off or we'll miss bytes
+       sta     <FDCREG         ; issue the command
+       nop                     ; give the FDC a moment to think
+       exg     a,a
+       exg     a,a
+       ldb     DIRECT,x
+       cmpb    #0x01           ; read ?
+       beq     fdio_in
+       cmpb    #0x02
+       beq     wait_drq        ; write
+;
+;      Status registers
+;
+fdxferdone:
+       ldb     fdcctrl
+       stb     <FDCCTRL
+       lda     <FDCREG
+       anda    #0x7C           ; Returns with A holding the status bits
+       rts
+;
+;      Relies on B being 2...
+;
+wait_drq:
+       bitb    <FDCREG
+       bne     drq_on
+       leay    -1,y
+       bne     wait_drq
+       ;
+       ;       Timed out - reset etc to clean up ??
+       ;
+       lda     #0xff           ; our error code
+       rts
+
+;
+;      Once the controller decides it is finished it will flag an NMI
+;      and the NMI will switch the PC on the return to fdxferdone.
+;
+;      Begin the actual copy to disk
+;
+drq_on:
+       ldx     DATA,x
+       lda     ,x+
+       bra     drq_go
+drq_loop:
+       sync
+drq_go:
+       sta     <FDCDATA
+       lda     ,x+
+       bra     drq_loop
+
+;
+;      Read from the disk
+;
+fdio_in:
+       ldx     DATA,x
+fdio_dwait:
+       ldb     <FDCREG
+       bitb    #0x02
+       bne     fdio_go
+       leay    -1,y
+       bne     fdio_dwait
+       ldb     fdcctrl
+       stb     <FDCCTRL
+       lda     #0xff
+       rts
+;
+;      Now do the data
+;
+fdio_loop:
+       sync
+fdio_go:
+       ldb     <0xFF22         ; clear the FIR (PIA1DB)
+       lda     <FDCDATA
+       sta     ,x+
+       bra     fdio_loop
+
+;
+;      PIA management
+;
+piasave:
+       pshs    x,y
+       ldx     #0xFF01         ; PIA0CRA
+       ldy     #pia_stash
+       lda     ,x
+       sta     ,y+
+       anda    #0xFC
+       sta     ,x++            ; move on to 0CRB
+       lda     ,x
+       sta     ,y+
+       anda    #0xFC
+       sta     ,x
+       leax    0x1e,x          ; PIA1CRA
+       lda     ,x
+       sta     ,y+
+       anda    #0xFC
+       sta     ,x++            ; on to PIA1CRB
+       lda     ,x
+       sta     ,y
+       ora     #0x37
+       sta     ,x              ; floppy FIR enabled
+       puls    x,y,pc
+
+piaload:
+       ; Must leave B untouched
+       pshs    x,y
+       ldx     #0xFF01
+       ldy     #pia_stash
+       lda     ,y+
+       sta     ,x++
+       lda     ,y+
+       sta     ,x
+       leax    0x1e,x
+       lda     ,y+
+       sta     ,x++
+       lda     ,y+
+       sta     ,x
+       puls    x,y,pc
+;
+;      C glue interface.
+;
+;      Because of the brain dead memory paging we dump the bits into
+;      kernel space always. The thought of taking an NMI while in the
+;      user memory and bank flipping to recover is just too odious !
+;
+
+;
+;      Reset to track 0, wait for the command then idle
+;
+;      fd_reset(uint16_t *drive)
+;
+_fd_reset:
+       pshs    x,y,dp
+       lda     #0xFF
+       tfr     a,dp
+       ldb     fdcctrl
+       stb     <FDCCTRL
+       lda     #0x01
+       sta     <FDCSEC
+       lda     #0x00           ; seek
+       sta     <FDCTRK
+       sta     <FDCREG
+       nop
+       exg     a,a
+       exg     a,a
+       jsr     waitdisk
+       jsr     disknap
+       ; FIXME: longer delay goes here ???
+       cmpa    #0xff
+       beq     rstff           ; Total fail
+       anda    #0x10           ; Error bit from the reset
+rstff:
+       tfr     a,b
+       puls    x,y,dp,pc
+;
+;      fd_operation(uint16_t *cmd, uint16_t *drive)
+;
+;      The caller must ensure the drive has been selected and the motor is
+;      running.
+;
+_fd_operation:
+       pshs y,cc,dp
+       lda     #0xFF
+       tfr     a,dp
+       orcc    #0x40           ; Make sure FIR is off
+       jsr     piasave
+       ldy     6,s             ; Drive struct
+       jsr     fdsetup         ; Set up for a command
+       tfr     a,b             ; Status code or 0xFF for total failure
+       bsr     piaload
+       puls    y,cc,dp,pc      ; Restore IRQ state etc
+;
+;      C interface fd_motor_on(uint8 drivesel)
+;
+;      Selects this drive and turns on the motors
+;
+_fd_motor_on:
+       pshs    y,dp
+       lda     #0xFF
+       tfr     a,dp
+
+       ;
+       ;       Select drive B, turn on motor if needed
+       ;
+       lda     motor_running   ; nothing selected
+       beq     notsel
+       cmpb    curdrive        ; check if we are good
+       bne     notsel
+;
+;      All is actually good
+;
+motor_was_on:
+       ldb     #0
+       puls    y,dp,pc
+;
+;      Select our drive
+;
+notsel:
+       orb     #0x04           ; motor on, single density + our drive id
+       stb     <FDCCTRL
+       stb     fdcctrl
+       bita    #0x4
+       bne     motor_was_on
+       jsr     disknap
+       ; FIXME: longer motor spin up delay goes here
+       jsr     waitdisk
+       tfr     a,b             ; return in the right place
+       puls    y,dp,pc
+
+;
+;      C interface fd_motor_off(void)
+;
+;      Turns off the drive motors, deselects all drives
+;
+_fd_motor_off:
+       pshs    y,dp
+       lda     #0xFF
+       tfr     a,dp
+
+;
+;      Deselect drives and turn off motor
+;
+       ldb     motor_running
+       beq     no_work_motor
+       ; Should we seek to track 0 ?
+       ldb     <FDCCTRL
+       andb    #0xF0
+       stb     <FDCCTRL
+       clr     motor_running
+no_work_motor:
+       puls y,dp,pc
+
+       .area .data
+
+nmivector:
+       .word   nmi_handler
+curdrive:
+       .byte   0xff
+
+       .area .bss
+motor_running:
+       .byte   0
+fdcctrl:
+       .byte   0
+pia_stash:
+       .byte   0
+       .byte   0
+       .byte   0
+       .byte   0
\ No newline at end of file
diff --git a/Kernel/platform-dragon-nx32/fuzix.link b/Kernel/platform-dragon-nx32/fuzix.link
new file mode 100644 (file)
index 0000000..4721232
--- /dev/null
@@ -0,0 +1,14 @@
+define basesympat __sectionbase_%s__
+define lensympat __sectionlen_%s__
+section .vectors load 0x0100
+section .start load 0x0800
+section .common
+section .text2
+section .discard
+section .udata load 0x7D00
+section .text load 0x8010
+section .bss high 0xFC00
+section .data
+section .videodata
+section .video
+entry start
diff --git a/Kernel/platform-dragon-nx32/kernel.def b/Kernel/platform-dragon-nx32/kernel.def
new file mode 100644 (file)
index 0000000..daed265
--- /dev/null
@@ -0,0 +1,21 @@
+; UZI mnemonics for memory addresses etc
+
+U_DATA                      equ 0x7D00       ; (this is struct u_data from kernel.h)
+U_DATA__TOTALSIZE           equ 0x300        ; 256+256+256 bytes.
+
+U_DATA_STASH                equ 0xFC00       ; FC00-FEFF
+
+
+; Have these defined so that lowlevel-6809.s can be used as-is
+SAM_USER macro
+       endm
+
+SAM_KERNEL macro
+       endm
+
+SAM_SAVE macro
+       endm
+
+SAM_RESTORE macro
+       endm
+
diff --git a/Kernel/platform-dragon-nx32/libc.c b/Kernel/platform-dragon-nx32/libc.c
new file mode 100644 (file)
index 0000000..a4cb9dd
--- /dev/null
@@ -0,0 +1,25 @@
+#include "cpu.h"
+
+void *memcpy(void *d, const void *s, size_t sz)
+{
+  unsigned char *dp = d;
+  const unsigned char *sp = s;
+  while(sz--)
+    *dp++=*sp++;
+  return d;
+}
+
+void *memset(void *d, int c, size_t sz)
+{
+  unsigned char *p = d;
+  while(sz--)
+    *p++ = c;
+  return d;
+}
+
+size_t strlen(const char *p)
+{
+  const char *e = p;
+  while(*e++);
+  return e-p-1;
+}
diff --git a/Kernel/platform-dragon-nx32/main.c b/Kernel/platform-dragon-nx32/main.c
new file mode 100644 (file)
index 0000000..e7168fb
--- /dev/null
@@ -0,0 +1,40 @@
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+
+uint8_t membanks;
+
+void platform_idle(void)
+{
+}
+
+void do_beep(void)
+{
+}
+
+/*
+ * Map handling: We have flexible paging. Each map table consists of a set of pages
+ * with the last page repeated to fill any holes.
+ */
+
+void pagemap_init(void)
+{
+       int i;
+       /* map bank 1 last for init, leave 0 for kernel */
+       for (i = membanks - 1; i > 0; i--)
+               pagemap_add(i);
+}
+
+void map_init(void)
+{
+}
+
+unsigned char vt_mangle_6847(unsigned char c)
+{
+       if (c >= 96)
+               c -= 32;
+       c &= 0x3F;
+       return c;
+}
diff --git a/Kernel/platform-dragon-nx32/mem-nx32.s b/Kernel/platform-dragon-nx32/mem-nx32.s
new file mode 100644 (file)
index 0000000..39d7955
--- /dev/null
@@ -0,0 +1,101 @@
+;
+; memory banking for external memory cartridge
+;
+; Copyright 2015 Tormod Volden
+;
+
+       .module mem_nx32
+
+       ; exported
+       .globl size_ram
+       .globl map_kernel
+       .globl map_process
+       .globl map_process_a
+       .globl map_process_always
+       .globl map_save
+       .globl map_restore
+
+       ; imported
+       .globl _ramsize
+       .globl _procmem
+       .globl _membanks
+
+banksel        equ 0xFFBF
+bankoff        equ 0xFFBE
+
+       include "kernel.def"
+       include "../kernel09.def"
+
+       .area .discard
+
+; Sets ramsize, procmem, membanks
+size_ram
+       ldx #0x8000     ; test location, no code can be preloaded here!
+       clra
+zbank  sta banksel     ; clear test byte on all possible banks
+       clr ,x
+       inca
+       cmpa #16
+       blo zbank
+       clra            ; now test writing to banks
+       ldb #0xA5
+size_next
+       sta banksel
+       cmpb ,x         ; if value was there already we have probably wrapped around
+       beq size_nonram
+       stb ,x
+       cmpb ,x
+       bne size_nonram
+       inca
+       cmpa #16
+       bne size_next
+size_nonram
+       clr banksel     ; leave bank 0 selected and kdata mapped in
+       sta _membanks
+       inca            ; add the internal 32K to the count
+       ldb #32
+       mul
+       std _ramsize
+       subd #48        ; whatever the kernel occupies
+       std _procmem
+       rts
+
+       .area .common
+
+map_kernel
+       pshs a
+       lda #0  
+       sta map_copy
+       sta banksel
+       puls a,pc
+
+map_process
+       tsta
+       beq map_kernel
+map_process_a
+       sta map_copy
+       sta banksel
+       rts
+
+map_process_always
+       pshs a
+       lda U_DATA__U_PAGE+1            ; LSB of 16-bit page
+map_set_a
+       sta map_copy
+       sta banksel
+       puls a,pc
+       
+map_save
+       pshs a
+       lda map_copy
+       sta map_store
+       puls a,pc
+
+map_restore
+       pshs a
+       lda map_store
+       bra map_set_a
+
+map_store      .db 0
+map_copy       .db 0
+
diff --git a/Kernel/platform-dragon-nx32/target.mk b/Kernel/platform-dragon-nx32/target.mk
new file mode 100644 (file)
index 0000000..e9abbba
--- /dev/null
@@ -0,0 +1 @@
+export CPU = 6809
diff --git a/Kernel/platform-dragon-nx32/tricks.s b/Kernel/platform-dragon-nx32/tricks.s
new file mode 100644 (file)
index 0000000..7af4997
--- /dev/null
@@ -0,0 +1,198 @@
+;
+;      6809 version
+;
+        .module tricks
+
+       #imported
+        .globl _swapout
+        .globl _newproc
+        .globl _chksigs
+        .globl _getproc
+        .globl _trap_monitor
+        .globl _inint
+        .globl map_kernel
+        .globl map_process
+        .globl map_process_a
+        .globl map_process_always
+
+       # exported
+        .globl _switchout
+        .globl _switchin
+        .globl _dofork
+       .globl _ramtop
+
+
+        include "kernel.def"
+        include "../kernel09.def"
+
+       .area .common
+
+_ramtop:
+       .dw 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().
+;
+; FIXME: make sure we optimise the switch to self case higher up the stack!
+; 
+; This function can have no arguments or auto variables.
+_switchout:
+       orcc #0x10              ; irq off
+        jsr _chksigs
+
+        ; save machine state
+        ldd #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:
+       pshs d
+       sts U_DATA__U_SP        ; this is where the SP is restored in _switchin
+
+        ; set inint to false
+       lda #0
+       sta _inint
+
+       ; Stash the uarea into process memory bank
+       jsr map_process_always
+       sty _swapstack+2
+
+       ldx #U_DATA
+       ldy #U_DATA_STASH
+stash  ldd ,x++
+       std ,y++
+       cmpx #U_DATA+U_DATA__TOTALSIZE
+       bne stash
+       ldy _swapstack+2
+
+       ; get process table in
+       jsr map_kernel
+
+        ; find another process to run (may select this one again) returns it
+        ; in X
+        jsr _getproc
+        jsr _switchin
+        ; we should never get here
+        jsr _trap_monitor
+
+_swapstack .dw 0
+       .dw 0
+
+badswitchmsg: .ascii "_switchin: FAIL"
+            .db 13
+           .db 10
+           .db 0
+
+; new process pointer is in X
+_switchin:
+        orcc #0x10             ; irq off
+
+       ;pshs x
+       stx _swapstack
+       ; get process table - must be in already from switchout
+       ; jsr map_kernel
+       lda P_TAB__P_PAGE_OFFSET+1,x            ; LSB of 16-bit page no
+       jsr map_process_a
+       
+       ; fetch uarea from process memory
+       sty _swapstack+2
+       ldx #U_DATA_STASH
+       ldy #U_DATA
+stashb ldd ,x++
+       std ,y++
+       cmpx #U_DATA_STASH+U_DATA__TOTALSIZE
+       bne stashb
+       ldy _swapstack+2
+
+       ; get back kernel page so that we see process table
+       jsr map_kernel
+
+       ;puls x
+       ldx _swapstack
+        ; check u_data->u_ptab matches what we wanted
+       cmpx U_DATA__U_PTAB
+        bne switchinfail
+
+       lda #P_RUNNING
+       sta P_TAB__P_STATUS_OFFSET,x
+
+       lda #0
+       sta _runticks
+
+        ; restore machine state -- note we may be returning from either
+        ; _switchout or _dofork
+        lds U_DATA__U_SP
+        puls x ; return code
+
+        ; enable interrupts, if the ISR isn't already running
+       lda _inint
+        beq swtchdone ; in ISR, leave interrupts off
+       andcc #0xef
+swtchdone:
+        rts
+
+switchinfail:
+       jsr outx
+        ldx #badswitchmsg
+        jsr outstring
+       ; something went wrong and we didn't switch in what we asked for
+        jmp _trap_monitor
+
+       .area .data
+fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry
+
+       .area .common
+;
+;      Called from _fork. We are in a syscall, the uarea is live as the
+;      parent uarea. The kernel is the mapped object.
+;
+;      FIXME: preserve y
+;
+_dofork:
+        ; always disconnect the vehicle battery before performing maintenance
+        orcc #0x10      ; should already be the case ... belt and braces.
+
+       ; new process in X, get parent pid into y
+
+       stx fork_proc_ptr
+       ldx P_TAB__P_PID_OFFSET,x
+
+        ; 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.
+        pshs x ; x  has p->p_pid from above, the return value in the parent
+
+        ; 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.
+        sts U_DATA__U_SP
+
+        ; now we're in a safe state for _switchin to return in the parent
+       ; process.
+
+       ldx U_DATA__U_PTAB              ; parent
+; FIXME
+       ; jsr _swapout                  ; swap the parent out, leaving
+                                       ; it in memory as the child
+
+       ; 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.
+       puls x
+
+        ldx fork_proc_ptr
+        jsr _newproc
+
+       ; any calls to map process will now map the childs memory
+
+        ; runticks = 0;
+        clr _runticks
+        ; 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().
+        rts
+
diff --git a/Kernel/platform-dragon-nx32/usermem_sam.s b/Kernel/platform-dragon-nx32/usermem_sam.s
new file mode 100644 (file)
index 0000000..1be408a
--- /dev/null
@@ -0,0 +1,131 @@
+       .module usermem
+
+;
+;      6809 copy to and from userspace
+;
+;      This is linked by the 6881 using platforms only. MMU based
+;      machines simply don't need it.
+
+
+       include "kernel.def"
+        include "../kernel09.def"
+
+       ; exported
+       .globl __ugetc
+       .globl __ugetw
+       .globl __uget
+       .globl __ugets
+
+       .globl __uputc
+       .globl __uputw
+       .globl __uput
+       .globl __uzero
+
+       ; imported
+       .globl map_process_always
+       .globl map_kernel
+       .area .common
+
+__ugetc:
+       pshs cc         ; save IRQ state
+       orcc #0x10
+       jsr map_process_always
+       ldb ,x
+       jsr map_kernel
+       clra
+       tfr d,x
+       puls cc,pc      ; back and return
+
+__ugetw:
+       pshs cc
+       orcc #0x10
+       jsr map_process_always
+       ldx ,x
+       jsr map_kernel
+       puls cc,pc
+
+__uget:
+       pshs u,y,cc
+       ldu 7,s         ; user address
+       ldy 9,s         ; count
+       orcc #0x10
+ugetl:
+       lda ,x+
+       jsr map_process_always
+       sta ,u+
+       jsr map_kernel
+       leay -1,y
+       bne ugetl
+       puls u,y,cc,pc
+
+__ugets:
+       pshs u,y,cc
+       ldu 7,s         ; user address
+       ldy 9,s         ; count
+       orcc #0x10
+ugetsl:
+       jsr map_process_always
+       lda ,x+
+       beq ugetse
+       jsr map_kernel
+       sta ,u+
+       leay -1,y
+       bne ugetsl
+       ldx #0xffff     ; unterminated - error
+       lda #0
+       sta -1,u        ; force termination
+       puls u,y,cc,pc
+ugetse:
+       jsr map_kernel
+       sta ,u
+       ldx #0
+       puls u,y,cc,pc
+
+
+__uputc:
+       pshs cc
+       orcc #0x10
+       ldd 3,s
+       jsr map_process_always
+       exg d,x
+       stb ,x
+       jsr map_kernel
+       puls cc,pc
+
+__uputw:
+       pshs cc
+       orcc #0x10
+       ldd 3,s
+       jsr map_process_always
+       exg d,x
+       std ,x
+       jsr map_kernel
+       puls cc,pc
+
+;      X = source, user, size on stack
+__uput:
+       pshs u,y,cc
+       orcc #0x10
+       ldu 7,s         ; user address
+       ldy 9,s         ; count
+uputl:
+       lda ,x+
+       jsr map_process_always
+       sta ,u+
+       jsr map_kernel
+       leay -1,y
+       bne uputl
+       puls u,y,cc,pc
+
+__uzero:
+       pshs y,cc
+       lda #0
+       ldy 5,s
+       orcc #0x10
+       jsr map_process_always
+uzloop:
+       sta ,x+
+       leay -1,y
+       bne uzloop
+       jsr map_kernel
+       puls y,cc,pc