dragon: Initial bits towards a Dragon64 port of sorts
authorAlan Cox <alan@etchedpixels.co.uk>
Tue, 11 Nov 2014 21:44:45 +0000 (21:44 +0000)
committerAlan Cox <alan@etchedpixels.co.uk>
Tue, 11 Nov 2014 21:44:45 +0000 (21:44 +0000)
That's if you count replacing the boot ROMs as a "port"

21 files changed:
Kernel/Makefile
Kernel/platform-dragon/Makefile [new file with mode: 0644]
Kernel/platform-dragon/README [new file with mode: 0644]
Kernel/platform-dragon/commonmem.s [new file with mode: 0644]
Kernel/platform-dragon/config.h [new file with mode: 0644]
Kernel/platform-dragon/crt0.s [new file with mode: 0644]
Kernel/platform-dragon/device.h [new file with mode: 0644]
Kernel/platform-dragon/devices.c [new file with mode: 0644]
Kernel/platform-dragon/devlpr.c [new file with mode: 0644]
Kernel/platform-dragon/devlpr.h [new file with mode: 0644]
Kernel/platform-dragon/devrd.c [new file with mode: 0644]
Kernel/platform-dragon/devrd.h [new file with mode: 0644]
Kernel/platform-dragon/devtty.c [new file with mode: 0644]
Kernel/platform-dragon/devtty.h [new file with mode: 0644]
Kernel/platform-dragon/fuzix.link [new file with mode: 0644]
Kernel/platform-dragon/kernel.def [new file with mode: 0644]
Kernel/platform-dragon/libc.c [new file with mode: 0644]
Kernel/platform-dragon/main.c [new file with mode: 0644]
Kernel/platform-dragon/p6809.s [new file with mode: 0644]
Kernel/platform-dragon/setup.s [new file with mode: 0644]
Kernel/platform-dragon/tricks.s [new file with mode: 0644]

index b9b091c..bd9d58c 100644 (file)
@@ -1,4 +1,4 @@
-TARGET_LIST = platform-nc100 platform-micropack platform-pcw8256 platform-socz80 platform-zx128 platform-trs80 platform-z80pack platform-z80pack-lite 
+TARGET_LIST = platform-nc100 platform-micropack platform-pcw8256 platform-socz80 platform-zx128 platform-trs80 platform-z80pack platform-z80pack-lite platform-dragon
 
 #export TARGET= msx1
 #export CPU = z80
diff --git a/Kernel/platform-dragon/Makefile b/Kernel/platform-dragon/Makefile
new file mode 100644 (file)
index 0000000..abc144c
--- /dev/null
@@ -0,0 +1,33 @@
+
+CSRCS = devlpr.c devtty.c devrd.c
+CSRCS += devices.c main.c libc.c
+
+ASRCS = p6809.s crt0.s
+ASRCS += tricks.s commonmem.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) -c $<
+
+$(AOBJS): %$(BINEXT): %.s
+       $(CROSS_AS) $(ASOPTS) $< -o $*.o
+
+clean:
+       rm -f $(OBJS) $(JUNK)  core *~ 
+
+image:
+       $(CROSS_LD) -o ../fuzix.bin --map=../fuzix.map --script=fuzix.link \
+       crt0.o commonmem.o \
+       p6809.o ../start.o ../version.o ../lowlevel-6809.o \
+       tricks.o main.o ../timer.o ../kdata.o devrd.o devices.o \
+       ../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
+       ../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o ../single.o \
+       ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o ../syscall_exec.o \
+       ../usermem_std-6809.o devlpr.o devtty.o libc.o ../vt.o
diff --git a/Kernel/platform-dragon/README b/Kernel/platform-dragon/README
new file mode 100644 (file)
index 0000000..0aa3002
--- /dev/null
@@ -0,0 +1,13 @@
+Dragon Experimental Build
+
+Currently we build for a Dragon64 but are not doing anything but initial
+boot testing work
+
+Memory usage:
+
+The Dragon 64 has 2x32K banks of RAM which isn't sufficient but also 16K
+of cartridge space that can appear at 0xC000->0xF??? and two ROMs
+
+
+This is a very experimental build to see what might be possible if we either
+replaced the ROM images or used a cartridge or both.
diff --git a/Kernel/platform-dragon/commonmem.s b/Kernel/platform-dragon/commonmem.s
new file mode 100644 (file)
index 0000000..67e7f26
--- /dev/null
@@ -0,0 +1,27 @@
+;
+;      Put the udata at the start of common. We have four 16K banks so we
+; keep the non .common kernel elements below C000 and then keep bank 3 as a
+; true common bank
+;
+        .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/config.h b/Kernel/platform-dragon/config.h
new file mode 100644 (file)
index 0000000..d8f4a15
--- /dev/null
@@ -0,0 +1,57 @@
+/* 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 */
+#undef CONFIG_MULTI
+/* Single tasking - for now while we get it booting */
+#undef CONFIG_SINGLETASK
+/* Use C helpers for usermem */
+#define CONFIG_USERMEM_C
+/* Pure swap */
+#define CONFIG_SWAP_ONLY
+#define CONFIG_BANKS   1
+/* FIXME */
+#define BANK_PROCESS   *((volatile uint8_t *)0xff91) &= ~1
+#define BANK_KERNEL    *((volatile uint8_t *)0xff91) |= 1
+/* And swapping */
+#define SWAPDEV 6      /* FIXME */
+#define SWAP_SIZE   0x80       /* 64K blocks */
+/* FIXME */
+#define SWAPBASE    0x0000     /* We swap the lot in one, include the */
+#define SWAPTOP            0x8000      /* uarea so its a round number of sectors */
+#define UDATA_BLOCKS   0       /* We swap the uarea in the data */
+#define UDATA_SWAPSIZE 0
+#define MAX_SWAPS      32
+
+/* Video terminal, not a serial tty */
+#define CONFIG_VT
+/* Simple text mode */
+#define CONFIG_VT_SIMPLE
+/* Vt definitions */
+#define VT_BASE                0x0400  /* Default video text mode base */
+#define VT_WIDTH       32
+#define VT_HEIGHT      24
+#define VT_RIGHT       31
+#define VT_BOTTOM      23
+
+#define TICKSPERSEC 100   /* Ticks per second */
+#define PROGBASE    ((uint8_t *)(0x8000))  /* also data base */
+#define PROGTOP     ((uint8_t *)(0xff00))  /* 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    10       /* Number of block buffers */
+#define NMOUNTS         3        /* Number of mounts at a time */
diff --git a/Kernel/platform-dragon/crt0.s b/Kernel/platform-dragon/crt0.s
new file mode 100644 (file)
index 0000000..df550ec
--- /dev/null
@@ -0,0 +1,47 @@
+               ; Ordering of segments for the linker.
+               ; WRS: Note we list all our segments here, even though
+               ; we don't use them all, because their ordering is set
+               ; when they are first seen.     
+
+               ; imported symbols
+               .globl _fuzix_main
+               .globl init_early
+               .globl init_hardware
+               .globl kstack_top
+
+               ; startup code @0
+               .area .start
+               jmp start
+
+               .area .text
+
+start:         orcc #0x10              ; interrupts definitely off
+               lds #kstack_top
+               ; move the common memory where it belongs    
+               ; we do this dowards, not out of any concern about
+               ; about overlap (although its correct for this) but because
+               ; it deals with linker reloc limits nicely
+;              ldd #s__INITIALIZER
+;              addd #l__COMMONMEM
+;              tfr d,x
+;              ldd #s__COMMONMEM
+;              addd #l__COMMONMEM
+;              tfr d,y
+               
+;copier:               lda ,-x
+;              sta ,-y
+;              cmpy #s__COMMONMEM
+;              bgt copier
+
+;wiper:                ldx #s__DATA
+;              ldd #l__DATA
+;              clr ,x+
+;              subd #1
+;              bne wiper
+
+               jsr init_early
+               jsr init_hardware
+               jsr _fuzix_main
+               orcc #0x10
+stop:          bra stop
+
diff --git a/Kernel/platform-dragon/device.h b/Kernel/platform-dragon/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/devices.c b/Kernel/platform-dragon/devices.c
new file mode 100644 (file)
index 0000000..0cfe40b
--- /dev/null
@@ -0,0 +1,39 @@
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <devrd.h>
+#include <devsys.h>
+#include <devlpr.h>
+#include <tty.h>
+#include <devtty.h>
+
+struct devsw dev_tab[] =  /* The device driver switch table */
+{
+// minor    open         close        read      write       ioctl
+// -----------------------------------------------------------------
+  /* 0: /dev/fd                Floppy disc block devices  */
+  {  rd_open,     no_close,    rd_read,   rd_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,  tty_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 */
+};
+
+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/devlpr.c b/Kernel/platform-dragon/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/devlpr.h b/Kernel/platform-dragon/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/devrd.c b/Kernel/platform-dragon/devrd.c
new file mode 100644 (file)
index 0000000..ddbf8b3
--- /dev/null
@@ -0,0 +1,69 @@
+/* 
+ * NC100 RD PCMCIA driver
+ *
+ */
+
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devrd.h>
+
+static int rd_transfer(bool is_read, uint8_t rawflag)
+{
+    blkno_t block;
+    int block_xfer;
+    uint16_t dptr;
+    int dlen;
+    int ct = 0;
+    int map;
+
+    /* FIXME: raw is broken unless nicely aligned */
+    if(rawflag) {
+        dlen = udata.u_count;
+        dptr = (uint16_t)udata.u_base;
+        if (dptr & 0x1FF) {
+            udata.u_error = EIO;
+            return -1;
+        }
+        block = udata.u_offset >> 9;
+        block_xfer = dlen >> 9;
+        map = 1;
+    } else { /* rawflag == 0 */
+        dlen = 512;
+        dptr = (uint16_t)udata.u_buf->bf_data;
+        block = udata.u_buf->bf_blk;
+        block_xfer = 1;
+        map = 0;
+    }
+    block += 2*320;    /* ramdisc starts at 320K in */
+        
+    while (ct < block_xfer) {
+/*        rd_memcpy(is_read, map, dptr, block); */
+        block++;
+        ct++;
+    }
+    return ct;
+}
+
+int rd_open(uint8_t minor, uint16_t flag)
+{
+    flag;
+    if(minor != 0) {
+        udata.u_error = ENODEV;
+        return -1;
+    }
+    return 0;
+}
+
+int rd_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+    flag;minor;
+    return rd_transfer(true, rawflag);
+}
+
+int rd_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+    flag;minor;
+    return rd_transfer(false, rawflag);
+}
+
diff --git a/Kernel/platform-dragon/devrd.h b/Kernel/platform-dragon/devrd.h
new file mode 100644 (file)
index 0000000..6320b26
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __DEVRD_DOT_H__
+#define __DEVRD_DOT_H__
+
+/* public interface */
+int rd_read(uint8_t minor, uint8_t rawflag, uint8_t flag);
+int rd_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
+int rd_open(uint8_t minor, uint16_t flag);
+
+/* asm banking helper */
+void rd_memcpy(uint8_t isread, uint8_t map, uint16_t dptr, uint16_t block);
+
+#endif /* __DEVRD_DOT_H__ */
+
diff --git a/Kernel/platform-dragon/devtty.c b/Kernel/platform-dragon/devtty.c
new file mode 100644 (file)
index 0000000..9934028
--- /dev/null
@@ -0,0 +1,84 @@
+#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);
+}
+
+bool tty_writeready(uint8_t minor)
+{
+       uint8_t c;
+       if (minor == 1)
+               return 1;
+       c = *uart_status;
+       return c & 16;  /* TX DATA empty */
+}
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+#if 0
+       if (minor == 1) {
+               vtoutput(&c, 1);
+               return;
+       }
+#endif 
+       *uart_data = c; /* Data */
+}
+
+void tty_setup(uint8_t minor)
+{
+       /* 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);
+       }       
+}
+
+void platform_interrupt(void)
+{
+       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/devtty.h b/Kernel/platform-dragon/devtty.h
new file mode 100644 (file)
index 0000000..948cc29
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __DEVTTY_DOT_H__
+#define __DEVTTY_DOT_H__
+
+extern int nc100_tty_open(uint8_t minor, uint16_t flag);
+extern int nc100_tty_close(uint8_t minor);
+extern void nc100_tty_init(void);
+#endif
diff --git a/Kernel/platform-dragon/fuzix.link b/Kernel/platform-dragon/fuzix.link
new file mode 100644 (file)
index 0000000..79e548a
--- /dev/null
@@ -0,0 +1,12 @@
+section .vectors load 0x0100
+section .discard load 0x2000
+section .data
+section .bss
+section _COMMONMEM load 0x8000
+section .text2
+section .video
+section .romvectors load 0xBFF0
+section .udata load 0x7D00
+section .start load 0xC000
+section .text
+
diff --git a/Kernel/platform-dragon/kernel.def b/Kernel/platform-dragon/kernel.def
new file mode 100644 (file)
index 0000000..a49e876
--- /dev/null
@@ -0,0 +1,5 @@
+; 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.
+
diff --git a/Kernel/platform-dragon/libc.c b/Kernel/platform-dragon/libc.c
new file mode 100644 (file)
index 0000000..8b3940b
--- /dev/null
@@ -0,0 +1,34 @@
+#include "cpu.h"
+
+void *memcpy(void *d, void *s, size_t sz)
+{
+  unsigned char *dp, *sp;
+  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;
+}
+
+/* Until we pull out the bits of libgcc that are useful instead */
+void abort(void)
+{
+}
+
+void *malloc(size_t size)
+{
+  return 0;
+}
\ No newline at end of file
diff --git a/Kernel/platform-dragon/main.c b/Kernel/platform-dragon/main.c
new file mode 100644 (file)
index 0000000..994c620
--- /dev/null
@@ -0,0 +1,42 @@
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+
+/* The uarea is already synched to the stash which is written with the
+   process */
+uint8_t *swapout_prepare_uarea(ptptr p)
+{
+  p;
+  return NULL;
+}
+
+/* The switchin code will move the uarea into the process itself, we just
+   need to fix up the u_page pointer */
+uint8_t *swapin_prepare_uarea(ptptr p)
+{
+  p;
+  return NULL;
+}
+
+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)
+{
+}
+
+void map_init(void)
+{
+}
diff --git a/Kernel/platform-dragon/p6809.s b/Kernel/platform-dragon/p6809.s
new file mode 100644 (file)
index 0000000..5ce13ee
--- /dev/null
@@ -0,0 +1,188 @@
+;
+;          6809 Simulation Platform 
+;
+
+            .module p6809
+
+            ; exported symbols
+            .globl init_early
+            .globl init_hardware
+            .globl interrupt_handler
+            .globl _program_vectors
+           .globl map_kernel
+           .globl map_process
+           .globl map_process_always
+           .globl map_save
+           .globl map_restore
+
+            ; exported debugging tools
+            .globl _trap_monitor
+            .globl outchar
+           .globl _di
+           .globl _ei
+           .globl _irqrestore
+
+            ; imported symbols
+            .globl _ramsize
+            .globl _procmem
+            .globl unix_syscall_entry
+           .globl nmi_handler
+
+            include "kernel.def"
+            include "../kernel09.def"
+
+; -----------------------------------------------------------------------------
+; COMMON MEMORY BANK (0xF000 upwards)
+; -----------------------------------------------------------------------------
+            .area _COMMONMEM
+
+trapmsg:    .ascii "Trapdoor: SP="
+            .db 0
+trapmsg2:   .ascii ", PC="
+            .db 0
+tm_user_sp: .dw 0
+
+_trap_monitor:
+           orcc #0x10
+           bra _trap_monitor
+
+_trap_reboot:
+           lda 0xff90
+           anda #0xfc          ; map in the ROM
+           jmp 0
+
+_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
+
+; -----------------------------------------------------------------------------
+; KERNEL MEMORY BANK (below 0xF000, only accessible when the kernel is mapped)
+; -----------------------------------------------------------------------------
+            .area .text
+
+init_early:
+            rts
+
+init_hardware:
+            ; set system RAM size
+           ldd #96
+           std _ramsize
+           ldd #32
+           std _procmem
+            rts
+
+
+           .area .vectors
+;
+;      At 0x100 as required by the Dragon ROM
+;
+           jmp badswi_handler                  ; 0x100
+           jmp badswi_handler                  ; 0x103
+           jmp unix_syscall_entry              ; 0x106
+           jmp nmi_handler                     ; 0x109
+           jmp interrupt_handler               ; 0x10C
+           jmp firq_handler                    ; 0x10F
+
+;
+;      Included if we are replacing the basic ROM and magically mapped from
+;      the ROM top (0xBFF0->FFF0)
+;
+           .area .romvectors
+
+           .dw 0x3634          ; Reserved
+           .dw 0x0100
+           .dw 0x0103
+           .dw 0x010f
+           .dw 0x010c
+           .dw 0x0106
+           .dw 0x0109
+           .dw 0xC000          ; Unused (reset)
+
+;------------------------------------------------------------------------------
+; COMMON MEMORY PROCEDURES FOLLOW
+
+
+            .area _COMMONMEM
+
+;
+;      In the Dragon64 case our vectors live in a fixed block
+;
+_program_vectors:
+           rts
+
+;
+;      FIXME:
+;
+firq_handler:
+badswi_handler:
+           rti
+
+;
+;      The Dragon mapping is a bit tangled
+;
+;      SAM ffd4/d5 reading turns off/on the upper 32K of RAM at 0x0-0x7FFF
+;      SAM ffde/ffdf makes it appear at 0x8000-0xffef (ff00... is  hardwired)
+;      PIA 1 B side data reg (ff22) bit 2 switches between the two ROMs
+;      
+;
+;
+;      All registers preserved
+;
+map_process_always:
+           pshs a
+map_process_2:
+           lda 0xffdf                  ; RAM please
+           lda #0
+           sta cart_map
+           puls a, pc    
+
+map_process:
+           cmpx #0
+           bne map_process_always
+;
+;      Map in the kernel below the current common, all registers preserved
+;
+map_kernel:
+           pshs a
+map_kernel_2:
+           lda 0xffde                  ; RAM out (cart in hopefully)
+           lda #1
+           sta cart_map
+           puls a, pc
+
+map_restore:
+           pshs a
+           lda saved_map
+           cmpa #0
+           beq map_process_2
+           bra map_kernel_2
+;
+;      Save the current mapping.
+;
+map_save:
+           pshs a
+           lda cart_map
+           sta saved_map
+           puls a,pc
+
+saved_map:  .db 0
+cart_map:   .db 0          
+
+; outchar: Wait for UART TX idle, then print the char in a
+
+outchar:
+           pshs b
+outcharw:
+           ldb 0xff05
+           bitb #0x04
+           beq outcharw
+           sta 0xff04
+           puls b,pc
diff --git a/Kernel/platform-dragon/setup.s b/Kernel/platform-dragon/setup.s
new file mode 100644 (file)
index 0000000..0a329b2
--- /dev/null
@@ -0,0 +1,66 @@
+;
+;      Raw machine set up for running in 'ROM' mode
+;
+       .area .startup
+
+       ; Optimise all this to use the direct page register as 0xffxx
+       orcc #0x10
+       ; Memory 64K dynamic (I guess...)
+       lda 0xffdd
+       lda 0xffda
+       ; Memory low map (cartridge high, RAM low)
+       lda 0xffde      ; Map type -> cartridge & rom
+       ; Serial
+       lda #0x01
+       sta 0xff06
+       lda #0x1e
+       sta 0xff07
+
+       ; 0.9Mhz
+       lda 0xffd6      ; R0
+       lda 0xffd8      ; R1
+       ; Put the video at 0x400
+       lda 0xffd2      ; F6 to F1 clear F0 set
+       lda 0xffd0
+       lda 0xffce
+       lda 0xffcc
+       lda 0xffca
+       lda 0xffc8
+       lda 0xffc7
+       ; SAM into ascii mode
+       lda 0xffc0
+       lda 0xffc2
+       lda 0xffc4
+
+       ; PIA0 A is all input
+       ; PIA0 B is all output
+       ; PIA1 A is mixed, both the same (input 0 only)
+       lda #0x4        ; enable access to DDR registers
+       sta 0xff01
+       sta 0xff03
+       sta 0xff21
+       sta 0xff23
+       lda #0x00
+       sta 0xff00
+       lda #0xff
+       sta 0xff02
+       lda #0xfe
+       sta 0xff21
+       sta 0xff23
+       lda #0x0        ; Disable access to DDR registers
+       sta 0xff01
+       sta 0xff03
+       sta 0xff21
+       sta 0xff23
+
+       ; VDG via PIA1
+       lda #0x00
+       ld 0xff22, a    ; Graphics, internal text rom
+
+       ;
+       ; Say hello
+       ;
+       ldx 0x400
+       lda #'H'
+       sta ,x+
+
diff --git a/Kernel/platform-dragon/tricks.s b/Kernel/platform-dragon/tricks.s
new file mode 100644 (file)
index 0000000..3fb76a3
--- /dev/null
@@ -0,0 +1,201 @@
+;
+;      6809 version
+;
+        .module tricks
+
+        .globl _newproc
+        .globl _chksigs
+        .globl _getproc
+        .globl _trap_monitor
+        .globl _inint
+        .globl _switchout
+        .globl _switchin
+        .globl _dofork
+       .globl _ramtop
+
+
+        include "kernel.def"
+        include "../kernel09.def"
+
+        .area _COMMONMEM
+
+; ramtop must be in common for single process swapping cases
+; and its a constant for the others from before init forks so it'll be fine
+; here
+_ramtop:
+       .dw 0
+
+; 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
+
+        ; set inint to false
+       lda #0
+       sta _inint
+
+        ; 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
+
+badswitchmsg: .ascii "_switchin: FAIL"
+            .db 13
+           .db 10
+           .db 0
+
+; new process pointer is in X
+_switchin:
+        orcc #0x10             ; irq off
+
+       ldy P_TAB__P_PAGE_OFFSET+3,x
+       ; FIXME: can we skip the usermaps here ?
+       stx 0xffa6              ; map the process uarea we want
+       adda #1
+       stx 0xffa7
+       stx 0xffaf              ; and include the kernel mapping
+
+       ; ------- No stack -------
+        ; check u_data->u_ptab matches what we wanted
+       cmpx U_DATA__U_PTAB
+        bne switchinfail
+
+       ; wants optimising up a bit
+       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
+
+fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry
+
+;
+;      Called from _fork. We are in a syscall, the uarea is live as the
+;      parent uarea. The kernel is the mapped object.
+;
+_dofork:
+        ; always disconnect the vehicle battery before performing maintenance
+        orcc #0x10      ; should already be the case ... belt and braces.
+
+       ; new process in X, get parent pid into y
+
+       stx fork_proc_ptr
+       ldy 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 y ; y  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.
+
+       ; --------- we switch stack copies in this call -----------
+       jsr fork_copy                   ; copy 0x000 to udata.u_top and the
+                                       ; uarea and return on the childs
+                                       ; common
+       ; We are now in the kernel child context
+
+        ; now the copy operation is complete we can get rid of the stuff
+        ; _switchin will be expecting from our copy of the stack.
+       puls y
+
+        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
+
+fork_copy:
+       ldd U_DATA__U_TOP
+       addd #0x0fff            ; + 0x1000 (-1 for the rounding to follow)
+       lsra            
+       lsra
+       lsra
+       lsra
+       lsra                    ; bits 2/1 for 8K pages
+       anda #6                 ; lose bit 0
+       adda #2                 ; and round up to the next bank (but in 8K terms)
+
+       ldx fork_proc_ptr
+       ldy P_TAB__P_PAGE_OFFSET,x
+       ; y now points to the child page pointers
+       ldx U_DATA__U_PAGE
+       ; and x to the parent
+fork_next:
+;      ld a,(hl)
+;      out (0x11), a           ; 0x4000 map the child
+;      ld c, a
+;      inc hl
+;      ld a, (de)
+;      out (0x12), a           ; 0x8000 maps the parent
+;      inc de
+;      exx
+;      ld hl, #0x8000          ; copy the bank
+;      ld de, #0x4000
+;      ld bc, #0x4000          ; we copy the whole bank, we could optimise
+;                              ; further
+;      ldir
+;      exx
+;      call map_kernel         ; put the maps back so we can look in p_tab
+; FIXME: can't map_kernel here - we've been playing with the maps, fix
+; directly
+       suba #1
+       bne fork_next
+
+;      ld a, c
+;      out (0x13), a           ; our last bank repeats up to common
+       ; --- we are now on the stack copy, parent stack is locked away ---
+       rts                     ; this stack is copied so safe to return on
+
+