From 119152a69a68132c4e35d3e04da005c9515d6f58 Mon Sep 17 00:00:00 2001 From: Will Sowerbutts Date: Fri, 8 May 2015 23:33:25 +0100 Subject: [PATCH] zeta-v2: Relocate the kernel in physical memory on boot. This will work if the kernel is loaded in either one contiguous 64KB block, or two discrete 32K blocks. This should cover the common ROM and CP/M boot techniques. --- Kernel/platform-zeta-v2/zeta-v2.s | 78 +++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/Kernel/platform-zeta-v2/zeta-v2.s b/Kernel/platform-zeta-v2/zeta-v2.s index bed7dfe4..5957e60a 100644 --- a/Kernel/platform-zeta-v2/zeta-v2.s +++ b/Kernel/platform-zeta-v2/zeta-v2.s @@ -48,6 +48,84 @@ CONSOLE_DIVISOR_LOW .equ (CONSOLE_DIVISOR & 0xFF) .area _DISCARD init_early: + ; We want to be at the bottom of the RAM in the physical address space. + ; This may or may not alredy be the case. We can't read out the current + ; values of the memory banking registers. + + ; We are going to assume that we are loaded in either one 64K chunk + ; or two 32K chunks, and that this code, plus the stack, live in the + ; top 16K bank. First we find ourselves in physical memory. + ld hl, #0x0000 ; go looking for bank 0 + call searchpage ; find it + ld d, a ; store mapping for low 32K + ld hl, #0x8000 ; now go looking for bank 3 + call searchpage ; find it + ld e, a ; store mapping for top 64K + push de + + ; Now we copy ourselves to the right place in physical memory. + ld a, #32 ; target = first page of RAM + call copy32k ; copy first 32K + pop de ; recover memory mapping + ld d, e ; now for the next 32K + ld a, #34 ; target = first page of RAM + call copy32k ; copy second 32K + + ; Finally remap all four 16K banks to the bottom of physical memory. + ld a, #32 ; first page of RAM + ld c, #MPGSEL_0 ; first bank register +mappage: + out (c), a ; map + inc c ; next bank + inc a ; next page + cp #36 ; done last page? + ret z + jr mappage + +copy32k: + out (MPGSEL_1), a + inc a + push af ; store next RAM page + ld a, d ; setup source + out (MPGSEL_0), a + call copy16k + inc a + out (MPGSEL_0), a ; source is now second half + pop af ; recover next RAM page + out (MPGSEL_1), a + ; fall through to copy16k +copy16k: ; copy bank 0 to bank 1 + ld hl, #0x0000 + ld de, #0x4000 + ld bc, #0x4000 + ldir + ret + +searchpage: ; search for a page of virtual memory in physical memory + ld a, (hl) ; read a byte + ld c, a ; save it + ld a, #0x55 ; known value + ld (hl), a ; write it at a fixed address + ld b, #32 ; first 512K is ROM on Zeta2 +checkpage: + ld a, b ; map the page + out (MPGSEL_1), a ; at 0x4000 + ld a, (0x4000) ; read test byte from remapped memory + cp #0x55 ; found it? + jr nz, nextpage ; no + ld a, #0x42 ; test with another value (possibly it was 0x55 by chance) + ld (hl), a ; write it + ld a, (0x4000) ; read it + cp #0x42 ; found it? + jr z, foundpage ; we got one! +nextpage: + inc b ; next page + jr nz, checkpage ; check next page -- note we test pages above 1MB too + halt ; wrapped to page 0, not found it: shouldn't happen +foundpage: + ld a, c ; get back the byte + ld (hl), a ; put it back before anyone notices + ld a, b ; return with page number in A ret init_hardware: -- 2.34.1