yaz180: initial bits
authorAlan Cox <alan@linux.intel.com>
Mon, 4 Feb 2019 18:37:49 +0000 (18:37 +0000)
committerAlan Cox <alan@linux.intel.com>
Mon, 4 Feb 2019 18:37:49 +0000 (18:37 +0000)
20 files changed:
Kernel/platform-yaz180/Makefile [new file with mode: 0644]
Kernel/platform-yaz180/README [new file with mode: 0644]
Kernel/platform-yaz180/commonmem.s [new file with mode: 0644]
Kernel/platform-yaz180/config.h [new file with mode: 0644]
Kernel/platform-yaz180/crt0.s [new file with mode: 0644]
Kernel/platform-yaz180/devices.c [new file with mode: 0644]
Kernel/platform-yaz180/devsdspi.c [new file with mode: 0644]
Kernel/platform-yaz180/devtty.c [new file with mode: 0644]
Kernel/platform-yaz180/devtty.h [new file with mode: 0644]
Kernel/platform-yaz180/discard.c [new file with mode: 0644]
Kernel/platform-yaz180/diskboot.s [new file with mode: 0644]
Kernel/platform-yaz180/fuzix.lnk [new file with mode: 0644]
Kernel/platform-yaz180/kernel.def [new file with mode: 0644]
Kernel/platform-yaz180/main.c [new file with mode: 0644]
Kernel/platform-yaz180/monitor.s [new file with mode: 0644]
Kernel/platform-yaz180/platform_ide.h [new file with mode: 0644]
Kernel/platform-yaz180/ppide.c [new file with mode: 0644]
Kernel/platform-yaz180/target.mk [new file with mode: 0644]
Kernel/platform-yaz180/yaz180.s [new file with mode: 0644]
Kernel/platform-yaz180/z180.s [new file with mode: 0644]

diff --git a/Kernel/platform-yaz180/Makefile b/Kernel/platform-yaz180/Makefile
new file mode 100644 (file)
index 0000000..75ad1bc
--- /dev/null
@@ -0,0 +1,48 @@
+ASRCS = crt0.s z180.s commonmem.s yaz180.s monitor.s
+CSRCS += devices.c main.c devtty.c ppide.c
+DISCARD_CSRCS = discard.c
+DISCARD_DSRCS = ../dev/devide_discard.c
+DSRCS = ../dev/devide.c ../dev/mbr.c ../dev/blkdev.c
+DASRCS = ../dev/devrd_z180_hw.s
+
+AOBJS = $(ASRCS:.s=.rel)
+COBJS = $(CSRCS:.c=.rel)
+DISCARD_COBJS = $(DISCARD_CSRCS:.c=.rel)
+DISCARD_DOBJS = $(patsubst ../dev/%.c,%.rel, $(DISCARD_DSRCS))
+DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS))
+DAOBJS = $(patsubst ../dev/%.s,%.rel, $(DASRCS))
+
+OBJS  = $(AOBJS) $(COBJS) $(DOBJS) $(DISCARD_DOBJS) $(DISCARD_COBJS) $(DAOBJS)
+
+CROSS_CCOPTS += -I../dev/
+
+JUNK = *.rel *.lst *.asm *.sym *.rst *.map *.ihx *.bin
+
+all:   $(OBJS)
+
+$(AOBJS): %.rel: %.s
+       $(CROSS_AS) $(ASOPTS) $<
+
+$(COBJS): %.rel: %.c
+       $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(DOBJS): %.rel: ../dev/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(DAOBJS): %.rel: ../dev/%.s
+       $(CROSS_AS) $(ASOPTS) $@ $<
+
+$(DISCARD_COBJS): %.rel: %.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
+$(DISCARD_DOBJS): %.rel: ../dev/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
+
+clean:
+       rm -f $(OBJS) $(JUNK)  core *~ fuzix.com makecpmloader diskboot.bin
+
+z180.rel:              z180.s kernel.def ../cpu-z180/z180.s
+
+image:
+       ../cpm-loader/makecpmloader ../cpm-loader/cpmload.bin ../fuzix.bin 0x88 fuzix.com
+       ../cpm-loader/makecpmloader ../cpm-loader/fuzixload.bin ../fuzix.bin 0x88 fuzix
diff --git a/Kernel/platform-yaz180/README b/Kernel/platform-yaz180/README
new file mode 100644 (file)
index 0000000..ad7d457
--- /dev/null
@@ -0,0 +1,27 @@
+TODO
+- Verify the Z80_IO_BASE setting is correct
+- Verify the memory bases are right and it boots
+- Worry about the fact the PPIDE port arrangement is different
+- Maybe - add SD support if the CSIO pins are exposed
+
+This is Fuzix for the YAZ180 based upon the Z180 code by Will Sowerbutts
+<will@sowerbutts.com>
+
+Supported hardware:
+ - PPIDE interface (TODO)
+ - SD interface
+ - RS232 serial port (ASCI channel 0, tty1)
+ - RS232 serial port (ASCI channel 1, tty2)
+
+The file "Kernel/platform-yaz180/fuzix.com" is a CP/M executable which
+will load and boot the Fuzix kernel from within CP/M.
+
+When booting the system from CP/M you can specify the root filesystem device on
+the command line after the command name or unit number.
+
+For example, with root filesystem on /dev/hdb1 (minor #17) at the CP/M command
+prompt:
+
+    A> FUZIX hdb1
+or  A> FUZIX 17
+
diff --git a/Kernel/platform-yaz180/commonmem.s b/Kernel/platform-yaz180/commonmem.s
new file mode 100644 (file)
index 0000000..cd68577
--- /dev/null
@@ -0,0 +1,3 @@
+        .module commonmem
+        .area _COMMONMEM
+       .include "../cpu-z80/std-commonmem.s"
diff --git a/Kernel/platform-yaz180/config.h b/Kernel/platform-yaz180/config.h
new file mode 100644 (file)
index 0000000..500a166
--- /dev/null
@@ -0,0 +1,51 @@
+/* Enable to make ^Z dump the inode table for debug */
+#undef CONFIG_IDUMP
+/* Enable to make ^A drop back into the monitor */
+#undef CONFIG_MONITOR
+/* Profil syscall support (not yet complete) */
+#undef CONFIG_PROFIL
+/* Multiple processes in memory at once */
+#define CONFIG_MULTI
+/* Single tasking */
+#undef CONFIG_SINGLETASK
+/* CP/M emulation */
+#undef CONFIG_CPM_EMU
+/* Fixed banking: 8 x 64K banks, top 4KB is shared with kernel, 60KB-62KB is user memory  */
+#define CONFIG_BANK_FIXED
+/* Permit large I/O requests to bypass cache and go direct to userspace */
+#define CONFIG_LARGE_IO_DIRECT(x)      1
+/* 8 60K banks, 1 is kernel */
+#define MAX_MAPS       8
+#define MAP_SIZE       PROGTOP    /* WRS: I feel this should be 60KB, but setting it so breaks pagemap_realloc() when exec calls it */
+
+/* Banks as reported to user space */
+#define CONFIG_BANKS   1
+
+#define TICKSPERSEC 40U     /* Ticks per second */
+#define PROGBASE    0x0000  /* also data base */
+#define PROGLOAD    0x0100  /* also data base */
+#define PROGTOP     0xF800  /* Top of program, base of U_DATA copy */
+#define KERNTOP     0xF000  /* Kernel has lower 60KB */
+#define PROC_SIZE   64      /* Memory needed per process */
+
+/* We need a tidier way to do this from the loader */
+#define CMDLINE        (0x0081)  /* Location of root dev name */
+#define BOOTDEVICENAMES "hd#"
+
+#define CONFIG_DYNAMIC_BUFPOOL /* we expand bufpool to overwrite the _DISCARD segment at boot */
+#define NBUFS    4        /* Number of block buffers, keep in line with space reserved in yaz180.s */
+#define NMOUNTS         4        /* Number of mounts at a time */
+
+/* Hardware parameters */
+#define Z180_IO_BASE       0x00
+
+#define MAX_BLKDEV 2       /* 2 IDE drives */
+
+#define CONFIG_IDE
+#define CONFIG_PPIDE
+
+#define NUM_DEV_TTY 2
+/* ASCI0 as the console */
+#define TTYDEV   (512+1)  /* System console (used by kernel, init) */
+
+#define platform_copyright()
diff --git a/Kernel/platform-yaz180/crt0.s b/Kernel/platform-yaz180/crt0.s
new file mode 100644 (file)
index 0000000..28c4b1c
--- /dev/null
@@ -0,0 +1,74 @@
+; 2013-12-18 William R Sowerbutts
+
+        .module crt0
+
+        ; 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.
+        .area _CODE
+        .area _HOME     ; compiler stores __mullong etc in here if you use them
+        .area _CODE2
+        .area _CONST
+        .area _INITIALIZED
+        .area _DATA
+        .area _BSEG
+        .area _BSS
+        .area _HEAP
+        ; note that areas below here may be overwritten by the heap at runtime, so
+        ; put initialisation stuff in here
+        .area _BUFFERS     ; _BUFFERS grows to consume all before it (up to KERNTOP)
+        .area _INITIALIZER
+        .area _GSINIT
+        .area _GSFINAL
+        .area _DISCARD
+        .area _COMMONMEM
+
+        ; imported symbols
+        .globl _fuzix_main
+        .globl init_early
+        .globl init_hardware
+        .globl s__INITIALIZER
+        .globl s__COMMONMEM
+        .globl l__COMMONMEM
+        .globl s__DISCARD
+        .globl l__DISCARD
+        .globl s__DATA
+        .globl l__DATA
+        .globl kstack_top
+
+        ; startup code
+        .area _CODE
+init:
+        di
+        ld sp, #kstack_top
+
+        ; move the common memory where it belongs    
+        ld hl, #s__DATA
+        ld de, #s__COMMONMEM
+        ld bc, #l__COMMONMEM
+        ldir
+        ; and the discard
+        ld de, #s__DISCARD
+        ld bc, #l__DISCARD
+        ldir
+        ; then zero the data area
+        ld hl, #s__DATA
+        ld de, #s__DATA + 1
+        ld bc, #l__DATA - 1
+        ld (hl), #0
+        ldir
+
+        ; Configure memory map
+        call init_early
+
+        ; Hardware setup
+        call init_hardware
+
+        ; Call the C main routine
+        call _fuzix_main
+    
+        ; fuzix_main() shouldn't return, but if it does...
+        di
+stop:   halt
+        jr stop
diff --git a/Kernel/platform-yaz180/devices.c b/Kernel/platform-yaz180/devices.c
new file mode 100644 (file)
index 0000000..71237ca
--- /dev/null
@@ -0,0 +1,34 @@
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <tty.h>
+#include <devsys.h>
+#include <devtty.h>
+#include <devide.h>
+#include <devsd.h>
+#include <blkdev.h>
+
+struct devsw dev_tab[] =  /* The device driver switch table */
+{
+/*   open          close       read            write           ioctl */
+  {  blkdev_open,   no_close,  blkdev_read,    blkdev_write,   blkdev_ioctl }, /* 0: /dev/hd -- standard block device interface */
+  {  no_open,      no_close,   no_rdwr,        no_rdwr,        no_ioctl },     /* 1: /dev/fd -- floppy disks */
+  {  tty_open,     tty_close,  tty_read,       tty_write,      tty_ioctl },    /* 2: /dev/tty -- serial ports */
+  {  no_open,      no_close,   no_rdwr,        no_rdwr,        no_ioctl },     /* 3: /dev/lp -- printer ports */
+  {  no_open,      no_close,   sys_read,       sys_write,      sys_ioctl  },   /* 4: /dev/mem etc      System devices (one offs) */
+};
+
+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-yaz180/devsdspi.c b/Kernel/platform-yaz180/devsdspi.c
new file mode 100644 (file)
index 0000000..1809082
--- /dev/null
@@ -0,0 +1,232 @@
+/*-----------------------------------------------------------------------*/
+/* N8VEM Mark IV Z180 CSI/O SPI SD driver                                */
+/* 2014-12-27 Will Sowerbutts                                            */
+/* 2014-12-29 Optimised for size/speed                                   */
+/*-----------------------------------------------------------------------*/
+
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <timer.h>
+#include <stdbool.h>
+#include "config.h"
+#include <z180.h>
+#include <blkdev.h>
+
+#define CSIO_CNTR_TE           (1<<4)   /* transmit enable */
+#define CSIO_CNTR_RE           (1<<5)   /* receive enable */
+#define CSIO_CNTR_END_FLAG     (1<<7)   /* operation completed flag */
+
+#define MARK4_SD_CS            (1<<2)   /* chip select */ 
+#define MARK4_SD_WRITE_PROTECT (1<<4)   /* write protect */ 
+#define MARK4_SD_CARD_DETECT   (1<<5)   /* card detect */
+#define MARK4_SD_INT_ENABLE    (1<<6)   /* interrupt enable */
+#define MARK4_SD_INT_PENDING   (1<<7)   /* interrupt enable */
+
+__sfr __at (MARK4_IO_BASE + 0x09) MARK4_SD;
+
+/* the CSI/O and SD card send the bits of each byte in opposite orders, so we need to flip them over */
+static uint8_t reverse_byte(uint8_t byte) __naked
+{
+    /* code by John Metcalf, from http://www.retroprogramming.com/2014/01/fast-z80-bit-reversal.html */
+    __asm
+        ld hl, #2
+        add hl, sp
+        ld a, (hl)
+reverse_byte_a:
+        ; reverse bits in A
+        ld l,a    ; a = 76543210
+        rlca
+        rlca      ; a = 54321076
+        xor l
+        and #0xAA
+        xor l     ; a = 56341270
+        ld l,a
+        rlca
+        rlca
+        rlca      ; a = 41270563
+        rrc l     ; l = 05634127
+        xor l
+        and #0x66
+        xor l     ; a = 01234567
+        ld l, a   ; return value in L
+        ret
+    __endasm;
+    byte; /* squelch compiler warning */
+}
+
+void sd_spi_clock(bool go_fast)
+{
+    unsigned char c;
+
+    c = CSIO_CNTR & 0xf8; /* clear low three bits, gives fastest rate (clk/20) */
+    if(!go_fast)
+        c = c | 0x03;     /* set low two bits, clk/160 (can go down to clk/1280, see data sheet) */
+    CSIO_CNTR = c;
+}
+
+void sd_spi_raise_cs(void)
+{
+    /* wait for idle */
+    while(CSIO_CNTR & (CSIO_CNTR_TE | CSIO_CNTR_RE));
+    MARK4_SD = MARK4_SD & (~MARK4_SD_CS);
+}
+
+void sd_spi_lower_cs(void)
+{
+    /* wait for idle */
+    while(CSIO_CNTR & (CSIO_CNTR_TE | CSIO_CNTR_RE));
+    MARK4_SD = MARK4_SD | MARK4_SD_CS;
+}
+
+void sd_spi_transmit_byte(unsigned char byte)
+{
+    unsigned char c;
+
+    /* reverse the bits before we busywait */
+    byte = reverse_byte(byte);
+
+    /* wait for any current transmit operation to complete */
+    do{
+        c = CSIO_CNTR;
+    }while(c & CSIO_CNTR_TE);
+
+    /* write the byte and enable transmitter */
+    CSIO_TRDR = byte;
+    CSIO_CNTR = c | CSIO_CNTR_TE;
+}
+
+uint8_t sd_spi_receive_byte(void)
+{
+    unsigned char c;
+
+    /* wait for any current transmit or receive operation to complete */
+    do{
+        c = CSIO_CNTR;
+    }while(c & (CSIO_CNTR_TE | CSIO_CNTR_RE));
+
+    /* enable receive operation */
+    CSIO_CNTR = c | CSIO_CNTR_RE;
+
+    /* wait for receive to complete */
+    while(CSIO_CNTR & CSIO_CNTR_RE);
+
+    /* read byte */
+    return reverse_byte(CSIO_TRDR);
+}
+
+/****************************************************************************/
+/* The innermost part of the transfer routines has to live in common memory */
+/* since it must be able to bank switch to the user memory bank.            */
+/****************************************************************************/
+COMMON_MEMORY
+
+/* WRS: measured byte transfer time as approx 5.66us with Z180 @ 36.864MHz,
+   three times faster. Main change is to start the next receive operation 
+   as soon as possible and overlap the loop housekeeping with the receive. */
+bool sd_spi_receive_sector(void) __naked
+{
+    __asm
+waitrx: 
+        in0 a, (_CSIO_CNTR)     ; wait for any current transmit or receive operation to complete
+        tst a, #0x30
+        jr nz, waitrx
+        set 5, a                ; set CSIO_CNTR_RE, enable receive operation for first byte
+        out0 (_CSIO_CNTR), a
+        ld h, a                 ; stash value for reuse later
+
+        ; load parameters
+        ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
+        ld de, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
+        ld bc, #512                             ; sector size
+        or a
+        push af                                 ; stash is_user flag now in Z bit (we cannot load it again after we remap)
+        call nz, map_process_always             ; map user process
+rxnextbyte:
+        dec bc                  ; length--
+        ld a, b
+        or c
+        jr nz, waitrx2
+        res 5, h                ; final byte: clear CSIO_CNTR_RE bit in H
+waitrx2:
+        ld l, c                 ; store C temporarily
+        ld c, #_CSIO_CNTR       ; load IO port address
+waitrx3:
+        tstio #0x20             ; test bits in IO port (C)
+        jr nz, waitrx3          ; wait for receive to complete
+        in0 a, (_CSIO_TRDR)     ; load received byte
+        out0 (_CSIO_CNTR), h    ; start next receive (or NOP, if this is the final byte)
+        ld c, l                 ; restore C
+        ; reverse bits in A
+        ld l,a    ; a = 76543210
+        rlca
+        rlca      ; a = 54321076
+        xor l
+        and #0xAA
+        xor l     ; a = 56341270
+        ld l,a
+        rlca
+        rlca
+        rlca      ; a = 41270563
+        rrc l     ; l = 05634127
+        xor l
+        and #0x66
+        xor l     ; a = 01234567
+        ld (de), a              ; store reversed byte value
+        inc de                  ; ptr++
+        bit 5, h
+        jr nz, rxnextbyte       ; go again if not yet done
+        jr transferdone         ; we are done
+    __endasm;
+}
+
+bool sd_spi_transmit_sector(void) __naked
+{
+    __asm
+        ; load parameters
+        ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
+        ld de, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
+        ld hl, #512                             ; sector size
+        or a
+        push af                                 ; stash is_user flag now in Z bit (we cannot load it again after we remap)
+        call nz, map_process_always             ; map user process
+gotransmit:
+        in0 a, (_CSIO_CNTR)
+        and #0xDF               ; mask off RE bit
+        or #0x10                ; set TE bit
+        ld b, a                 ; B now contains CNTR register value to start transmission
+txnextbyte:
+        ld a, (de)
+        ; reverse bits in A
+        ld c,a
+        rlca
+        rlca
+        xor c
+        and #0xAA
+        xor c
+        ld c,a
+        rlca
+        rlca
+        rlca
+        rrc c
+        xor c
+        and #0x66
+        xor c
+        ld c, #_CSIO_CNTR       ; load IO port address
+waittx: 
+        tstio #0x10             ; test bits in IO port (C)
+        jr nz, waittx           ; wait for transmit to complete
+        out0 (_CSIO_TRDR), a    ; write byte to transmit
+        out0 (_CSIO_CNTR), b    ; start transmit
+        inc de                  ; ptr++
+        dec hl                  ; length--
+        ld a, h
+        or l
+        jr nz, txnextbyte       ; length != 0, go again
+transferdone:                   ; note this code is shared with sd_spi_receive_block
+        ld l, #1                ; return true
+        pop af                  ; recover is_user bit in Z flag
+        ret z                   ; return if kernel still mapped
+        jp map_kernel           ; else map kernel and return
+    __endasm;
+}
diff --git a/Kernel/platform-yaz180/devtty.c b/Kernel/platform-yaz180/devtty.c
new file mode 100644 (file)
index 0000000..9ab6c8b
--- /dev/null
@@ -0,0 +1,91 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <tty.h>
+#include <devtty.h>
+#include <z180.h>
+
+static char tbuf1[TTYSIZ];
+static 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 },
+};
+
+static tcflag_t console_mask[4] = {
+       _ISYS,
+       _OSYS,
+       _CSYS,
+       _LSYS
+};
+
+/* TODO: stty support for  the Z180 ports */
+tcflag_t *termios_mask[NUM_DEV_TTY + 1] = {
+       NULL,
+       console_mask,
+       console_mask,
+};
+
+void tty_setup(uint8_t minor, uint8_t flags)
+{
+    minor;
+}
+
+/* For the moment */
+int tty_carrier(uint8_t minor)
+{
+    minor;
+    return 1;
+}
+
+void tty_pollirq_asci0(void)
+{
+    while(ASCI_STAT0 & 0x80)
+        tty_inproc(1, ASCI_RDR0);
+}
+
+void tty_pollirq_asci1(void)
+{
+    while(ASCI_STAT1 & 0x80)
+        tty_inproc(2, ASCI_RDR1);
+}
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+    switch(minor){
+        case 1:
+            while(!(ASCI_STAT0 & 2));
+            ASCI_TDR0 = c;
+            break;
+        case 2:
+            while(!(ASCI_STAT1 & 2));
+            ASCI_TDR1 = c;
+            break;
+    }
+}
+
+void tty_sleeping(uint8_t minor)
+{
+    minor;
+}
+
+void tty_data_consumed(uint8_t minor)
+{
+}
+
+ttyready_t tty_writeready(uint8_t minor)
+{
+    minor;
+    return TTY_READY_NOW;
+}
+
+/* kernel writes to system console -- never sleep! */
+void kputchar(char c)
+{
+    tty_putc(TTYDEV & 0xFF, c);
+    if(c == '\n')
+        tty_putc(TTYDEV & 0xFF, '\r');
+}
diff --git a/Kernel/platform-yaz180/devtty.h b/Kernel/platform-yaz180/devtty.h
new file mode 100644 (file)
index 0000000..12401d8
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __DEVTTY_DOT_H__
+#define __DEVTTY_DOT_H__
+void tty_pollirq_asci0(void);
+void tty_pollirq_asci1(void);
+
+#ifdef CONFIG_PROPIO2
+void tty_poll_propio2(void);
+#endif
+#endif
diff --git a/Kernel/platform-yaz180/discard.c b/Kernel/platform-yaz180/discard.c
new file mode 100644 (file)
index 0000000..94ca9af
--- /dev/null
@@ -0,0 +1,43 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include "config.h"
+#include <z180.h>
+
+void init_hardware_c(void)
+{
+    ramsize = 912;
+    procmem = 848;
+    /* zero out the initial bufpool */
+    memset(bufpool, 0, (char*)bufpool_end - (char*)bufpool);
+}
+
+void pagemap_init(void)
+{
+    int i;
+
+    /* YAZ180 has RAM from 0C000 to EFFFF
+     * First 64K is used by the kernel. 
+     * Each process gets the full 64K for now.
+     * Page size is 4KB.
+     * We don't do anything right now with C000-FFFF so that is
+     * a good place to load any additional tools
+     */
+    for(i = 0x20; i < 0xF0; i+=0x10)
+        pagemap_add(i);
+}
+
+void map_init(void)
+{
+    /* clone udata and stack into a regular process bank, return with common memory
+       for the new process loaded */
+    copy_and_map_process(&init_process->p_page);
+    /* kernel bank udata (0x300 bytes) is never used again -- could be reused? */
+}
+
+uint8_t platform_param(char *p)
+{
+    used(p);
+    return 0;
+}
diff --git a/Kernel/platform-yaz180/diskboot.s b/Kernel/platform-yaz180/diskboot.s
new file mode 100644 (file)
index 0000000..9b57d5e
--- /dev/null
@@ -0,0 +1,197 @@
+; 2015-01-21 Will Sowerbutts <will@sowerbutts.com>
+;
+; Boot sector for N8VEM Mark IV SBC with UNA BIOS, based on
+; my UNA CP/M boot sector (2014-07-11)
+
+        .module diskboot
+
+
+; we are loaded at 0x8000
+himem     = 0xFA00 ; our location in memory
+buffer    = 0xF800 ; disk buffer (512 bytes)
+stacktop  = 0xFE00 ; top of stack (512 bytes)
+
+; UNA BIOS constants
+UNABIOS_STUB_ENTRY          = 0xFFFD    ; main UNA entry vector
+UNABIOS_BOOTHISTORY         = 0xFC      ; C register (subfunction in B)
+UNABIOS_BOOT_GET            = 0x00      ;   B register (BOOTHISTORY subfunction)
+UNABIOS_GETINFO             = 0xFA      ; C regsister (subfunction in B)
+UNABIOS_GET_USER_PAGES      = 0x05      ;   B register (GETINFO subfunction)
+UNABIOS_BANKEDMEM           = 0xFB      ; C register (subfunction in B)
+UNABIOS_BANK_GET            = 0x00      ;   B register (BANKEDMEM subfunction)
+UNABIOS_BANK_SET            = 0x01      ;   B register (BANKEDMEM subfunction)
+UNABIOS_GET_HMA             = 0xF1      ; C register (subfunction in B)
+UNABIOS_BLOCK_SETLBA        = 0x41      ; C register (unit number in B, 28-bit LBA in DEHL)
+UNABIOS_BLOCK_READ          = 0x42      ; C register (unit number in B, buffer address in DE, sector count in L)
+UNABIOS_OUTPUT_WRITE        = 0x12      ; C register (unit number in B)
+
+        .area _LOADER (ABS)
+        .org himem
+start:
+        ; UNA BIOS loads us from disk sector 0 at 0x8000
+        jr gocopy                       ; we must start with a JP or JR instruction.
+        .ds 0x40 - (.-start)            ; must leave room for floppy or partition superblock information
+
+        ; Copy us up into high memory
+gocopy: ld hl, #0x8000
+        ld de, #himem
+        ld bc, #512
+        ldir
+        jp go
+        
+        ; Executes in high memory
+go:     ld sp, #stacktop                ; set inital stack
+        ; write a character
+        ld e, #0x5B                     ; '['
+        call printchar
+
+        ; determine the boot unit
+        ld bc, #(UNABIOS_BOOT_GET << 8 | UNABIOS_BOOTHISTORY)
+        call #UNABIOS_STUB_ENTRY
+        ld a, l
+        ld (unit), a                    ; save boot unit
+
+        ; get the page number for the user memory bank
+        ld bc, #(UNABIOS_GET_USER_PAGES << 8 | UNABIOS_GETINFO)
+        call #UNABIOS_STUB_ENTRY
+        ; returns EXEC_PAGE value in DE
+
+        ; map in user memory bank
+        ld bc, #(UNABIOS_BANK_SET << 8 | UNABIOS_BANKEDMEM)
+        call #UNABIOS_STUB_ENTRY
+
+        ; write unabios vector in user memory
+        ld hl, #UNABIOS_STUB_ENTRY
+        ld de, #0x0008
+        ld bc, #3
+        ldir
+
+        ; wipe BDOS entry vector
+        ld a, #0x76                     ; halt instruction
+        ld (0x0005), a                  ; this is used as a marker to detect cold boot versus warm reload
+
+        ; wipe persistent memory pointer (persist_ptr, immediately below UNA UBIOS stub / HMA)
+        ld c, #UNABIOS_GET_HMA          ; get pointer to lowest byte used by UNA BIOS stub
+        call #UNABIOS_STUB_ENTRY        ; returns lowest used byte in HL.
+        xor a                           ; zero out the two bytes below that.
+        dec hl
+        ld (hl), a
+        dec hl
+        ld (hl), a
+
+        ld a, (firstblock)
+        ld (block), a
+
+nextblock:
+        ; print a = character only every other block
+        ld a, (block)
+        and #1
+        jr z, setlba
+        ld e, #0x3D                     ; '='
+        call printchar
+
+setlba: ; set LBA
+        xor a
+        ld d, a
+        ld e, a
+        ld h, a
+        ld a, (block)
+        ld l, a
+        inc a               ; setup for next block now
+        ld (block), a
+        ld c, #UNABIOS_BLOCK_SETLBA
+        ld a, (unit)
+        ld b, a
+        call #UNABIOS_STUB_ENTRY
+        jr nz, error
+
+        ; read block into buffer
+        ld c, #UNABIOS_BLOCK_READ
+        ld a, (unit)
+        ld b, a
+        ld l, #1
+        ld de, #buffer
+        call #UNABIOS_STUB_ENTRY
+        jr nz, error
+
+        ; copy block into low memory
+        ld hl, #buffer
+        ld de, (copyaddr)
+        ld bc, #512
+        ldir
+
+        ld (copyaddr), de
+        ld a, (firstblock)
+        ld d, a
+        ld a, (count)
+        ld e, a
+        ld a, (block)
+        sub d
+        cp e
+        jr nz, nextblock
+
+        ld e, #0x5D         ; ']'
+        call printchar
+        ld e, #0x0D
+        call printchar
+        ld e, #0x0A
+        call printchar
+
+        ; we're loaded. let's go.
+        ld hl, (entryaddr)
+        jp (hl)
+
+
+; print a hex byte in A
+byt_out:
+        push af         ; save low nibble
+        rrca            ; move high nibble into position
+        rrca            ; **
+        rrca
+        rrca
+        call nib_out    ; put out the high nibble
+        pop af          ; fall into nib_out to put out low nibble
+; print a hex-nibble in A
+nib_out:
+        and #0x0F       ; mask the nibble
+        add #0          ; clear the AUX carry bit
+        daa             ; decimal adjust the A
+        add #0xF0       ; move hi-nib into carry, hi-nib is 0 or F
+        adc #0x40       ; form ascii character
+        ld  e, a
+        ; fall through into printchar
+printchar:
+        ld bc, #UNABIOS_OUTPUT_WRITE
+        jp UNABIOS_STUB_ENTRY
+
+error:
+        ; print the error
+        ld a, c
+        call byt_out
+        ld e, a
+        call printchar
+
+        ; sad face :(
+        ld e, #0x20     ; space
+        call printchar
+        ld e, #0x3A     ; ':'
+        call printchar
+        ld e, #0x28     ; '('
+        call printchar
+
+        ; park the vehicle
+        halt
+
+block:      .ds 1
+unit:       .ds 1
+firstblock: .db 2       ; start loading at sector 2
+count:      .db 124     ; max sectors we can load before we overwrite ourselves (62KB)
+copyaddr:   .dw 0x0088  ; load address
+entryaddr:  .dw 0x0088  ; entry address
+
+    .ds 0x1BE - ( . -start) ; pad to start of partition tables
+    .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; partition 1
+    .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; partition 2
+    .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; partition 3
+    .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; partition 4
+    .dw 0xAA55              ; DOS boot signature
diff --git a/Kernel/platform-yaz180/fuzix.lnk b/Kernel/platform-yaz180/fuzix.lnk
new file mode 100644 (file)
index 0000000..db459b7
--- /dev/null
@@ -0,0 +1,43 @@
+-mwxuy
+-i fuzix.ihx
+-b _CODE=0x0088
+-b _COMMONMEM=0xF800
+-b _DISCARD=0xE000
+-l z180
+platform-yaz180/crt0.rel
+platform-yaz180/commonmem.rel
+platform-yaz180/z180.rel
+platform-yaz180/yaz180.rel
+platform-yaz180/main.rel
+start.rel
+version.rel
+lowlevel-z180.rel
+usermem_std-z180.rel
+timer.rel
+kdata.rel
+usermem.rel
+platform-yaz180/devices.rel
+devio.rel
+filesys.rel
+process.rel
+inode.rel
+syscall_exec16.rel
+syscall_fs.rel
+syscall_fs2.rel
+syscall_fs3.rel
+syscall_proc.rel
+syscall_other.rel
+tty.rel
+mm.rel
+bankfixed.rel
+swap.rel
+devsys.rel
+platform-yaz180/discard.rel
+platform-yaz180/devtty.rel
+platform-yaz180/devide.rel
+platform-yaz180/devide_discard.rel
+platform-yaz180/ppide.rel
+platform-yaz180/mbr.rel
+platform-yaz180/blkdev.rel
+platform-yaz180/monitor.rel
+-e
diff --git a/Kernel/platform-yaz180/kernel.def b/Kernel/platform-yaz180/kernel.def
new file mode 100644 (file)
index 0000000..c36d8ae
--- /dev/null
@@ -0,0 +1,21 @@
+; UZI mnemonics for memory addresses etc
+
+; Move down to 0xF600 to fit the monitor in
+U_DATA                      .equ 0xF800       ; (this is struct u_data from kernel.h)
+U_DATA__TOTALSIZE           .equ 0x200        ; 256+256 bytes.
+Z80_TYPE                    .equ 2
+
+OS_BANK                     .equ 0x00         ; value from include/kernel.h
+
+; N8VEM Mark IV mnemonics
+FIRST_RAM_BANK              .equ 0x10         ; 10000 (actually C000-FFFF is avaiable)
+Z180_IO_BASE                .equ 0x00
+
+; No standard clock speed for the Mark IV board, but this is a common choice.
+USE_FANCY_MONITOR           .equ 1            ; disabling this saves around approx 0.5KB
+CPU_CLOCK_KHZ               .equ 36864        ; 18.432MHz * 2
+Z180_TIMER_SCALE            .equ 20           ; CPU clocks per timer tick
+TICKSPERSEC                 .equ 40           ; timer interrupt rate (Hz)
+
+PROGBASE                   .equ 0x0000
+PROGLOAD                   .equ 0x0100
diff --git a/Kernel/platform-yaz180/main.c b/Kernel/platform-yaz180/main.c
new file mode 100644 (file)
index 0000000..1303c6f
--- /dev/null
@@ -0,0 +1,59 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include "config.h"
+#include <z180.h>
+
+uint16_t ramtop = PROGTOP;
+extern unsigned char irqvector;
+
+struct blkbuf *bufpool_end = bufpool + NBUFS; /* minimal for boot -- expanded after we're done with _DISCARD */
+
+void platform_discard(void)
+{
+    while(bufpool_end < (struct blkbuf*)(KERNTOP - sizeof(struct blkbuf))){
+        memset(bufpool_end, 0, sizeof(struct blkbuf));
+#if BF_FREE != 0
+        bufpool_end->bf_busy = BF_FREE; /* redundant when BF_FREE == 0 */
+#endif
+        bufpool_end->bf_dev = NO_DEVICE;
+        bufpool_end++;
+    }
+}
+
+void z180_timer_interrupt(void)
+{
+    unsigned char a;
+
+    /* we have to read both of these registers in order to reset the timer */
+    a = TIME_TMDR0L;
+    a = TIME_TCR;
+    timer_interrupt();
+}
+
+void platform_idle(void)
+{
+    /* Let's go to sleep while we wait for something to interrupt us;
+     * Makes the Mark IV's run LED go red, which amuses me greatly. */
+    __asm
+        halt
+    __endasm;
+}
+
+void platform_interrupt(void)
+{
+    switch(irqvector){
+        case Z180_INT_TIMER0:
+            z180_timer_interrupt(); 
+            return;
+        case Z180_INT_ASCI0:
+            tty_pollirq_asci0();
+            return;
+        case Z180_INT_ASCI1:
+            tty_pollirq_asci1();
+            return;
+        default:
+            return;
+    }
+}
diff --git a/Kernel/platform-yaz180/monitor.s b/Kernel/platform-yaz180/monitor.s
new file mode 100644 (file)
index 0000000..bf9bca7
--- /dev/null
@@ -0,0 +1,41 @@
+; 2015-01-17 William R Sowerbutts
+
+                .module monitor
+                .include "kernel.def"
+                .globl _platform_monitor
+               .globl _platform_reboot
+                .globl map_kernel
+
+; -----------------------------------------------------------------------------
+.ifne USE_FANCY_MONITOR ; -----------------------------------------------------
+                .area _CODE ; actual monitor lives in kernel bank
+                .include "../lib/monitor-z80.s"
+
+                .area _COMMONMEM ; just a stub goes in common memory
+_platform_monitor:
+                di
+                call map_kernel
+                jp monitor_entry
+
+
+; -----------------------------------------------------------------------------
+.else ; MICRO MONITOR ---------------------------------------------------------
+                .globl outchar
+                .globl outnewline
+                .globl outhl
+
+                .area _COMMONMEM
+_platform_monitor:  di
+                call outnewline
+                ; just dump a few words from the stack
+                ld b, #50
+stacknext:      pop hl
+                call outhl
+                ld a, #' '
+                call outchar
+                djnz stacknext
+                halt
+.endif
+
+_platform_reboot:      ; TODO
+               jr _platform_monitor
diff --git a/Kernel/platform-yaz180/platform_ide.h b/Kernel/platform-yaz180/platform_ide.h
new file mode 100644 (file)
index 0000000..95d67e1
--- /dev/null
@@ -0,0 +1,38 @@
+#ifdef CONFIG_PPIDE
+#define PPIDE_BASE 0x60         /* 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)
+#endif /* CONFIG_PPIDE */
+
+#define ide_select(x)
+#define ide_deselect()
diff --git a/Kernel/platform-yaz180/ppide.c b/Kernel/platform-yaz180/ppide.c
new file mode 100644 (file)
index 0000000..f6d0ee1
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *     FIXME: this is wrong for the YAZ180 as the bit mappings are
+ *     different.
+ */
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <timer.h>
+#include <devide.h>
+#include <blkdev.h>
+
+#ifdef CONFIG_PPIDE
+
+__sfr __at (PPIDE_BASE + 0x00) ppi_port_a;   /* IDE bus LSB */
+__sfr __at (PPIDE_BASE + 0x01) ppi_port_b;   /* IDE bus MSB */
+__sfr __at (PPIDE_BASE + 0x02) ppi_port_c;   /* IDE bus control signals */
+__sfr __at (PPIDE_BASE + 0x03) ppi_control;  /* 8255 command register */
+
+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;
+}
+
+/****************************************************************************/
+/* The innermost part of the transfer routines has to live in common memory */
+/* since it must be able to bank switch to the user memory bank.            */
+/****************************************************************************/
+COMMON_MEMORY
+
+void devide_read_data(void) __naked
+{
+    __asm
+            ld a, #ide_reg_data
+            ld c, #PPIDE_BASE+2                     ; select control lines
+            out (c), a                              ; select IDE data register
+            ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
+            ld d, #ide_reg_data                     ; register address
+            ld e, #ide_reg_data | PPIDE_RD_LINE     ; register address with /RD asserted
+            ld b, #0                                ; setup count
+            ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
+            or a                                    ; test is_user
+            push af                                 ; save flags
+            ld a, #PPIDE_BASE+0                     ; I will be needing this later
+            call nz, map_process_always             ; map user memory first if required
+goread:     ; now we do the transfer
+            out (c), e                              ; assert /RD
+            ld c, a                                 ; PPIDE_BASE
+            ini                                     ; read byte from LSB
+            inc c                                   ; up to MSB
+            ini                                     ; read byte from MSB
+            inc c                                   ; control lines
+            out (c), d                              ; de-assert /RD
+            inc b                                   ; (delay) counteract second ini instruction
+            jr nz, goread                           ; (delay) next word
+            ; read completed
+            pop af                                  ; recover is_user test result
+            ret z                                   ; done if kernel memory transfer
+            jp map_kernel                           ; else map kernel then return
+    __endasm;
+}
+
+void devide_write_data(void) __naked
+{
+    __asm
+            ld c, #PPIDE_BASE+2                     ; select control lines
+            ld a, #ide_reg_data
+            out (c), a                              ; select data register
+            ld a, #PPIDE_PPI_BUS_WRITE
+            inc c                                   ; up to 8255A command register
+            out (c), a                              ; 8255A ports A, B to output mode
+            dec c                                   ; back down to the control lines
+            ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
+            ld d, #ide_reg_data                     ; register address
+            ld e, #ide_reg_data | PPIDE_WR_LINE     ; register address with /WR asserted
+            ld b, #0                                ; setup count
+            ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
+            or a                                    ; test is_user
+            push af                                 ; save flags
+            ld a, #PPIDE_BASE+0                     ; I will be needing this later
+            call nz, map_process_always             ; map user memory first if required
+gowrite:    ; now we do the transfer
+            out (c), d                              ; de-assert /WR
+            ld c, a                                 ; PPIDE_BASE
+            outi                                    ; write byte to LSB
+            inc c                                   ; up to MSB
+            outi                                    ; write byte to MSB
+            inc c                                   ; up to control lines
+            out (c), e                              ; assert /WR
+            inc b                                   ; (delay) offset to counteract second outi instruction
+            jr nz, gowrite                          ; (delay) next word
+            ; write completed
+            out (c), d                              ; de-assert /WR
+            ld a, #PPIDE_PPI_BUS_READ
+            inc c                                   ; up to 8255A command register
+            out (c), a                              ; 8255A ports A, B to read mode
+            pop af                                  ; recover is_user test result
+            ret z                                   ; done if kernel memory transfer
+            jp map_kernel                           ; else map kernel then return
+    __endasm;
+}
+
+#endif
diff --git a/Kernel/platform-yaz180/target.mk b/Kernel/platform-yaz180/target.mk
new file mode 100644 (file)
index 0000000..cacca5d
--- /dev/null
@@ -0,0 +1,2 @@
+export CPU = z180
+export USERCPU = z80
diff --git a/Kernel/platform-yaz180/yaz180.s b/Kernel/platform-yaz180/yaz180.s
new file mode 100644 (file)
index 0000000..98da09f
--- /dev/null
@@ -0,0 +1,87 @@
+; 2014-12-16 William R Sowerbutts
+; N8VEM Mark IV SBC hardware specific code
+
+        .module mark4
+        .z180
+
+        ; exported symbols
+        .globl init_early
+        .globl init_hardware
+        .globl inchar
+        .globl outchar
+        .globl platform_interrupt_all
+        .globl _bufpool
+
+        ; imported symbols
+        .globl z180_init_hardware
+        .globl z180_init_early
+        .globl outhl
+        .globl outnewline
+
+        .include "kernel.def"
+        .include "../cpu-z180/z180.def"
+        .include "../kernel.def"
+
+; -----------------------------------------------------------------------------
+; Buffers
+; -----------------------------------------------------------------------------
+        .area _BUFFERS
+_bufpool:
+        .ds (BUFSIZE * 4) ; adjust NBUFS in config.h in line with this
+
+; -----------------------------------------------------------------------------
+; Initialisation code
+; -----------------------------------------------------------------------------
+        .area _DISCARD
+
+init_early:
+        jp z180_init_early
+
+init_hardware:
+        ; enable ASCI interrupts
+        in0 a, (ASCI_STAT0)
+        or #0x08                ; enable ASCI0 receive interrupts
+        out0 (ASCI_STAT0), a
+        in0 a, (ASCI_ASEXT0)
+        and #0x7f               ; disable RDRF interrupt inhibit
+        out0 (ASCI_ASEXT0), a
+        in0 a, (ASCI_STAT1)
+        or #0x08                ; enable ASCI1 receive interrupts
+        out0 (ASCI_STAT1), a
+        in0 a, (ASCI_ASEXT1)
+        and #0x7f               ; disable RDRF interrupt inhibit
+        out0 (ASCI_ASEXT1), a
+
+        jp z180_init_hardware
+
+; -----------------------------------------------------------------------------
+; COMMON MEMORY BANK
+; -----------------------------------------------------------------------------
+        .area _COMMONMEM
+
+; outchar: Wait for UART TX idle, then print the char in A
+; destroys: AF
+outchar:
+        push bc
+        ld b, a
+        ; wait for transmitter to be idle
+ocloop: in0 a, (ASCI_STAT0)
+        bit 1, a        ; and 0x02
+        jr z, ocloop    ; loop while busy
+        ; now output the char to serial port
+        ld a, b
+        out0 (ASCI_TDR0), a
+        pop bc
+        ret
+
+; inchar: Wait for character on UART, return in A
+; destroys: AF
+inchar:
+        in0 a, (ASCI_STAT0)
+        rlca
+        jr nc, inchar
+        in0 a, (ASCI_RDR0)
+        ret
+
+platform_interrupt_all:
+        ret
diff --git a/Kernel/platform-yaz180/z180.s b/Kernel/platform-yaz180/z180.s
new file mode 100644 (file)
index 0000000..7371295
--- /dev/null
@@ -0,0 +1 @@
+.include "../cpu-z180/z180.s"