zx128: initial code for swap on microdrive
authorAlan Cox <alan@linux.intel.com>
Mon, 13 Apr 2015 21:28:02 +0000 (22:28 +0100)
committerAlan Cox <alan@linux.intel.com>
Mon, 13 Apr 2015 21:28:02 +0000 (22:28 +0100)
Wheee...

Kernel/platform-zx128/config.h
Kernel/platform-zx128/devmdv.c
Kernel/platform-zx128/main.c
Kernel/platform-zx128/microdrive.s
Kernel/platform-zx128/zx128.s

index d13a723..58f8575 100644 (file)
 #define NUM_DEV_TTY 1
 
 #define TTYDEV   BOOT_TTY /* Device used by kernel for messages, panics */
-#undef  SWAPDEV           /* Do not use swap */
+#define SWAPDEV  2051  /* Microdrive 3 : FIXME - configure and probe */
 #define NBUFS    9       /* Number of block buffers */
 #define NMOUNTS         4        /* Number of mounts at a time */
 #define MAX_BLKDEV 2       /* 2 IDE drives, 1 SD drive */
+
+#define SWAPBASE 0x8000
+#define SWAPTOP  0x10000UL
+#define SWAP_SIZE 0x40
+#define MAX_SWAPS 3            /* For now */
index 17e22cd..8785a88 100644 (file)
@@ -43,22 +43,37 @@ static int mdv_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
        irqflags_t irq;
        uint16_t block, nblock;
        uint8_t on = 0;
+       uint8_t altbank = 0;    /* Using alternate banks ? */
 
-       if (rawflag == 2)
-               goto bad;
        if (rawflag == 0) {
                mdv_buf = udata.u_buf->bf_data;
                block = udata.u_buf->bf_blk;
                nblock = 1;
                mdv_page = 0;
-       } else {
+       } else if (rawflag == 1) {
                /* Direct to user */
                if (((uint16_t)udata.u_offset|udata.u_count) & BLKMASK)
                        goto bad;
                mdv_buf = (uint8_t *)udata.u_base;
                nblock = udata.u_count >> 9;
                block = udata.u_offset >> 9;
-               mdv_page = 1;
+               mdv_page = udata.u_page;
+       } else {
+               /* Microdrive swap awesomeness */
+               nblock = swapcnt >> 9;
+               block = swapblk;
+               mdv_page = swapproc->p_page;
+               mdv_buf = swapbase;
+
+               /* Platform specific magic time. We know the swapper
+                  will do I/O to/from "us" (easy) or from the
+                  other process, in which case we need to juggle
+                  banks half way */
+               if (swapproc != udata.u_ptab) {
+                       altbank = 1;
+                       mdv_buf = (uint8_t *)0xC000;
+                       mdv_page = 6;   /* Switched bank */
+               }
        }
 
        irq = di();
@@ -88,6 +103,11 @@ static int mdv_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
                        goto bad;
                }
                mdv_buf += 512;
+               /* Switch bank */
+               if (altbank && mdv_buf == 0x0000) {     /* Wrapped */
+                       mdv_page = swapproc->p_page;
+                       mdv_buf = (uint8_t *)0xC000;
+               }
        }
        return 0;
 bad:
index ec0c630..1172695 100644 (file)
@@ -12,6 +12,10 @@ void pagemap_init(void)
   /* The live process also has 2 and the non running one 6 */
   pagemap_add(4);
   pagemap_add(3);
+  /* Swap */
+  swapmap_add(0);
+  swapmap_add(1);
+  swapmap_add(2);
 }
 
 /* On idle we spin checking for the terminals. Gives us more responsiveness
index ffd5773..3e89b85 100644 (file)
@@ -42,6 +42,8 @@
 
                .globl map_process_save
                .globl map_kernel_restore
+               .globl current_map
+               .globl switch_bank
 
                .area _COMMONMEM
 
@@ -438,27 +440,30 @@ _mdv_motor_on:    pop de
 ;      ZX128. It will break if this ceases to be true.
 ;
 _mdv_bread:
+               ld de, (current_map)            ; Current map into e
                ld a, (_mdv_page)
                or a
+               ld a, e                         ; Save old map
                push af
-               call nz, map_process_save
-               call mdv_fetch
+               call nz, switch_bank            ; Switch if mdv_page set
+               call mdv_fetch                  ; Do the I/O
 mdv_bout:
-               jr nz, poprete
+               jr nz, poprete                  ; Error codes for C
                xor a
 poprete:
                ld l, a
                xor a
                ld h, a
                pop af
-               call nz, map_kernel_restore
+               call nz, switch_bank            ; Switch bank if needed
                ret
 
 _mdv_bwrite:
+               ld de, (current_map)
                ld a, (_mdv_page)
                or a
-               push af
-               call nz, map_process_save
+               ld a, e
+               call nz, switch_bank
                call mdv_store
                jr mdv_bout
 
index d9328a6..4aaf070 100644 (file)
@@ -20,6 +20,7 @@
        .globl map_process_save
        .globl map_kernel_restore
        .globl current_map
+       .globl switch_bank
 
         .globl _kernel_flag