spx302: Initial code sketch for the SPX302/MPU302 conversion
authorAlan Cox <alan@linux.intel.com>
Wed, 20 Feb 2019 01:06:16 +0000 (01:06 +0000)
committerAlan Cox <alan@linux.intel.com>
Wed, 20 Feb 2019 01:06:16 +0000 (01:06 +0000)
See https://www.retrobrewcomputers.org/doku.php?id=builderpages:plasmo:spx-mpu
for more information about this system.

This is just an initial set of buildable code. It needs a loader and debugging
before we can get further

16 files changed:
Kernel/platform-spx302/Makefile [new file with mode: 0644]
Kernel/platform-spx302/README [new file with mode: 0644]
Kernel/platform-spx302/config.h [new file with mode: 0644]
Kernel/platform-spx302/crt0.S [new file with mode: 0644]
Kernel/platform-spx302/devices.c [new file with mode: 0644]
Kernel/platform-spx302/devtty.c [new file with mode: 0644]
Kernel/platform-spx302/devtty.h [new file with mode: 0644]
Kernel/platform-spx302/fuzix.ld [new file with mode: 0644]
Kernel/platform-spx302/kernel.def [new file with mode: 0644]
Kernel/platform-spx302/libc.c [new file with mode: 0644]
Kernel/platform-spx302/main.c [new file with mode: 0644]
Kernel/platform-spx302/p68000.S [new file with mode: 0644]
Kernel/platform-spx302/platform_ide.h [new file with mode: 0644]
Kernel/platform-spx302/ppide_spx302.c [new file with mode: 0644]
Kernel/platform-spx302/target.mk [new file with mode: 0644]
Kernel/platform-spx302/tricks.S [new file with mode: 0644]

diff --git a/Kernel/platform-spx302/Makefile b/Kernel/platform-spx302/Makefile
new file mode 100644 (file)
index 0000000..0af3636
--- /dev/null
@@ -0,0 +1,51 @@
+
+CSRCS = devtty.c
+CSRCS += devices.c main.c libc.c ppide_spx302.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))
+
+LSRCS = ../lib/68000exception.c
+LOBJS = $(patsubst ../lib/%.c,%.o, $(LSRCS))
+
+COBJS = $(CSRCS:.c=.o)
+AOBJS = $(ASRCS:.S=.o)
+OBJS  = $(COBJS) $(AOBJS) $(DOBJS) $(LOBJS)
+
+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 $<
+
+$(LOBJS): %.o: ../lib/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+tricks.S: ../lib/68000flat.S
+
+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 main.o ../timer.o ../kdata.o 68000exception.o devices.o \
+       ../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
+       ../syscall_proc.o ../syscall_other.o ../mm.o ../flat.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 ppide_spx302.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
diff --git a/Kernel/platform-spx302/README b/Kernel/platform-spx302/README
new file mode 100644 (file)
index 0000000..d158e89
--- /dev/null
@@ -0,0 +1,81 @@
+Adapted Sonoplex MC68302 board
+
+https://retrobrewcomputers.org/doku.php?id=builderpages:plasmo:spx-mpu
+
+This a system with a 68302@16MHz, 2.25MB of flash (holding a boot ROM and CP/M
+68K) as well as a monitor, 1MB of RAM (256K battery backed) a 68692 DUART
+providing a console port, an 82C55 PIO and an RTC (not yet handled).
+
+There is a plug in board which provides a CF interface using the 82C55, and
+interface points for the second DUART port and minimal SPI.
+
+
+Memory Map
+
+When are loaded we have the 68302 internal I/O mapped at FFF000 and the
+RAM mapped at 0.
+
+000000-0FFFFF          RAM (1MB)
+300000-300007          82C55 (odd side)
+300000-300020          DUART (68692) (even side)
+300040-30005F          RTC72743 (odd side)
+
+Chip Selects
+
+0              Boot Flash 256K (1 wait)
+1              RAM, 4MB mapping (0 wait)
+2              400000, 1MB 1 wait (flash)
+3              500000, 1MB 1 wait (flash)
+
+RAM is aliased in the low 1MB
+GIMR is set to vector 80-9F
+TMR1 is set to 10ms
+The RTC is kicked into 24hr mode
+DUART and TMR1 are the interrupt sources
+
+As we boot CP/M 68K from ROM we need to run from CP/M 68K as follows
+
+Binary header
+601AH
+Size of text.L
+Size of data.L
+Size of BSS.L
+0.L (Sizeof syms)
+0.L
+0.L (beginning of text segment and start)
+0.W (no reloc)
+[text][data]
+
+Supervisor mode:
+
+MOVE.W #$3E,D0
+TRAP #2
+
+returns in supervisor mode on the CP/M supervisor stack
+
+
+The serial ports are mapped as follows
+
+tty1   The DB25 serial port
+tty2   The port on the CF card
+Future:
+tty3-5 The SCC ports (these are wired as RS422/485)
+
+TODO
+
+Figure out the right rituals to get the CP/M 68K filesystem working in the
+CP/M utils
+Write a front end CP/M loader module that has the kernel as data and boots it
+Test the console and timer drivers
+Test IDE
+Write RTC driver
+Investigate the SPI state of affairs, see if we can get SD working
+Reboot logic
+
+Longer Term
+
+SCC RS485 drivers (serial and/or networking ?)
+Ethernet over SPI
+
+How to do swap ?
+
diff --git a/Kernel/platform-spx302/config.h b/Kernel/platform-spx302/config.h
new file mode 100644 (file)
index 0000000..7fb99bd
--- /dev/null
@@ -0,0 +1,47 @@
+/* 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
+
+#define CONFIG_MULTI
+#define CONFIG_FLAT
+#define CONFIG_PARENT_FIRST
+#define CONFIG_USERMEM_DIRECT
+#define CONFIG_BANKS   (65536/512)
+
+#define CONFIG_LARGE_IO_DIRECT(x)      1
+
+#define CONFIG_SPLIT_UDATA
+#define UDATA_SIZE     1024
+#define UDATA_BLKS     2
+
+#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()
+
+#define BOOTDEVICENAMES "hd#"
diff --git a/Kernel/platform-spx302/crt0.S b/Kernel/platform-spx302/crt0.S
new file mode 100644 (file)
index 0000000..910e1d7
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *     Need to wipe BSS etc once we figure out our preferred boot method
+ *
+ *     On entry we are loaded at $0400 with the loader and the loaders
+ *     supervisor stack a mystery. We are in supervisor mode and the rest
+ *     is our problem.
+ */
+               #include "../kernel-68000.def"
+
+               .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
+
+               lea udata_block0+UBLOCK_SIZE,a7
+               bsr init_early
+               bsr init_hardware
+               bsr fuzix_main
+               or #$0700,sr
+stop:          bra stop
diff --git a/Kernel/platform-spx302/devices.c b/Kernel/platform-spx302/devices.c
new file mode 100644 (file)
index 0000000..a1729bc
--- /dev/null
@@ -0,0 +1,39 @@
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <devide.h>
+#include <blkdev.h>
+#include <devsys.h>
+#include <tty.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)
+{
+  devide_init();
+}
diff --git a/Kernel/platform-spx302/devtty.c b/Kernel/platform-spx302/devtty.c
new file mode 100644 (file)
index 0000000..ecffc83
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *     The SPX302 has multiple serial ports but the 68302 built in ones are
+ *     wired for RS485 so for now ignore them. Some day they'll be handy for
+ *     TCP/IP ;-)
+ *
+ *     This wants rewriting once it is all stable so that the serial interrupt
+ *     isn't masked by the kernel and drives queues.
+ */
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <devtty.h>
+#include <tty.h>
+
+static unsigned char tbuf1[TTYSIZ];
+static unsigned char tbuf2[TTYSIZ];
+
+#define UART_MRA       0x00
+#define UART_SRA       0x02
+#define UART_CSRA      0x02
+#define UART_CRA       0x04
+#define UART_RHRA      0x06
+#define UART_THRA      0x06
+#define UART_IPCR      0x08
+#define UART_ACR       0x08
+#define UART_ISR       0x0A
+#define UART_IMR       0x0A
+#define UART_CTU       0x0C
+#define UART_CTUR      0x0C
+#define UART_CTL       0x0E
+#define UART_CTLR      0x0E
+#define UART_MRB       0x10
+#define UART_SRB       0x12
+#define UART_CSRB      0x12
+#define UART_CRB       0x14
+#define UART_RHRB      0x16
+#define UART_THRB      0x16
+#define UART_IVR       0x18
+#define UART_OPCR      0x1A
+#define UART_STARTCTR  0x1C
+#define UART_SETOPR    0x1C
+#define UART_STOPCTR   0x1E
+#define UART_CLROPR    0x1E
+
+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
+};
+
+static volatile uint8_t *uart_base = (volatile uint8_t *)0x300020;
+
+#define GETB(x)                (uart_base[(x)])
+#define PUTB(x,y)      uart_base[(x)] = (y)
+
+/* Output for the system console (kprintf etc). Polled. */
+void kputchar(char c)
+{
+       if (c == '\n') {
+               while(!(GETB(UART_SRA) &  4));
+               PUTB(UART_THRA, '\r');
+       }
+       while(!(GETB(UART_SRA) &  4));
+       PUTB(UART_THRA, c);
+}
+
+ttyready_t tty_writeready(uint8_t minor)
+{
+       uint8_t c = GETB(0x10 * (minor - 1) + UART_SRA);
+       return (c & 4) ? TTY_READY_NOW : TTY_READY_SOON; /* TX DATA empty */
+}
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+       PUTB(0x10 * (minor - 1) + UART_THRA, c);
+}
+
+void tty_setup(uint8_t minor, uint8_t flags)
+{
+       /* TODO */
+}
+
+int tty_carrier(uint8_t minor)
+{
+       return 1;
+}
+
+void tty_sleeping(uint8_t minor)
+{
+       sleeping |= 1 << minor;
+}
+
+void tty_data_consumed(uint8_t minor)
+{
+}
+
+static void tty_interrupt(uint8_t r)
+{
+       if (r & 0x02) {
+               r = GETB(UART_RHRA);
+               tty_inproc(1,r);
+       }       
+       if (r & 0x01) {
+               if (sleeping & 2)
+                       tty_outproc(1);
+       }
+       if (r & 0x04) {
+               /* How to clear break int ? */
+       }
+       if (r & 0x20) {
+               r = GETB(UART_RHRB);
+               tty_inproc(2,r);
+       }       
+       if (r & 0x10) {
+               if (sleeping & 4)
+                       tty_outproc(2);
+       }
+       if (r & 0x40) {
+               /* How to clear break int ? */
+       }
+}
+
+void duart_interrupt(void)
+{
+       uint8_t r = GETB(UART_ISR);
+       tty_interrupt(r);
+}
+
+void platform_interrupt(void)
+{
+       timer_interrupt();
+}
diff --git a/Kernel/platform-spx302/devtty.h b/Kernel/platform-spx302/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-spx302/fuzix.ld b/Kernel/platform-spx302/fuzix.ld
new file mode 100644 (file)
index 0000000..ea455a5
--- /dev/null
@@ -0,0 +1,87 @@
+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)
+  }
+}
diff --git a/Kernel/platform-spx302/kernel.def b/Kernel/platform-spx302/kernel.def
new file mode 100644 (file)
index 0000000..4b1466f
--- /dev/null
@@ -0,0 +1,2 @@
+#define DI_MASK                $700            /* or bits for DI */
+#define EI_MASK                $000            /* or bits for EI */
\ No newline at end of file
diff --git a/Kernel/platform-spx302/libc.c b/Kernel/platform-spx302/libc.c
new file mode 100644 (file)
index 0000000..f172e3b
--- /dev/null
@@ -0,0 +1,52 @@
+#include "cpu.h"
+
+/* FIXME: use proper fast methods */
+
+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 *memcpy32(void *d, const void *s, size_t sz)
+{
+  uint32_t *dp = d;
+  const uint32_t *sp = s;
+  sz >>= 2;
+  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;
+}
diff --git a/Kernel/platform-spx302/main.c b/Kernel/platform-spx302/main.c
new file mode 100644 (file)
index 0000000..2924722
--- /dev/null
@@ -0,0 +1,81 @@
+#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;
+
+uint8_t platform_param(char *p)
+{
+       return 0;
+}
+
+void platform_discard(void)
+{
+       /* We need to put discard last and then adjust _end */
+}
+
+void memzero(void *p, usize_t len)
+{
+       memset(p, 0, len);
+}
+
+void pagemap_init(void)
+{
+       /* Linker provided end of kernel */
+       extern uint8_t _end;
+       uint32_t e = (uint32_t)&_end;
+       kprintf("Kernel end %p\n", e);
+       /* Allocate the rest of memory to the userspace. We have 1MB. For now
+          ignore the battery backed area */
+       kmemaddblk((void *)e, 0xC0000 - e);
+}
+
+/* Udata and kernel stacks */
+/* We need an initial kernel stack and udata so the slot for init is
+   set up at compile time */
+u_block udata_block0;
+static u_block *udata_block[PTABSIZE] = {&udata_block0,};
+
+/* 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);
+}
+
+uint8_t platform_udata_set(ptptr p)
+{
+       u_block **up = &udata_block[p - ptab];
+       if (*up == NULL) {
+               *up = kmalloc(sizeof(struct u_block), 0);
+               if (*up == NULL)
+                       return ENOMEM;
+       }
+       p->p_udata = &(*up)->u_d;
+       return 0;
+}
diff --git a/Kernel/platform-spx302/p68000.S b/Kernel/platform-spx302/p68000.S
new file mode 100644 (file)
index 0000000..e53d7c5
--- /dev/null
@@ -0,0 +1,203 @@
+
+#include "../kernel-68000.def"
+
+               .globl platform_reboot
+               .globl init_early
+               .globl init_hardware
+               .globl program_vectors
+               .globl outchar
+               .globl platform_monitor
+               .globl udata_block0
+               .globl devide_read_data
+               .globl devide_write_data
+
+.mri 1
+platform_monitor:
+platform_reboot:
+;
+;      FIXME: remap ROM at 0 and get back to it
+;
+           or #$0700,sr
+           bra platform_monitor
+
+init_early:
+           lea.l udata_block0,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 #768,d0              ; ignore the ramdisc
+           move.w d0,ramsize
+           sub.w  #64,d0               ; Guess for kernel
+           move.w d0,procmem           ; guesses for now
+
+           bsr install_vectors
+
+           /* We use Vector 0x81 for the DUART */
+           move.l #duart_irq,$204
+           /* and the timer.. */
+           /* 0x89 is the 68302 10ms timer */
+           move.l #timer_irq,$224
+
+            rts
+
+duart_irq:
+           movem.l a0/a1/a5/d0/d1,-(sp)
+           jsr duart_interrupt
+           move.w #2,$FFF818           ; clear interrupt flag
+           movem.l (sp)+,a0/a1/a5/d0/d1
+           rte
+
+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)
+           ; Now ack the hardware interrupt
+           move.b #3,$FFF849           ; Timer A event register
+           move.w #$200,$FFF818        ; Interrupt service
+           jsr platform_interrupt
+           clr.b U_DATA__U_ININTERRUPT(a5)
+
+           tst.b U_DATA__U_INSYS(a5)
+           bne no_preempt
+           tst.b need_resched
+           beq no_preempt
+           ;
+           ;   Vanish into the scheduler. Some other task will pop back out
+           ;   and eventually we'll re-appear here and continue.
+           ;
+           move.l U_DATA__U_PTAB(a5),a0
+           ; We might be in STOPPED state in which case do not go back
+           ; to ready !
+           cmp.b #P_RUNNING,P_TAB__P_STATUS_OFFSET(a0)
+           bne no_ready
+           move.b #P_READY,P_TAB__P_STATUS_OFFSET(a0)
+no_ready:
+           bsr switchout
+no_preempt:
+           tst.b U_DATA__U_CURSIG(a5)
+           beq no_signal
+           ;   FIXME: this is ugly
+           movem.l (sp)+,a0-a1/a5/d0-d1
+           move.w sr,-(sp)
+           move.w #0,-(sp)
+           movem.l a0-a6/d0-d7,-(sp)
+           move.l (sp),-(sp)
+           bsr exception
+           addq #4,sp
+           movem.l (sp)+,a0-a6/d0-d7
+           addq #4,sp
+           rte
+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,$00C00002
+       beq outcharw
+       move.b d0,$00C00006
+       rts
+
+;
+;      ATA CF support via PPIDE
+;
+
+#define PortA8255      $300001
+#define PortB8255      $300003
+#define PortC8255      $300005
+#define Port8255Ctrl   $300007
+
+;
+;      Need to look at the fixes on write for the V1 board reliability.
+;
+devide_read_data:
+       movem.l a2/d2/d3,-(sp)
+       ; Target address
+       move.l (blk_op),a0
+       ; Set up constants for speed
+       lea.l PortC8255,a1
+       lea.l PortA8255,a2
+       move.b #$40,d1
+       move.b #$48,d2
+       ; 256 words
+       ; Just in case a user is trying to do a misaligned raw I/O
+       move.w a0,d0
+       btst #0,d0
+       bne doreadblock8
+       move.w #255,d0
+readblock:
+       ; Waggle the control signals
+       move.b d1,(a1)
+       move.b d2,(a1)
+       ; 16bits split across two words
+       movep.w 0(a2),d3
+       ; Store to the target buffer
+       move.w d3,(a0)+
+       dbra d0,readblock
+       move.b d1,(a1)
+       movem.l (sp)+,a2/d2/d3
+       rts
+
+doreadblock8:
+       move.l a3,-(sp)
+       lea.l PortB8255,a3
+       move.w #255,d0
+readblock8:
+       ; Waggle the control signals
+       move.b d1,(a1)
+       move.b d2,(a1)
+       ; 16bits split across two words
+       move.b (a3),(a0)+
+       move.b (a2),(a0)+
+       dbra d0,readblock8
+       move.b d1,(a1)
+       move.l (sp)+,a3
+       movem.l (sp)+,a2/d2/d3
+       rts
+
+; FIXME: can we use movep
+
+devide_write_data:
+       movem.l a2-a3/d2,-(sp)
+       move.l (blk_op),a0
+       lea.l PortA8255,a1
+       lea.l PortB8255,a2
+       lea.l PortC8255,a3
+       move.b #$40,d1
+       move.b #$50,d2
+       move.b #$80,Port8255Ctrl
+       move.w #255,d0
+writeblock:
+       move.b (a0)+,(a1)
+       move.b (a0)+,(a2)
+       move.b d1,(a3)
+       move.b d2,(a3)
+       move.b d1,(a3)
+       dbra d0,writeblock
+       move.b #$92,Port8255Ctrl
+       movem.l (sp)+,a2-a3/d2
+       rts
diff --git a/Kernel/platform-spx302/platform_ide.h b/Kernel/platform-spx302/platform_ide.h
new file mode 100644 (file)
index 0000000..3249b0e
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *     Platform specific declarations for the ParPort IDE device.
+ *     This tells the shared driver how the thing is wired up. In our case
+ *     it's MMIO
+ */
+
+#define PPIDE_BASE 0x300000     /* Base address of 8255A */
+#define IDE_REG_INDIRECT        /* IDE registers are not directly connected to the CPU bus */
+
+/* IDE control signal to 8255 port C mapping */
+#define PPIDE_A0_LINE           0x01 // Direct from 8255 to IDE interface
+#define PPIDE_A1_LINE           0x02 // Direct from 8255 to IDE interface
+#define PPIDE_A2_LINE           0x04 // Direct from 8255 to IDE interface
+#define PPIDE_CS0_LINE          0x08 // Inverter between 8255 and IDE interface
+#define PPIDE_CS1_LINE          0x10 // Inverter between 8255 and IDE interface
+#define PPIDE_WR_LINE           0x20 // Inverter between 8255 and IDE interface
+#define PPIDE_WR_BIT            5    // (1 << PPIDE_WR_BIT) = PPIDE_WR_LINE
+#define PPIDE_RD_LINE           0x40 // Inverter between 8255 and IDE interface
+#define PPIDE_RD_BIT            6    // (1 << PPIDE_RD_BIT) = PPIDE_RD_LINE
+#define PPIDE_RST_LINE          0x80 // Inverter between 8255 and IDE interface
+
+/* 8255 configuration */
+#define PPIDE_PPI_BUS_READ      0x92
+#define PPIDE_PPI_BUS_WRITE     0x80
+
+/* IDE register addresses */
+#define ide_reg_data      (PPIDE_CS0_LINE)
+#define ide_reg_error     (PPIDE_CS0_LINE | PPIDE_A0_LINE)
+#define ide_reg_features  (PPIDE_CS0_LINE | PPIDE_A0_LINE)
+#define ide_reg_sec_count (PPIDE_CS0_LINE | PPIDE_A1_LINE)
+#define ide_reg_lba_0     (PPIDE_CS0_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE)
+#define ide_reg_lba_1     (PPIDE_CS0_LINE | PPIDE_A2_LINE)
+#define ide_reg_lba_2     (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A0_LINE)
+#define ide_reg_lba_3     (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE)
+#define ide_reg_devhead   (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE)
+#define ide_reg_command   (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE)
+#define ide_reg_status    (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE)
+#define ide_reg_altstatus (PPIDE_CS1_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE)
+#define ide_reg_control   (PPIDE_CS1_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE)
+
+#define ide_select(x)
+#define ide_deselect()
diff --git a/Kernel/platform-spx302/ppide_spx302.c b/Kernel/platform-spx302/ppide_spx302.c
new file mode 100644 (file)
index 0000000..3fbc235
--- /dev/null
@@ -0,0 +1,42 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <timer.h>
+#include <devide.h>
+#include <blkdev.h>
+
+#define  ppi_port_a *((volatile uint8_t *)0xC00001)    /* LSB */
+#define  ppi_port_b *((volatile uint8_t *)0xC00003)    /* MSB */
+#define  ppi_port_c *((volatile uint8_t *)0xC00005)    /* IDE Control */
+#define  ppi_control *((volatile uint8_t *)0xC00007)   /* 82C55 Control */
+
+void ppide_init(void)
+{
+    ppi_control = PPIDE_PPI_BUS_READ;
+    ppi_port_c = ide_reg_status;
+}
+
+uint8_t devide_readb(uint8_t regaddr)
+{
+    uint8_t r;
+
+    /* note: ppi_control should contain PPIDE_PPI_BUS_READ already */
+    ppi_port_c = regaddr;
+    ppi_port_c = regaddr | PPIDE_RD_LINE; /* begin /RD pulse */
+    r = ppi_port_a;
+    ppi_port_c = regaddr;       /* end /RD pulse */
+    return r;
+}
+
+void devide_writeb(uint8_t regaddr, uint8_t value)
+{
+    ppi_control = PPIDE_PPI_BUS_WRITE;
+    ppi_port_c = regaddr;
+    ppi_port_a = value;
+    ppi_port_b = 0;
+    ppi_port_c = regaddr | PPIDE_WR_LINE;
+    /* FIXME: check timing */
+    ppi_port_c = regaddr;
+    ppi_control = PPIDE_PPI_BUS_READ;
+}
diff --git a/Kernel/platform-spx302/target.mk b/Kernel/platform-spx302/target.mk
new file mode 100644 (file)
index 0000000..df1c235
--- /dev/null
@@ -0,0 +1 @@
+export CPU = 68000
diff --git a/Kernel/platform-spx302/tricks.S b/Kernel/platform-spx302/tricks.S
new file mode 100644 (file)
index 0000000..b98eaa3
--- /dev/null
@@ -0,0 +1,3 @@
+#include "../kernel-68000.def"
+
+#include "../lib/68000flat.S"