nc100: updates - basics of suspend/resume NMI path and some cleaning
authorAlan Cox <alan@linux.intel.com>
Thu, 15 Sep 2016 20:02:27 +0000 (21:02 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 15 Sep 2016 20:02:27 +0000 (21:02 +0100)
Kernel/platform-nc100/README
Kernel/platform-nc100/bootblock.s
Kernel/platform-nc100/nc100.s

index 469f1cf..09fcfe0 100644 (file)
@@ -44,9 +44,6 @@ resulting nc100.cim as the bootscript for the emulator.
 
 TODO
 
-- baud rate/serial mode setting
-- RTC (note: the RTC only works 1900-1999 so must be rejigged to get it to
-  work 1990 - 2099)
 - driver for the power status bits
 - lots of testing
 - control doesn't seem to work ???
index e9d6208..2d40a55 100644 (file)
@@ -5,8 +5,50 @@
 ;      FIXME: we need a valid NMI vector in the low 0x100 at all times
 ;
 
+;
+;      These must match the actual nc100.s code
+;
+entry_so       .equ 0x1BE
+kernel_sp      .equ 0x1C0
+resume_vector  .equ 0x1C2
+suspend_map    .equ 0x1C4
+entry_banks    .equ 0x1C8
+suspend_stack  .equ 0x1FE
+
+               .org 0xE0
+;
+;      Stub to switch into the resume bank and code
+;
+               out (0x13),a
+               jp (hl)
+;
+;      We are assembled for 0x100 but actually load at 0xC000 initially
+;      but will relocate ourselves.
+;
                .org 0x100
                di
+               ld (entry_sp),sp
+                ld hl, (0xB000)        ; Save MMU bank copies from the OS
+               ld (entry_banks),hl
+               ld hl, (0xB002)
+               ld (entry_banks+2),hl
+               ;
+               ;       Resume or new ?
+               ;
+               ld hl,(resume_vector)
+               ld de,#0
+               ld (resume_vector),de
+               ld a,h
+               or l
+               jr z, no_resume
+;
+;      We want to put our suspend page back at 0xC000 but we can't do that
+;      directly as we are right now executing that bank
+;
+               ld a,(suspend_map + 3)
+               jp 0xE0         ; stub to bank switch and jp
+
+no_resume:
                ld a, 0x83      ; map the low 16K of the kernel
                out (0x10), a
                ld hl, 0xC000   ; copy ourself into the low 16K
index ee72c7d..7266250 100644 (file)
@@ -153,11 +153,120 @@ _program_vectors:
             ld (0x0001), hl
 
             ld (0x0066), a  ; Set vector for NMI
-            ld hl, #nmi_handler
+            ld hl, #my_nmi_handler
             ld (0x0067), hl
-           jr map_kernel
+           jp map_kernel
 
 ;
+;      These are shared and agreed with the bootstrap code in the
+;      bootstrap low page
+;
+entry_sp     .equ 0x1BE
+kernel_sp   .equ 0x1C0
+resume_vector .equ 0x1C2
+suspend_map .equ 0x1C4
+entry_banks .equ 0x1C8
+suspend_stack .equ 0x1FE
+
+suspend_r:   .db 0
+
+my_nmi_handler:
+           push af
+           xor a
+           jr suspend_1
+           push af
+suspend:
+           ld a,#1
+suspend_1:
+           ld (suspend_r),a
+           ld a,i
+           push af
+           di
+           ld a,#0x80
+           out (0x10),a
+           ; Save our SP
+           ld (kernel_sp), sp
+           ld sp,#suspend_stack
+           push bc
+           push de
+           push hl
+           push ix
+           push iy
+           exx
+           push bc
+           push de
+           push hl
+           ex af,af'
+           push af
+           ; Register map saved
+           ld hl,#suspend_map
+           call save_maps
+           ld hl,#resume
+           ld (resume_vector),hl
+           ld de,(suspend_r)
+           ; Now switch the low 48K (OS) banks back as they were
+           ; and run the "official" OS NMI handler
+           ld hl,(entry_banks)
+           ld sp,(entry_sp);
+           ld a,l
+           out (0x10),a
+           ld a,h
+           out (0x11),a
+           ld a,(entry_banks+2)
+           out (0x12),a
+           ld a,e
+           or a
+           jr z, nmi_and_resume
+           ; Hand triggered suspend
+           ld a,(entry_sp)
+           ; To NC100 OS
+           ret
+nmi_and_resume:
+           call 0x66
+;
+;      Called by the booter via our resume vector. The bootstrap or ROM has
+;      already set the high 16K correctly before calling us there
+;
+resume:
+           ld hl,#0
+           ld (resume_vector),hl
+           ld hl,#suspend_map+1
+           ; Begin by restoring the mapping for 0x4000-0xBFFF
+           ld a,(hl)
+           out (0x11),a
+           inc hl
+           ld a,(hl)
+           out (0x12),a
+           ; Map the bootstrap bank back in at 0x0000-0x3FFF so we can get
+           ; our data back
+            ld a,#0x80
+           out (0x10),a
+           ; Restore the registers
+           ld sp,#suspend_stack-36
+           pop af
+           ex af,af
+           pop hl
+           pop de
+           pop bc
+           exx
+           pop iy
+           pop ix
+           pop hl
+           pop de
+           pop bc
+           ; Switch back to the kernel stack pointer. This could be in any
+           ; bank so we must not dereference it until we fix the low 16K
+           ld sp,(kernel_sp)
+           ; Grab the low 16K mapping we had before
+           ld a,(suspend_map)
+           out (0x10),a        ; booter page in 0x0000-0x3FFF vanishes here
+                               ; and our vectors re-appear
+           pop af              ; IRQ state
+           jp po,no_irq_on
+           ei
+no_irq_on:  pop af
+           ret
+;
 ;      Userspace mapping pages 7+  kernel mapping pages 3-5, first common 6
 ;
 ;
@@ -222,6 +331,12 @@ map_save:
            push hl
            push af
            ld hl, #map_savearea
+           call save_maps
+           pop af
+           pop hl
+           ret
+
+save_maps:
            in a, (0x10)
            ld (hl), a
            inc hl
@@ -233,8 +348,6 @@ map_save:
            inc hl
            in a, (0x13)
            ld (hl), a
-           pop af
-           pop hl
            ret
 
 map_savearea: