rc2014: lay groundwork to make rc2014 run a banked kernel.
authorAlan Cox <alan@linux.intel.com>
Fri, 15 Mar 2019 22:03:37 +0000 (22:03 +0000)
committerAlan Cox <alan@linux.intel.com>
Fri, 15 Mar 2019 22:03:37 +0000 (22:03 +0000)
RC2014 has so many toys they do not all fit any more and there is still sound,
PIO and TMS9918A support to add!

This breaks everything. The loader needs a rewrite and the code debugging so
if you are doing a build go back before this commit

16 files changed:
Kernel/platform-rc2014/Makefile
Kernel/platform-rc2014/README
Kernel/platform-rc2014/config.h
Kernel/platform-rc2014/crt0.s
Kernel/platform-rc2014/devrd_zeta2.c [deleted file]
Kernel/platform-rc2014/devrd_zeta2_hw.s [deleted file]
Kernel/platform-rc2014/discard.c
Kernel/platform-rc2014/extbuffer.c [deleted file]
Kernel/platform-rc2014/fuzix.lnk
Kernel/platform-rc2014/kernel.def
Kernel/platform-rc2014/main.c
Kernel/platform-rc2014/monitor.s
Kernel/platform-rc2014/rc2014.s
Kernel/platform-rc2014/tricks.s
Kernel/platform-rc2014/vfd-term.c
Kernel/platform-rc2014/vfdterm.s

index a012b53..2c89259 100644 (file)
@@ -1,11 +1,11 @@
 ASRCS = crt0.s tricks.s commonmem.s rc2014.s monitor.s vfdterm.s buffers.s
-CSRCS = devices.c main.c devtty.c vfd-debug.c vfd-term.c extbuffer.c
+CSRCS = devices.c main.c devtty.c vfd-debug.c vfd-term.c
 CSRCS += devinput.c
 DISCARD_CSRCS = discard.c
 DISCARD_DSRCS = ../dev/devide_discard.c ../dev/ds1302_discard.c
 DSRCS = ../dev/devfd.c ../dev/devide.c ../dev/mbr.c ../dev/blkdev.c
 DSRCS +=  ../dev/ds1302.c ../dev/ppide_rbc.c
-DASRCS = ../dev/devfd_hw.s ../dev/ds1302_rc2014.s
+DASRCS = ../dev/devfd_hw-banked.s ../dev/ds1302_rc2014-banked.s
 NSRCS = ../dev/net/net_native.c
 
 AOBJS = $(ASRCS:.s=.rel)
@@ -28,10 +28,10 @@ $(AOBJS): %.rel: %.s
        $(CROSS_AS) $(ASOPTS) $<
 
 $(COBJS): %.rel: %.c
-       $(CROSS_CC) $(CROSS_CCOPTS) --codeseg COMMONMEM -c $<
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG1) -c $<
 
 $(DOBJS): %.rel: ../dev/%.c
-       $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG1) -c $<
 
 $(DAOBJS): %.rel: ../dev/%.s
        $(CROSS_AS) $(ASOPTS) $@ $<
@@ -43,7 +43,7 @@ $(DISCARD_DOBJS): %.rel: ../dev/%.c
        $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $<
 
 $(NOBJS): %.rel: ../dev/net/%.c
-       $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+       $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG2) -c $<
 
 clean:
        rm -f $(OBJS) $(JUNK)  core *~ bootrom.ihx bootrom.bin fuzix.com fuzix.rom
@@ -52,7 +52,7 @@ clean:
 #      Compile up the boot block
 #
 image: bootblock
-       cat boot-romwbw.bin ../fuzix.bin >fuzix.romwbw
+#      cat boot-romwbw.bin ../fuzix.bin >fuzix.romwbw
 
 bootblock:
        sdasz80 -o boot-romwbw.s
index 41d054c..937b6b5 100644 (file)
@@ -35,17 +35,25 @@ Supported Hardware
 
        PPIDE
 
+Pending
+
+       TMS99918A VDP as timer
+
+       Sound cards (until Fuzix gets proper audio support)
+
+
 Unsupported Hardware
 
        SC108/SC114/Z80SBC64 or other CPU boards with their own banking instead
-       of the 512K ROM/RAM
+       of the 512K ROM/RAM. Please see the relevant port instead.
 
        SC114 bit bang serial
 
        Z80 PIO cards (really because I've no idea how to present them)
 
        SC110 CTC/serial (does not appear to be able to chain CTC pairs, as
-       is neeed for IM1 mode).
+       is neeed for IM1 mode). You can run a wire by hand.
+
 
 
 Things To Note When Modifying
@@ -66,8 +74,6 @@ Stuff To Do
 
   * Other tty options - can we autodetect 16550A at 0x80.
 
-  * Probe both 0x10 and 0xE0 for CF ?
-
   * How to represent a Z80 PIO usefully to Fuzix (similar issues with Nascom)
     both raw and hosting an interface (eg /dev/lp or even floppy)
 
index 506bfb9..138a408 100644 (file)
@@ -7,11 +7,15 @@
 /* Set this if you have the 8255 IDE adapter (mutually exclusive of RC2014_CF) */
 #undef CONFIG_RC2014_PPIDE
 /* Set this if you have the floppy interface */
-#undef CONFIG_RC2014_FLOPPY
+#define CONFIG_RC2014_FLOPPY
 /* Set this if you have a VFD interface */
 #undef CONFIG_RC2014_VFD
 
 
+#define OFTSIZE                64
+#define ITABSIZE       48
+#define PTABSIZE       24
+
 /*
  *     Turn selections into system level defines
  */
@@ -71,9 +75,8 @@ extern unsigned int swap_dev;
 #define MAX_SWAPS   16         /* We will size if from the partition */
 /* Swap will be set up when a suitably labelled partition is seen */
 #define CONFIG_DYNAMIC_SWAP
-/* We have lots of RAM so make better use of it for disk buffers. We grab
-   a 16K page and use it as our disk cache */
-#define CONFIG_BLKBUF_EXTERNAL
+/* Kept in bank 2 */
+#define CONFIG_DYNAMIC_BUFPOOL
 /*
  *     When the kernel swaps something it needs to map the right page into
  *     memory using map_for_swap and then turn the user address into a
@@ -86,7 +89,7 @@ extern unsigned int swap_dev;
 #define CMDLINE        NULL  /* Location of root dev name */
 #define BOOTDEVICENAMES "hd#,fd,,rd"
 
-#define NBUFS    32       /* Number of block buffers, keep in line with space reserved in zeta-v2.s */
+#define NBUFS    5        /* Number of block buffers - must match kernel.def */
 #define NMOUNTS         4        /* Number of mounts at a time */
 
 #define MAX_BLKDEV 5       /* 1 floppy, 4 IDE */
index 1fb6e38..5a207d7 100644 (file)
@@ -7,21 +7,24 @@
         ; 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 _CODE
         .area _HOME     ; compiler stores __mullong etc in here if you use them
-        .area _CODE2
+       .area _STUBS
         .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 _INITIALIZER ; binman copies this to the right place for us
         .area _GSINIT      ; unused
         .area _GSFINAL     ; unused
+       .area _BUFFERS
         .area _DISCARD
+        .area _INITIALIZER ; binman copies this to the right place for us
+       .area _CODE1
+       .area _DISCARD1
+        .area _CODE2
+       .area _DISCARD2
         .area _COMMONMEM
 
         ; exported symbols
         .globl l__COMMONMEM
         .globl s__DISCARD
         .globl l__DISCARD
+        .globl s__BUFFERS
+        .globl l__BUFFERS
         .globl s__DATA
         .globl l__DATA
         .globl kstack_top
 
        .include "kernel.def"
+       .include "../kernel-z80.def"
 
-       ; Dummy page0 area so binman doesn't pack us
+        ; startup code. Starts _CODE because we want it to be at 0x0100
 
-       .area _PAGE0
-
-        ; startup code
         .area _CODE
 init:                       ; must be at 0x0100 as we are loaded at that
        ; setup the memory paging for kernel
@@ -67,14 +70,42 @@ mappedok:
         ld (hl), #0
         ldir
 
+       ; Zero buffers area
+       ld hl, #s__BUFFERS
+       ld de, #s__BUFFERS + 1
+       ld bc, #l__BUFFERS - 1
+       ld (hl), #0
+       ldir
+
         ; Hardware setup
+       push af
         call init_hardware
+       pop af
 
         ; Call the C main routine
+       push af
         call _fuzix_main
+       pop af
     
         ; fuzix_main() shouldn't return, but if it does...
         di
 stop:   halt
         jr stop
 
+;
+;      Call stubs are filled in here by the linker
+;
+
+       .area _STUBS
+       .ds 600
+
+       .area _BUFFERS
+;
+; Buffers (we use asm to set this up as we need them in a special segment
+; so we can grow to fit the space free
+;
+       .globl _bufpool
+       .area _BUFFERS
+
+_bufpool:
+       .ds BUFSIZE * NBUFS
diff --git a/Kernel/platform-rc2014/devrd_zeta2.c b/Kernel/platform-rc2014/devrd_zeta2.c
deleted file mode 100644 (file)
index 9588060..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Zeta SBC V2  memory driver
- *
- * 2017-01-03 William R Sowerbutts, based on RAM disk code by Sergey Kiselev
- */
-
-#include <kernel.h>
-#include <kdata.h>
-#include <printf.h>
-#define DEVRD_PRIVATE
-#include "devrd.h"
-
-void rd_page_copy(void); // devrd_zeta2_hw.s
-
-void rd_platform_copy(void)
-{
-    uint16_t ocount, count, maxcpy;
-
-    ocount = count = rd_cpy_count;
-
-    while(true){
-        /* ensure transfer will not span a 16KB bank boundary */
-        maxcpy = ((uint16_t)rd_src_address) & 0x3FFF;
-        if((rd_dst_address & 0x3FFF) > maxcpy)
-            maxcpy = rd_dst_address & 0x3FFF;
-        maxcpy = 0x4000 - maxcpy;
-        if(rd_cpy_count > maxcpy)
-            rd_cpy_count = maxcpy;
-#ifdef DEBUG
-        kprintf("rd_transfer: src=0x%lx, dst=0x%x(%s) reverse=%d count=%d\n",
-                rd_src_address, rd_dst_address, rd_dst_userspace?"user":"kern",
-                rd_reverse, rd_cpy_count);
-#endif
-        rd_page_copy();
-
-        count -= rd_cpy_count;
-        if(!count)
-            break;
-
-        rd_dst_address += rd_cpy_count;
-        rd_src_address += rd_cpy_count;
-        rd_cpy_count = count;
-    }
-
-    rd_cpy_count = ocount;
-}
diff --git a/Kernel/platform-rc2014/devrd_zeta2_hw.s b/Kernel/platform-rc2014/devrd_zeta2_hw.s
deleted file mode 100644 (file)
index 048ab7e..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-        .module devrd_hw
-
-        ; imported symbols
-        .globl map_kernel, mpgsel_cache, _kernel_pages
-        .globl _rd_platform_copy
-       .globl _udata
-
-        ; exported symbols
-        .globl _rd_page_copy
-        .globl _rd_cpy_count
-        .globl _rd_reverse
-        .globl _rd_dst_userspace
-        .globl _rd_dst_address
-        .globl _rd_src_address
-        .globl _devmem_read
-        .globl _devmem_write
-
-        .include "kernel.def"
-        .include "../kernel-z80.def"
-
-        .area _CODE
-_devmem_write:
-        ld a, #1
-        ld (_rd_reverse), a             ; 1 = write
-        jr _devmem_go
-
-_devmem_read:
-        xor a
-        ld (_rd_reverse), a             ; 0 = read
-        inc a
-_devmem_go:
-        ld (_rd_dst_userspace), a       ; 1 = userspace
-        ; load the other parameters
-        ld hl, (_udata + U_DATA__U_BASE)
-        ld (_rd_dst_address), hl
-        ld hl, (_udata + U_DATA__U_OFFSET)
-        ld (_rd_src_address), hl
-        ld hl, (_udata + U_DATA__U_OFFSET+2)
-        ld (_rd_src_address+2), hl
-        ld hl, (_udata + U_DATA__U_COUNT)
-        ld (_rd_cpy_count), hl
-        ; for single byte transfers we can optimise away the outer loop
-        dec l                           ; test for HL=1
-        ld a, h
-        or l
-        jp nz, _rd_platform_copy        ; > 1 byte, do it the hard way
-        call _rd_page_copy              ; transfer single byte
-        ld hl, #1                       ; return with HL set appropriately
-        ret
-
-        .area _COMMONMEM
-;=========================================================================
-; _rd_page_copy - Copy data from one physical page to another
-; See notes in devrd.h for input parameters
-;=========================================================================
-_rd_page_copy:
-        ; split rd_src_address into page and offset -- it's limited to 20 bits (max 0xFFFFF)
-        ; example address 0x000ABCDE 
-        ; in memory it is stored: DE BC 0A 00
-        ; offset would be 0x0ABCDE & 0x3FFF = 0x3CDE
-        ; page would be   0x0ABCDE >> 14    = 0x2A
-
-        ; compute source page number
-        ld a,(_rd_src_address+1)        ; load 0xBC -> B
-        ld b, a
-        ld a,(_rd_src_address+2)        ; load 0x0A -> A
-        rl b                            ; grab the top bit into carry
-        rla                             ; shift accumulator left, load carry bit at the bottom 
-        rl b                            ; and again
-        rla                             ; now A is the page number (0x2A)
-
-        ; map source page
-        ld (mpgsel_cache+1),a           ; save the mapping
-        out (MPGSEL_1),a                ; map source page to bank #1
-
-        ; compute source page offset, store in DE
-        ld a,(_rd_src_address+1)
-        and #0x3F                       ; mask to 16KB
-        or #0x40                        ; add offset for bank 1
-        ld d, a
-        ld a,(_rd_src_address+0)
-        ld e, a                         ; now offset is in DE
-
-        ; compute destination page index (addr 0xABCD >> 14 = 0x02)
-        ld a,(_rd_dst_address+1)        ; load top 8 bits
-        and #0xc0                       ; mask off top 2 bits
-        rlca                            ; rotate into lower 2 bits
-        rlca
-        ld b, #0
-        ld c, a                         ; store in l
-
-        ; look up page number
-        ld a,(_rd_dst_userspace)        ; are we loading into userspace memory?
-        or a
-        jr nz, rd_translate_userspace
-        ld hl, #_kernel_pages           ; get kernel page table
-        jr rd_do_translate
-rd_translate_userspace:
-        ld hl, #_udata + U_DATA__U_PAGE          ; get user process page table
-rd_do_translate:
-        add hl, bc                      ; add index to base ptr (uint8_t *)
-        ld a, (hl)                      ; load the page number from the page table
-
-        ; map destination page
-        ld (mpgsel_cache+2),a           ; save the mapping
-        out (MPGSEL_2),a                ; map destination page to bank #2
-
-        ; compute destination page offset, store in HL
-        ld a,(_rd_dst_address+1)
-        and #0x3F                       ; mask to 16KB
-        or #0x80                        ; add offset for bank #2
-        ld h, a
-        ld a, (_rd_dst_address+0)
-        ld l, a                         ; now offset is in HL
-
-        ; load byte count
-        ld bc,(_rd_cpy_count)           ; bytes to copy
-
-        ; check if reversed
-        ld a, (_rd_reverse)
-        or a
-        jr nz, go
-        ex de,hl                        ; reverse if necessary
-go:
-        ldir                            ; do the copy
-        jp map_kernel                   ; map back the kernel
-
-; variables
-_rd_cpy_count:
-        .dw     0                       ; uint16_t
-_rd_reverse:
-        .db     0                       ; bool
-_rd_dst_userspace:
-        .db     0                       ; bool
-_rd_dst_address:
-        .dw     0                       ; uint16_t
-_rd_src_address:
-        .db     0                       ; uint32_t
-        .db     0
-        .db     0
-        .db     0
-;=========================================================================
index 9c4209b..6724d56 100644 (file)
@@ -30,8 +30,9 @@ void pagemap_init(void)
         * Pages 32-34 are used by the kernel
         * Page 35 is the common area for init
         * Page 36 is the disk cache
+        * Pages 37 amd 38 are the second kernel bank
         */
-       for (i = 32 + 5; i < 64; i++)
+       for (i = 32 + 7; i < 64; i++)
                pagemap_add(i);
 
        /* finally add the common area */
@@ -53,15 +54,6 @@ void pagemap_init(void)
 
 void map_init(void)
 {
-       /* Point the buffers into the 16-32K range that will be used by
-          the buffer remap. We offset by 0x4000 if need be in the access
-          functions when handling overlaps */
-       bufptr bp = bufpool;
-       uint8_t *p = (uint8_t *) 0x4000;
-       while (bp < bufpool_end) {
-               bp++->__bf_data = p;
-               p += BLKSIZE;
-       }
 }
 
 /*
diff --git a/Kernel/platform-rc2014/extbuffer.c b/Kernel/platform-rc2014/extbuffer.c
deleted file mode 100644 (file)
index 28cb97c..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#include <kernel.h>
-#include <kdata.h>
-#include <printf.h>
-
-extern uint8_t *bdest;
-extern uint16_t blen;
-extern void do_blkzero(uint8_t *ptr) __z88dk_fastcall;
-extern void do_blkcopyk(uint8_t *src) __z88dk_fastcall;
-extern void do_blkcopyul(uint8_t *src) __z88dk_fastcall;
-extern void do_blkcopyuh(uint8_t *src) __z88dk_fastcall;
-
-/*
- *     Must live in CODE2
- */
-
-void blktok(void *kaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
-{
-    bdest = kaddr;
-    blen = len;
-    do_blkcopyk(buf->__bf_data + off);
-}
-
-void blkfromk(void *kaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
-{
-    bdest = buf->__bf_data + off;
-    blen = len;
-    do_blkcopyk(kaddr);
-}
-
-/* FIXME: work out a nice way to share the logic */
-void blktou(void *uaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
-{
-    uint16_t split;
-    bdest = uaddr;
-    blen = len;
-    /* If it's all below 16K or all over 32K then use the 0x4000 window */
-    if ((uint16_t)uaddr + len < 0x4000 || (uint16_t)uaddr > 0x8000) {
-        do_blkcopyul(buf->__bf_data + off);
-        return;
-    }
-    /* If it's all below 0x8000 then use the 0x8000 window */
-    if ((uint16_t)uaddr + len < 0x8000) {
-        do_blkcopyuh(buf->__bf_data + off + 0x4000);
-        return;
-    }
-    /* Split case */
-    split = 0x8000 - (uint16_t)uaddr;
-    blen = split;
-    do_blkcopyuh(buf->__bf_data + off + 0x4000);
-    blen = len - split;
-    bdest += split;
-    do_blkcopyul(buf->__bf_data + off + split);
-}
-
-void blkfromu(void *uaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
-{
-    uint16_t split;
-    bdest = buf->__bf_data + off;
-    blen = len;
-    /* If it's all below 16K or all over 32K then use the 0x4000 window */
-    if ((uint16_t)uaddr + len < 0x4000 || (uint16_t)uaddr > 0x8000) {
-        do_blkcopyul(uaddr);
-        return;
-    }
-    /* If it's all below 0x8000 then use the 0x8000 window */
-    if ((uint16_t)uaddr + len < 0x8000) {
-        bdest += 0x4000;
-        do_blkcopyuh(uaddr);
-        return;
-    }
-    /* Split case */
-    split = 0x8000 - uaddr;
-    blen = split;
-    bdest += 0x4000;
-    do_blkcopyuh(uaddr);
-    blen = len - split;
-    bdest += split- 0x4000;
-    do_blkcopyul((uint8_t *)uaddr + split);
-}
-
-static uint8_t scratchbuf[64];
-
-/* Worst case is needing to copy over about 64 bytes */
-void *blkptr(struct blkbuf *buf, uint16_t offset, uint16_t len)
-{
-    if (len > 64)
-        panic("blkptr");
-    bdest = scratchbuf;
-    blen = sizeof(scratchbuf);
-    do_blkcopyk(buf->__bf_data + offset);
-    return scratchbuf;
-}
-
-void blkzero(struct blkbuf *buf)
-{
-    do_blkzero(buf->__bf_data);
-}
-
-/*
- *     Scratch buffers for syscall arguments - until we can rework
- *     execve and realloc to avoid this need
- *
- *     The buffers must be valid in both kernel and buffer mappings.
- */
-
-extern uint8_t workbuf[2][BLKSIZE];
-static uint8_t tfree = 3;
-
-void tmpfree(void *p)
-{
-  if (p == workbuf[0]) {
-      tfree |= 1;
-      return;
-  }
-  if (p == workbuf[1]) {
-      tfree |= 2;
-      return;
-  }
-  panic("tmpfree");
-}
-
-void *tmpbuf(void)
-{
-   if (tfree & 1) {
-       tfree &= ~1;
-       return workbuf[0];
-   }
-   if (tfree & 2) {
-       tfree &= ~2;
-       return workbuf[1];
-   }
-   panic("tmpbuf");
-}
index 2149422..7625aaf 100644 (file)
@@ -1,8 +1,10 @@
--mwxuy
+-rmwxuy
 -i fuzix.ihx
 -b _CODE=0x0100
--b _COMMONMEM=0xD000
--b _DISCARD=0xC300
+-b _CODE1=0x4000
+-b _CODE2=0x4000
+-b _COMMONMEM=0xF000
+-b _DISCARD=0xC000
 -l z80
 platform-rc2014/crt0.rel
 platform-rc2014/commonmem.rel
@@ -12,15 +14,14 @@ platform-rc2014/vfdterm.rel
 platform-rc2014/vfd-term.rel
 start.rel
 version.rel
-lowlevel-z80.rel
+lowlevel-z80-banked.rel
 platform-rc2014/tricks.rel
 platform-rc2014/main.rel
-platform-rc2014/extbuffer.rel
 platform-rc2014/buffers.rel
 timer.rel
 kdata.rel
 platform-rc2014/devfd.rel
-platform-rc2014/devfd_hw.rel
+platform-rc2014/devfd_hw-banked.rel
 platform-rc2014/devices.rel
 devio.rel
 filesys.rel
@@ -40,7 +41,7 @@ tty.rel
 devsys.rel
 devinput.rel
 usermem.rel
-usermem_std-z80.rel
+usermem_std-z80-banked.rel
 platform-rc2014/ppide_rbc.rel
 platform-rc2014/discard.rel
 platform-rc2014/devtty.rel
@@ -52,6 +53,6 @@ platform-rc2014/monitor.rel
 platform-rc2014/devinput.rel
 platform-rc2014/ds1302.rel
 platform-rc2014/ds1302_discard.rel
-platform-rc2014/ds1302_rc2014.rel
+platform-rc2014/ds1302_rc2014-banked.rel
 platform-rc2014/net_native.rel
 -e
index 1d9a6c4..587dc47 100644 (file)
@@ -40,3 +40,5 @@ MPGSEL_1      .equ    0x79    ; Bank_1 page select register (W/O)
 MPGSEL_2       .equ    0x7A    ; Bank_2 page select register (W/O)
 MPGSEL_3       .equ    0x7B    ; Bank_3 page select register (W/O)
 MPGENA         .equ    0x7C    ; memory paging enable register, bit 0 (W/O)
+
+NBUFS          .equ    5
index d5e9ed1..b63760e 100644 (file)
@@ -17,8 +17,25 @@ uint8_t ctc_present;
 uint8_t sio_present;
 uint8_t sio1_present;
 
+struct blkbuf *bufpool_end = bufpool + NBUFS;
+
 void platform_discard(void)
 {
+       uint16_t discard_size = 0x4000 - (uint16_t)bufpool_end;
+       bufptr bp = bufpool_end;
+
+       discard_size /= sizeof(struct blkbuf);
+
+       kprintf("%d buffers added\n", discard_size);
+
+       bufpool_end += discard_size;
+
+       memset( bp, 0, discard_size * sizeof(struct blkbuf) );
+
+       for( bp = bufpool + NBUFS; bp < bufpool_end; ++bp ){
+               bp->bf_dev = NO_DEVICE;
+               bp->bf_busy = BF_FREE;
+       }
 }
 
 void platform_idle(void)
@@ -66,6 +83,20 @@ void platform_interrupt(void)
        }
 }
 
+
+/*
+ *     So that we don't suck in a library routine we can't use from
+ *     the runtime
+ */
+
+int strlen(const char *p)
+{
+  int len = 0;
+  while(*p++)
+    len++;
+  return len;
+}
+
 /*
  *     Logic for tickless system. If you have an RTC you can ignore this.
  */
index 5a18d1a..51df996 100644 (file)
@@ -7,7 +7,7 @@
 
 ; -----------------------------------------------------------------------------
 .ifne USE_FANCY_MONITOR ; -----------------------------------------------------
-                .area _CODE ; actual monitor lives in kernel bank
+                .area _CODE2 ; actual monitor lives in kernel bank
                 .include "../lib/monitor-z80.s"
 
                 .area _COMMONMEM ; just a stub goes in common memory
index 49ad65a..ad55755 100644 (file)
@@ -7,7 +7,9 @@
         .globl init_hardware
        .globl _program_vectors
        .globl map_kernel
+       .globl map_kernel_restore
        .globl map_process
+       .globl map_process_save
        .globl map_buffers
        .globl map_buffers_user
        .globl map_buffers_user_h
@@ -79,6 +81,11 @@ ACIA_RTS_HIGH_A      .EQU     0xD6   ; rts high, xmit interrupt disabled
 ACIA_RTS_LOW_A       .EQU     0x96   ; rts low, xmit interrupt disabled
 ;ACIA_RTS_LOW_A       .EQU     0xB6   ; rts low, xmit interrupt enabled
 
+MAP_BANK1      .equ    0x2221  ; 20 is low, 23 is high
+BANK1          .equ    0x21
+MAP_BANK2      .equ    0x2625  ; for now 24 is buffers - FIXME
+BANK2          .equ    0x25
+
 ;=========================================================================
 ; Initialization code
 ;=========================================================================
@@ -304,7 +311,7 @@ sio_setup:
 ;=========================================================================
 ; Kernel code
 ;=========================================================================
-        .area _CODE
+        .area _COMMONMEM
 
 _platform_reboot:
         ; We need to map the ROM back in -- ideally into every page.
@@ -332,10 +339,12 @@ platform_interrupt_all:
 ; install interrupt vectors
 _program_vectors:
        di
+       pop bc                          ; bank
        pop de                          ; temporarily store return address
        pop hl                          ; function argument -- base page number
        push hl                         ; put stack back as it was
        push de
+       push bc
 
        ; At this point the common block has already been copied
        call map_process
@@ -381,11 +390,23 @@ _program_vectors:
 ; Outputs: none; all registers preserved
 ;=========================================================================
 map_process_always:
+map_process_save:
 map_process_always_di:
        push hl
+       ld hl,#_kernel_pages + 1
+       ; Save the current versions of MPGSEL 1 and 2 for map_kernel_restore
+       ; so we return to the right kernel bank
+       in a,(MPGSEL_1)
+       ld (hl),a
+       inc hl
+       in a,(MPGSEL_2)
+       ld (hl),a
        ld hl,#_udata + U_DATA__U_PAGE
         jr map_process_2_pophl_ret
 
+;
+;      FIXME: needs to save the old kernel mid mapping
+;
 map_buffers_user:
        push hl
        ld hl,(_udata + U_DATA__U_PAGE)
@@ -423,6 +444,7 @@ map_process_di:
 ; Outputs: none; all registers preserved
 ;=========================================================================
 map_kernel:
+map_kernel_restore:
 map_kernel_di:
        push hl
        ld hl,#_kernel_pages
@@ -508,18 +530,140 @@ map_for_swap:
        out (MPGSEL_1),a
        ret
 
+;
+;      Bank switch functions
+;
+       .globl __bank_0_1
+       .globl __bank_0_2
+       .globl __bank_1_2
+       .globl __bank_2_1
+
+       .globl __stub_0_1
+       .globl __stub_0_2
+
+;
+;      We are calling into bank 1 from common. We don't know the current
+;      bank but we need to restore it as was.
+;
+__bank_0_1:
+       ld bc,#MAP_BANK1                ; target pairs always a pair
+bank0:
+       pop hl                          ; in linear order
+       ld e,(hl)
+       inc hl
+       ld d,(hl)
+       inc hl
+       push hl
+       ld (_kernel_pages + 1),bc
+       in a, (MPGSEL_1)                ; existing page
+       ld b,a
+       ld a,c                          ; set new page
+       out (MPGSEL_1),a
+       inc a                           ; next page follows
+       out (MPGSEL_2),a
+       ex de,hl
+       ld a,b                          ; old bank
+       cp #BANK1                       ; 1 or 2
+       jr z, retbank1
+       call callhl
+       ld bc,#MAP_BANK2
+banksetbc:
+       ld (_kernel_pages + 1), bc
+       ld a,c
+       out (MPGSEL_1),a
+       ld a,b
+       out (MPGSEL_2),a
+       ret
+retbank1:
+       ld bc,#MAP_BANK1
+       jr banksetbc
+__bank_0_2:
+       ld bc,#MAP_BANK2
+       jr bank0
+;
+;      These are easier because we have two banks so know the target and
+;      return bank in each case
+;
+__bank_1_2:
+       ld bc,#MAP_BANK2
+       pop hl                          ; in linear order
+       ld e,(hl)
+       inc hl
+       ld d,(hl)
+       inc hl
+       push hl
+       call banksetbc
+       call callhl
+       ld bc,#MAP_BANK1
+       jr banksetbc
+
+__bank_2_1:
+       ld bc,#MAP_BANK1
+       pop hl                          ; in linear order
+       ld e,(hl)
+       inc hl
+       ld d,(hl)
+       inc hl
+       push hl
+       call banksetbc
+       call callhl
+       ld bc,#MAP_BANK2
+       jr banksetbc
+
+__stub_0_1:
+       ld bc,#MAP_BANK1
+       jr stub_call
+__stub_0_2:
+       ld bc,#MAP_BANK2
+stub_call:
+       pop hl                          ; return address
+       ex (sp),hl                      ; bank space now target
+       in a,(MPGSEL_1)                 ; current bank
+       ld (_kernel_pages+1),bc         ; target
+       ld b,a
+       ld a,c
+       out (MPGSEL_1),a
+       inc a
+       out (MPGSEL_2),a
+       ld a,b
+       cp #BANK1
+       jr z, stub_ret_1
+       call callhl
+       ld bc,#MAP_BANK2
+stub_ret:
+       ld (_kernel_pages+1),bc
+       ld a,c
+       out (MPGSEL_1),a
+       inc a
+       out (MPGSEL_2),a
+       pop bc                          ; return
+       push bc                         ; correct stack padding
+       push bc
+       ret                             ; done
+stub_ret_1:
+       call callhl
+       ld bc,#MAP_BANK1
+       jr stub_ret
+
+callhl:        jp (hl)
+;
+;      Helpers for swap
+;
+
 _copy_common:
+       pop bc
        pop hl
        pop de
        push de
        push hl
+       push bc
        ld a,e
        call map_for_swap
        ld hl,#0xD300
        ld de,#0x4300
        ld bc,#0x2D00
        ldir
-       jr map_kernel
+       jp map_kernel
 
 
 ; MPGSEL registers are read only, so their content is cached here
index d73b6d8..46414c2 100644 (file)
@@ -5,7 +5,213 @@
 
 TOP_PORT       .equ    MPGSEL_3
 
-       .include "../lib/z80bank16.s"
+        .globl _ptab_alloc
+        .globl _makeproc
+        .globl _chksigs
+        .globl _getproc
+        .globl _platform_monitor
+        .globl trap_illegal
+        .globl _platform_switchout
+        .globl _switchin
+        .globl _doexec
+        .globl _dofork
+        .globl _runticks
+        .globl unix_syscall_entry
+        .globl interrupt_handler
+       .globl map_kernel
+       .globl _ramtop
+       .globl _need_resched
+       .globl top_bank
+       .globl _int_disabled
+       .globl _udata
+       .globl _kernel_pages
+       .globl map_kernel_restore
+
+        ; imported debug symbols
+        .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex
+
+        .area _COMMONMEM
+
+; ramtop must be in common for single process swapping cases
+; and its a constant for the others from before init forks so it'll be fine
+; here
+_ramtop:
+       .dw 0
+_need_resched:
+       .db 0
+
+; Switchout switches out the current process, finds another that is READY,
+; possibly the same process, and switches it in.  When a process is
+; restarted after calling switchout, it thinks it has just returned
+; from switchout().
+_platform_switchout:
+        ; save machine state
+
+        ld hl, #0 ; return code set here is ignored, but _switchin can
+        ; return from either _switchout OR _dofork, so they must both write
+        ; _udata + U_DATA__U_SP with the following on the stack:
+        push hl ; return code
+       ld hl,(_kernel_pages + 1)       ; Save the kernel banks
+       push hl
+        push ix
+        push iy
+        ld (_udata + U_DATA__U_SP), sp ; this is where the SP is restored in _switchin
+
+        ; find another process to run (may select this one again)
+       push af
+        call _getproc
+       pop af
+
+        push hl
+        call _switchin
+
+        ; we should never get here
+        call _platform_monitor
+
+badswitchmsg: .ascii "_switchin: FAIL"
+        .db 13, 10, 0
+
+_switchin:
+        di
+       pop hl  ; bank
+        pop bc  ; return address
+        pop de  ; new process pointer
+;
+;      FIXME: do we actually *need* to restore the stack !
+;
+        push de ; restore stack
+        push bc ; restore stack
+       push hl ; bank
+
+        ld hl, #P_TAB__P_PAGE_OFFSET+3 ; Common
+       add hl, de              ; process ptr
+       ld a, (hl)
+       ld (top_bank),a
+       out (TOP_PORT), a       ; *CAUTION* our stack just left the building
+
+       ; ------- No stack -------
+        ; check u_data->u_ptab matches what we wanted
+        ld hl, (_udata + U_DATA__U_PTAB) ; u_data->u_ptab
+        or a                    ; clear carry flag
+        sbc hl, de              ; subtract, result will be zero if DE==IX
+        jr nz, switchinfail
+
+       ; wants optimising up a bit
+       ld hl, #P_TAB__P_STATUS_OFFSET
+       add hl, de
+       ld (hl), #P_RUNNING
+
+        ; runticks = 0
+        ld hl, #0
+        ld (_runticks), hl
+
+        ; restore machine state -- note we may be returning from either
+        ; _switchout or _dofork
+        ld sp, (_udata + U_DATA__U_SP)
+
+       ; ---- New task stack ----
+
+        pop iy
+        pop ix
+       pop hl
+       ld (_kernel_pages + 1),hl
+       call map_kernel_restore
+        pop hl ; return code
+
+        ; enable interrupts, if the ISR isn't already running
+        ld a, (_udata + U_DATA__U_ININTERRUPT)
+       ld (_int_disabled),a
+        or a
+        ret nz ; in ISR, leave interrupts off
+        ei
+        ret ; return with interrupts on
+
+switchinfail:
+       call outhl
+        ld hl, #badswitchmsg
+        call outstring
+       ; something went wrong and we didn't switch in what we asked for
+        jp _platform_monitor
+
+fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry
+
+;
+;      Called from _fork. We are in a syscall, the uarea is live as the
+;      parent uarea. The kernel is the mapped object.
+;
+_dofork:
+        ; always disconnect the vehicle battery before performing maintenance
+        di ; should already be the case ... belt and braces.
+
+        pop de  ; return address
+        pop hl  ; new process p_tab*
+        push hl
+        push de
+
+        ld (fork_proc_ptr), hl
+
+        ; prepare return value in parent process -- HL = p->p_pid;
+        ld de, #P_TAB__P_PID_OFFSET
+        add hl, de
+        ld a, (hl)
+        inc hl
+        ld h, (hl)
+        ld l, a
+
+        ; Save the stack pointer and critical registers.
+        ; When this process (the parent) is switched back in, it will be as if
+        ; it returns with the value of the child's pid.
+        push hl ; HL still has p->p_pid from above, the return value in the parent
+       ld hl,(_kernel_pages + 1)
+       push hl
+        push ix
+        push iy
+
+        ; save kernel stack pointer -- when it comes back in the parent we'll be in
+        ; _switchin which will immediately return (appearing to be _dofork()
+       ; returning) and with HL (ie return code) containing the child PID.
+        ; Hurray.
+        ld (_udata + U_DATA__U_SP), sp
+
+        ; now we're in a safe state for _switchin to return in the parent
+       ; process.
+
+       ; --------- we switch stack copies in this call -----------
+       call fork_copy                  ; copy 0x000 to udata.u_top and the
+                                       ; uarea and return on the childs
+                                       ; common
+       ; We are now in the kernel child context
+
+        ; now the copy operation is complete we can get rid of the stuff
+        ; _switchin will be expecting from our copy of the stack.
+       pop bc
+        pop bc
+        pop bc
+        pop bc
+
+        ; The child makes its own new process table entry, etc.
+       ld hl, #_udata
+       push hl
+        ld hl, (fork_proc_ptr)
+        push hl
+       push af
+        call _makeproc
+       pop af
+        pop bc 
+       pop bc
+
+       ; any calls to map process will now map the childs memory
+
+        ; runticks = 0;
+        ld hl, #0
+        ld (_runticks), hl
+        ; in the child process, fork() returns zero.
+       ;
+       ; And we exit, with the kernel mapped, the child now being deemed
+       ; to be the live uarea. The parent is frozen in time and space as
+       ; if it had done a switchout().
+        ret
+
 
         .area _COMMONMEM
 
index 1d74ea6..f7b15a3 100644 (file)
@@ -8,7 +8,7 @@ void vfd_term_init(void) {
 
 void vfd_term_write(char c) {
   __asm
-        ld      hl, #2+0
+        ld      hl, #4+0               ; banked
         add     hl, sp
         ld      e, (hl)
         call    VFDTERM_PUTC
index 36730ce..6ca7e67 100644 (file)
@@ -26,7 +26,7 @@ vfdLine4:        .DW     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 vfdLineLen       .EQU    40
 
 
-                 .area _CODE
+                 .area _CODE1
 VFDTERM_PREINIT:
                   ; initialize first two lines
                   LD      A, #0x30