px4plus: Initial cut of banking support
authorAlan Cox <alan@linux.intel.com>
Sun, 22 Mar 2015 21:48:33 +0000 (21:48 +0000)
committerAlan Cox <alan@linux.intel.com>
Sun, 22 Mar 2015 21:48:33 +0000 (21:48 +0000)
Nothing runnable yet but we now build the PX4/PX4 Plus as a set of banked ROM
images which is what is needed. The actual box has

64K RAM (some used for video)
32K OS ROM (CP/M) - overlays low 32K if switched in
2 x up to 32K ROM - overlay 0x6000-0xDFFF

The "intelligent" RAMdisc and the sidecar RAM discs are not memory mapped but
can be used for task switching/swap.

The floppy drive is serial attached at a whopping 19200 baud.

Kernel/platform-px4plus/README
Kernel/platform-px4plus/config.h
Kernel/platform-px4plus/crt0.s
Kernel/platform-px4plus/fuzix.lnk
Kernel/platform-px4plus/px4plus.s
Kernel/platform-px4plus/tricks.s

index 799b1f9..87db925 100644 (file)
@@ -9,48 +9,38 @@ top window is awkward as we need to get udata and our kernel data/common in
 that space if possible. We can hide the font/video below that under the top of
 the ROM however.
 
-
-Intended Memory Map
-
-
-0x0000-0x00FF          Vectors
-0x0100-0x7CFF (RAM)    User program (and discard area)
-(could go to 0xBFFF for 48K but our swap is very limiting and might need
- smarter algorithms for swap - eg 16K banking for swap alone)
-0x7D00-0xCFFF          Space for things we can bank under the ROM
-                       (secondary floppy cache ??)
-0xD000-0xDFFF          Framebuffer, font, video code
-0xE000-0xF7FFish       Data for kernel
-0xF800-0xFCFF          Common (currently ends FBCC)
-0xFD00-0xFFFF          Udata
-
-In kernel execution modes we then are either
-
-0x0000-0x00FF          Vectors
-0x0100-0x5FFF          Lower part of user
-0x6000-0xDFFF          Kernel code in ROM
-0xE000-0xF7FFish       Data for kernel
-0xF800-0xFCFF          Common (currently ends FBCC)
-0xFD00-0xFFFF          Udata
-
-and we will need to tuck the video code/font/framebuffer at 0xD000 or
-similar in RAM under the ROM area. May need to hide the floppy driver
-there too as its all a little bit tight
-
-In practice it appears the answer is
-
-1. Yes
-2. But only if the linker is taught to do banking. In fact once the linker
-does its own banking there is plenty of space although the bootloader might
-be a bit odd to make it work.
-
-A better layout given the 128K total swap limit might appear to be
-
-0x0000-0x00FF          Vectors
-0x0100-0x7CFF          Application
-0x7D00-0x7FFF          Uarea
-
-but we actually can't do this because the 32K ROM is always mapped from
-0x6000-0xDFFF and needs to access the Uarea
-
+Banked Memory Map
+-----------------
+
+0x0000-0x00FF          Vectors (which IM ? PX8 is IM2)
+0x0100-0x5FFF          Kernel mappings
+0x6000-0xDFFF          Switched segments 8/16/32K ROM x 2 or RAM
+       0x6000-0xDFFF   Application space (32K) [need to use a bit under
+                       as 120K not 128K of swap]
+       0x6000-0xDFFF   CODE1/CODE2 } Both with copies of some of common
+       0x6000-0xDFFF   CODE3/Video } and rodata at same address range
+       [ Do we want to generate interleaved banking ? ]
+
+0xE000-0xFCFF          Writable kernel data
+                       Framebuffer (4K)
+0xFD00-0xFFFF          UDATA
+
+We also need to put a catalogue in the middle of one of the two ROM blocks
+annoyingly. However that plays into our hands in other ways as we can
+minimally fake a disk rom holding a CP/M app which in fact runs the OS.
+
+
+Applications are swapped to/from the PX4Plus RAM disc (120K) allowing about
+4 apps of just under 32K each. Storage I/O is via the serial floppy and/or
+optional RAM/ROM cartriges. External 128K cartridges would also work for
+swap with floppy for OS. If the swap is custom handled in switching then
+we can switch the 32K rather than copy and gain another process, plus real
+floppy swap option.
+
+CP/M BIOS can be used (it's another 32K map over 0-7FFF, but as that maps
+over the vectors we must ensure its always called with interrupts off).
+
+The PX-8 is different: There is only a single 32K system ROM, but no video
+overhead. In theory its sufficient if we are replacing the OS ROM, and using
+the intelligent RAM disc, or the homebrew 512K one, plus floppies
 
index f8522b1..da94d3c 100644 (file)
@@ -12,8 +12,6 @@
 #define CONFIG_VT
 /* We want the 8x8 font for now (actually we want 6x8) */
 #define CONFIG_FONT8X8
-/* And we only want 128 symbols of it (1K) for now */
-#define CONFIG_FONT8X8SMALL
 /* CP/M emulation */
 #undef CONFIG_CPM_EMU
 /* Fixed banking */
 /* FIXME: the OVL timer isn't quite 100/sec and we have an accurate 1Hz
    timer available, so needs some tweaking */
 #define TICKSPERSEC 100   /* Ticks per second */
-#define PROGBASE    0x0000  /* also data base */
-#define PROGLOAD    0x0100
-#define PROGTOP     0x4000  /* Top of program for debug */
+#define PROGBASE    0x6000  /* also data base */
+#define PROGLOAD    0x6000
+#define PROGTOP     0xDD00  /* Top of program */
 
-#define SWAP_SIZE   0x40       /* 32K in blocks (with uarea means 31K max app size) */
-#define SWAPBASE    0x0000     /* We swap the lot in one, include the */
-#define SWAPTOP            0x8000      /* vectors so its a round number of sectors */
-#define MAX_SWAPS      4       /* We have a whopping 128K of RAMDISC! */
+/* FIXME: treat the banks of the ramdisc as memory not swap, also trim
+   to 30K as only have 120K of RAMdisc */
+#define SWAP_SIZE   0x3C       /* 30K in blocks (with uarea means 29.25K max app size) */
+#define SWAPBASE    (uint8_t *)0x5D00  /* We swap the lot in one, include the */
+#define SWAPTOP            (uint8_t *)0xDD00   /* vectors so its a round number of sectors */
+#define MAX_SWAPS      4       /* We have a whopping 120K of RAMDISC! */
 
 #define BOOT_TTY (512 + 1)/* Set this to default device for stdio, stderr */
                           /* In this case, the default is the first TTY device */
@@ -60,4 +60,4 @@
 #define VT_BOTTOM      7
 
 
-#define PFTABSIZE      4       /* All we have room for right now */
+#define PFTABSIZE      5       /* All we have room for right now */
index d559e89..558ed26 100644 (file)
@@ -6,26 +6,33 @@
         ; 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
+
+       ; Stuff that ends up in RAM, initialized bits first then data
+       ; We will need to pull the initialized bits into ROM for crt0.s
+       ; to ldir down
+        .area _COMMONMEM
         .area _CONST
-        .area _DATA
         .area _INITIALIZED
-        .area _COMMONMEM
+       .area _STUBS
+        .area _DATA
         .area _BSEG
         .area _BSS
         .area _HEAP
         .area _GSINIT
         .area _GSFINAL
-
-       .area _DISCARD
+       ; Udata ends up just below program code (so we can swap it easily)
        .area _UDATA
-       ; This is fixed up by the compile tool but we need it somewhere
-       ; so the copier can fix it up !
-        .area _INITIALIZER
-
+       ; First ROM is CODE (CODE2 folded in)
+        .area _CODE
+       ; Second ROM is CODE3 VIDEO FONT and initialized data to copy down
+       .area _CODE3
        .area _FONT
        .area _VIDEO
+        .area _INITIALIZER
+       ; Discard needs splitting code/data!
+       .area _DISCARD
+       ; and the bitmap display lives at E000-FFFF
+
 
         ; imported symbols
         .globl _fuzix_main
@@ -62,3 +69,6 @@ init:
 stop:   halt
         jr stop
 
+       .area _STUBS
+stubs:
+       .ds 768
index 533af34..2dbacb5 100644 (file)
@@ -1,19 +1,19 @@
 -mwxuy
 -i fuzix.ihx
+-b _COMMONMEM=0x0100
+-b _UDATA=0x5D00
 -b _DISCARD=0x4000
--b _UDATA=0xFD00
 -b _CODE=0x6000
--b _DATA=0xE000
--b _FONT=0x5000
--b _INITIALIZER=0x3000
+-b _CODE3=0x6000
 -l z80
+-r
 platform-px4plus/crt0.rel
 platform-px4plus/commonmem.rel
 platform-px4plus/px4plus.rel
 platform-px4plus/main.rel
 start.rel
 version.rel
-lowlevel-z80.rel
+lowlevel-z80-banked.rel
 platform-px4plus/tricks.rel
 timer.rel
 kdata.rel
index 30e00d0..b9bcddf 100644 (file)
            .globl _ramd_uaddr
 
 
+           .globl __bank_0_1
+           .globl __bank_0_2
+           .globl __bank_0_3
+           .globl __bank_1_2
+           .globl __bank_1_3
+           .globl __bank_2_1
+           .globl __bank_2_3
+           .globl __bank_3_1
+           .globl __bank_3_2
+
+           .globl __stub_0_1
+           .globl __stub_0_2
+           .globl __stub_0_3
+           .globl __stub_1_2
+           .globl __stub_1_3
+           .globl __stub_2_1
+           .globl __stub_2_3
+           .globl __stub_3_1
+           .globl __stub_3_2
+
+
             .include "kernel.def"
             .include "../kernel.def"
 
@@ -89,14 +110,18 @@ init_hardware:
             ; set up interrupt vectors for the kernel
             ld hl, #0
             push hl
+           push af
             call _program_vectors
+           pop af
             pop hl
 
            ; IRQ enables
            ld a, #0xB          ; OVF (timer), RXRDY (gapnio), 7508
            out (0x04), a
 
+           push af
            call _vtinit
+           pop af
             im 1 ; set CPU interrupt mode
             ret
 
@@ -234,3 +259,194 @@ hd_xoloop:
        inc (hl)
        dec hl
        jr hd_xiloop
+
+
+;
+;      FIXME
+current_map:
+       .byte 0
+switch_bank:
+       ret
+;
+;
+;      Banking helpers
+;
+;      FIXME: these are from zx128 - not yet converted to px4plus. We
+; should also be able to dump all to/from bank2 versions
+;
+;
+;      Logical         Physical
+;      0               COMMON (0x4000)
+;      1               0
+;      2               1
+;      3               7
+;
+;
+__bank_0_1:
+       xor a              ; switch to physical bank 0 (logical 1)
+bankina0:
+       ;
+       ;       Get the target address first, otherwise we will change
+       ;       bank and read it from the wrong spot!
+       ;
+       pop hl             ; Return address (points to true function address)
+       ld e, (hl)         ; DE = function to call
+       inc hl
+       ld d, (hl)
+       inc hl
+       push hl            ; Restore corrected return pointer
+       ld bc, (current_map)    ; get current bank into B
+       call switch_bank   ; Move to new bank
+       ; figure out which bank to map on the return path
+       ld a, c
+       or a
+       jr z, __retmap1
+       dec a
+       jr z, __retmap2
+       jr __retmap3
+
+callhl:        jp (hl)
+__bank_0_2:
+       ld a, #1           ; logical 2 -> physical 1
+       jr bankina0
+__bank_0_3:
+       ld a, #7           ; logical 3 -> physical 7
+       jr bankina0
+
+__bank_1_2:
+       ld a, #1
+bankina1:
+       pop hl             ; Return address (points to true function address)
+       ld e, (hl)         ; DE = function to call
+       inc hl
+       ld d, (hl)
+       inc hl
+       push hl            ; Restore corrected return pointer
+       call switch_bank   ; Move to new bank
+__retmap1:
+       ex de, hl
+       call callhl        ; call the function
+       xor a              ; return to bank 1 (physical 0)
+       jp switch_bank
+
+__bank_1_3:
+       ld a, #7
+       jr bankina1
+__bank_2_1:
+       xor a
+bankina2:
+       pop hl             ; Return address (points to true function address)
+       ld e, (hl)         ; DE = function to call
+       inc hl
+       ld d, (hl)
+       inc hl
+       push hl            ; Restore corrected return pointer
+       call switch_bank   ; Move to new bank
+__retmap2:
+       ex de, hl
+       call callhl        ; call the function
+       ld a, #1           ; return to bank 2
+       jp switch_bank
+__bank_2_3:
+       ld a, #7
+       jr bankina2
+__bank_3_1:
+       xor a
+bankina3:
+       pop hl             ; Return address (points to true function address)
+       ld e, (hl)         ; DE = function to call
+       inc hl
+       ld d, (hl)
+       inc hl
+       push hl            ; Restore corrected return pointer
+       call switch_bank   ; Move to new bank
+__retmap3:
+       ex de, hl
+       call callhl        ; call the function
+       ld a, #7           ; return to bank 0
+       jp switch_bank
+
+__bank_3_2:
+       ld a, #1
+       jr bankina3
+
+;
+;      Stubs need some stack munging and use DE
+;
+
+__stub_0_1:
+       xor a
+__stub_0_a:
+       pop hl          ; the return
+       ex (sp), hl     ; write it over the discard
+       ld bc, (current_map)
+       call switch_bank
+       ld a, c
+       or a
+       jr z, __stub_1_ret
+       dec a
+       jr z, __stub_2_ret
+       jr __stub_3_ret
+__stub_0_2:
+       ld a, #1
+       jr __stub_0_a
+__stub_0_3:
+       ld a, #7
+       jr __stub_0_a
+
+__stub_1_2:
+       ld a, #1
+__stub_1_a:
+       pop hl          ; the return
+       ex (sp), hl     ; write it over the discad
+       call switch_bank
+__stub_1_ret:
+       ex de, hl
+       call callhl
+       xor a
+       call switch_bank
+       pop de
+       push de         ; dummy the caller will discard
+       push de
+       ret
+__stub_1_3:
+       ld a, #7
+       jr __stub_1_a
+
+__stub_2_1:
+       xor a
+__stub_2_a:
+       pop hl          ; the return
+       ex (sp), hl     ; write it over the discad
+       call switch_bank
+__stub_2_ret:
+       ex de, hl       ; DE is our target
+       call callhl
+       ld a,#1
+       call switch_bank
+       pop de
+       push de         ; dummy the caller will discard
+       push de
+       ret
+__stub_2_3:
+       ld a, #7
+       jr __stub_2_a
+
+__stub_3_1:
+       xor a
+__stub_3_a:
+       pop hl          ; the return
+       ex (sp), hl     ; write it over the discad
+       call switch_bank
+__stub_3_ret:
+       ex de, hl
+       call callhl
+       ld a,#7
+       call switch_bank
+       pop de
+       push de         ; dummy the caller will discard
+       push de
+       ret
+__stub_3_2:
+       ld a, #1
+       jr __stub_3_a
index 2571090..00a546e 100644 (file)
@@ -37,7 +37,9 @@
 ; This function can have no arguments or auto variables.
 _switchout:
         di
+       push af
         call _chksigs
+       pop af
         ; save machine state
 
         ld hl, #0 ; return code set here is ignored, but _switchin can 
@@ -53,10 +55,14 @@ _switchout:
         ld (_inint), a
 
         ; find another process to run (may select this one again)
+       push af
         call _getproc
+       pop af
 
         push hl
+       push af
         call _switchin
+       pop af
 
         ; we should never get here
         call _trap_monitor
@@ -68,6 +74,7 @@ swapped: .ascii "_switchin: SWAPPED"
 
 _switchin:
         di
+       pop hl
         pop bc  ; return address
         pop de  ; new process pointer
 ;
@@ -75,6 +82,7 @@ _switchin:
 ;
         push de ; restore stack
         push bc ; restore stack
+       push hl
 
        push de
         ld hl, #P_TAB__P_PAGE_OFFSET
@@ -95,11 +103,15 @@ _switchin:
        ; We will always swap out the current process
        ld hl, (U_DATA__U_PTAB)
        push hl
+       push af
        call _swapout
+       pop af
        pop hl
        pop hl
        push de
+       push af
        call _swapper
+       pop af
        pop de
        pop hl
        ld a, (hl)
@@ -156,10 +168,12 @@ _dofork:
         ; always disconnect the vehicle battery before performing maintenance
         di ; should already be the case ... belt and braces.
 
+       pop bc
         pop de  ; return address
         pop hl  ; new process p_tab*
         push hl
         push de
+       push bc
 
         ld (fork_proc_ptr), hl
 
@@ -189,7 +203,9 @@ _dofork:
 
        ld hl, (U_DATA__U_PTAB)
        push hl
+       push af
        call _swapout
+       pop af
        pop hl
 
         ; now the copy operation is complete we can get rid of the stuff
@@ -201,7 +217,9 @@ _dofork:
         ; Make a new process table entry, etc.
         ld  hl, (fork_proc_ptr)
         push hl
+       push af
         call _newproc
+       pop af
         pop bc 
 
         ; runticks = 0;