v85: intial merge of the port
authorAlan Cox <alan@linux.intel.com>
Sat, 16 Feb 2019 22:12:09 +0000 (22:12 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 16 Feb 2019 22:12:09 +0000 (22:12 +0000)
15 files changed:
Kernel/platform-v85/Makefile [new file with mode: 0644]
Kernel/platform-v85/README [new file with mode: 0644]
Kernel/platform-v85/commonmem.s [new file with mode: 0644]
Kernel/platform-v85/config.h [new file with mode: 0644]
Kernel/platform-v85/crt0.s [new file with mode: 0644]
Kernel/platform-v85/devices.c [new file with mode: 0644]
Kernel/platform-v85/devtty.c [new file with mode: 0644]
Kernel/platform-v85/devtty.h [new file with mode: 0644]
Kernel/platform-v85/end.s [new file with mode: 0644]
Kernel/platform-v85/kernel.def [new file with mode: 0644]
Kernel/platform-v85/main.c [new file with mode: 0644]
Kernel/platform-v85/platform_ide.h [new file with mode: 0644]
Kernel/platform-v85/target.mk [new file with mode: 0644]
Kernel/platform-v85/tricks.s [new file with mode: 0644]
Kernel/platform-v85/v85.s [new file with mode: 0644]

diff --git a/Kernel/platform-v85/Makefile b/Kernel/platform-v85/Makefile
new file mode 100644 (file)
index 0000000..4ac258b
--- /dev/null
@@ -0,0 +1,55 @@
+LIBPATH=../../Library/libs
+LIBC=$(LIBPATH)/libc8080.a $(ACK_ROOT)/share/ack/cpm/libem.a
+
+CSRCS += devices.c main.c devtty.c
+
+DISCARD_DSRCS = ../dev/devide_discard.c
+DSRCS = ../dev/devide.c ../dev/mbr.c ../dev/blkdev.c
+
+CROSS_CCOPTS += -I../dev/
+
+ASRCS = crt0.s commonmem.s v85.s tricks.s end.s
+
+AOBJS = $(ASRCS:.s=.o)
+COBJS = $(CSRCS:.c=.o)
+DISCARD_DOBJS = $(patsubst ../dev/%.c,%.o, $(DISCARD_DSRCS))
+DOBJS = $(patsubst ../dev/%.c,%.o, $(DSRCS))
+
+OBJS  = $(AOBJS) $(COBJS) $(DISCARD_DOBJS) $(DOBJS)
+
+JUNK = *.o *.lst *.asm *.sym *.rst
+
+all:   $(OBJS)
+
+$(AOBJS): %.o: %.s
+       $(CROSS_AS) $(ASOPTS) $<
+
+$(COBJS): %.o: %.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $<
+
+$(DOBJS): %.o: ../dev/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $<
+
+# Need to make discard work yet
+$(DISCARD_DOBJS): %.o: ../dev/%.c
+       $(CROSS_CC) $(CROSS_CCOPTS) $<
+
+tricks.s: ../lib/8080fixedbank.s ../lib/8080fixedbank-core.s
+
+clean:
+       rm -f $(OBJS) $(JUNK)  core *~ bootblock.bin bootblock
+
+image: 
+       $(CROSS_LD) -b0:0x0100 -b4:0xE800 -o fuzix.bin crt0.o devices.o main.o \
+       commonmem.o tricks.o v85.o devtty.o \
+       ../start.o ../version.o ../lowlevel-8080.o \
+       ../bankfixed.o ../timer.o ../kdata.o  \
+       ../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \
+       ../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o \
+       ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o \
+       ../syscall_fs3.o ../syscall_exec16.o  \
+       blkdev.o mbr.o devide.o devide_discard.o \
+       ../usermem_std-8080.o $(LIBC) end.o
+       anm fuzix.bin | ../tools/8080map > ../fuzix.map
+       ../tools/ack2kernel -v fuzix.bin ../fuzix.bin
+       ../tools/check8080 fuzix.bin
diff --git a/Kernel/platform-v85/README b/Kernel/platform-v85/README
new file mode 100644 (file)
index 0000000..d366d45
--- /dev/null
@@ -0,0 +1,4 @@
+This is an emulated platform driver for the V85 virtual 8085. The main goal is
+to see what can be done to improve 8085 over 8080. It also provides a way to test
+the IDE and modern block layer code with ackcc.
+
diff --git a/Kernel/platform-v85/commonmem.s b/Kernel/platform-v85/commonmem.s
new file mode 100644 (file)
index 0000000..30bec32
--- /dev/null
@@ -0,0 +1,8 @@
+#include "../kernel-8080.def"
+
+!
+!      Common on z80pack is at 0xF000 as defined by hardware.
+!
+.sect .common
+
+#include "../cpu-8080/std-commonmem.s"
diff --git a/Kernel/platform-v85/config.h b/Kernel/platform-v85/config.h
new file mode 100644 (file)
index 0000000..3c869e5
--- /dev/null
@@ -0,0 +1,61 @@
+/* We have an RTC */
+#undef CONFIG_RTC
+/* And we can read ToD from it */
+#undef CONFIG_RTC_FULL
+/* 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
+/* Fixed banking */
+#define CONFIG_BANK_FIXED
+/* 8 48K banks, 1 is kernel */
+#define MAX_MAPS       7
+#define MAP_SIZE       0xC000U
+
+/* Read processes and big I/O direct into process space */
+#define CONFIG_LARGE_IO_DIRECT(x)      1
+
+/* Banks as reported to user space */
+#define CONFIG_BANKS   1
+
+#define TICKSPERSEC 10   /* Ticks per second */
+#define PROGBASE    0x0000  /* also data base */
+#define PROGLOAD    0x0100  /* also data base */
+#define PROGTOP     0xBE00  /* Top of program, base of U_DATA copy */
+#define PROC_SIZE   60   /* Memory needed per process */
+
+#define SWAPDEV     (swap_dev) /* A variable for dynamic, or a device major/minor */
+
+#define SWAP_SIZE   0x60       /* 48K in blocks (we actually don't need the low 256) */
+#define SWAPBASE    0x0000     /* We swap the lot in one, include the */
+#define SWAPTOP            0xC000      /* vectors so its a round number of sectors */
+#define MAX_SWAPS   16         /* The full drive would actually be 85! */
+/* Swap will be set up when a suitably labelled partition is seen */
+#define CONFIG_DYNAMIC_SWAP
+
+#define CONFIG_IDE
+#define MAX_BLKDEV 1       /* One IDE */
+
+#define swap_map(x)    ((uint8_t *)(x)) /* Simple zero based mapping */
+
+#define BOOT_TTY (512 + 1)/* Set this to default device for stdio, stderr */
+                          /* In this case, the default is the first TTY device */
+
+/* We need a tidier way to do this from the loader */
+#define CMDLINE        NULL      /* Location of root dev name */
+
+/* Device parameters */
+#define NUM_DEV_TTY 1
+
+#define TTYDEV   BOOT_TTY /* Device used by kernel for messages, panics */
+#define NBUFS    8       /* Number of block buffers */
+#define NMOUNTS         4        /* Number of mounts at a time */
+
+#define platform_discard()
+#define platform_copyright()
diff --git a/Kernel/platform-v85/crt0.s b/Kernel/platform-v85/crt0.s
new file mode 100644 (file)
index 0000000..0645517
--- /dev/null
@@ -0,0 +1,71 @@
+#include "../kernel-8080.def"
+
+.sect .text
+.sect .rom
+.sect .data
+datastart:
+.sect .bss
+bssstart:
+.sect .common
+commonstart:
+
+.sect .text
+
+.define init
+
+       .data2 0x8085
+
+init:
+        di
+       lxi sp,kstack_top
+
+        call init_early
+
+
+       lxi h,commonend
+       lxi d,commonstart
+       call calcsize
+
+       lxi h,bssstart
+       lxi d,commonstart
+       
+nextbyte:
+       mov a,m
+       stax d
+       inx h
+       inx d
+       dcx b
+       mov a,b
+       ora c
+       jnz nextbyte
+
+!      lxi h,bssend            ! We should really do this but bssend
+                               ! isnt appearing at the end so plan b
+       lxi h,commonstart       ! Wipe all the free space
+       lxi d,bssstart
+       call calcsize
+
+       lxi h,bssstart
+wipe:
+       mvi m,0
+       inx h
+       dcx b
+       mov a,b
+       ora c
+       jnz wipe
+
+        call init_hardware
+
+        call _fuzix_main
+        di
+stop:   hlt
+        jmp stop
+
+calcsize:
+       mov a,l
+       sub e
+       mov c,a
+       mov a,h
+       sbb d
+       mov b,a
+       ret
diff --git a/Kernel/platform-v85/devices.c b/Kernel/platform-v85/devices.c
new file mode 100644 (file)
index 0000000..317f270
--- /dev/null
@@ -0,0 +1,42 @@
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <tty.h>
+#include <devsys.h>
+#include <devtty.h>
+#include <devfd.h>
+#include <blkdev.h>
+#include <devide.h>
+
+
+struct devsw dev_tab[] =  /* The device driver switch table */
+{
+// minor    open         close        read      write       ioctl
+// -----------------------------------------------------------------
+  /* 0: /dev/hd                Hard disc block devices */
+  {  blkdev_open, no_close,    blkdev_read,   blkdev_write,  blkdev_ioctl },
+  /* 1: /dev/fd                Floppy disc block devices  */
+  {  no_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,     sys_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-v85/devtty.c b/Kernel/platform-v85/devtty.c
new file mode 100644 (file)
index 0000000..3863368
--- /dev/null
@@ -0,0 +1,86 @@
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#include <stdbool.h>
+#include <tty.h>
+#include <devtty.h>
+
+static unsigned char tbuf1[TTYSIZ];
+
+struct  s_queue  ttyinq[NUM_DEV_TTY+1] = {       /* ttyinq[0] is never used */
+    {   NULL,    NULL,    NULL,    0,        0,       0    },
+    {   tbuf1,   tbuf1,   tbuf1,   TTYSIZ,   0,   TTYSIZ/2 },
+};
+
+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,
+};
+
+void tty_setup(uint8_t minor, uint8_t flags)
+{
+    minor;
+}
+
+/* For the moment */
+int tty_carrier(uint8_t minor)
+{
+    minor;
+    return 1;
+}
+
+void tty_putc(uint8_t minor, unsigned char c)
+{
+    switch(minor){
+        case 1:
+            ttyout(c);
+            break;
+    }
+}
+
+void tty_sleeping(uint8_t minor)
+{
+    minor;
+}
+
+void tty_data_consumed(uint8_t minor)
+{
+}
+
+ttyready_t tty_writeready(uint8_t minor)
+{
+    uint8_t r;
+#if 0
+    if (minor == 1)
+        r = ttyready();
+    else
+        r = ttyready2();
+    if (r)
+        return TTY_READY_NOW;
+    return TTY_READY_SOON;
+#endif
+    return TTY_READY_NOW;
+}
+
+void tty_poll(void)
+{
+    uint16_t r;
+    while((r = acia_poll()) != 0xFFFF)
+        tty_inproc(1, r);
+}
+
+/* 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-v85/devtty.h b/Kernel/platform-v85/devtty.h
new file mode 100644 (file)
index 0000000..44a1006
--- /dev/null
@@ -0,0 +1,6 @@
+extern void tty_poll(void);
+extern void ttyout(uint8_t c);
+
+extern uint16_t acia_poll(void);
+
+
diff --git a/Kernel/platform-v85/end.s b/Kernel/platform-v85/end.s
new file mode 100644 (file)
index 0000000..ae8ac45
--- /dev/null
@@ -0,0 +1,12 @@
+#include "../kernel-8080.def"
+
+.sect .common
+
+.define commonend
+
+commonend:
+
+.sect .bss
+.define bssend
+
+bssend:
diff --git a/Kernel/platform-v85/kernel.def b/Kernel/platform-v85/kernel.def
new file mode 100644 (file)
index 0000000..4077bba
--- /dev/null
@@ -0,0 +1,11 @@
+! UZI mnemonics for memory addresses etc
+
+U_DATA                      = 0xE800       ! (this is struct u_data from kernel.h)
+U_DATA__TOTALSIZE           = 0x200        ! 256+256 bytes.
+
+U_DATA_STASH               = 0xBE00       ! BE00-BFFF
+
+PROGBASE                   = 0x0000
+PROGLOAD                   = 0x0100
+
+CONFIG_SWAP                = 1
diff --git a/Kernel/platform-v85/main.c b/Kernel/platform-v85/main.c
new file mode 100644 (file)
index 0000000..62b4bb8
--- /dev/null
@@ -0,0 +1,84 @@
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+#include <blkdev.h>
+
+uaddr_t ramtop = PROGTOP;
+uint16_t swap_dev = 0xFFFF;
+
+extern uint16_t probe_bank(uint16_t);
+
+void pagemap_init(void)
+{
+ uint8_t i;
+ uint8_t m = 2;
+ for (i = 1; i < 8; i++) {
+  if (probe_bank(m) == 0) {
+       pagemap_add(m);
+       ramsize += 48;
+       procmem += 48;
+  }
+  m <<= 1;
+ }
+ if (procmem < 96)
+       panic("insufficient memory");
+}
+
+/* On idle we spin checking for the terminals. Gives us more responsiveness
+   for the polled ports */
+void platform_idle(void)
+{
+  /* We don't want an idle poll and IRQ driven tty poll at the same moment */
+  irqflags_t irq = di();
+  tty_poll(); 
+  irqrestore(irq);
+}
+
+void platform_interrupt(void)
+{
+ tty_poll();
+ timer_interrupt();
+}
+
+/* Nothing to do for the map of init */
+void map_init(void)
+{
+}
+
+uint8_t platform_param(char *p)
+{
+ used(p);
+ return 0;
+}
+
+/*
+ *     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;
+       
+       if (blk->lba_count[m - 1] > 0xFFFF)
+               n = 0xFFFF;
+       else
+               n = (uint16_t)blk->lba_count[m-1];
+       n /= SWAP_SIZE;
+       if (n > MAX_SWAPS)
+               n = MAX_SWAPS;
+#ifdef SWAPDEV
+       while (n)
+               swapmap_init(n--);
+#endif
+}
+
diff --git a/Kernel/platform-v85/platform_ide.h b/Kernel/platform-v85/platform_ide.h
new file mode 100644 (file)
index 0000000..a147c6a
--- /dev/null
@@ -0,0 +1,18 @@
+#define ide_select(x)
+#define ide_deselect()
+
+/*CF card: 8bit, no altstatus/control */
+#define IDE_8BIT_ONLY
+#define IDE_REG_INDIRECT
+
+#define ide_reg_data      0x10
+#define ide_reg_error     0x11
+#define ide_reg_features  0x11
+#define ide_reg_sec_count 0x12
+#define ide_reg_lba_0     0x13
+#define ide_reg_lba_1     0x14
+#define ide_reg_lba_2     0x15
+#define ide_reg_lba_3     0x16
+#define ide_reg_devhead   0x16
+#define ide_reg_command   0x17
+#define ide_reg_status    0x17
diff --git a/Kernel/platform-v85/target.mk b/Kernel/platform-v85/target.mk
new file mode 100644 (file)
index 0000000..2173aca
--- /dev/null
@@ -0,0 +1 @@
+export CPU = 8080
diff --git a/Kernel/platform-v85/tricks.s b/Kernel/platform-v85/tricks.s
new file mode 100644 (file)
index 0000000..66623cd
--- /dev/null
@@ -0,0 +1,84 @@
+#
+
+#include "../kernel-8080.def"
+#include "../lib/8080fixedbank.s"
+
+.sect .common
+
+.define bankfork
+
+bankfork:
+       sta patch1+1
+       mov a,c
+       sta patch2+1
+       lxi h,0
+       dad sp
+       shld copy_done+1        ! patch stack restore in
+
+       ! Go from the break to 0-5
+       lhld U_DATA__U_BREAK
+       lxi d,-6                ! move down 6 for the copier loop
+       dad d
+       sphl
+       mvi a,0xff              ! end between 5 and 0 (which is fine)
+       sta patch3+1
+       lxi h,copy_stack
+       jmp copier
+       !
+       !       Go from BE00 to the stack pointer
+       !
+copy_stack:
+       lxi sp,0xBE00-6
+       ! Trickier .. need to work out where to stop
+       lhld U_DATA__U_SYSCALL_SP
+       lxi d,-0x0106           ! 6 for the underrun 0x100 for the round down
+       dad d
+       mov a,h
+       sta patch3+1
+       lxi h,copy_done
+       jmp copier
+copy_done:
+       lxi h,0
+       sphl
+       ret
+
+copier:
+       shld patch4+1
+loop:
+                               ! sp points to top of block
+patch1:
+       mvi a,0                 !                                       7
+       out 0x40                ! source bank                           10
+       pop h                   !                                       10
+       pop d                   !                                       10
+       pop b                   !                                       10
+patch2:
+       mvi a,0                 !                                       7
+       out 0x40                ! dest bank                             10
+       push b                  !                                       11
+       push d                  !                                       11
+       push h                  ! sp now back where it started          11
+       lxi h,-6                !                                       10
+       dad sp                  !                                       10
+       sphl                    ! sp ready for next burst               5
+       mov a,h                 !                                       5
+patch3:
+       cpi 0                   ! wrapped to FFFx                       7
+       jnz loop                !                                       10
+
+!
+!      144 cycles per 6 bytes = 24 per byte which is actually not far off
+!      a naive Z80 implementation and about half a good one. Still means
+!      a second to do the fork() bank copy on a 1MHz 8080. Not quite so bad
+!      on a 6MHz 8085 though 8)
+!
+!      We halt at somewhere around xx05-xx00 so we have to tidy up by hand
+!      or accept an underrun. We go the overlap approach on the grounds
+!      it's cheap and our main overcopy is at most 5 bytes in common,
+!      whlist the bank to bank overcopy is harmless and small
+!
+!
+       mvi a,1
+       out 0x40
+patch4:
+       jmp 0
diff --git a/Kernel/platform-v85/v85.s b/Kernel/platform-v85/v85.s
new file mode 100644 (file)
index 0000000..3a6b96e
--- /dev/null
@@ -0,0 +1,418 @@
+#
+!
+!      Low level platform support for v8080
+!
+
+       #include "../kernel-8080.def"
+
+.sect .common
+
+.define _platform_monitor
+.define _platform_reboot
+
+_platform_monitor:
+_platform_reboot:
+       di
+       hlt
+
+.define platform_interrupt_all
+
+platform_interrupt_all:
+       mvi a,0x50
+       out 0xFE
+       ret
+
+.sect .text
+
+.define init_early
+
+init_early:
+       ret
+
+.sect .common
+
+
+.define init_hardware
+
+init_hardware:
+       mvi a,8
+       out 20
+       ! Hack for now
+       lxi h,64                ! 1 * 48K + 16K common
+       shld _ramsize
+       lxi h,0
+       shld _procmem
+
+       mvi a,0x40
+       out 0xFE                ! 10Hz timer on
+
+       mvi a,0x96              ! Intialize the ACIA
+       out 0
+
+       jmp _program_vectors_k
+
+.define _int_disabled
+_int_disabled:
+       .data1 1
+
+.define _program_vectors
+
+_program_vectors:
+       di
+       pop d
+       pop h
+       push h
+       push d
+       call map_process
+       call _program_vectors_u
+       call map_kernel_di
+       ret
+
+_program_vectors_k:
+       push b
+       call .rst_init
+       pop b
+!
+!      The 8085 has some vectors of its own
+!      0x24 is NMI
+!      0x2C/0x34/0x3C are vectored interrupts
+!      This also means we need a customised .rst handler to leave room for
+!      NMI and RST 5.5 ideally.
+!
+!      We have the ACIA on 0x3C (polled for the moment) and the timer
+!      on 0x34
+!
+_program_vectors_u:
+       mvi a,0xc3
+       sta 0
+       lxi h,null_handler
+       shld 1
+!
+!      FIXME: rst code fouls NMI
+!      
+!      sta 0x24
+!      lxi h,nmi_handler
+!      shld 0x25
+       sta 0x30
+       lxi h,unix_syscall_entry
+       shld 0x31
+       sta 0x3c
+       lxi h,acia_interrupt
+       shld 0x3d
+       sta 0x34
+       lxi h,interrupt_handler
+       shld 0x35
+       !
+       !       Just in case
+       !
+       lxi h,unexpected
+!      sta 0x2C
+!      shld 0x2D
+       sta 0x38
+       shld 0x39
+       ret
+
+unexpected:
+       lxi h,unexpect
+       call outstring
+       ei
+       ret
+
+unexpect:
+       .ascii '[unexpected irq]'
+       .data1 10,0
+!
+!      Memory mapping
+!
+.define map_kernel
+.define map_kernel_di
+
+map_kernel:
+map_kernel_di:
+map_buffers:
+       push psw
+       mvi a,1
+       sta curmap
+       out 0x40
+       pop psw
+       ret
+
+.define map_process
+.define map_process_di
+.define map_process_a
+
+map_process:
+map_process_di:
+       mov a,h
+       ora l
+       jz map_kernel
+       mov a,m
+map_for_swap:
+map_process_a:
+       sta curmap
+       out 0x40
+       ret
+
+.define map_process_always
+.define map_process_always_di
+
+map_process_always:
+map_process_always_di:
+       push psw
+       lda U_DATA__U_PAGE
+       sta curmap
+       out 0x40
+       pop psw
+       ret
+
+.define map_save_kernel
+
+map_save_kernel:
+       push psw
+       lda curmap
+       sta map_save
+       mvi a,1
+       sta curmap
+       out 0x40
+       pop psw
+       ret
+
+.define map_restore
+
+map_restore:
+       push psw
+       lda map_save
+       sta curmap
+       out 0x40
+       pop psw
+       ret
+
+.define _probe_bank
+
+_probe_bank:
+       pop d
+       pop h
+       push h
+       push d
+       mov a,l
+       call map_process_a
+       lxi d,-1
+       lxi h,4
+       mvi a,0x55
+       mov m,a
+       cmp m
+       jnz nobank
+       inr m
+       inr a
+       cmp m
+       jnz nobank
+       inx d
+nobank:
+       jmp map_kernel
+
+map_save:
+       .data1 0
+curmap:
+       .data1 1
+.define outchar
+.define _ttyout
+
+!
+!      6850 ACIA
+!
+_ttyout:
+       pop h
+       pop d
+       push d
+       push h
+       mov a,e
+outchar:
+       push psw
+outcharw:
+       in 0
+       ani 2
+       jz outcharw
+       pop psw
+       out 1
+       ret
+
+.define _ttyready
+
+_ttyready:
+       in 0
+       ani 2
+       mov e,a
+       ret
+
+.define _acia_poll
+
+!
+!      Call with interrupts off
+!
+_acia_poll:
+       lxi h,acia_queue+1
+       mov a,m                 ! read pointer
+       mov e,a                 ! save it
+       dcx h                   ! queue pointer
+       cmp m                   ! queue = read + 1 -> empty
+       jz empty
+       inr a
+       inx h                   ! point back to read
+       mov m,a                 ! move on one
+       lxi h,acia_rxbuf        ! data buffer
+       mvi d,0
+       dad d                   ! plus offset
+       mov e,m                 ! return char in DE
+       mvi d,0
+       ret
+empty:
+       lxi d,0xffff            ! No luck
+       ret
+
+
+!
+!      ACIA interrupt
+!
+acia_interrupt:
+       push psw
+       in 0
+       rar
+       cc acia_rx              ! we only do rx interrupts for now
+       pop psw
+       ei
+       ret
+acia_rx:
+       push h
+       push d
+       lxi h,acia_queue
+       mov a,m                 ! queue pointer
+       mov e,a                 ! save it
+       inx h                   ! move on to rx pointer
+       inr a                   ! move on
+       cmp m                   ! if we would hit rx pointer we are full
+       jz acia_rx_over         ! so bail out
+       dcx h                   ! back to queue pointer
+       mov m,a                 ! save new pointer
+       mvi d,0
+       lxi h,acia_rxbuf        ! get data offset and save
+       dad d                   ! could simplify if page aligned...
+       in 1
+       mov m,a
+acia_rx_over:
+       pop d
+       pop h
+       ret
+
+acia_rxbuf:
+       .space 256
+acia_queue:
+       .data1 1                ! queue pointer
+       .data1 0                ! read pointer
+       
+!
+!      IDE controller
+!
+.sect .common
+
+.define _devide_readb
+.define _devide_writeb
+
+_devide_readb:
+       pop h
+       pop d
+       push d
+       push h
+       mov a,e
+       sta .patch1+1
+.patch1:
+       in 0
+       mov e,a
+       mvi d,0
+       ret
+
+_devide_writeb:
+       lxi h,2
+       dad sp
+       mov a,m
+       sta .patch2+1
+       inx h
+       inx h
+       mov a,m
+.patch2:
+       out 0
+       ret
+
+.define _devide_read_data
+.define _devide_write_data
+
+_devide_read_data:
+       push b
+       lxi h,_blk_op
+       mov e,m
+       inx h
+       mov d,m                 ! Address
+       inx h
+       mov a,m                 ! Mapping type
+       cpi 2
+       jnz not_swapin
+       inx h                   ! Swap page
+       mov a,m
+       call map_for_swap
+       jmp doread
+not_swapin:
+       ora a
+       jz rd_kernel
+       call map_process_always
+       jmp doread
+rd_kernel:
+       call map_buffers
+doread:
+       mvi b,0
+       xchg
+readloop:
+       in 0x10
+       mov m,a
+       inx h
+       in 0x10
+       mov m,a
+       inx h
+       inr b
+       jnz readloop
+       pop b
+       jmp map_kernel
+
+_devide_write_data:
+       push b
+       lxi h,_blk_op
+       mov e,m
+       inx h
+       mov d,m
+       inx h
+       mov a,m
+       cpi 2
+       jnz not_swapout
+       inx h
+       mov a,m
+       call map_for_swap
+       jmp dowrite
+not_swapout:
+       ora a
+       jz wr_kernel
+       call map_process_always
+       jmp dowrite
+wr_kernel:
+       call map_buffers
+dowrite:
+       mvi b,0
+       xchg
+writeloop:
+       mov a,m
+       out 0x10
+       inx h
+       mov a,m
+       out 0x10
+       inx h
+       inr b
+       jnz writeloop
+       pop b
+       jmp map_kernel