z80: unified z80 4 x 16 bank tricks code
authorAlan Cox <alan@linux.intel.com>
Tue, 19 Feb 2019 14:42:29 +0000 (14:42 +0000)
committerAlan Cox <alan@linux.intel.com>
Tue, 19 Feb 2019 14:42:29 +0000 (14:42 +0000)
And apply it to rc2014 and zeta2

Kernel/lib/z80bank16.s [new file with mode: 0644]
Kernel/platform-rc2014/rc2014.s
Kernel/platform-rc2014/tricks.s
Kernel/platform-zeta-v2/tricks.s
Kernel/platform-zeta-v2/zeta-v2.s

diff --git a/Kernel/lib/z80bank16.s b/Kernel/lib/z80bank16.s
new file mode 100644 (file)
index 0000000..fd0cde1
--- /dev/null
@@ -0,0 +1,210 @@
+; Based on code 2013-12-21 William R Sowerbutts
+
+;
+;      This is intended to provide generic support for most 16K multibank
+;      platforms.
+;
+;      The platform should define
+;      TOP_PORT                the I/O port that the top page byte is
+;                              written into
+;
+;      top_bank must resolve to the byte used to store the top bank value
+;      in memory
+;
+;      If the platform needs to maniuplate the page byte values then this
+;      code will need to be copied and tweaked, for now anyway.
+;
+;      fork_copy remains platform specific.
+;
+
+        .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
+
+        ; 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 
+        ; 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
+
+        ; find another process to run (may select this one again)
+        call _getproc
+
+        push hl
+        call _switchin
+
+        ; we should never get here
+        call _platform_monitor
+
+badswitchmsg: .ascii "_switchin: FAIL"
+        .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
+
+        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, (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, (U_DATA__U_SP)
+
+       ; ---- New task stack ----
+
+        pop iy
+        pop ix
+        pop hl ; return code
+
+        ; enable interrupts, if the ISR isn't already running
+        ld a, (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
+        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.
+
+       ; --------- 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
+
+        ; The child makes its own new process table entry, etc.
+       ld hl, #_udata
+       push hl
+        ld hl, (fork_proc_ptr)
+        push hl
+        call _makeproc
+        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
+
index 69ba516..f6bf94a 100644 (file)
@@ -21,6 +21,7 @@
        .globl platform_interrupt_all
        .globl _copy_common
        .globl mpgsel_cache
+       .globl top_bank
        .globl _kernel_pages
        .globl _platform_reboot
        .globl _bufpool
@@ -522,7 +523,9 @@ _copy_common:
 
 ; MPGSEL registers are read only, so their content is cached here
 mpgsel_cache:
-       .db     0,0,0,0
+       .db     0,0,0
+top_bank:      ; the shared tricks code needs this name for cache+3
+       .db     0
 
 ; kernel page mapping
 _kernel_pages:
index 871fd0f..b7f6d3d 100644 (file)
-; 2013-12-21 William R Sowerbutts
-
         .module tricks
 
-        .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 mpgsel_cache
-       .globl _int_disabled
-       .globl _udata
-
-        ; imported debug symbols
-        .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex
-
         .include "kernel.def"
         .include "../kernel.def"
 
-        .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().
-;
-; This function can have no arguments or auto variables.
-_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 
-        ; 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
-
-        ; find another process to run (may select this one again)
-        call _getproc
-
-        push hl
-        call _switchin
-
-        ; we should never get here
-        call _platform_monitor
-
-badswitchmsg: .ascii "_switchin: FAIL"
-            .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
-
-        ld hl, #P_TAB__P_PAGE_OFFSET+3 ; Common
-       add hl, de              ; process ptr
-       ld a, (hl)
-       out (MPGSEL_3), a       ; *CAUTION* our stack just left the building
-
-       ; ------- No stack -------
-        ; 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 hl, #P_TAB__P_STATUS_OFFSET
-       add hl, de
-       ld (hl), #P_RUNNING
-
-        ; runticks = 0
-        ld hl, #0
-        ld (_runticks), hl
+TOP_PORT       .equ    MPGSEL_3
 
-        ; restore machine state -- note we may be returning from either
-        ; _switchout or _dofork
-        ld sp, (U_DATA__U_SP)
+       .include "../lib/z80bank16.s"
 
-       ; ---- New task stack ----
-
-        pop iy
-        pop ix
-        pop hl ; return code
-
-        ; enable interrupts, if the ISR isn't already running
-        ld a, (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
-        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.
-
-       ; --------- 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
-
-        ; The child makes its own new process table entry, etc.
-       ld hl, #_udata
-       push hl
-        ld hl, (fork_proc_ptr)
-        push hl
-        call _makeproc
-        pop bc 
-       pop bc
-
-       ; any calls to map process will now map the childs memory
+        .area _COMMONMEM
 
-        ; 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
+       .globl mpgsel_cache
 
 fork_copy:
        ld hl, (U_DATA__U_TOP)
index c0e8da2..b7f6d3d 100644 (file)
-; 2013-12-21 William R Sowerbutts
-
         .module tricks
 
-        .globl _ptab_alloc
-        .globl _makeproc
-       .globl _udata
-        .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 mpgsel_cache
-
-        ; imported debug symbols
-        .globl outstring, outde, outhl, outbc, outnewline, outchar, outcharhex
-
         .include "kernel.def"
         .include "../kernel.def"
 
-        .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:
-        di
-        ; 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
-
-        ; find another process to run (may select this one again)
-        call _getproc
-
-        push hl
-        call _switchin
-
-        ; we should never get here
-        call _platform_monitor
-
-badswitchmsg: .ascii "_switchin: FAIL"
-            .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
-
-        ld hl, #P_TAB__P_PAGE_OFFSET+3 ; Common
-       add hl, de              ; process ptr
-       ld a, (hl)
-       out (MPGSEL_3), a       ; *CAUTION* our stack just left the building
-
-       ; ------- No stack -------
-        ; 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 hl, #P_TAB__P_STATUS_OFFSET
-       add hl, de
-       ld (hl), #P_RUNNING
-
-        ; runticks = 0
-        ld hl, #0
-        ld (_runticks), hl
+TOP_PORT       .equ    MPGSEL_3
 
-        ; restore machine state -- note we may be returning from either
-        ; _switchout or _dofork
-        ld sp, (U_DATA__U_SP)
+       .include "../lib/z80bank16.s"
 
-       ; ---- New task stack ----
-
-        pop iy
-        pop ix
-        pop hl ; return code
-
-        ; enable interrupts, if the ISR isn't already running
-        ld a, (U_DATA__U_ININTERRUPT)
-        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
-        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.
-
-       ; --------- 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
-
-        ; The child makes its own new process table entry, etc.
-       ld hl, #_udata
-       push hl
-        ld hl, (fork_proc_ptr)
-        push hl
-        call _makeproc
-        pop bc 
-       pop bc
-
-       ; any calls to map process will now map the childs memory
+        .area _COMMONMEM
 
-        ; 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
+       .globl mpgsel_cache
 
 fork_copy:
        ld hl, (U_DATA__U_TOP)
index 891f859..f85dd38 100644 (file)
@@ -18,6 +18,7 @@
        .globl _irqvector
        .globl platform_interrupt_all
        .globl mpgsel_cache
+       .globl top_bank
        .globl _kernel_pages
        .globl _platform_reboot
        .globl _bufpool
@@ -319,7 +320,9 @@ map_save_kernel:
 
 ; MPGSEL registers are read only, so their content is cached here
 mpgsel_cache:
-       .db     0,0,0,0
+       .db     0,0,0
+top_bank:              ; common library needs this name for the right byte
+       .db     0
 
 ; kernel page mapping
 _kernel_pages: