--- /dev/null
+
+CSRCS = devtty.c
+CSRCS += devices.c main.c libc.c
+
+ASRCS = p68000.S crt0.S
+ASRCS += tricks.S
+
+DSRCS = ../dev/devide.c ../dev/mbr.c ../dev/blkdev.c ../dev/devide_discard.c
+DOBJS = $(patsubst ../dev/%.c,%.o, $(DSRCS))
+
+COBJS = $(CSRCS:.c=$(BINEXT))
+AOBJS = $(ASRCS:.S=.o)
+OBJS = $(COBJS) $(AOBJS) $(DOBJS)
+
+CROSS_CCOPTS += -I../dev/
+
+all: $(OBJS)
+
+$(COBJS): %.o: %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(AOBJS): %.o: %.S
+ $(CROSS_AS) $(ASOPTS) $< -o $*.o
+
+$(DOBJS): %.o: ../dev/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+clean:
+ rm -f *.o fuzix.elf loader.elf loader.map loader.bin core *~
+
+image:
+ $(CROSS_LD) -M -o fuzix.elf -T fuzix.ld \
+ crt0.o \
+ p68000.o ../start.o ../version.o ../lowlevel-68000.o \
+ tricks.o ../simple.o main.o ../timer.o ../kdata.o devices.o \
+ ../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
+ ../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o ../buddy.o \
+ ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o \
+ ../syscall_fs3.o ../syscall_exec32.o blkdev.o devide.o devide_discard.o mbr.o \
+ ../usermem_std-68000.o devtty.o libc.o ../malloc.o \
+ ../level2.o ../syscall_level2.o ../select.o > ../fuzix.map
+ m68k-uclinux-objcopy fuzix.elf -O binary ../fuzix.bin
+
+ $(CROSS_CC) -c loader.S
+ $(CROSS_LD) -M -o loader.elf -T loader.ld loader.o >loader.map
+ m68k-uclinux-objcopy loader.elf -O binary loader.bin
--- /dev/null
+Just a test build to start the Tiny68K port
+
+Nothing interesting to see here yet
--- /dev/null
+/* Enable to make ^Z dump the inode table for debug */
+#define CONFIG_IDUMP
+/* Enable to make ^A drop back into the monitor */
+#undef CONFIG_MONITOR
+/* Profil syscall support (not yet complete) */
+#undef CONFIG_PROFIL
+
+#define CONFIG_32BIT
+#define CONFIG_LEVEL_2
+
+/* To get us up and running then debug the flat model space */
+#undef CONFIG_MULTI
+#define CONFIG_SWAP_ONLY
+#define CONFIG_USERMEM_DIRECT
+#define CONFIG_BANKS 1
+#define PROC_SIZE 128 /* 64K, 128 * 512 */
+
+#define CONFIG_SPLIT_UDATA
+#define UDATA_SIZE 1024
+#define UDATA_BLKS 2
+
+#define PROGBASE 0x20000UL
+#define PROGTOP 0x30000UL
+#define SWAP_SIZE (130 + 2) /* 2 for the udata */
+#define SWAPBASE PROGBASE
+#define SWAPTOP 0x30000UL
+#define MAX_SWAPS PTABSIZE /* Mandatory for swap only */
+#define swap_map(x) ((uint8_t *)(x))
+
+#define CONFIG_DYNAMIC_SWAP
+#define SWAPDEV (swap_dev)
+
+#define TICKSPERSEC 100 /* Ticks per second */
+
+#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 TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */
+
+/* Could be bigger but we need to add hashing first and it's not clearly
+ a win with a CF card anyway */
+#define NBUFS 16 /* Number of block buffers */
+#define NMOUNTS 8 /* Number of mounts at a time */
+
+#define MAX_BLKDEV 2
+
+#define CONFIG_IDE
+
+#define platform_copyright()
+
+/* Note: select() in the level 2 code will not work on this configuration
+ at the moment as select is limited to 16 processes. FIXME - support a
+ hash ELKS style for bigger systems where wakeup aliasing is cheaper */
+
+#define PTABSIZE 125
+#define UFTSIZE 16
+#define OFTSIZE 160
+#define ITABSIZE 176
+
--- /dev/null
+/*
+ * Need to wipe BSS etc once we figure out our preferred boot method
+ *
+ * On entry we are loaded at $2000 with the loader and the loaders
+ * supervisor stack below us. We are in supervisor mode and the rest
+ * is our problem.
+ */
+ .globl __end
+ .globl __bss_start
+
+.mri 1
+ byte $15
+ byte $05
+ byte $C0
+ byte $DE
+start:
+ or #$0700,sr
+ move.l #__bss_start,a0
+ move.l #__end,d0
+ sub.l a0,d0
+ lsr.l #2,d0
+wipebss:
+ clr.l (a0)+
+ dbra d0,wipebss
+
+ /* FIXME: hard coded ugly */
+ move.l #udata_block+1016,a7
+ /* udata global */
+ move.l #udata_block,a5
+ bsr init_early
+ bsr init_hardware
+ bsr fuzix_main
+ or #$0700,sr
+stop: bra stop
--- /dev/null
+#ifndef __DEVICE_DOT_H__
+#define __DEVICE_DOT_H__
+
+extern void mod_control(uint8_t set, uint8_t clr);
+
+#endif /* __DEVICE_DOT_H__ */
--- /dev/null
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <devide.h>
+#include <blkdev.h>
+#include <devsys.h>
+#include <tty.h>
+#include <vt.h>
+
+struct devsw dev_tab[] = /* The device driver switch table */
+{
+// minor open close read write ioctl
+// -----------------------------------------------------------------
+ /* 0: /dev/hd Disc block devices */
+ { blkdev_open, no_close, blkdev_read, blkdev_write, blkdev_ioctl },
+ /* 1: /dev/fd 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 */
+ { no_open, no_close, no_rdwr, no_rdwr, no_ioctl },
+ /* 4: /dev/mem etc System devices (one offs) */
+ { no_open, no_close, sys_read, sys_write, sys_ioctl },
+ /* Pack to 7 with nxio if adding private devices and start at 8 */
+};
+
+bool validdev(uint16_t dev)
+{
+ /* This is a bit uglier than needed but the right hand side is
+ a constant this way */
+ if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) - 1)
+ return false;
+ else
+ return true;
+}
+
+void device_init(void)
+{
+ int i;
+
+ devide_init();
+
+ for (i = 1; i <= MAX_SWAPS; i++)
+ swapmap_init(i);
+}
--- /dev/null
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <devtty.h>
+#include <device.h>
+#include <tty.h>
+
+static unsigned char tbuf1[TTYSIZ];
+static unsigned char tbuf2[TTYSIZ];
+
+#define UART_MRA 0x01
+#define UART_SRA 0x03
+#define UART_CSRA 0x03
+#define UART_CRA 0x05
+#define UART_RHRA 0x07
+#define UART_THRA 0x07
+#define UART_IPCR 0x09
+#define UART_ACR 0x09
+#define UART_ISR 0x0B
+#define UART_IMR 0x0B
+#define UART_CTU 0x0D
+#define UART_CTUR 0x0D
+#define UART_CTL 0x0F
+#define UART_CTLR 0x0F
+#define UART_MRB 0x11
+#define UART_SRB 0x13
+#define UART_CSRB 0x13
+#define UART_CRB 0x15
+#define UART_RHRB 0x17
+#define UART_THRB 0x17
+#define UART_IVR 0x19
+#define UART_OPCR 0x1B
+#define UART_STARTCTR 0x1D
+#define UART_SETOPR 0x1D
+#define UART_STOPCTR 0x1F
+#define UART_CLROPR 0x1F
+
+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},
+};
+
+static uint8_t sleeping;
+
+/* For now */
+static tcflag_t console_mask[4] = {
+ _ISYS,
+ _OSYS,
+ _CSYS,
+ _LSYS
+};
+
+tcflag_t *termios_mask[NUM_DEV_TTY + 1] = {
+ NULL,
+ console_mask,
+ console_mask
+};
+
+/* Output for the system console (kprintf etc) */
+void kputchar(char c)
+{
+ if (c == '\n')
+ tty_putc(1, '\r');
+ tty_putc(1, c);
+}
+
+static volatile uint8_t *uart_base = (volatile uint8_t *)0xFFF000;
+
+#define GETB(x) (uart_base[(x)])
+#define PUTB(x,y) uart_base[(x)] = (y)
+
+ttyready_t tty_writeready(uint8_t minor)
+{
+ uint8_t c = GETB(0x10 * minor + UART_SRA);
+ return (c & 2) ? TTY_READY_NOW : TTY_READY_SOON; /* TX DATA empty */
+}
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+ PUTB(0x10 * minor + UART_THRA, c);
+}
+
+void tty_setup(uint8_t minor, uint8_t flags)
+{
+}
+
+int tty_carrier(uint8_t minor)
+{
+ return 1;
+}
+
+void tty_sleeping(uint8_t minor)
+{
+ sleeping |= 1 << minor;
+}
+
+void tty_data_consumed(uint8_t minor)
+{
+}
+
+/* Currently run off the timer */
+static void tty_interrupt(uint8_t r)
+{
+ if (r & 0x01) {
+ r = GETB(UART_RHRA);
+ tty_inproc(1,r);
+ }
+ if (r & 0x02) {
+ if (sleeping & 2)
+ tty_outproc(1);
+ }
+ if (r & 0x04) {
+ /* How to clear break int ? */
+ }
+ if (r & 0x10) {
+ r = GETB(UART_RHRB);
+ tty_inproc(2,r);
+ }
+ if (r & 0x20) {
+ if (sleeping & 4)
+ tty_outproc(2);
+ }
+ if (r & 0x40) {
+ /* How to clear break int ? */
+ }
+}
+
+void platform_interrupt(void)
+{
+ uint8_t r = GETB(UART_ISR);
+ tty_interrupt(r);
+ if (r & 0x08)
+ timer_interrupt();
+ /* and 0x80 is the GPIO */
+}
+
--- /dev/null
+#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
--- /dev/null
+STARTUP(crt0.o)
+OUTPUT_ARCH(m68k)
+
+SEARCH_DIR(.)
+
+MEMORY
+{
+ ram (rwx) : ORIGIN = 0x400, LENGTH = 0x80000-0x400
+}
+
+/*
+ * stick everything in ram (of course)
+ */
+SECTIONS
+{
+ .text :
+ {
+ CREATE_OBJECT_SYMBOLS
+ *(.text .text.*)
+
+ . = ALIGN(0x4);
+ /* These are for running static constructors and destructors under ELF. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+
+ *(.rodata .rodata.*)
+
+ . = ALIGN(0x4);
+ *(.gcc_except_table)
+
+ . = ALIGN(0x4);
+ *(.eh_frame)
+
+ . = ALIGN(0x4);
+ __INIT_SECTION__ = . ;
+ LONG (0x4e560000) /* linkw %fp,#0 */
+ *(.init)
+ SHORT (0x4e5e) /* unlk %fp */
+ SHORT (0x4e75) /* rts */
+
+ . = ALIGN(0x4);
+ __FINI_SECTION__ = . ;
+ LONG (0x4e560000) /* linkw %fp,#0 */
+ *(.fini)
+ SHORT (0x4e5e) /* unlk %fp */
+ SHORT (0x4e75) /* rts */
+
+ . = ALIGN(0x4);
+ _etext = .;
+ *(.lit)
+ } > ram
+
+ .data :
+ {
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.*)
+ _edata = .;
+ } > ram
+
+ .bss :
+ {
+ . = ALIGN(0x4);
+ __bss_start = . ;
+ *(.shbss)
+ *(.bss .bss.*)
+ *(COMMON)
+ _end = ALIGN (0x8);
+ __end = _end;
+ } > ram
+
+ .stab 0 (NOLOAD) :
+ {
+ *(.stab)
+ }
+
+ .stabstr 0 (NOLOAD) :
+ {
+ *(.stabstr)
+ }
+}
--- /dev/null
+#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;
+}
+
+int memcmp(const void *a, const void *b, size_t n)
+{
+ const uint8_t *ap = a;
+ const uint8_t *bp = b;
+ while(n--) {
+ if (*ap < *bp)
+ return -1;
+ if (*ap != *bp)
+ return 1;
+ ap++;
+ bp++;
+ }
+ return 0;
+}
--- /dev/null
+#define DATA 0
+#define ERR 3
+#define NSEC 5
+#define LBA0 7
+#define LBA1 9
+#define LBA2 11
+#define LBA3 13
+#define COMMAND 15
+#define STATUS 15
+
+#define READY 6
+#define DRQ 3
+
+#define READ $20
+
+/*
+ * Simple loader to get us going
+ */
+ .globl start
+ .globl loader
+
+.mri 1
+
+start:
+ jmp.l $15050
+ jmp.l $15050 ; any value will do
+ ; This bit fools the CP/M bootloader checking
+ ; 34 words of padding
+ .ds 34
+ ; should be where we end up from the bra
+loader:
+ lea $00FF0000,a0
+ lea $00FFF000,a2
+ move.b #13,(a2)
+ lea strap,a1
+ move.w #1024,d0
+reloc:
+ move.w (a1)+,(a0)+
+ dbra d0,reloc
+ jmp.l $00FF0000
+
+strap:
+ move.b #10,(a2)
+ lea $00FFE000,a1
+ lea $00000400,a0
+ move.b #2,d2 ; Sector
+ move.b #$80,d1 ; Count to load (64K for now)
+ move.b #0xE0,LBA3(a0)
+wait0:
+ btst #READY,STATUS(a1)
+ beq wait0
+
+ move.b #0,LBA2(a0)
+ move.b #0,LBA1(a0)
+load:
+ move.b d2,LBA0(a1)
+ move.b #1,NSEC(a1)
+ add.q #1,d2
+wait1:
+ btst #READY,STATUS(a1)
+ beq wait1
+ move.b #READ,COMMAND(a1)
+ nop
+wait2:
+ btst #DRQ,STATUS(a1)
+ beq wait2
+
+ move.b #'.',(a2)
+ move.w #255,d0
+sector:
+ move.w (a1),(a0)+
+ dbra d0,sector
+ dbra d1,load
+
+ move.b #13,(a2)
+ jmp.l $00000400
--- /dev/null
+OUTPUT_ARCH(m68k)
+
+SEARCH_DIR(.)
+
+MEMORY
+{
+ ram (rwx) : ORIGIN = 0x15000, LENGTH = 0x200
+}
+
+/*
+ * stick everything in ram (of course)
+ */
+SECTIONS
+{
+ .text :
+ {
+ CREATE_OBJECT_SYMBOLS
+ *(.text .text.*)
+
+ . = ALIGN(0x4);
+ /* These are for running static constructors and destructors under ELF. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+
+ *(.rodata .rodata.*)
+
+ . = ALIGN(0x4);
+ *(.gcc_except_table)
+
+ . = ALIGN(0x4);
+ *(.eh_frame)
+
+ . = ALIGN(0x4);
+ __INIT_SECTION__ = . ;
+ LONG (0x4e560000) /* linkw %fp,#0 */
+ *(.init)
+ SHORT (0x4e5e) /* unlk %fp */
+ SHORT (0x4e75) /* rts */
+
+ . = ALIGN(0x4);
+ __FINI_SECTION__ = . ;
+ LONG (0x4e560000) /* linkw %fp,#0 */
+ *(.fini)
+ SHORT (0x4e5e) /* unlk %fp */
+ SHORT (0x4e75) /* rts */
+
+ . = ALIGN(0x4);
+ _etext = .;
+ *(.lit)
+ } > ram
+
+ .data :
+ {
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.*)
+ _edata = .;
+ } > ram
+
+ .bss :
+ {
+ . = ALIGN(0x4);
+ __bss_start = . ;
+ *(.shbss)
+ *(.bss .bss.*)
+ *(COMMON)
+ _end = ALIGN (0x8);
+ __end = _end;
+ } > ram
+
+ .stab 0 (NOLOAD) :
+ {
+ *(.stab)
+ }
+
+ .stabstr 0 (NOLOAD) :
+ {
+ *(.stabstr)
+ }
+}
--- /dev/null
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include <blkdev.h>
+
+uint16_t swap_dev = 0xFFFF;
+
+void platform_idle(void)
+{
+ /* Use STOP ? */
+}
+
+void do_beep(void)
+{
+}
+
+/*
+ * MMU initialize
+ */
+
+void map_init(void)
+{
+}
+
+uaddr_t ramtop;
+uint8_t need_resched;
+
+uaddr_t pagemap_base(void)
+{
+ return 0x20000UL;
+}
+
+uint8_t platform_param(char *p)
+{
+ return 0;
+}
+
+void platform_discard(void)
+{
+}
+
+void memzero(void *p, usize_t len)
+{
+ memset(p, 0, len);
+}
+
+arg_t _memalloc(void)
+{
+ udata.u_error = ENOSYS;
+ return -1;
+}
+
+arg_t _memfree(void)
+{
+ udata.u_error = ENOSYS;
+ return -1;
+}
+
+
+/*
+ * This function is called for partitioned devices if a partition is found
+ * and marked as swap type. The first one found will be used as swap. We
+ * only support one swap device.
+ */
+void platform_swap_found(uint8_t letter, uint8_t m)
+{
+ blkdev_t *blk = blk_op.blkdev;
+ uint16_t n;
+ if (swap_dev != 0xFFFF)
+ return;
+ letter -= 'a';
+ kputs("(swap) ");
+ swap_dev = letter << 4 | m;
+ n = blk->lba_count[m - 1] / SWAP_SIZE;
+ if (n > MAX_SWAPS)
+ n = MAX_SWAPS;
+#ifdef SWAPDEV
+ while (n)
+ swapmap_init(n--);
+#endif
+}
+/* Live udata and kernel stack */
+u_block udata_block;
+uint16_t irqstack[128]; /* Used for swapping only */
+
+/* This will belong in the core 68K code once finalized */
+
+void install_vdso(void)
+{
+ extern uint8_t vdso[];
+ /* Should be uput etc */
+ memcpy((void *)udata.u_codebase, &vdso, 0x40);
+}
+
+
+extern void *get_usp(void);
+extern void set_usp(void *p);
+
+void signal_frame(uint8_t *trapframe, uint32_t d0, uint32_t d1, uint32_t a0,
+ uint32_t a1)
+{
+ extern void *udata_shadow;
+ uint8_t *usp = get_usp();
+ udata_ptr = udata_shadow;
+ uint16_t ccr = *(uint16_t *)trapframe;
+ uint32_t addr = *(uint32_t *)(trapframe + 2);
+ int err = 0;
+
+ /* Build the user stack frame */
+
+ /* FIXME: eventually we should put the trap frame details and trap
+ info into the frame */
+ usp -= 4;
+ err |= uputl(addr, usp);
+ usp -= 4;
+ err |= uputw(ccr, usp);
+ usp -= 2;
+ err |=uputl(a1, usp);
+ usp -= 4;
+ err |= uputl(a0, usp);
+ usp -= 4;
+ err |= uputl(d1, usp);
+ usp -= 4;
+ err |= uputl(d0, usp);
+ usp -= 4;
+ err |= uputl(udata.u_codebase + 4, usp);
+ set_usp(usp);
+
+ if (err) {
+ kprintf("%d: stack fault\n", udata.u_ptab->p_pid);
+ doexit(SIGKILL/* FIXME dump_core(SIGKILL)*/);
+ }
+ /* Now patch up the kernel frame */
+ *(uint16_t *)trapframe = 0;
+ *(uint32_t *)(trapframe + 2) = (uint32_t)udata.u_sigvec[udata.u_cursig];
+ udata.u_sigvec[udata.u_cursig] = SIG_DFL;
+ udata.u_cursig = 0;
+}
--- /dev/null
+
+#include "../kernel-68000.def"
+/*
+ * Lots left to fill in
+ */
+
+ .globl platform_reboot
+ .globl init_early
+ .globl init_hardware
+ .globl program_vectors
+ .globl outchar
+ .globl platform_monitor
+ .globl udata_block
+ .globl devide_read_data
+ .globl devide_write_data
+ .globl vdso
+.mri 1
+platform_reboot:
+platform_monitor:
+ or #0700,sr
+ bra platform_monitor
+
+init_early:
+ lea.l udata_block,a5 ; udata ptr
+ move.l a5,udata_shadow ; shadow copy for entry/exit
+ rts
+
+;
+; FIXME: could be in discard if we wanted
+;
+init_hardware:
+ ; set system RAM size(hardcode hacks for now)
+ move.w #16352,d0
+ move.w d0,ramsize
+ sub.w #64,d0 ; Guess for kernel
+ move.w d0,procmem ; guesses for now
+
+ move.l #8,a0
+ move.w #253,d0
+ move.l #unexpected,d1
+init_trap_loop:
+ move.l d1,(a0)+
+ dbra d0,init_trap_loop
+ ;
+ ; Now set the vectors we care about
+ ;
+ move.w #8,a0
+ move.l #bus_error,(a0)+
+ move.l #addr_error,(a0)+
+ move.l #illegal,(a0)+
+ move.l #divzero,(a0)+
+ move.l #chk,(a0)+
+ move.l #trapv,(a0)+
+ move.l #priv,(a0)+
+ move.l #trace,(a0)+
+ move.l #unimpa,(a0)+ ; A and F line traps
+ move.l #unimpf,(a0)+
+ move.w #$80,a0
+ move.w #13,d0
+trapset:
+ move.l #misctrap,(a0)+
+ dbra d0,trapset
+ move.l #trap14,(a0)+
+ move.l #trap15,(a0)+
+ move.w #$0,a0
+ move.l #uninit,$3c(a0)
+ move.l #spurious,$60(a0)
+ ; FIXME: vectored so actually vector 0x81 I think ?
+ move.l #timer_irq,$78(a0)
+
+ rts
+
+timer_irq:
+ ; C will save and restore a2+/d2+
+ movem.l a0-a1/a5/d0-d1,-(sp)
+ move.l udata_shadow,a5 ; set up the register global
+ move.b #1,U_DATA__U_ININTERRUPT(a5)
+ jsr platform_interrupt
+ clr.b U_DATA__U_ININTERRUPT(a5)
+
+ tst.b U_DATA__U_INSYS(a5)
+ bne no_preempt
+ tst.b need_resched
+ bne no_preempt
+ ;
+ ; Vanish into the scheduler. Some other task will pop back out
+ ; and eventually we'll re-appear here and continue.
+ ;
+ ; FIXME: check IRQ masking
+ ;
+ move.l U_DATA__U_PTAB(a5),a0
+ move.b #P_READY,P_TAB__P_STATUS_OFFSET(a0)
+ bsr switchout
+no_preempt:
+ tst.b U_DATA__U_CURSIG(a5)
+ beq no_signal
+ bra trap_via_signal ; a0/a1/d0/d1 already stacked
+
+no_signal:
+ movem.l (sp)+,a0-a1/a5/d0-d1
+ rte
+
+;
+; Nothing to do in 68000 - all set up once at boot
+;
+program_vectors:
+ rts
+
+;
+; We do no banking so we need to do nothing here.
+;
+map_process_always:
+map_process:
+map_kernel:
+map_restore:
+map_save:
+ rts
+
+; outchar: Wait for UART TX idle, then print the char in d0
+
+outchar:
+outcharw:
+ btst #2,$00FFF003
+ beq outcharw
+ move.b d0,$00FFF000
+ rts
+;
+; IDE:
+;
+devide_read_data:
+ move.l blk_op,a0
+ move.l #$00FFE000,a1
+ move.w #255,d0
+devide_read_l:
+ move.w (a1),(a0)+
+ dbra d0,devide_read_l
+ rts
+
+devide_write_data:
+ move.l blk_op,a0
+ move.l #$00FFE000,a1
+ move.w #255,d0
+devide_write_l:
+ move.w (a0)+,(a1)
+ dbra d0,devide_write_l
+ rts
+
+;
+; 'VDSO'
+;
+vdso: trap #14 ; syscall entry
+ rts
+ ; signal unwind
+ movem.l (sp)+,a0/a1/d0/d1
+ move.w (sp)+,ccr
+ rts
+ ; rest is spare for now
+
+.section data
+
+kernel_flag: byte 1
--- /dev/null
+#define IDE_IS_MMIO 1 /* MMIO IDE */
+
+#define IDE_REG_DATA 0x00F01000
+#define IDE_REG_ERROR 0x00F01003
+#define IDE_REG_FEATURES 0x00F01003
+#define IDE_REG_SEC_COUNT 0x00F01005
+#define IDE_REG_LBA_0 0x00F01007
+#define IDE_REG_LBA_1 0x00F01009
+#define IDE_REG_LBA_2 0x00F0100B
+#define IDE_REG_LBA_3 0x00F0100D
+#define IDE_REG_DEVHEAD 0x00F0100D
+#define IDE_REG_STATUS 0x00F0100F
+#define IDE_REG_COMMAND 0x00F0100F
+
+/* FIXME: Check altstatus/control mapping */
+
+#define ide_select(x)
+#define ide_deselect()
--- /dev/null
+export CPU = 68000
--- /dev/null
+#include "../kernel-68000.def"
+
+
+.globl platform_switchout,switchin,dofork,udata_shadow
+
+.mri 1
+
+; 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().
+platform_switchout:
+ or #$0700,sr
+ ; save machine state
+
+ clr.w -(sp) ; 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:
+ move.l usp,a0
+ movem.l a0/a2-a4/a6/d2-d7,-(sp)
+ move.l sp,U_DATA__U_SP(a5) ; this is where the SP is restored in switchin
+
+ ; find another process to run (may select this one again)
+ bsr getproc
+
+ move.l d0,-(sp)
+ bsr switchin
+
+ ; we should never get here
+ bra platform_monitor
+
+switchin:
+ or #$0700,sr
+ move.l 4(sp),a0 ; task to switch to
+ move.l P_TAB__P_UDATA_OFFSET(a0),a5
+ tst.w P_TAB__P_PAGE_OFFSET(a0) ; swapped or existing process ?
+ bne not_swapped
+
+;
+; If you have one udata and swap them then you need to stack switch
+; for the swap in as you'll overwrite the kernel stack. You can use
+; the IRQ stack but only if you leave IRQs off for a swap in (ugghh)
+;
+
+;
+; FIXME: sort IRQ enables
+;
+
+;
+; In simple mode the existing process always gets the boot here
+; before we can swap the new one in
+;
+ move.l U_DATA__U_PTAB(a5),a1 ; old process
+ tst.w P_TAB__P_PAGE_OFFSET(a1) ; swapped out/dead ?
+ beq its_dead_jim ; corpses don't need swapping out
+
+ move.l a0,-(sp)
+ move.l a1,-(sp)
+ jsr swapout
+ addq #4,sp
+ move.l (sp)+,a0
+
+its_dead_jim:
+ move.l sp,a1
+ move.l #irqstack+256,sp
+ move.l a1,-(sp)
+ move.l a0,-(sp)
+ move.l a0,-(sp)
+ jsr swapper
+ addq #4,sp
+ move.l (sp)+,a0
+ move.w #1,P_TAB__P_PAGE_OFFSET(a0) ; swapped in
+ move.l (sp)+,a1 ; straight into a7 fails
+ move.l a1,a7 ; emulator bug or CPU funny ??
+
+ or #$0700,sr
+
+not_swapped:
+ ; check u_data->u_ptab matches what we wanted
+ cmp.l U_DATA__U_PTAB(a5),a0
+ bne switchinfail
+
+ move.b #P_RUNNING,P_TAB__P_STATUS_OFFSET(a0)
+
+ ; runticks = 0
+ clr.w runticks
+
+ ; restore machine state
+ move.l U_DATA__U_SP(a5),sp
+ movem.l (sp)+,a0/a2-a4/a6/d2-d7
+ move.l a0,usp
+ move.w (sp)+,d0 ; FIXME: can we merge ?
+
+ tst.b U_DATA__U_ININTERRUPT(a5)
+ bne keepoff ; in ISR, leave interrupts off
+ and #$F8FF,sr
+keepoff:
+ rts ; return with interrupts on
+
+switchinfail:
+ bsr outa0hex
+ lea badswitchmsg,a0
+ bsr outstring
+ ; something went wrong and we didn't switch in what we asked for
+ bra platform_monitor
+
+ ;
+ ; this gets exciting on the 68000 because our udata is not in a
+ ; fixed location except for swap only platforms. That means any
+ ; udata relative pointers on the stack when we duplicate the kernel
+ ; stack point to the parent. For the simple case we have a single
+ ; swapped udata and stack so all is fairly easy. For the other
+ ; cases we have to return as the parent but set up a fake stack
+ ; frame for the child to exit the syscall. Simply being careful
+ ; about pointers doesn't work - the compiler will internally
+ ; use link/unlk and other stuff.
+ ;
+ ; Entry:
+ ; A5 = u_data pointer for parent
+ ; 4(sp) = child process table entry
+ ;
+ ; Exit:
+ ; We are running as the child, A5 = u_data pointer of child, on
+ ; child stack
+ ;
+dofork:
+ ;
+ ; simple edition for swap only
+ ;
+ move.l 4(sp),a0 ; child p_tab
+ ;
+ ; in the simple case we only have one udata. In the complex cases
+ ; we would have to compute the new one and load it into a5 and
+ ; offset
+ ;
+ move.l a5,P_TAB__P_UDATA_OFFSET(a0)
+ move.w P_TAB__P_PID_OFFSET(a0),-(sp) ; child pid (parent return)
+ move.l usp,a0
+ movem.l a0/a2-a4/a6/d2-d7,-(sp) ; save state
+ move.l sp,U_DATA__U_SP(a5) ; save pointer
+ move.l U_DATA__U_PTAB(a5),-(sp) ; parent p_tab
+
+ ; FIXME: for the single case with less swaps than processes the
+ ; out of swap case is one out (we must swap out to swap in so need
+ ; one swap free after the fork. Right now we deal with this in
+ ; Config by not setting it that way
+ jsr swapout
+ add.w #50,sp ; throw the call frame and
+ ; the frame we built for
+ ; switchin
+ tst.w d0
+ bne forked_up
+
+ movel a5,-(sp) ; U_DATA
+ move.l 4(sp),a0
+ move.l a0,-(sp)
+ jsr makeproc
+ addq #8,sp
+
+ moveq #0,d0 ; child, ok
+ clr.w runticks
+ rts
+forked_up:
+ moveq #-1,d0 ; parent, failed
+ rts
+
+badswitchmsg: ascii "_switchin: FAIL"
+ byte 13,10,0
+.even