From: Alan Cox Date: Fri, 7 Nov 2014 20:51:12 +0000 (+0000) Subject: msx1: memory mapping and other logic X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=3faa2dff49c39b2a9fa59009b84a398912dd1be0;p=FUZIX.git msx1: memory mapping and other logic The big TODO for userspace here is to implement forkcopy (copying 32K between two blocks of MegaRAM) --- diff --git a/Kernel/platform-msx1/config.h b/Kernel/platform-msx1/config.h index 50ba56d3..b70d226b 100644 --- a/Kernel/platform-msx1/config.h +++ b/Kernel/platform-msx1/config.h @@ -28,7 +28,7 @@ #define TICKSPERSEC 50 /* Ticks per second (actually should be dynamic FIXME) */ #define PROGBASE ((char *)(0x0100)) /* also data base */ -#define PROGTOP ((char *)(0x8000)) /* Top of program */ +#define PROGTOP ((char *)(0x7D00)) /* Top of program (uarea stash) */ #define BOOT_TTY (512 + 1) /* Set this to default device for stdio, stderr */ /* In this case, the default is the first TTY device */ diff --git a/Kernel/platform-msx1/main.c b/Kernel/platform-msx1/main.c index 52ce283e..3f9a50dc 100644 --- a/Kernel/platform-msx1/main.c +++ b/Kernel/platform-msx1/main.c @@ -7,7 +7,6 @@ /* These are set by the msx startup asm code */ uint16_t vdpport = 0x99 + 256 * 40; uint16_t infobits; -uint16_t msxmaps; void platform_idle(void) { @@ -21,23 +20,21 @@ void do_beep(void) } /* - * Map handling: We have flexible paging. Each map table consists of a set - * of pages with the last page repeated to fill any holes. + * We have one bank per 32K and we number them upwards from 1 as the + * core kernel code uses 0 for swapped out. */ void pagemap_init(void) { - int i = msxmaps - 1; - /* Add all the RAM, except 0,1,2,3 which is the kernel data/bss, add 0 - last to become the common for init */ - while (i > 4) + int i = procmem / 32; + while (i > 0) pagemap_add(i--); - /* Init will pick this up correctly as its common */ - pagemap_add(4); } void map_init(void) { + if (procmem == 0) + panic("MegaRAM not found.\n"); } diff --git a/Kernel/platform-msx1/msx1.s b/Kernel/platform-msx1/msx1.s index 4dc51df6..716bbe32 100644 --- a/Kernel/platform-msx1/msx1.s +++ b/Kernel/platform-msx1/msx1.s @@ -2,7 +2,7 @@ ; MSX2 hardware support ; - .module msx2 + .module msx1 ; exported symbols .globl init_early @@ -25,7 +25,6 @@ ; imported symbols .globl _ramsize .globl _procmem - .globl _msxmaps .globl _tty_inproc .globl unix_syscall_entry @@ -134,12 +133,16 @@ init_hardware: ; there is ; size_memory: - ; set system RAM size in KB - ld hl, #64 - ld (_ramsize), hl - ld de, #0xFFD0 - add hl, de ; subtract 48K for the kernel + call megaram_scan + ld l, a + ld h, #0 + add hl, hl + add hl, hl + add hl, hl ; megaram for the user space ld (_procmem), hl + ld de, #0x40 ; main memory for kernel + add hl, de + ld (_ramsize), hl ret _program_vectors: @@ -186,6 +189,10 @@ _program_vectors: ; All registers preserved ; map_process_always: + push hl + ld hl, #U_DATA__U_PAGE + call map_process_2 + pop hl ret ; ; HL is the page table to use, A is eaten, HL is eaten @@ -195,25 +202,105 @@ map_process: or l jr nz, map_process_2 ; -; Map in the kernel below the current common, go via the helper -; so our cached copy is correct. +; Map in the kernel low area (0x0000-0x7FFF) ; map_kernel: + push af + ld a, i + push af + di + ld a, #'K' + out (0x2f), a + ld a, (map_cache) ; Already mapped + or a + jr z, map_kernel_out + push bc + push de + push hl + call restoreslotmap + xor a + ld (map_cache), a + pop hl + pop de + pop bc +map_kernel_out: + ld a, #'k' + out (0x2f), a + pop af + jp po, map_kernel_di + ei +map_kernel_di: + pop af ret map_process_2: + push af + ld a, i + push af + di + push de + ld a, #'U' + out (0x2f), a + ld a, (map_cache) + or a + jr nz, inter_mega + ld a, #'M' + out (0x2f), a + call map_megaram + ld a, #'m' + out (0x2f), a +inter_mega: + ld a, (hl) + ld (map_cache), a + dec a ; turn the bank number into 0 offset + add a, a + add a, a ; 4 pages per process + out (0x8E), a + ld (0), a + inc a + ld (1), a + inc a + ld (0x4000), a + inc a + ld (0x4001), a + in a, (0x8E) + pop de + ld a, #'u' + out (0x2f), a + pop af + jp po, map_proc_di + ei +map_proc_di:pop af ret ; ; Restore a saved mapping. We are guaranteed that we won't switch ; common copy between save and restore. Preserve all registers ; map_restore: + push hl + push af + ld hl, #map_saved + ld a, (hl) ; Kernel ? + or a + jr nz, map_ruser + ld hl, #0 ; Do a kernel remap not a user one +map_ruser: + call map_process ; Map it + pop af + pop hl ret ; -; Save the current mapping. +; Save the current mapping (trivial) ; map_save: + push af + ld a, (map_cache) + ld (map_saved), a + pop af ret +map_cache: .db 0 +map_saved: .db 0 + ; emulator debug port for now outchar: push af @@ -235,21 +322,24 @@ outchar: .area _HIGHCODE setslot0: push bc - in a, (0xA8) - and #0xFC - ld b, a + push de + ld a, #'S' + out (0x2f), a + ld a, #'0' + out (0x2f), a ld a, d - and #0x03 - or b - ld b, a ; Final mapping + call outcharhex + ld a, e + call outcharhex in a, (0xA8) - and #0x3C + and #0xFC ; For final setting + ld b, a + and #0x3C ; For setting sslot ld c, a ld a, d and #0xC3 or c - ld c, a ; Temporary mapping for SSLOT crap - out (0xA8), a + out (0xA8), a ; Map the right slot in bank 0 and 3 ld a, e and #0x03 ld e, a @@ -258,8 +348,14 @@ setslot0: and #0xFC or e ld (0xFFFF), a ; Set SSLOT - ld a, b ; Final PSLOT (unmap the SSLOT) + ld a, d + and #0x03 + or b out (0xA8), a + call outcharhex + ld a, #'/' + out (0x2f), a + pop de pop bc ret @@ -269,21 +365,24 @@ setslot0: setslot1: push bc - in a, (0xA8) - and #0xF3 - ld b, a + push de + ld a, #'S' + out (0x2f), a + ld a, #'1' + out (0x2f), a ld a, d - and #0x0C - or b - ld b, a ; Final mapping + call outcharhex + ld a, e + call outcharhex in a, (0xA8) - and #0x33 + and #0xF3 ; For final setting + ld b, a + and #0x33 ; For setting sslot ld c, a ld a, d and #0xCC or c - ld c, a ; Temporary mapping for SSLOT crap - out (0xA8), a + out (0xA8), a ; Map the right slot in bank 1 and 3 ld a, e and #0x0C ld e, a @@ -292,105 +391,99 @@ setslot1: and #0xF3 or e ld (0xFFFF), a ; Set SSLOT - ld a, b ; Final PSLOT (unmap the SSLOT) + ld a, d + and #0x0C + or b out (0xA8), a + call outcharhex + ld a, #'/' + out (0x2f), a + pop de pop bc ret ; -; Sufficient ?? FIXME - maybe wrong approach anyway +; Save the slot/subslot map. This requires much mucking about +; remapping the top bank ; saveslotmap: - in a, (0xA8) - ld (slot), a ; Slots + ld hl, #slotsave + ld bc, #0x05A8 ; count for slots (+ 1 for ini), port + ini + in d, (c) ; Load again for working + ld e, #0 ; Slot number +saveslotmap1: + ld a, d + and #0x3f ; Mask off top bank + or e + out (c), a ld a, (0xFFFF) cpl - ld (slots), a + ld (hl), a + inc hl + ld a, #0x40 + add e + ld e, a + djnz saveslotmap1 + out (c), d ret restoreslotmap: - ld a, (slot) - out (0xA8), a - ld a, (slots) - ld (0xFFFF), a + ld hl, #slotsave + ld bc, #0x05A8 + outi + in d, (c) + ld e, #0 ; Slot number +resslotmap1: + ld a, d + and #0x3f ; Mask off top bank + or e + out (c), a + ld a, (hl) + ld (0xFFFF), a ; Load the subslot into each + inc hl + ld a, #0x40 + add e + ld e, a + djnz resslotmap1 + out (c), d ret -; -; Can't be in common as we bugger about with 0xC000+ -; - .area _HIGHCODE +slotsave: .db 0 + .db 0, 0, 0, 0 -systemslotmap: +slotexpanded: + push hl + push de + in a, (0xA8) + call outcharhex in a, (0xA8) - ld (system_pslot), a - ld d, a ; need this in a register - and #0x3F ; all but top 16K ld e, a - and #3 ; Low 16K - rrca ; Into the top 16K space - rrca - or e - ld (system_pslot0), a - out (0xA8), a - ld a, (0xFFFF) - ld a, d - out (0xA8), a ; Put things back to sanity - cpl - ld (system_sslot0), a - ld a, d and #0x3F - ld e, a + ld d, a and #0x0C rlca rlca rlca rlca - or e - ld (system_pslot1), a - out (0xA8), a - ld a, (0xFFFF) - ld a, d + or d + push af + call outcharhex + pop af out (0xA8), a - cpl - ld (system_sslot1), a - ret - -system_pslot0: .db 0 ; Keep paired.. -system_sslot0: .db 0 -system_pslot1: .db 0 -system_sslot1: .db 0 -system_pslot: .db 0 - -; -; Map the system as we recorded it in systemslotmap -; -; Must reside below 0xC000 -; -map_system: - ld c, #0xA8 - in b, (c) - ld de, (system_pslot0) ; e=pslot0, d=sslot0 - out (c), e - ld a, d - ld (0xFFFF), a - out (c), b - ld de, (system_pslot1) ; e=pslot1, d=sslot1 - out (c), e - ld a, d - ld (0xFFFF), a - out (c), b - ld a, (system_pslot) - out (c), a - ret - -slotexpanded: - push hl ld hl, #0xFFFF ld a, (hl) ; Read cpl value cpl ; A is now the write value ld (hl), a ; Write it cpl cp (hl) + jr z, isexp + ld a, #'N' + out (0x2f), a +isexp: + ld a,e + out (0xA8), a + pop de pop hl ret ; Z = Expanded @@ -408,21 +501,32 @@ slotscan1: ld d, #0 nextslot: ld e, #0 -nextexpanded: call setslot1 exx call callhl ; Scan exx call slotexpanded jr nz, noexpanded + jr expanders +nextexpanded: + call setslot1 + exx +; call callhl ; Scan + exx +expanders: ld a, #0x55 add e ld e, a + ld a, #'.' + out (0x2f), a jr nc, nextexpanded noexpanded: - inc e - bit 2, e - jr z, nextslot + ld a, #'|' + out (0x2f), a + ld a, d + add #0x55 + ld d, a + jr nc, nextslot call restoreslotmap ret @@ -430,30 +534,46 @@ callhl: jp (hl) megaset0: xor a megaset: out (c), a ; ROM mode - ld (0x5fff), a ; page A - in a, (c) + ld (hl), a ; page A + in a, (c) ; RAM mode ret ; ; Hunt for a MegaRAM (assumes c set correctly by caller) ; -megaram_p: call megaset0 - ld a, b ; Just using d for check code - ld (0x5FFF), a ; Now should store this either way +; The basic idea is +; Stick it in paging mode +; Page it to 0 +; Stick it in RAM mode +; Write a value +; Stick it back in paging mode +; Write 0 +; +; If it's a MegaRAM the memory will remain as the value, if it's real RAM +; it will be zeroed by the paging write back +; +megaram_p: + ld d, (hl) call megaset0 - ld a, (0x5FFF) + ld (hl), b ; Now should store this either way + call megaset0 ; Should not change if megaram + ld a, (hl) + ld (hl), d ; Restore old bits cp b ; Z = MegaRAM (probably) ret megaram_chk: - ld bc, #0xA58E + ld hl, #0x5FFF + ld bc, #0xA58E ; A5 is the pattern we use call megaram_p ret nz ; Not MegaRAM - ld c, #0x5A + ld b, #0x5A call megaram_p ; Paranoia check ret megaram_scan_f: + push hl call megaram_chk + pop hl ret nz exx ld (megaram_i), de ; save de' (slot/subslot info) @@ -470,9 +590,11 @@ megaram_scan: ld a, d or e jr z, megaram_no + ld a, #'M' + out (0x2f), a call setslot1 ; select the megaram ld bc, #0x8E - ld hl, #0x5fff + ld hl, #0x4000 call megaset0 ld (hl), #0x55 megaram_size: diff --git a/Kernel/platform-msx1/tricks.s b/Kernel/platform-msx1/tricks.s index 6a170fa2..b22f7fcc 100644 --- a/Kernel/platform-msx1/tricks.s +++ b/Kernel/platform-msx1/tricks.s @@ -57,6 +57,16 @@ _switchout: xor a ld (_inint), a + ; Stash the uarea back into process memory + ; We need to flip to the process map to copy this high + call map_process_always + ld hl, #U_DATA + ld de, #U_DATA_STASH + ld bc, #U_DATA__TOTALSIZE + ldir + ; Then flip back as we need to call getproc + call map_kernel + ; find another process to run (may select this one again) call _getproc @@ -81,10 +91,33 @@ _switchin: ld hl, #P_TAB__P_PAGE_OFFSET+3 ; Common add hl, de ; process ptr - ld a, (hl) - out (0xFF), a ; *CAUTION* our stack just left the building - ; ------- No stack ------- + call map_process + + ; ------- No stack from here as we will LDIR over it + + exx ; thank goodness for exx 8) + ld hl, #U_DATA_STASH + ld de, #U_DATA + ld bc, #U_DATA__TOTALSIZE + ldir + exx + + ; ------- No stack still ------- + + ; Restore the stack into the newly copied stack udata. We do this + ; earlier than most ports as the convoluted banking means we need + ; a stack to flip back to kernel mappings + ; + ; FIXME: should look at making this the usual way around ? + ; + ld sp, (U_DATA__U_SP) + ; ------- stack good ------- + + ; Map kernel memory back so we can actually get our hands on the + ; process table data + call map_kernel + ; check u_data->u_ptab matches what we wanted ld hl, (U_DATA__U_PTAB) ; u_data->u_ptab or a ; clear carry flag @@ -100,15 +133,6 @@ _switchin: 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 ---- - - ld hl, #0 - add hl, sp - pop iy pop ix pop hl ; return code @@ -121,8 +145,6 @@ _switchin: ret ; return with interrupts on switchinfail: - ; This will crap somewhere random in the stack space of the failure - ; case. We aren't coming back, it doesn't matter call outhl ld hl, #badswitchmsg call outstring @@ -205,43 +227,10 @@ _dofork: ; and map_restore ; fork_copy: - ld hl, (U_DATA__U_TOP) - ld de, #0x0fff - add hl, de ; + 0x1000 (-1 for the rounding to follow) - ld a, h - rlca - rlca ; get just the number of banks in the bottom - ; bits - and #3 - inc a ; and round up to the next bank - ld b, a - ; we need to copy the relevant chunks - ld hl, (fork_proc_ptr) - ld de, #P_TAB__P_PAGE_OFFSET - add hl, de - ; hl now points into the child pages - ld de, #U_DATA__U_PAGE - ; and de is the parent -fork_next: - ld a,(hl) - out (0xFD), a ; 0x4000 map the child - ld c, a - inc hl - ld a, (de) - out (0xFE), a ; 0x8000 maps the parent - inc de - exx - ld hl, #0x8000 ; copy the bank - ld de, #0x4000 - ld bc, #0x4000 ; we copy the whole bank, we could optimise - ; further - ldir - exx - call map_kernel ; put the maps back so we can look in p_tab - djnz fork_next - ld a, c - out (0xFF), a ; our last bank repeats up to common - ; --- we are now on the stack copy, parent stack is locked away --- +; FIXME: copy the 32K bank from one chunk of megaram to the other +; +; See bankfork on z80pack for guidance on udata stash etc +; ret ; this stack is copied so safe to return on