From: Alan Cox Date: Thu, 27 Nov 2014 23:39:43 +0000 (+0000) Subject: dragon: Major updates X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=23452ffb32f8bcc3e7e6ab787674793a03f2625e;p=FUZIX.git dragon: Major updates - Crazy SAM RAM mapping support - Propogate vectors correctly to user pages - Flesh out the tricks.s code as needed (mostly by deleting bits) - Keyboard driver - IRQ support now working This is sufficient to boot to the bootdev prompt, type a device number and fail to mount the file system. --- diff --git a/Kernel/cpu-6809/cpu.h b/Kernel/cpu-6809/cpu.h index 575896f5..eef09d40 100644 --- a/Kernel/cpu-6809/cpu.h +++ b/Kernel/cpu-6809/cpu.h @@ -21,6 +21,7 @@ extern void irqrestore(irqflags_t f); extern void *memcpy(void *, void *, size_t); extern void *memset(void *, int, size_t); extern size_t strlen(const char *); +extern uint16_t swab(uint16_t); /* 6809 doesn't benefit from making a few key variables in non-reentrant functions static */ @@ -29,6 +30,9 @@ extern size_t strlen(const char *); /* FIXME: should be 64bits - need to add helpers and struct variants */ typedef unsigned long long time_t; +#define cpu_to_le16(x) swab(x) +#define le16_to_cpu(x) swab(x) + #ifdef CONFIG_BANKED #define CODE1 __attribute__((far("1"))) #define CODE2 __attribute__((far("2"))) diff --git a/Kernel/lowlevel-6809.s b/Kernel/lowlevel-6809.s index 2fdd9bb0..6c7aa9cc 100644 --- a/Kernel/lowlevel-6809.s +++ b/Kernel/lowlevel-6809.s @@ -13,6 +13,7 @@ .globl _udivhi3 .globl _umodhi3 .globl _mulhi3 + .globl _swab ; debugging aids .globl outcharhex @@ -56,39 +57,46 @@ include "platform/kernel.def" include "kernel09.def" - .area _COMMONMEM + .area .common -; entry point for UZI system calls +; entry point for Fuzix system calls ; ; Called by swi, which has already saved our CPU state for us ; +; The lack of shared RAM leads to the rather ugly SAM_ macros needing to +; be here for SAM based boxes as we have no valid stack at this point +; unix_syscall_entry: - orcc #0x10 ; interrupts off - ; FIXME: save the zero page ptr ?? - + SAM_KERNEL ; stack now invalid ; make sure the interrupt logic knows we are in kernel mode lda #1 sta _kernel_flag -;FIXME -; -; locate function call arguments on the userspace stack -; ld hl, #18 ; 16 bytes machine state, plus 2 bytes return address -; add hl, sp -; ; save system call number -; ld a, (hl) -; ld (U_DATA__U_CALLNO), a -; ; advance to syscall arguments -; inc hl -; inc hl -; ; copy arguments to common memory -; ld bc, #8 ; four 16-bit values -; ld de, #U_DATA__U_ARGN -; ldir ; copy - - ; save process stack pointer + leax 12,s ; stacked by the swi + ldy #U_DATA__U_ARGN + SAM_USER + ldd ,x++ ; copy arguments + SAM_KERNEL + std ,y++ + SAM_USER + ldd ,x++ + SAM_KERNEL + std ,y++ + SAM_USER + ldd ,x++ + SAM_KERNEL + std ,y++ + SAM_USER + ldd ,x++ + SAM_KERNEL + std ,y++ + SAM_USER + ldd 4,s ; X register -> syscall number + SAM_KERNEL + std U_DATA__U_CALLNO + ; save process stack pointer (in user page) sts U_DATA__U_SYSCALL_SP - ; switch to kernel stack + ; switch to kernel stack (makes our stack valid again) lds #kstack_top ; map in kernel keeping common @@ -111,12 +119,17 @@ unix_syscall_entry: ; switch back to user stack lds U_DATA__U_SYSCALL_SP + ; stack is no longer valid + SAM_USER + ; stack is now valid but user stack ; check for signals, call the handlers jsr dispatch_process_signal + SAM_KERNEL ; check if error condition to be signalled on return ldd U_DATA__U_ERROR + beq not_error ldx #-1 ; error code in d, result in x bra unix_return @@ -126,12 +139,17 @@ not_error: ldx U_DATA__U_RETVAL ldd #0 unix_return: - ; zero page restore ?? - andcc #0xef + ; we never make a syscall from in kernel space + SAM_USER rti +; +; In SAM land this function is called on the user stack with the user +; memory mapped, we must rts on the right bank ! +; dispatch_process_signal: ; check if any signal outstanding + SAM_KERNEL ldb U_DATA__U_CURSIG beq dosigrts ; put number on the stack as the argument for the signal handler @@ -155,6 +173,7 @@ dispatch_process_signal: clr ,y ldu #signal_return + SAM_USER pshs u ; push return address andcc #0xef @@ -167,6 +186,8 @@ signal_return: ; FIXME: port over the Z80 loop and check for next signal ; dosigrts: + ; right stack for the rts instruction + SAM_USER rts _doexec: @@ -181,19 +202,34 @@ _doexec: ; preserves x jsr map_process_always - lds U_DATA__U_ISP - ; u_data.u_insys = false clr U_DATA__U_INSYS - andcc #0xef + ; At this point the stack goes invalid + lds U_DATA__U_ISP + andcc #0xef ; IRQs on + SAM_USER ; Stack valid, go to user code jmp ,x ; -; Very simple IRQ handler, we get interrupts at 50Hz and we have to +; Very simple IRQ handler, we get interrupts and we may have to ; poll ttys from it. The more logic we could move to common here the ; better. ; +; For SAM based machines this involves some craziness as we have no +; common inter-bank RAM. In the SAM case we will always enter with +; the kernel mapped, but our stack on entry is likely to be invalid +; +; Thus we have to have inlined SAM conditionals - bletch +; +; Y is used for the SAM logic so preserve it always +; interrupt_handler: + SAM_SAVE ; loads Y + SAM_KERNEL + + ; Do not use the stack before the switch... + + ; machine state stored by the cpu ; save zero page ?? ldd _system_tick_counter @@ -211,13 +247,16 @@ interrupt_handler: ; switch stacks sts istack_switched_sp - ; the istack is not banked (very important!) - lds #istack_top - ; FIXME: check store/dec order might need to be -2 here!!!! + ; Unlike Z80 even the istack is banked, it's only valid on SAM + ; based boxes when SAM_KERNEL is true + lds #istack_top-2 + ; FIXME: check store/dec order might not need to be -2 here!!!! jsr map_save + SAM_USER lda 0 ; save address 0 contents for checking + SAM_KERNEL ; preserves registers jsr map_kernel @@ -226,14 +265,14 @@ interrupt_handler: ; need to map anyway for trap_signal ; ldb _kernel_flag - pshs b + pshs b,cc bne in_kernel ; we're not in kernel mode, check for signals and fault - cmpa #0xA5 ;FIXME correct code needed!! + cmpa #0x0E ; JMP at 0 beq nofault jsr map_process_always ; map the process - lda #0xA5 ; put it back + lda #0x0E ; put it back sta 0 ; write jsr map_kernel ; restore the map ldx #11 ; SIGSEGV @@ -248,11 +287,17 @@ in_kernel: ; this may task switch if not within a system call ; if we switch then istack_switched_sp is out of date. ; When this occurs we will exit via the resume path + ; + ; Y is caller saves so we'll get the right Y back + ; for our SAM_RESTORE + inc 0x200 +; lda 0xFF03 +; lda 0xFF02 jsr _platform_interrupt clr _inint - puls b ; Z = in kernel + puls b,cc ; Z = in kernel bne in_kernel_2 ; On a return to user space always do a new map, we may have @@ -263,41 +308,47 @@ in_kernel: ; mapping as it will vary during kernel activity and the kernel ; wants it put back as it was before in_kernel_2: - jsr map_restore + jsr map_restore int_switch: lds istack_switched_sp ; stack back clr U_DATA__U_ININTERRUPT lda U_DATA__U_INSYS bne interrupt_return + SAM_USER ; we're not in kernel mode, check for signals + ; runs off the user stack so need user ram mapped on a SAM + ; based platform + pshs y jsr dispatch_process_signal + puls y interrupt_return: - ; restore zero page ?? - andcc #0xef - rts + SAM_RESTORE ; uses the saved Y + rti ; Enter with X being the signal to send ourself trap_signal: - ldy U_DATA__U_PTAB - pshs x,y + pshs x + ldx U_DATA__U_PTAB ; ssig(pid, X) jsr _ssig - puls x,y,pc + puls x,pc ; Called from process context (hopefully) null_handler: + SAM_KERNEL ; kernel jump to NULL is bad lda U_DATA__U_INSYS beq trap_illegal + SAM_USER ; user is merely not good ; check order of push arguments !! ldx #7 ldy U_DATA__U_PTAB ldd #10 ; signal (getpid(), SIGBUS) - pshs d,x,y + pshs d,y swi - puls d,x,y + puls d,y ldd #0 tfr d,x pshs d,x @@ -321,13 +372,14 @@ nmimsg: .ascii "[NMI]" .db 13,10,0 nmi_handler: + SAM_KERNEL + lds #istack_top - 2 ; We aren't coming back so this is ok jsr map_kernel ldx #nmimsg jsr outstring jsr _trap_monitor - .area _COMMONMEM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; outstring: Print the string at X until 0 byte is found @@ -483,3 +535,9 @@ _mulhi3: mul leax d,x puls d,pc ; kill D to remove initial push + +_swab: + exg x,d ; into accumulator + exg a,b ; swap bytes over + exg d,x ; back into result + rts diff --git a/Kernel/platform-dragon/README b/Kernel/platform-dragon/README index 6e9d70d2..1b66ee81 100644 --- a/Kernel/platform-dragon/README +++ b/Kernel/platform-dragon/README @@ -1,7 +1,13 @@ Dragon Experimental Build Currently we build for a Dragon64 but are not doing anything but initial -boot testing work +boot testing work. As we replace the ROMs it is kind of cheating. It won't +run on a Dragon 32 right now because it assumes the two page switching and +also it uses both ROMs on the 64. With banking it could in theory fit +entirely in a banked cartridge on COCO or COCO2 or Dragon32, but the +emulator doesn't emulate this and there is some hackery to be done to make +banking work ! On a COCO with text mode you'd get about 24K out of the 32K +RAM available for the user process. Set Up @@ -15,8 +21,12 @@ copy the platform/*.rom files into your xroar working directory xroar -machine dragon64 -cart-rom cart1.rom -cart-rom2 cart2.rom -cart becker +Boot Sequence - +The first ROM image is currently mostly empty. It contains a small bootstrap +that sets up the SAM (this must be done from ROM), clears low memory and +then unpacks the kernel data and other RAM based bits as a DECB stream. +Once unpacked it flips ROM and enters the kernel crt0. Dragon & COCO Memory Mapping Notes: @@ -72,7 +82,8 @@ low (there is no access to the high RAM with the cartridge paged in). Equally we want user space to run from low addresses (for commonality) and we want to protect kernel data from user accidents. -The map we use is thus +The map we are forced to use to handle the DragonPlus and to make the other +cases for userspace sane are: Kernel 0xC000-0xFEFF Cartridge OS image @@ -82,50 +93,53 @@ User 0xC000-0xFEFF Cartridge OS image 0x0000-0x7FFF RAM0 (or any other bank) +or (on a 64K box) in theory + +User + 0x0000-0xDFFF User + 0xE000-0xFFFF RAM1 top used for display and kernel + +To do that latter requires adding some additional vectors and bounce points +in the bottom 0x200 bytes of the RAM0 data area which for big processes do + + move stack down into the low space + switch in catridge/ROM + copy and restack the syscall arguments + jsr rom interrupt vector + switch out catridge/ROM + switch stack back + +and similar without the argument shuffle for interrupts. + this allows us to use all the banks effectively for 32K apps on all the combinations. It also allows us to use some banks in the fat COCO2 case to allow ~64K userspace apps -The downside is that the interrupt handling and syscall entry are -interesting as we have no common RAM to use for the stack as we switch -around. - -As a result we are going to need to make stuff like syscall - - map kernel RAM high - set kernel stack in highspace - enter syscall path - save registers and stuff - copy arguments into udata - jump back into a RAM 0 address - remap the catridge slot - jump into a cartridge helper - cartridge helper maps kernel pages low - shift S by $8000 bytes - do the actual syscall - in cartridge code switch the low memory back to RAM 0 (user) - jump into ram0 - switch the kernel RAM high - shift S by $8000 bytes - restore everything - switch the ROM back in - return to user - -Thankfully the IRQ path can be a lot cleaner as we have nothing to save -but the entry/exit registers +interrupt handling and syscall entry are interesting as we have no common RAM + +To handle this the 6809 low-level code is polluted by SAM_ macros that sane +boxes can leave as blank. On a SAM based box we play pingpoing with the +banks using inline code (as the stack keeps vanishing under us) and the +map_ helpers are no-ops (we can't remap in a subroutine really). On a sane +box it works like you'd expect. The video is fortunately simpler as the top bit for the CPU accesses via the SAM uses the P bit as A15. The video takes B15 from the SAM not via P (unclear how this works on DragonPlus and this is complicated on the 'fat' - COCO add-ons as the video can be moved into high space too) + COCO add-ons as the video can be moved into high space too. The DragonPlus +fortunately has its own video anyway). This basic setup should be compatible with any 6883/74LS783 based system -with 64K of RAM and at least 16K of ROM we can hide in. Note that the SAM +with 64K of RAM and at least 32K of ROM we can hide in. Note that the SAM decoder doesn't require the other 32K of ROM decodes is ROM, it can be RAM. However the COCO and Dragon don't allow for them being RAM. In theory Dragon32 + DragonPlus would also work but the lack of common RAM -might make the the bank switch syscall path truely epic +might make the the bank switch syscall path truely epic, ditto using the +64K to hold two user apps providing one is under 24K. Not impossible - we'd +need to stash the real "user" page map in address in the kernel map at say +address 6 when we flipped task and fixed in the user map. SAM_USER would +then become sta [6]. Something like that anyway. Disks @@ -163,3 +177,4 @@ Becker port at 0xFF40 (FF46 ? on Dragon) IDE: FF70-FF78 - data latched (write high/load, read low/high) [0-7 IDE regs 8 maps the latches] +Graphics option to do a less ugly console diff --git a/Kernel/platform-dragon/config.h b/Kernel/platform-dragon/config.h index 86ba4b35..ae11c549 100644 --- a/Kernel/platform-dragon/config.h +++ b/Kernel/platform-dragon/config.h @@ -15,9 +15,10 @@ #define CONFIG_BANKS 1 /* Banked Kernel: need to fix GCC first */ #undef CONFIG_BANKED -/* FIXME */ -#define BANK_PROCESS *((volatile uint8_t *)0xff91) &= ~1 -#define BANK_KERNEL *((volatile uint8_t *)0xff91) |= 1 +/* We use the C code for usermem and pray it doesn't use the stack for the + copies */ +#define BANK_PROCESS *((volatile uint8_t *)0xffd4) = 0 +#define BANK_KERNEL *((volatile uint8_t *)0xffd5) = 0 /* And swapping */ #define SWAPDEV 6 /* FIXME */ #define SWAP_SIZE 0x80 /* 64K blocks */ @@ -31,7 +32,7 @@ /* Simple text mode */ #define CONFIG_VT_SIMPLE /* Vt definitions */ -#define VT_BASE (uint8_t *)0x0200 /* Default video text mode base */ +#define VT_BASE (uint8_t *)0x6000 /* Default video text mode base */ #define VT_WIDTH 32 #define VT_HEIGHT 16 #define VT_RIGHT 31 @@ -60,5 +61,5 @@ extern unsigned char vt_mangle_6847(unsigned char c); #define NDEVS 2 /* Devices 0..NDEVS-1 are capable of being mounted */ /* (add new mountable devices to beginning area.) */ #define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ -#define NBUFS 10 /* Number of block buffers */ -#define NMOUNTS 3 /* Number of mounts at a time */ +#define NBUFS 6 /* Number of block buffers */ +#define NMOUNTS 2 /* Number of mounts at a time */ diff --git a/Kernel/platform-dragon/crt0.s b/Kernel/platform-dragon/crt0.s index afdf6143..dc88794a 100644 --- a/Kernel/platform-dragon/crt0.s +++ b/Kernel/platform-dragon/crt0.s @@ -26,13 +26,6 @@ bootme: main: orcc #0x10 ; interrupts definitely off lds #kstack_top - -;wiper: ldx #s__DATA -; ldd #l__DATA -; clr ,x+ -; subd #1 -; bne wiper - jsr init_early jsr init_hardware jsr _fuzix_main diff --git a/Kernel/platform-dragon/devtty.c b/Kernel/platform-dragon/devtty.c index bf2d7964..7d8fdc76 100644 --- a/Kernel/platform-dragon/devtty.c +++ b/Kernel/platform-dragon/devtty.c @@ -76,9 +76,113 @@ void tty_interrupt(void) } } +static uint8_t keymap[8]; +static uint8_t keyin[8]; +static uint8_t keybyte, keybit; +static uint8_t newkey; +static int keysdown = 0; +static uint8_t shiftmask[8] = { + 0, 0x40, 0, 0, 0, 0, 0, 0x40 +}; + +static uint8_t rbit[8] = { + 0xFE, + 0xFD, + 0xFB, + 0xF7, + 0xEF, + 0xDF, + 0xBF, + 0x7F, +}; + +/* Row inputs: multiplexed with the joystick */ +static volatile uint8_t *pia_row = (uint8_t *)0xFF00; +/* Columns for scanning: multiplexed with the printer port */ +static volatile uint8_t *pia_col = (uint8_t *)0xFF02; +/* Control */ +static volatile uint8_t *pia_ctrl = (uint8_t *)0xFF03; + +static void keyproc(void) +{ + int i; + uint8_t key; + + for (i = 0; i < 8; i++) { + /* We do the scan in software on the Dragon */ + *pia_col = rbit[i]; + keyin[i] = ~*pia_row; + key = keyin[i] ^ keymap[i]; + if (key) { + int n; + int m = 1; + for (n = 0; n < 7; n++) { + if ((key & m) && (keymap[i] & m)) { + if (!(shiftmask[i] & m)) + keysdown--; + } + if ((key & m) && !(keymap[i] & m)) { + if (!(shiftmask[i] & m)) + keysdown++; + keybyte = i; + keybit = n; + newkey = 1; + } + m += m; + } + } + keymap[i] = keyin[i]; + } +} + +static uint8_t keyboard[8][7] = { + { '0', '8', '@', 'h', 'p', 'x', 10 }, + { '1', '9', 'a', 'i', 'q', 'y', 0 /* clear - used as ctrl*/ }, + { '2', ':', 'b', 'j', 'r', 'z', 27 /* break (used for esc) */ }, + { '3', ';', 'c', 'k', 's', '^' /* up */, 0 /* NC */ }, + { '4', ',', 'd', 'l', 't', '|' /* down */, 0 /* NC */ }, + { '5', '-', 'e', 'm', 'u', 8 /* left */, 0 /* NC */ }, + { '6', '.', 'f', 'n', 'v', '\t' /* right */, 0 /* NC */ }, + { '7', '/', 'g', 'o', 'w', ' ', 0 /* shift */ }, +}; + +static uint8_t shiftkeyboard[8][7] = { + { '_', '(', '\\', 'H', 'P', 'X', 10 }, + { '!', ')', 'A', 'I', 'Q', 'Y', 0 /* clear */ }, + { '"', '*', 'B', 'J', 'R', 'Z', 3 /* break */ }, + { '#', '+', 'C', 'K', 'S', '[' /* up */, 0 /* NC */ }, + { '$', '<', 'D', 'L', 'T', ']' /* down */, 0 /* NC */ }, + { '%', '=', 'E', 'M', 'U', '{' /* left */, 0 /* NC */ }, + { '&', '>', 'F', 'N', 'V', '}' /* right */, 0 /* NC */ }, + { '\'', '?', 'G', 'O', 'W', ' ', 0 /* shift */ }, +}; + +static void keydecode(void) +{ + uint8_t c; + + if (keymap[7] & 64) /* shift */ + c = shiftkeyboard[keybyte][keybit]; + else + c = keyboard[keybyte][keybit]; + if (keymap[1] & 64) { /* control */ + if (c > 31 && c < 96) + c &= 31; + } + tty_inproc(1, c); +} + void platform_interrupt(void) { - timer_interrupt(); + uint8_t i = *pia_ctrl; + if (i & 0x80) { + *pia_col; + newkey = 0; + keyproc(); + if (keysdown < 3 && newkey) + keydecode(); + timer_interrupt(); + } } /* This is used by the vt asm code, but needs to live at the top of the kernel */ diff --git a/Kernel/platform-dragon/fuzix.link b/Kernel/platform-dragon/fuzix.link index 3ded73d0..a1a7dc61 100644 --- a/Kernel/platform-dragon/fuzix.link +++ b/Kernel/platform-dragon/fuzix.link @@ -1,11 +1,11 @@ section .vectors load 0x0100 section .udata load 0x7D00 -section _COMMONMEM high 0x7D00 -section .bss +section .bss high 0x7D00 section .data section .videodata -section .discard +section .discard load 0x5000 section .start load 0x8000 +section .common section .text section .video section .text2 load 0xC000 diff --git a/Kernel/platform-dragon/kernel.def b/Kernel/platform-dragon/kernel.def index a49e8762..c14daee9 100644 --- a/Kernel/platform-dragon/kernel.def +++ b/Kernel/platform-dragon/kernel.def @@ -3,3 +3,20 @@ U_DATA equ 0x7D00 ; (this is struct u_data from kernel.h) U_DATA__TOTALSIZE equ 0x300 ; 256+256+256 bytes. + +SAM_USER macro + sta 0xFFD4 + endm + +SAM_KERNEL macro + sta 0xFFD5 + endm + +SAM_SAVE macro + ldy 4 + endm + +SAM_RESTORE macro + sta ,y + endm + diff --git a/Kernel/platform-dragon/p6809.s b/Kernel/platform-dragon/p6809.s index 8b1be558..90f39f27 100644 --- a/Kernel/platform-dragon/p6809.s +++ b/Kernel/platform-dragon/p6809.s @@ -32,10 +32,7 @@ include "kernel.def" include "../kernel09.def" -; ----------------------------------------------------------------------------- -; COMMON MEMORY BANK (0xF000 upwards) -; ----------------------------------------------------------------------------- - .area _COMMONMEM + .area .common trapmsg: .ascii "Trapdoor: SP=" .db 0 @@ -64,9 +61,6 @@ _irqrestore: ; B holds the data tfr b,cc rts -; ----------------------------------------------------------------------------- -; KERNEL MEMORY BANK (below 0xF000, only accessible when the kernel is mapped) -; ----------------------------------------------------------------------------- .area .text init_early: @@ -76,8 +70,12 @@ init_hardware: ; set system RAM size ldd #64 std _ramsize - ldd #32 + ldd #56 std _procmem + ; Turn on PIA CB1 (50Hz interrupt) + lda 0xFF03 + ora #1 + sta 0xFF03 rts @@ -99,25 +97,44 @@ init_hardware: .area .romvectors .dw 0x3634 ; Reserved - .dw 0x0100 - .dw 0x0103 - .dw 0x010f - .dw 0x010c - .dw 0x0106 - .dw 0x0109 + .dw 0x0100 ; SWI3 + .dw 0x0103 ; SWI2 + .dw 0x010f ; FIRQ + .dw 0x010c ; IRQ + .dw 0x0106 ; SWI + .dw 0x0109 ; NMI .dw 0xC000 ; Unused (reset) ;------------------------------------------------------------------------------ ; COMMON MEMORY PROCEDURES FOLLOW - .area _COMMONMEM + .area .common ; ; In the Dragon64 case our vectors live in a fixed block ; _program_vectors: - rts + pshs cc + orcc #0x10 + lda #0x0E + sta 0 ; NULL pointer trap +; FIXME: add a target address for NULL execution + ldd #0xFFD5 + cmpx #0 ; Kernel or user ? + beq setsamvec + ldx #0x100 +vecl: SAM_KERNEL ; Copy vectors + ldd ,x + SAM_USER + std ,x+ + cmpx #0x112 + bne vecl + ; in SAM_USER so we hit the right page + ldd #0xFFD4 +setsamvec: std 4 ; [4] can now be used for SAM_RESTORE + SAM_KERNEL + puls cc,pc ; ; FIXME: @@ -132,50 +149,17 @@ badswi_handler: ; SAM ffd4/d5 reading turns off/on the upper 32K of RAM at 0x0-0x7FFF ; SAM ffde/ffdf makes it appear at 0x8000-0xffef (ff00... is hardwired) ; PIA 1 B side data reg (ff22) bit 2 switches between the two ROMs -; -; ; -; All registers preserved +; This basically means that all the mapping has to be inlined. If we +; ever support the DragonPlus we'll need to rather carefully address +; the case of flipping user bank between 0/A/B ; map_process_always: - pshs a -map_process_2: - lda 0xffdf ; RAM please - lda #0 - sta cart_map - puls a, pc - map_process: - cmpx #0 - bne map_process_always -; -; Map in the kernel below the current common, all registers preserved -; map_kernel: - pshs a -map_kernel_2: - lda 0xffde ; RAM out (cart in hopefully) - lda #1 - sta cart_map - puls a, pc - map_restore: - pshs a - lda saved_map - cmpa #0 - beq map_process_2 - bra map_kernel_2 -; -; Save the current mapping. -; map_save: - pshs a - lda cart_map - sta saved_map - puls a,pc - -saved_map: .db 0 -cart_map: .db 0 + rts ; outchar: Wait for UART TX idle, then print the char in a @@ -188,4 +172,6 @@ outcharw: sta 0xff04 puls b,pc + .area .data + _kernel_flag: .db 1 diff --git a/Kernel/platform-dragon/tricks.s b/Kernel/platform-dragon/tricks.s index 3fb76a3f..3d648940 100644 --- a/Kernel/platform-dragon/tricks.s +++ b/Kernel/platform-dragon/tricks.s @@ -17,14 +17,17 @@ include "kernel.def" include "../kernel09.def" - .area _COMMONMEM -; ramtop must be in common for single process swapping cases + .area .data + +; ramtop must usually 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 +; here. In our case with SAM it's all a bit special so data is fine + _ramtop: .dw 0 + .area .common ; 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 @@ -64,19 +67,10 @@ badswitchmsg: .ascii "_switchin: FAIL" _switchin: orcc #0x10 ; irq off - ldy P_TAB__P_PAGE_OFFSET+3,x - ; FIXME: can we skip the usermaps here ? - stx 0xffa6 ; map the process uarea we want - adda #1 - stx 0xffa7 - stx 0xffaf ; and include the kernel mapping - - ; ------- No stack ------- ; check u_data->u_ptab matches what we wanted cmpx U_DATA__U_PTAB bne switchinfail - ; wants optimising up a bit lda #P_RUNNING sta P_TAB__P_STATUS_OFFSET,x @@ -86,7 +80,6 @@ _switchin: ; restore machine state -- note we may be returning from either ; _switchout or _dofork lds U_DATA__U_SP - puls x ; return code ; enable interrupts, if the ISR isn't already running @@ -103,12 +96,16 @@ switchinfail: ; something went wrong and we didn't switch in what we asked for jmp _trap_monitor + .area .data fork_proc_ptr: .dw 0 ; (C type is struct p_tab *) -- address of child process p_tab entry + .area .common ; ; Called from _fork. We are in a syscall, the uarea is live as the ; parent uarea. The kernel is the mapped object. ; +; FIXME: preserve y +; _dofork: ; always disconnect the vehicle battery before performing maintenance orcc #0x10 ; should already be the case ... belt and braces. @@ -116,12 +113,12 @@ _dofork: ; new process in X, get parent pid into y stx fork_proc_ptr - ldy P_TAB__P_PID_OFFSET,x + ldx P_TAB__P_PID_OFFSET,x ; 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. - pshs y ; y has p->p_pid from above, the return value in the parent + pshs x ; x has p->p_pid from above, the return value in the parent ; save kernel stack pointer -- when it comes back in the parent we'll be in ; _switchin which will immediately return (appearing to be _dofork() @@ -132,15 +129,15 @@ _dofork: ; now we're in a safe state for _switchin to return in the parent ; process. - ; --------- we switch stack copies in this call ----------- - jsr fork_copy ; copy 0x000 to udata.u_top and the - ; uarea and return on the childs - ; common + ldx U_DATA__U_PTAB ; parent + jsr _swapout ; swap the parent out, leaving + ; it in memory as the child + ; 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. - puls y + puls x ldx fork_proc_ptr jsr _newproc @@ -156,46 +153,3 @@ _dofork: ; if it had done a switchout(). rts -fork_copy: - ldd U_DATA__U_TOP - addd #0x0fff ; + 0x1000 (-1 for the rounding to follow) - lsra - lsra - lsra - lsra - lsra ; bits 2/1 for 8K pages - anda #6 ; lose bit 0 - adda #2 ; and round up to the next bank (but in 8K terms) - - ldx fork_proc_ptr - ldy P_TAB__P_PAGE_OFFSET,x - ; y now points to the child page pointers - ldx U_DATA__U_PAGE - ; and x to the parent -fork_next: -; ld a,(hl) -; out (0x11), a ; 0x4000 map the child -; ld c, a -; inc hl -; ld a, (de) -; out (0x12), 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 -; FIXME: can't map_kernel here - we've been playing with the maps, fix -; directly - suba #1 - bne fork_next - -; ld a, c -; out (0x13), a ; our last bank repeats up to common - ; --- we are now on the stack copy, parent stack is locked away --- - rts ; this stack is copied so safe to return on - -