--- /dev/null
+extern volatile uint8_t *baud;
+extern volatile uint8_t *sccr1;
+extern volatile uint8_t *sccr2;
+extern volatile uint8_t *scdr;
+extern volatile uint8_t *scsr;
--- /dev/null
+
+CSRCS = devtty.c devrd.c
+CSRCS += devices.c main.c libc.c
+
+ASRCS = crt0.s p68hc11.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 -M >../fuzix.map \
+ crt0.o commonmem.o \
+ p68hc11.o ../start.o ../version.o ../lowlevel-68hc11.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 ../bankfixed.o \
+ ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o ../syscall_exec16.o \
+ ../usermem_std-68hc11.o devtty.o libc.o
--- /dev/null
+
+68HC811E Development board
+
+Memory map:
+0000-00FF: internal RAM (unbanked)
+0100-F7FF: externam RAM (banked)
+ but with hole
+F000-F03F: I/O devices (unbanked)
+F800-FFFF: 2K EEPROM (unbanked)
+
+
+8 banks of 64K (minus 2.5K or so per bank unusable)
+
+Kernel in bank 0, user space in 1-7
+
+Serial is the onchip port
+SPI drives the SD card
--- /dev/null
+;
+; udata is a bit special we have to copy it on a task switch as we've
+; got almost no common memory space on the simple board design
+;
+ .file "commonmem"
+ .mode mshort
+
+ ; exported symbols
+ .globl _ub
+ .globl udata
+ .globl kstack_top
+ .globl istack_top
+ .globl istack_switched_sp
+
+ .sect .udata
+
+ .comm udata,512,1
+ .comm kstack_top,0,1
+ .comm istack_base,254,1
+ .comm istack_top,2,1
+ .comm istack_switched_sp,2,1
--- /dev/null
+/* Enable to make ^Z dump the inode table for debug */
+#undef CONFIG_IDUMP
+/* Enable to make ^A drop back into the monitor */
+#undef CONFIG_MONITOR
+/* Profil syscall support (not yet complete) */
+#define CONFIG_PROFIL
+/* Multiple processes in memory at once */
+#define CONFIG_MULTI
+/* Single tasking - for now while we get it booting */
+#undef CONFIG_SINGLETASK
+#undef CONFIG_USERMEM_C
+/* We use big banks so use the helper */
+#define CONFIG_BANK_FIXED
+#define CONFIG_BANKS 7 /* and one for the kernel */
+#define MAX_MAPS 7
+#define MAPBASE 0x200
+#define MAP_SIZE 0xEE00
+/* And swapping */
+#define SWAPDEV 6 /* FIXME */
+#define SWAP_SIZE 0x78 /* Almost a full 64K */
+/* FIXME: udata swap separately */
+#define SWAPBASE 0x0200 /* We swap the lot in one */
+#define SWAPTOP 0xF000
+#define MAX_SWAPS 32
+
+/* Serial tty */
+#undef CONFIG_VT
+
+#define TICKSPERSEC 100 /* Ticks per second */
+#define PROGBASE 0x0200 /* also data base */
+#define PROGLOAD 0x0200 /* also data base */
+#define PROGTOP 0xF000 /* Top of program, base of I/O */
+
+#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 1
+#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */
+#define NBUFS 7 /* Number of block buffers */
+#define NMOUNTS 2 /* Number of mounts at a time */
+
+#define swap_map(x) ((uint8_t *)(x))
--- /dev/null
+ ; imported symbols
+
+ .file "crt0.s"
+ .mode mshort
+
+ .globl fuzix_main
+ .globl init_early
+ .globl init_hardware
+ .globl kstack_top
+
+ ; startup code @0
+ .sect .start
+ jmp start
+
+ .sect .text
+start:
+ sei
+ lds #kstack_top
+;
+; FIXME: any set up needed ?
+;
+
+ jsr init_early
+ jsr init_hardware
+ jsr fuzix_main
+ sei
+stop: bra stop
+
+;
+; Zeropage compiler goo
+;
+
+ .globl _.frame
+ .globl _.tmp
+ .globl _.d0
+ .globl _.d1
+ .globl _.d2
+ .globl _.d3
+ .globl _.d4
+ .globl _.d5
+ .globl _.xy
+ .globl _.z
+
+.equ _.frame,0x40
+.equ _.tmp,0x42
+.equ _.d0,0x44
+.equ _.d1,0x46
+.equ _.d2,0x48
+.equ _.d3,0x4A
+.equ _.d4,0x4C
+.equ _.d5,0x4E
+.equ _.xy,0x50
+.equ _.z,0x52
\ No newline at end of file
--- /dev/null
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <devrd.h>
+#include <devsys.h>
+#include <tty.h>
+#include <devtty.h>
+
+struct devsw dev_tab[] = /* The device driver switch table */
+{
+// minor open close read write ioctl
+// -----------------------------------------------------------------
+ /* 0: /dev/hd Hard disc block devices (SD card) */
+ { rd_open, no_close, rd_read, rd_write, no_ioctl },
+ /* 1: /dev/fd Floppy 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 (none) */
+ { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl },
+ /* 4: /dev/mem etc System devices (one offs) */
+ { no_open, no_close, sys_read, sys_write, sys_ioctl },
+ /* 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)
+{
+}
+
--- /dev/null
+/*
+ * 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 (((uint16_t)dptr | dlen) & BLKMASK) {
+ 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);
+}
+
--- /dev/null
+#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__ */
+
--- /dev/null
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <devtty.h>
+#include <vt.h>
+#include <tty.h>
+#include <68hc11.h>
+
+static char tbuf1[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},
+};
+
+/* tty1 is the HC11 port B serial */
+
+/* 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 = *scsr;
+ return (c & 0x80) ? TTY_READY_NOW : TTY_READY_SOON;
+}
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+ *scdr = c;
+}
+
+void tty_sleeping(uint8_t minor)
+{
+ used(minor);
+}
+
+/* Assumes 8MHz crystal and SCPR set to 011 */
+void tty_setup(uint8_t minor)
+{
+ uint8_t b = ttydata[1].termios.c_cflag & CBAUD;
+ *sccr1 = 0;
+ *sccr2 = 0x2C; /* rx interrupt, rx/tx enabled */
+ if (b < B75)
+ b = B75; /* Lowest with fixed divider.. we can do 50
+ but its much mucking about */
+ if (b > B9600)
+ b = B9600;
+ /* Only 8N1 */
+ ttydata[1].termios.c_cflag &= ~(CBAUD|PARENB);
+ ttydata[1].termios.c_cflag |= b | CS8;
+
+ b = B9600 - b;
+
+ *baud = b | 0x3;
+ minor;
+}
+
+/* Carrier etc are done via extra control lines. We don't have any spare! */
+int tty_carrier(uint8_t minor)
+{
+ minor;
+ return 1;
+}
+
+void platform_interrupt(void)
+{
+ uint8_t c = *scsr;
+ if (c & 0x20) {
+ /* Character arrived */
+ c = *scdr; /* This clears the irq as well */
+ tty_inproc(1, c);
+ }
+ timer_interrupt();
+}
+
--- /dev/null
+#ifndef __DEVTTY_DOT_H__
+#define __DEVTTY_DOT_H__
+
+#endif
--- /dev/null
+;
+; Hide the udata above the I/O in the gap before the EEPROM
+;
+.equ U_DATA , 0xF200 ; (this is struct u_data from kernel.h)
+.equ U_DATA__TOTALSIZE , 0x200 ;
+.equ IRQ_STACK , 0xF400
+.equ EESTACK , 0xF600 ; used for eeprom stuff
+
+;
+; EEPROM entry points
+;
+; A = srcbank, B = dstbank
+; IX = src, returns value in D
+.equ fargetb , 0xF840
+.equ fargetw , 0xF842
+;
+; A = srcbank, B = dstbank
+; IX = dst, IY = dstval
+;
+.equ farputb , 0xF844
+.equ farputw , 0xF846
+;
+; A = srcbank, B = dstbank
+; IX = dst, IY = src
+; kernel:_tmp1 = length (in kernel bank)
+;
+.equ farcopy , 0xF848
+;
+; A = bank, IX = function, IY = far stack
+;
+.equ farcall , 0xF84A
+;
+; A = bank, IX = function, IY = far stack
+;
+.equ farjump , 0xF84C
+;
+; A = bank
+;
+.equ setbank , 0xF84E
+;
+; D = 0
+;
+.equ reboot , 0xF850
+;
+;
+; Low memory usage (not banked)
+;
+.equ tmp1 , 0xFE ; 16bits
+.equ curbank , 0xFD
+.equ usrbank , 0xFC ; we track this to emulate
+ ; usermode copy stuff
\ No newline at end of file
--- /dev/null
+#include "cpu.h"
+
+void *memcpy(void *d, const 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;
+}
+
--- /dev/null
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+
+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;
+ for (i = 0x01; i < 0x08; i++)
+ pagemap_add(i);
+}
+
+void map_init(void)
+{
+}
+
+
+uint8_t need_resched;
--- /dev/null
+;
+; 68HC11 Simulation Platform
+;
+
+ .file "p68hc11"
+ .mode mshort
+
+ ; 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 trap_reboot
+
+ include "kernel.def"
+ include "../kernel-hc11.def"
+
+;
+; TODO: hardware registers
+;
+
+ .globl baud
+.equ baud,0xf000
+ .globl sccr1
+.equ sccr1,0xf000
+ .globl sccr2
+.equ sccr2,0xf000
+ .globl scdr
+.equ scdr,0xf000
+ .globl scsr
+.equ scsr,0xf000
+
+ .sect .data
+
+trapmsg:
+ .ascii "Trapdoor: SP="
+ .byte 0
+trapmsg2:
+ .ascii ", PC="
+ .byte 0
+tm_user_sp:
+ .word 0
+
+savedbank:
+ .word 0
+
+ .sect .text
+trap_monitor:
+ sei
+ bra trap_monitor
+
+trap_reboot:
+ jmp reboot
+
+init_early:
+ rts
+
+init_hardware:
+ ; set system RAM size
+ ldd #512
+ std ramsize
+ ldd #512-64
+ std procmem
+
+ ; Our vectors are in high memory unlike Z80 but we still
+ ; need vectors
+ clra
+ clrb ; pass NULL
+ jsr program_vectors
+ rts
+
+
+program_vectors:
+;
+; FIXME: figure out how this will interact with eeprom (eeprom should
+; bank switch then call into some secondary vector)
+;
+ rts ; rti will be in eeprom
+
+;
+; Memory is fully banked, with no real common. We simply track the
+; "correct" user bank for use by the copiers.
+;
+map_process_always:
+ psha
+ ldaa U_DATA__U_PAGE
+ staa usrbank
+ pula
+ rts
+
+map_kernel:
+ clr usrbank
+ rts
+
+map_restore:
+ psha
+ ldaa savedbank
+ pula
+ rts
+map_save:
+ psha
+ ldaa curbank
+ staa savedbank
+ pula
+ rts
+
+map_process:
+ xgdx
+ ldaa P_TAB__P_PAGE_OFFSET,x
+ staa usrbank
+ xgdx
+ rts
+
+;
+; Bank handling
+;
+ .globl doexec
+ .globl sigdispatch
+ .globl _ugetc
+ .globl _ugetw
+ .globl _ugets
+ .globl _uget
+ .globl _uputc
+ .globl _uputw
+ .globl _uputs
+ .globl _uput
+ .globl _uzero
+
+
+doexec:
+sigdispatch:
+_ugetc:
+_ugetw:
+_ugets:
+_uget:
+_uputc:
+_uputw:
+_uput:
+_uzero:
+ /* FIXME */
+ rts
--- /dev/null
+export CPU = 68hc11
--- /dev/null
+;
+; 68HC11 fully banked (so no real 'common')
+;
+ .file "tricks"
+ .mode mshort
+
+ .globl newproc
+ .globl chksigs
+ .globl getproc
+ .globl trap_monitor
+ .globl inint
+ .globl switchout
+ .globl switchin
+ .globl dofork
+ .globl ramtop
+
+ include "kernel.def"
+ include "../kernel-hc11.def"
+
+ .sect .data
+
+; 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:
+ .word 0
+
+ .sect .code
+
+; 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:
+ sei
+ jsr chksigs
+
+ ; save machine state
+ ldx #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:
+ pshx
+ sts U_DATA__U_SP
+
+ ; set inint to false
+ clr 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"
+ .byte 13
+ .byte 10
+ .byte 0
+
+; new process pointer is in D
+switchin:
+ sei
+
+ xgdx
+
+ ;
+ ; FIXME: implement dragon-nx uarea copy logic for HC11 via
+ ; eeprom copy helpers
+ ;
+
+ ; ------- No stack -------
+ ; check u_data->u_ptab matches what we wanted
+ cmpx U_DATA__U_PTAB
+ bne switchinfail
+
+ ; wants optimising up a bit
+ ldaa #P_RUNNING
+ staa P_TAB__P_STATUS_OFFSET,x
+
+ clr runticks
+
+ ; restore machine state -- note we may be returning from either
+ ; _switchout or _dofork
+ lds U_DATA__U_SP
+
+
+ ; enable interrupts, if the ISR isn't already running
+ ldaa inint
+ beq swtchdone ; in ISR, leave interrupts off
+ cli
+swtchdone:
+ pulx ; return code
+ xgdx
+ 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: .word 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:
+ sei
+ ; new process is in D, get parent pid into d and process into x
+
+ xgdx
+
+ stx fork_proc_ptr
+ ldd 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.
+ xgdx
+ pshx ; 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.
+
+ ; --------- we switch stack copies in this call -----------
+ ; d is the process pointer
+ jsr fork_copy
+
+ ; 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.
+ pulx
+
+ ldd 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:
+ ; FIXME
+ rts ; this stack is copied so safe to return on
+
+