rc2014: RTC, tickless and swap work
authorAlan Cox <alan@linux.intel.com>
Mon, 3 Sep 2018 17:34:41 +0000 (18:34 +0100)
committerAlan Cox <alan@linux.intel.com>
Mon, 3 Sep 2018 17:34:41 +0000 (18:34 +0100)
Swap isn't yet completed but the RTC and tickless should now work

Kernel/platform-rc2014/config.h
Kernel/platform-rc2014/discard.c
Kernel/platform-rc2014/fuzix.lnk
Kernel/platform-rc2014/kernel.def
Kernel/platform-rc2014/main.c
Kernel/platform-rc2014/rc2014.s

index 9fa4ea6..3e592ab 100644 (file)
 /* 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 */
index 115fb9d..9d92750 100644 (file)
@@ -3,17 +3,14 @@
 #include <printf.h>
 #include <devtty.h>
 #include <ds1302.h>
+#include <devide.h>
+#include <blkdev.h>
 #include "config.h"
 #include "devrd.h"
 #include "vfd-term.h"
 
 /* Everything in here is discarded after init starts */
 
-#ifdef CONFIG_PPIDE
-#include <devide.h>
-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
index 75a5d5f..8102847 100644 (file)
@@ -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
index 131c676..5371e15 100644 (file)
@@ -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
 
index f7fa65d..2b3636e 100644 (file)
@@ -1,12 +1,17 @@
 #include <kernel.h>
 #include <kdata.h>
 #include <printf.h>
+#include <timer.h>
 #include <devtty.h>
 #include <devfd.h>
 #include <devinput.h>
+#include <rtc.h>
+#include <ds1302.h>
 
 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)
+{
+}
index 7b3239e..5c3fc30 100644 (file)
@@ -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