From: Alan Cox Date: Mon, 3 Sep 2018 17:34:41 +0000 (+0100) Subject: rc2014: RTC, tickless and swap work X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=0e58488ee102e65e67a0e05e4ba5676dfdf7608b;p=FUZIX.git rc2014: RTC, tickless and swap work Swap isn't yet completed but the RTC and tickless should now work --- diff --git a/Kernel/platform-rc2014/config.h b/Kernel/platform-rc2014/config.h index 9fa4ea6a..3e592ab8 100644 --- a/Kernel/platform-rc2014/config.h +++ b/Kernel/platform-rc2014/config.h @@ -18,37 +18,44 @@ /* Banks as reported to user space */ #define CONFIG_BANKS 4 -#define TICKSPERSEC 20 /* Ticks per second */ +#define TICKSPERSEC 10 /* Ticks per second */ #define PROGBASE 0x0000 /* also data base */ #define PROGLOAD 0x0100 /* also data base */ #define PROGTOP 0xF000 /* Top of program, base of U_DATA copy */ #define KERNTOP 0xC000 /* Top of kernel (first 3 banks), base of shared bank */ #define PROC_SIZE 64 /* Memory needed per process */ -/* WRS: this is probably wrong -- we want to swap the full 64K minus the common code */ -/* For now let's just use something and fix this up later when we have a swap device */ +#define SWAPDEV (swap_dev) /* A variable for dynamic, or a device major/minor */ +extern unsigned int swap_dev; #define SWAP_SIZE 0x79 /* 60.5K in blocks (prog + udata) */ #define SWAPBASE 0x0000 /* start at the base of user mem */ #define SWAPTOP 0xF200 /* Swap out udata and program */ -/* FIXME: do this off partition tables */ -#define MAX_SWAPS 10 /* Well, that depends really, hmmmmmm. Pick a number, any number. */ +#define MAX_SWAPS 16 /* We will size if from the partition */ +/* Swap will be set up when a suitably labelled partition is seen */ +#define CONFIG_DYNAMIC_SWAP + +/* + * When the kernel swaps something it needs to map the right page into + * memory using map_for_swap and then turn the user address into a + * physical address. For a simple banked setup there is no conversion + * needed so identity map it. + */ +#define swap_map(x) ((uint8_t *)((((x) & 0x3FFF)) + 0x4000)) /* We need a tidier way to do this from the loader */ #define CMDLINE NULL /* Location of root dev name */ #define BOOTDEVICENAMES "hd#,fd,,rd" -//#define SWAPDEV (256 + 1) /* Device for swapping */ #define CONFIG_DYNAMIC_BUFPOOL /* we expand bufpool to overwrite the _DISCARD segment at boot */ #define NBUFS 4 /* Number of block buffers, keep in line with space reserved in zeta-v2.s */ #define NMOUNTS 4 /* Number of mounts at a time */ #define MAX_BLKDEV 4 /* 1 ROM disk, 1 RAM disk, 1 floppy, 1 IDE */ -#if 0 /* for now */ /* On-board DS1302, we can read the time of day from it */ #define CONFIG_RTC -#define CONFIG_RTC_INTERVAL 30 /* deciseconds between reading RTC seconds counter */ -#endif +#define CONFIG_RTC_FULL +#define CONFIG_NO_CLOCK /* Floppy support */ #define CONFIG_FLOPPY /* #define CONFIG_FLOPPY to enable floppy */ diff --git a/Kernel/platform-rc2014/discard.c b/Kernel/platform-rc2014/discard.c index 115fb9d3..9d927508 100644 --- a/Kernel/platform-rc2014/discard.c +++ b/Kernel/platform-rc2014/discard.c @@ -3,17 +3,14 @@ #include #include #include +#include +#include #include "config.h" #include "devrd.h" #include "vfd-term.h" /* Everything in here is discarded after init starts */ -#ifdef CONFIG_PPIDE -#include -void ppide_init(void); -#endif - void init_hardware_c(void) { // vfd_debug_init(); @@ -47,8 +44,31 @@ void map_init(void) { } +/* + * This function is called for partitioned devices if a partition is found + * and marked as swap type. The first one found will be used as swap. We + * only support one swap device. + */ +void platform_swap_found(uint8_t letter, uint8_t m) +{ + blkdev_t *blk = blk_op.blkdev; + uint16_t n; + if (swap_dev != 0xFFFF) + return; + letter -= 'a'; + kputs("(swap) "); + swap_dev = letter << 4 | m; + n = blk->lba_count[m - 1] / SWAP_SIZE; + if (n > MAX_SWAPS) + n = MAX_SWAPS; + while(n) + swapmap_add(n--); +} + + void device_init(void) { + ds1302_init(); #ifdef CONFIG_IDE devide_init(); #endif diff --git a/Kernel/platform-rc2014/fuzix.lnk b/Kernel/platform-rc2014/fuzix.lnk index 75a5d5f5..8102847c 100644 --- a/Kernel/platform-rc2014/fuzix.lnk +++ b/Kernel/platform-rc2014/fuzix.lnk @@ -50,4 +50,7 @@ platform-rc2014/devide.rel platform-rc2014/devide_discard.rel platform-rc2014/monitor.rel platform-rc2014/devinput.rel +platform-rc2014/ds1302.rel +platform-rc2014/ds1302_discard.rel +platform-rc2014/ds1302_rc2014.rel -e diff --git a/Kernel/platform-rc2014/kernel.def b/Kernel/platform-rc2014/kernel.def index 131c6762..5371e15a 100644 --- a/Kernel/platform-rc2014/kernel.def +++ b/Kernel/platform-rc2014/kernel.def @@ -7,6 +7,8 @@ USE_FANCY_MONITOR .equ 1 ; disabling this saves around approx 0.5KB Z80_MMU_HOOKS .equ 0 +CONFIG_SWAP .equ 1 + PROGBASE .equ 0x0000 PROGLOAD .equ 0x0100 diff --git a/Kernel/platform-rc2014/main.c b/Kernel/platform-rc2014/main.c index f7fa65d3..2b3636ee 100644 --- a/Kernel/platform-rc2014/main.c +++ b/Kernel/platform-rc2014/main.c @@ -1,12 +1,17 @@ #include #include #include +#include #include #include #include +#include +#include extern unsigned char irqvector; struct blkbuf *bufpool_end = bufpool + NBUFS; /* minimal for boot -- expanded after we're done with _DISCARD */ +uint8_t timermsr = 0; +uint16_t swap_dev = 0xFFFF; void platform_discard(void) { @@ -28,6 +33,8 @@ void platform_idle(void) * Makes the HALT LED go yellow, which amuses me greatly. */ // __asm halt __endasm; irqflags_t irq = di(); + sync_clock(); + /* FIXME: need to cover ACIA option.. */ tty_pollirq_sio(); irqrestore(irq); } @@ -47,6 +54,78 @@ void platform_interrupt(void) // poll_input(); // timer_interrupt(); } + /* FIXME: need to cover ACIA option.. */ tty_pollirq_sio(); return; } + +/* + * Logic for tickless system. If you have an RTC you can ignore this. + */ + +static uint8_t newticks = 0xFF; +static uint8_t oldticks; + +static uint8_t re_enter; + +/* + * Hardware specific logic to get the seconds. We really ought to enhance + * this to check minutes as well just in case something gets stuck for + * ages. + */ +static void sync_clock_read(void) +{ + uint8_t s; + oldticks = newticks; + ds1302_read_clock(&s, 1); + s = (s & 0x0F) + (((s & 0xF0) >> 4) * 10); + newticks = s; +} + +/* + * The OS core will invoke this routine when idle (via platform_idle) but + * also after a system call and in certain other spots to ensure the clock + * is roughly valid. It may be called from interrupts, without interrupts + * or even recursively so it must protect itself using the framework + * below. + * + * Having worked out how much time has passed in 1/10ths of a second it + * performs that may timer_interrupt events in order to advance the clock. + * The core kernel logic ensures that we won't do anything silly from a + * jump forward of many seconds. + * + * We also choose to poll the ttys here so the user has some chance of + * getting control back on a messed up process. + */ +void sync_clock(void) +{ + if (!timermsr) { + irqflags_t irq = di(); + int16_t tmp; + if (!re_enter++) { + sync_clock_read(); + if (oldticks != 0xFF) { + tmp = newticks - oldticks; + if (tmp < 0) + tmp += 60; + tmp *= 10; + while(tmp--) { + timer_interrupt(); + } + /* FIXME: need to cover ACIA option.. */ + tty_pollirq_sio(); + } + re_enter--; + } + irqrestore(irq); + } +} + +/* + * This method is called if the kernel has changed the system clock. We + * don't work out how much work we need to do by using it as a reference + * so we don't care. + */ +void update_sync_clock(void) +{ +} diff --git a/Kernel/platform-rc2014/rc2014.s b/Kernel/platform-rc2014/rc2014.s index 7b3239e0..5c3fc30f 100644 --- a/Kernel/platform-rc2014/rc2014.s +++ b/Kernel/platform-rc2014/rc2014.s @@ -11,7 +11,9 @@ .globl map_process_always .globl map_save .globl map_restore + .globl map_for_swap .globl platform_interrupt_all + .globl _copy_common .globl mpgsel_cache .globl _kernel_pages .globl _platform_reboot @@ -142,7 +144,7 @@ init_partial_uart: ld a,#0x01 out (SIOA_C),a - ld a,#0x1A ; Receive int mode 11, tx int enable (was $18) + ld a,#0x18;A? ; Receive int mode 11, tx int enable (was $18) out (SIOA_C),a ld a,#0x03 @@ -167,7 +169,7 @@ init_partial_uart: ld a,#0x01 out (SIOB_C),a - ld a, #0x1A ; Receive int mode 11, tx int enable (was $18) + ld a, #0x18;A? ; Receive int mode 11, tx int enable (was $18) out (SIOB_C),a ld a,#0x02 @@ -191,14 +193,14 @@ init_partial_uart: ; If you don't have a CTC probably nothing bad will happen, other than ; your floppy not working. - ld a,#0x57 ; counter mode, disable interrupts - out (CTC_CH0),a ; set CH0 mode - ld a,#0 ; time constant = 256 - out (CTC_CH0),a ; set CH0 time constant - ld a,#0xC7 ; counter mode, enable interrupts - out (CTC_CH1),a ; set CH1 mode - ld a,#180 ; time constant = 180 - out (CTC_CH1),a ; set CH1 time constant +; ld a,#0x57 ; counter mode, disable interrupts +; out (CTC_CH0),a ; set CH0 mode +; ld a,#0 ; time constant = 256 +; out (CTC_CH0),a ; set CH0 time constant +; ld a,#0xC7 ; counter mode, enable interrupts +; out (CTC_CH1),a ; set CH1 mode +; ld a,#180 ; time constant = 180 +; out (CTC_CH1),a ; set CH1 time constant ; Done CTC Stuff ; --------------------------------------------------------------------- @@ -362,6 +364,35 @@ map_save: pop hl ret +;========================================================================= +; map_for_swap - map a page into a bank for swap I/O +; Inputs: none +; Outputs: none +; +; The caller will later map_kernel to restore normality +; +; We use 0x4000-0x7FFF so that all the interrupt stuff is mapped. +; +;========================================================================= +map_for_swap: + ld (mpgsel_cache + 1),a + out (MPGSEL_1),a + ret + +_copy_common: + pop hl + pop de + push de + push hl + ld a,e + call map_for_swap + ld hl,#0xF300 + ld de,#0x7300 + ld bc,#0x0D00 + ldir + jr map_kernel + + ; MPGSEL registers are read only, so their content is cached here mpgsel_cache: .db 0,0,0,0