-TARGET_LIST = platform-nc100 platform-micropack platform-pcw8256 platform-socz80 platform-zx128 platform-trs80 platform-z80pack platform-z80pack-lite platform-dragon
+TARGET_LIST = platform-nc100 platform-micropack platform-pcw8256 platform-socz80 platform-zx128 platform-trs80 platform-z80pack platform-z80pack-lite platform-z80pack32 platform-dragon
-export TARGET= z80pack
+export TARGET= z80pack32
export CPU = z80
#export TARGET = dragon
#export CPU = 6809
#ifdef CONFIG_BANK32
-#ifndef bank32_invalidate_cache
-#define bank32_invalidate_cache(x) do {} while(0)
+/* 32K common, ldir copying to use for 48K apps */
+#ifndef CONFIG_COMMON_COPY
+#define invalidate_cache(x) do {} while(0)
#endif
/*
pfree[pfptr--] = *ptr;
if (*ptr != ptr[1]) {
pfree[pfptr--] = ptr[1];
- bank32_invalidate_cache(ptr[1]);
+ invalidate_cache((uint16_t)ptr[1]);
}
}
/* Usually we have 0x1000 common - 1 for shift and inc */
if (needed & 0x8000)
return 2;
- return return 1;
+ return 1;
}
/*
{
uint8_t *ptr = (uint8_t *) & p->p_page;
int needed = maps_needed(udata.u_top);
- int i;
#ifdef SWAPDEV
/* Throw our toys out of our pram until we have enough room */
/*
* Reallocate the maps for a process
+ *
+ * Subtlety: On a 32K box we have the udata area being copied to/from
+ * the stash. As we always realloc for the live process we don't have
+ * to worry about this in the 32K + common case because we'll switchin
+ * at one size, and switchout at the other and the udata will just get
+ * saved/restored to the right places.
*/
int pagemap_realloc(uint16_t size) {
int have = maps_needed(udata.u_top);
int want = maps_needed(size);
uint8_t *ptr = (uint8_t *) & udata.u_page;
- int i;
/* If we are shrinking then free pages and propogate the
common page into the freed spaces */
/* Will need a uptr_t eventually */
extern uint16_t ramtop; /* Note: ramtop must be in common in some cases */
CODE2 extern void platform_interrupt(void);
+COMMON void invalidate_cache(uint16_t page);
+COMMON void flush_cache(ptptr p);
CODE2 int16_t __exit(void); /* FUZIX system call 0 */
CODE2 int16_t _open(void); /* FUZIX system call 1 */
--- /dev/null
+
+DSRCS = ../dev/z80pack/devlpr.c ../dev/z80pack/devtty.c ../dev/z80pack/devfd.c
+CSRCS += devices.c main.c
+
+ASRCS = crt0.s z80pack.s
+ASRCS += tricks.s commonmem.s
+
+AOBJS = $(ASRCS:.s=.rel)
+COBJS = $(CSRCS:.c=.rel)
+DOBJS = $(patsubst ../dev/z80pack/%.c,%.rel, $(DSRCS))
+
+OBJS = $(AOBJS) $(COBJS) $(DOBJS)
+
+CROSS_CCOPTS += -I../dev/z80pack/ --codeseg CODE3
+
+JUNK = *.rel *.lst *.asm *.sym *.rst
+
+all: $(OBJS)
+
+$(AOBJS): %.rel: %.s
+ $(CROSS_AS) $(ASOPTS) $<
+
+$(COBJS): %.rel: %.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+$(DOBJS): %.rel: ../dev/z80pack/%.c
+ $(CROSS_CC) $(CROSS_CCOPTS) -c $<
+
+
+clean:
+ rm -f $(OBJS) $(JUNK) core *~
+
+image:
+ sdasz80 -o bootblock.s
+ sdldz80 -m -i bootblock.rel
+ makebin -s 128 bootblock.ihx > bootblock.bin
--- /dev/null
+Z80 Pack Test For 32K + cached high for bigger binaries
+
+Kernel
+0000-07FFF CODE1, CODE2
+0x8000-0xBFFF User cache area (0xB000 discard)
+0xC000 Udata
+0xC300 CONST, CODE3, DATA ...
+0xF000 Common
+
+TODO
+
+We waste 16K per high process but its not clear how much of a win it would
+be to pack them, and if we can squash stuff better we might go over 48K and
+break it.
+
+binman has no idea how to pack such an image, probably better to have a new
+tool as binman is getting too unwieldy. Perhaps it's time to have a tool and
+crt0.s that simply reads a table of block/offsets to ldir then runs ?
+
+Also need to pack carefully so we don't overwrite source data. Probably
+means we need to start at the end of the image and lddr back down it.
+
+Need to fix the packing/crt0.s before we can test any of this
+
+
+Disk swap device recommended
+
+Put the kernel at the end of a floppy image from cyl 60
+Add the fs in the first 60 cyls (390 blocks)
+
+Put the bootblock in sector 0
+
+dd the kernel image to offset 199680
+
+ie
+
+dd if=fuzix.bin of=drivea.cpm bs=1 seek=199680 conv=notrunc
--- /dev/null
+;
+; Z80pack cpmsim loads the first (128 byte) sector from the disk
+; into memory at 0 then executes it
+; We are a bit tight on space here
+;
+; Floppy loader:
+; Our boot disc is 77 tracks of 26 x 128 byte sectors, and we put
+; the OS on tracks 60+, which means we can put a file system in the
+; usual place providing its a bit smaller than a whole disc.
+;
+;
+; assemble with sdasz80
+;
+ .area ASEG(ABS)
+ .org 0
+
+start: jr diskload
+
+rootdev: .dw 0 ; patched by hand
+swapdev: .dw 0 ; ditto
+ .dw 0 ; spare
+
+progress: .db '/', '-', '\', '|'
+
+diskload: di
+ ld sp, #stack
+ ld hl, #0x88
+ exx
+ xor a
+ ld h, a
+ ld b, a
+ out (17), a ; sector high always 0
+ out (10), a ; drive always 0
+ ld a, #59 ; start on track 60
+ out (11), a
+ exx
+ ld c, #17 ; number of tracks to load (56Kish)
+load_tracks: in a, (11)
+ inc a ; track
+ out (11), a
+ xor a
+ out (12), a
+ ld b, #26 ; sectors
+load_sectors: exx
+ ld a, b
+ and #3
+ add #progress
+ ld l, a
+ ld a, (hl)
+ out (01), a
+ ld a, #8
+ out (01), a
+ inc b
+ exx
+
+ in a, (12)
+ inc a
+ out (12), a ; sector
+ ld a, l
+ out (15), a ; dma low
+ ld a, h
+ out (16), a ; dma high
+ xor a ; read
+ out (13), a ; go
+ in a, (14) ; status
+ ld de, #128
+ add hl, de
+ djnz load_sectors ; 26 sectors = 3328 bytes
+ dec c
+ jr nz, load_tracks
+ ld a, #0xc9 ; to help debug
+ ld (start), a
+ ld a, #13
+ out (1), a
+ ld a, #10
+ out (1), a
+ jp 0x88
+
+ .ds 26
+stack:
+ .db 0xff
--- /dev/null
+;
+; Common on z80pack is at 0xF000 as defined by hardware.
+;
+
+ .module commonmem
+
+ .area _COMMONMEM
+
+ .include "../cpu-z80/std-commonmem.s"
--- /dev/null
+/* 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) */
+#define CONFIG_PROFIL
+/* Multiple processes in memory at once */
+#define CONFIG_MULTI
+/* Single tasking */
+#undef CONFIG_SINGLETASK
+/* CP/M emulation */
+#undef CONFIG_CPM_EMU
+/* 32K banking */
+#define CONFIG_BANK32
+/* but with the high block copied on switch as needed */
+#define CONFIG_COMMON_COPY
+/* 8 32K banks, 1 is kernel */
+#define MAX_MAPS 7
+#define MAP_SIZE 0x8000U
+
+/* Banks as reported to user space */
+#define CONFIG_BANKS 2
+
+#define TICKSPERSEC 100 /* Ticks per second */
+#define PROGBASE 0x0000 /* also data base */
+#define PROGLOAD 0x0100 /* also data base */
+#define PROGTOP 0xBC00 /* Top of program, base of U_DATA copy */
+
+#define SWAP_SIZE 0x60 /* 48K in blocks */
+#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 64 /* The full drive would actually be 85! */
+
+#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 3
+
+#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */
+#define SWAPDEV (256 + 1) /* Device for swapping. (z80pack drive J) */
+#define NBUFS 10 /* Number of block buffers */
+#define NMOUNTS 4 /* Number of mounts at a time */
--- /dev/null
+; 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 _CODE2
+ .area _CODE3
+ .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
+ .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
+
+ ; Configure memory map
+ call init_early
+
+ ; move the common memory where it belongs
+ ld hl, #s__INITIALIZER
+ 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
+
+ ; Hardware setup
+ call init_hardware
+
+ ; Call the C main routine
+ call _fuzix_main
+
+ ; main shouldn't return, but if it does...
+ di
+stop: halt
+ jr stop
+
--- /dev/null
+#include <kernel.h>
+#include <version.h>
+#include <kdata.h>
+#include <tty.h>
+#include <devfd.h>
+#include <devsys.h>
+#include <devlpr.h>
+#include <devtty.h>
+
+struct devsw dev_tab[] = /* The device driver switch table */
+{
+// minor open close read write ioctl
+// -----------------------------------------------------------------
+ /* 0: /dev/fd Floppy disc block devices */
+ { fd_open, no_close, fd_read, fd_write, no_ioctl },
+ /* 1: /dev/hd Hard disc block devices (absent) */
+ { hd_open, no_close, hd_read, hd_write, no_ioctl },
+ /* 2: /dev/tty TTY devices */
+ { tty_open, tty_close, tty_read, tty_write, tty_ioctl },
+ /* 3: /dev/lpr Printer devices */
+ { lpr_open, lpr_close, no_rdwr, lpr_write, no_ioctl },
+ /* 4: /dev/mem etc System devices (one offs) */
+ { no_open, no_close, sys_read, sys_write, sys_ioctl },
+ /* Pack to 7 with nxio if adding private devices and start at 8 */
+};
+
+bool validdev(uint16_t dev)
+{
+ /* This is a bit uglier than needed but the right hand side is
+ a constant this way */
+ if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) + 255)
+ return false;
+ else
+ return true;
+}
+
+void device_init(void)
+{
+ int i;
+ /* Add 64 swaps (4MB) to use the entire J drive */
+ for (i = 0; i < MAX_SWAPS; i++)
+ swapmap_add(i);
+}
--- /dev/null
+; UZI mnemonics for memory addresses etc
+
+U_DATA .equ 0xF000 ; (this is struct u_data from kernel.h)
+U_DATA__TOTALSIZE .equ 0x300 ; 256+256+256 bytes.
+
+U_STASH_HIGH .equ 0xBD00 ; BD00-BFFF
+U_STASH_LOW .equ 0x7D00 ; 7D00-BFFF
--- /dev/null
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <devtty.h>
+
+uint16_t ramtop = PROGTOP;
+
+
+void pagemap_init(void)
+{
+ int i;
+ for (i = 1; i < 8; i++)
+ pagemap_add(i);
+}
+
+/* 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_pollirq();
+ irqrestore(irq);
+}
+
+void platform_interrupt(void)
+{
+ tty_pollirq();
+ timer_interrupt();
+}
+
+/* Nothing to do for the map of init */
+void map_init(void)
+{
+}
--- /dev/null
+; 2013-12-21 William R Sowerbutts
+
+ .module tricks
+
+ .globl _ptab_alloc
+ .globl _newproc
+ .globl _chksigs
+ .globl _getproc
+ .globl _trap_monitor
+ .globl trap_illegal
+ .globl _inint
+ .globl _switchout
+ .globl _switchin
+ .globl _doexec
+ .globl _dofork
+ .globl _runticks
+ .globl unix_syscall_entry
+ .globl interrupt_handler
+ .globl dispatch_process_signal
+ .globl _swapper
+ .globl _cached_page
+ .globl _flush_cache
+ .globl _invalidate_cache
+
+ ; imported debug symbols
+ .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex
+
+ .include "kernel.def"
+ .include "../kernel.def"
+
+ .area _COMMONMEM
+
+; 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().
+;
+; FIXME: make sure we optimise the switch to self case higher up the stack!
+;
+; This function can have no arguments or auto variables.
+_switchout:
+ di
+ call _chksigs
+ ; 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
+ ; U_DATA__U_SP with the following on the stack:
+ push hl ; return code
+ push ix
+ push iy
+ ld (U_DATA__U_SP), sp ; this is where the SP is restored in _switchin
+
+ ; set inint to false
+ xor a
+ ld (_inint), a
+
+ ; Stash the uarea back into process memory
+ ld hl, (U_DATA__U_PAGE)
+ ld a, l
+ out (21), a
+ cp h ; small or large process ?
+ jr z, switchoutlow
+ ld de, #U_STASH_HIGH
+switchoutlow:
+ ld hl, #U_DATA
+ ld de, #U_STASH_LOW
+ ld bc, #U_DATA__TOTALSIZE
+ ldir
+ xor a
+ out (21), a
+
+ ; find another process to run (may select this one again)
+ call _getproc
+
+ push hl
+ call _switchin
+
+ ; we should never get here
+ call _trap_monitor
+
+badswitchmsg: .ascii "_switchin: FAIL"
+ .db 13, 10, 0
+swapped: .ascii "_switchin: SWAPPED"
+ .db 13, 10, 0
+
+_switchin:
+ di
+ 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
+
+ xor a
+ out (21), a
+
+ push de
+ ld hl, #P_TAB__P_PAGE_OFFSET
+ add hl, de ; process ptr
+ pop de
+
+ ld a, (hl)
+
+ or a
+ jr nz, not_swapped
+
+ ;
+ ; We are still on the departing processes stack, which is
+ ; fine for now.
+ ;
+ ld sp, #_swapstack
+ push hl
+ push de
+ call _swapper
+ pop de
+ pop hl
+ ld a, (hl)
+
+not_swapped:
+ ; Decide where the uarea stash lives right now and check the cache
+ inc hl
+ cp (hl) ; must cp first as (hl) vanishes on the out
+ jr z, switchinlow
+ ld hl, #_cached_page
+ cp (hl)
+ push af
+ call z, update_cache
+ pop af
+ out (21), a
+ exx ; thank goodness for exx 8)
+ ld hl, #U_STASH_HIGH
+ jr switchin_page
+switchinlow:
+ ; Pages please !
+ out (21), a
+ exx ; thank goodness for exx 8)
+ ld hl, #U_STASH_LOW
+switchin_page:
+ ; bear in mind that the stack will be switched now, so we can't use it
+ ; to carry values over this point
+ ld de, #U_DATA
+ ld bc, #U_DATA__TOTALSIZE
+ ldir
+ exx
+
+ ; Return to kernel mappings
+ xor a
+ out (21), a
+
+switchlow2:
+
+ ; check u_data->u_ptab matches what we wanted
+ ld hl, (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 ix, (U_DATA__U_PTAB)
+ ; next_process->p_status = P_RUNNING
+ ld P_TAB__P_STATUS_OFFSET(ix), #P_RUNNING
+
+ ; Fix the moved page pointers
+ ; Just do two bytes as that is all we use on this platform
+ ld l, P_TAB__P_PAGE_OFFSET(ix)
+ ld h, P_TAB__P_PAGE_OFFSET+1(ix)
+ ld (U_DATA__U_PAGE), hl
+ ; runticks = 0
+ ld hl, #0
+ ld (_runticks), hl
+
+ ; restore machine state -- note we may be returning from either
+ ; _switchout or _dofork
+ ld sp, (U_DATA__U_SP)
+
+ pop iy
+ pop ix
+ pop hl ; return code
+
+ ; enable interrupts, if the ISR isn't already running
+ ld a, (_inint)
+ or a
+ ret z ; 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 _trap_monitor
+
+; (hl) points to cached page ptr, a is desired page
+update_cache:
+ ld (hl), a
+ ld hl, #0
+ ld de, #0x8000
+ ld bc, #0x7D00
+ ; map that page low (interrupts *must* be off)
+ out (21), a
+ ldir
+ ; put the kernel back
+ xor a
+ out (21), a
+ ret
+
+;
+; Invalidate a freed page - cache becomes void
+;
+_invalidate_cache:
+ pop de
+ pop hl
+ push hl
+ push de
+ ld a, (_cached_page)
+ cp l
+ ret nz
+ ld a, #0xff
+ ld (_cached_page), a
+ ret
+
+
+_flush_cache: ; argument is the process it may apply to
+ pop de
+ pop hl
+ push hl
+ push de
+ ld a, i
+ push af
+ ld de, #P_TAB__P_PAGE_OFFSET + 1
+ add hl, de
+ ld a, (_cached_page)
+ cp (hl)
+ jr nz, flush_none
+ di
+ call flush_cache_self
+ pop af
+ ret po
+ ei
+ ret
+flush_none:
+ pop af
+ ret
+
+; interrupts must be disabled
+flush_cache_self:
+ push af
+ ld a, (_cached_page)
+ cp #0xff
+ jr z, no_cache
+ push bc
+ push de
+ push hl
+ ld hl, #0x8000 ; copy into the page
+ ld de, #0
+ ld bc, #0x7D00
+ ; map that page low (interrupts *must* be off)
+ out (21), a
+ ldir
+ ; put the kernel back
+ xor a
+ out (21), a
+ pop hl
+ pop de
+ pop bc
+no_cache:
+ pop af
+ ret
+
+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
+ 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 (U_DATA__U_SP), sp
+
+ ; now we're in a safe state for _switchin to return in the parent
+ ; process.
+ ; --------- copy process ---------
+
+ ld hl, (fork_proc_ptr)
+ ld de, #P_TAB__P_PAGE_OFFSET
+ add hl, de
+ ; load p_page
+ ld c, (hl)
+ inc hl
+ ; load p_page + 1 (high page)
+ ld b, (hl)
+ push af
+ ld a, c
+ call outcharhex
+ pop af
+ ; load existing page ptr
+ ld a, (U_DATA__U_PAGE)
+
+ call bankfork ; do the bank to bank copy
+
+ ; Copy done
+
+ ld a, (U_DATA__U_PAGE) ; parent memory
+ out (21), a ; Switch context to parent
+
+ ; We are going to copy the uarea into the parents uarea stash
+ ; we must not touch the parent uarea after this point, any
+ ; changes only affect the child
+ ld de, #U_STASH_LOW ; parent location
+ ld hl, #U_DATA__U_PAGE
+ ld a, (hl)
+ inc hl
+ cp (hl)
+ jr z, stash_low
+ ld de, #U_STASH_HIGH ; high stash
+stash_low:
+ ld hl, #U_DATA ; copy the udata from common
+ ld bc, #U_DATA__TOTALSIZE
+ ldir
+ ; Return to the kernel mapping
+ xor a
+ out (21), a
+ ; 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
+
+ ; Make a new process table entry, etc.
+ ld hl, (fork_proc_ptr)
+ push hl
+ call _newproc
+ pop bc
+
+ ; 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
+
+;
+; This is related so we will keep it here. Copy the process memory
+; for a fork. a is the page base of the parent, c of the child
+; (this API will be insufficient once we have chmem and proper use of
+; banks - as well as needing to support fork to disk)
+;
+; Assumption - fits into a fixed number of whole 256 byte blocks
+;
+; The parent must be running here, therefore the parent must be
+; mapped, therefore the cached page is loaded with the parent
+;
+bankfork:
+ push af
+ ld hl, #U_DATA__U_PAGE + 1
+ cp (hl) ; Are we a two pager ?
+ jr z, bankfork_low ; If not skip the high space
+ call flush_cache_self ; Flush the parent cache
+ ld a, b
+ ld (_cached_page), a ; High cache is now child (which runs first)
+ ld b, #0x80
+ jr bankfork_go ; Now copy the low 32K
+bankfork_low:
+ ld b, #0x7D ; 32K minus UAREA stash
+bankfork_go:
+ pop af ; A is now the parent bank
+ ld hl, #0 ; base of memory to fork (vectors included)
+bankfork_1:
+ push bc ; Save our counter and also child offset
+ push hl
+ out (21), a ; switch to parent bank
+ ld de, #bouncebuffer
+ ld bc, #256
+ ldir ; copy into the bounce buffer
+ pop de ; recover source of copy to bounce
+ ; as destination in new bank
+ pop bc ; recover child page number
+ push bc
+ ld b, a ; save the parent bank id
+ ld a, c ; switch to the child
+ out (21), a
+ push bc ; save the bank pointers
+ ld hl, #bouncebuffer
+ ld bc, #256
+ ldir ; copy into the child
+ pop bc ; recover the bank pointers
+ ex de, hl ; destination is now source for next bank
+ ld a, b ; parent bank is wanted in a
+ pop bc
+ djnz bankfork_1 ; rinse, repeat
+ ret
+
+;
+; For the moment
+;
+bouncebuffer:
+ .ds 256
+;
+; We can keep a stack in common because we will complete our
+; use of it before we switch common block. In this case we have
+; a true common so it's even easier. This can share with the bounce
+; buffer used by bankfork as we won't switchin mid way through the
+; banked fork() call.
+;
+_swapstack:
+_cached_page:
+ .db 0xff
--- /dev/null
+-mwxuy
+-i uzi.ihx
+-b _CODE=0x0088
+-b _CODE3=0xC000
+-b _COMMONMEM=0xF000
+-b _DISCARD=0xB000
+-l z80
+platform-z80pack32/crt0.rel
+platform-z80pack32/commonmem.rel
+platform-z80pack32/z80pack.rel
+platform-z80pack32/main.rel
+start.rel
+version.rel
+lowlevel-z80.rel
+usermem_std-z80.rel
+platform-z80pack32/tricks.rel
+timer.rel
+kdata.rel
+usermem.rel
+platform-z80pack32/devfd.rel
+platform-z80pack32/devices.rel
+devio.rel
+filesys.rel
+process.rel
+inode.rel
+syscall_exec.rel
+syscall_fs.rel
+syscall_fs2.rel
+syscall_proc.rel
+syscall_other.rel
+tty.rel
+mm.rel
+bank32k.rel
+swap.rel
+devsys.rel
+platform-z80pack32/devlpr.rel
+platform-z80pack32/devtty.rel
+-e
--- /dev/null
+;
+; Z80Pack hardware support
+;
+;
+; This goes straight after udata for common. Because of that the first
+; 256 bytes get swapped to and from disk with the uarea (512 byte disk
+; blocks). This isn't a problem but don't put any variables in here.
+;
+; If you make this module any shorter, check what follows next
+;
+
+
+ .module z80pack
+
+ ; exported symbols
+ .globl init_early
+ .globl init_hardware
+ .globl _program_vectors
+ .globl _system_tick_counter
+ .globl platform_interrupt_all
+
+ .globl map_kernel
+ .globl map_process
+ .globl map_process_always
+ .globl map_save
+ .globl map_restore
+
+ .globl _fd_bankcmd
+
+ .globl _kernel_flag
+
+ ; exported debugging tools
+ .globl _trap_monitor
+ .globl outchar
+
+ ; imported symbols
+ .globl _ramsize
+ .globl _procmem
+
+ .globl unix_syscall_entry
+ .globl null_handler
+ .globl nmi_handler
+ .globl interrupt_handler
+
+ .globl outcharhex
+ .globl outhl, outde, outbc
+ .globl outnewline
+ .globl outstring
+ .globl outstringhex
+
+ .include "kernel.def"
+ .include "../kernel.def"
+
+; -----------------------------------------------------------------------------
+; COMMON MEMORY BANK (0xF000 upwards)
+; -----------------------------------------------------------------------------
+ .area _COMMONMEM
+
+_trap_monitor:
+ ld a, #128
+ out (29), a
+platform_interrupt_all:
+ ret
+
+_trap_reboot:
+ ld a, #1
+ out (29), a
+
+;
+; We need the right bank present when we cause the transfer
+;
+_fd_bankcmd:pop de ; return
+ pop bc ; command
+ pop hl ; bank
+ push hl
+ push bc
+ push de ; fix stack
+ ld a, i
+ di
+ push af ; save DI state
+ call map_process ; HL alread holds our bank
+ ld a, c ; issue the command
+ out (13), a ;
+ call map_kernel ; return to kernel mapping
+ pop af
+ ret po
+ ei
+ ret
+
+; -----------------------------------------------------------------------------
+; KERNEL MEMORY BANK (below 0xC000, only accessible when the kernel is mapped)
+; -----------------------------------------------------------------------------
+ .area _CODE
+
+init_early:
+ ld a, #240 ; 240 * 256 bytes (60K)
+ out (22), a ; set up memory banking
+ ld a, #8
+ out (20), a ; 8 segments
+ ret
+
+init_hardware:
+ ; set system RAM size
+ ld hl, #480
+ ld (_ramsize), hl
+ ld hl, #(480-64) ; 64K for kernel
+ ld (_procmem), hl
+
+ ld a, #1
+ out (27), a ; 100Hz timer on
+
+ ; set up interrupt vectors for the kernel (also sets up common memory in page 0x000F which is unused)
+ ld hl, #0
+ push hl
+ call _program_vectors
+ pop hl
+
+ im 1 ; set CPU interrupt mode
+ ret
+
+
+;------------------------------------------------------------------------------
+; COMMON MEMORY PROCEDURES FOLLOW
+
+ .area _COMMONMEM
+
+
+_program_vectors:
+ ; we are called, with interrupts disabled, by both newproc() and crt0
+ ; will exit with interrupts off
+ di ; just to be sure
+ pop de ; temporarily store return address
+ pop hl ; function argument -- base page number
+ push hl ; put stack back as it was
+ push de
+
+ call map_process
+
+ ; write zeroes across all vectors
+ ld hl, #0
+ ld de, #1
+ ld bc, #0x007f ; program first 0x80 bytes only
+ ld (hl), #0x00
+ ldir
+
+ ; now install the interrupt vector at 0x0038
+ ld a, #0xC3 ; JP instruction
+ ld (0x0038), a
+ ld hl, #interrupt_handler
+ ld (0x0039), hl
+
+ ; set restart vector for UZI system calls
+ ld (0x0030), a ; (rst 30h is unix function call vector)
+ ld hl, #unix_syscall_entry
+ ld (0x0031), hl
+
+ ; Set vector for jump to NULL
+ ld (0x0000), a
+ ld hl, #null_handler ; to Our Trap Handler
+ ld (0x0001), hl
+
+ ld (0x0066), a ; Set vector for NMI
+ ld hl, #nmi_handler
+ ld (0x0067), hl
+
+ ; our platform has a "true" common area, if it did not we would
+ ; need to copy the "common" code into the common area of the new
+ ; process.
+
+ ; falls through
+
+ ; put the paging back as it was -- we're in kernel mode so this is predictable
+map_kernel:
+ push af
+ xor a
+ out (21), a
+ pop af
+ ret
+map_process:
+ ld a, h
+ or l
+ jr z, map_kernel
+ ld a, (hl)
+ out (21), a
+ ret
+map_process_always:
+ push af
+ ld a, (U_DATA__U_PAGE)
+ out (21), a
+ pop af
+ ret
+map_save:
+ push af
+ in a, (21)
+ ld (map_store), a
+ pop af
+ ret
+map_restore:
+ push af
+ ld a, (map_store)
+ out (21), a
+ pop af
+ ret
+map_store:
+ .db 0
+
+_kernel_flag:
+ .db 1
+
+; outchar: Wait for UART TX idle, then print the char in A
+; destroys: AF
+outchar:
+ out (0x01), a
+ ret
#define UDATA_BLOCKS 0
#endif
-#ifndef swap_flush_cache
-#define swap_flush_cache(p) do {} while(0)
+#ifndef CONFIG_COMMON_COPY
+#define flush_cache(p) do {} while(0)
#endif
uint8_t *swapbase;
/* Are we out of swap ? */
if (swapptr == 0)
return ENOMEM;
- swap_flush_cache(p);
+ flush_cache(p);
map = swapmap[--swapptr];
blk = map * SWAP_SIZE;
#ifdef UDATA_SWAPSIZE