msx1: memory mapping and other logic
authorAlan Cox <alan@etchedpixels.co.uk>
Fri, 7 Nov 2014 20:51:12 +0000 (20:51 +0000)
committerAlan Cox <alan@etchedpixels.co.uk>
Fri, 7 Nov 2014 20:51:12 +0000 (20:51 +0000)
The big TODO for userspace here is to implement forkcopy (copying 32K between
two blocks of MegaRAM)

Kernel/platform-msx1/config.h
Kernel/platform-msx1/main.c
Kernel/platform-msx1/msx1.s
Kernel/platform-msx1/tricks.s

index 50ba56d..b70d226 100644 (file)
@@ -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 */
index 52ce283..3f9a50d 100644 (file)
@@ -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");
 }
 
 
index 4dc51df..716bbe3 100644 (file)
@@ -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:
index 6a170fa..b22f7fc 100644 (file)
@@ -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