swap: introduce swapping onto IDE, add the needed ZX128 bits
authorAlan Cox <alan@linux.intel.com>
Thu, 21 May 2015 08:33:30 +0000 (09:33 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 21 May 2015 08:33:30 +0000 (09:33 +0100)
The concept is:

swap_map(x) turns x into an address that will hold the data to be
written out.
swap_page holds the "page" which is a cookie passed from the bank
manager to the swapper and on to the drivers.
map_for_swap takes the cookie and puts the page in the required space
map_kernel_{restore} then goes back to kernel mappings

The bank manager is responsible for not queuing a single I/O that spans two
"pages"

This then allows for swapping support, including banked memory from bank16k and
the like to use a generic shared driver without platform specifics leaking into
the driver layer code.

Kernel/dev/blkdev.c
Kernel/dev/blkdev.h
Kernel/dev/devide.c
Kernel/platform-zx128/config.h
Kernel/platform-zx128/zx128.s

index 1475736..603e9c5 100644 (file)
@@ -80,13 +80,13 @@ static int blkdev_transfer(uint8_t minor, uint8_t rawflag)
     blk_op.blkdev = &blkdev_table[minor >> 4];
     partition = minor & 0x0F;
 
+    blk_op.is_user = rawflag;
     switch(rawflag){
         case 0:
             /* read single 512-byte sector to buffer in kernel memory */
             blk_op.nblock = 1;
             blk_op.lba = udata.u_buf->bf_blk;
             blk_op.addr = udata.u_buf->bf_data;
-            blk_op.is_user = false;
             break;
         case 1:
             /* read some number of 512-byte sectors directly to user memory */
@@ -95,8 +95,15 @@ static int blkdev_transfer(uint8_t minor, uint8_t rawflag)
                 panic("blkdev: not integral");
             blk_op.lba = (udata.u_offset >> BLKSHIFT);
             blk_op.addr = udata.u_base;
-            blk_op.is_user = true;
             break;
+#ifdef SWAPDEV
+        case 2:
+            blk_op.nblock = swapcnt >> BLKSHIFT;
+            blk_op.lba = swapblk;
+            blk_op.addr = swapbase;
+            blk_op.swap_page = swappage;
+            break;
+#endif
         default:
             goto xferfail;
     }
index c1b5f32..ef00875 100644 (file)
@@ -23,7 +23,8 @@ typedef struct {
 struct blkparam {
     /* do not change the order without adjusting BLKPARAM_*_OFFSET macros below */
     void *addr;                             /* address for transfer buffer */
-    bool is_user;                           /* true: addr is in user memory, false: addr is in kernel memory */
+    uint8_t is_user;                       /* 0: kernel 1: user 2: swap */
+    uint8_t swap_page;                      /* page to pass to map_swap */
     blkdev_t *blkdev;                       /* active block device */
     uint32_t lba;                           /* LBA for first sectors to transfer */
     uint8_t nblock;                         /* number of sectors to transfer */
@@ -31,7 +32,12 @@ struct blkparam {
 };
 /* macros that inline assembler code can use to access blkparam fields */
 #define BLKPARAM_ADDR_OFFSET    0
+#ifdef POINTER32
+#define BLKPARAM_IS_USER_OFFSET 4
+#else
 #define BLKPARAM_IS_USER_OFFSET 2
+#endif
+#define BLKPARAM_SWAP_PAGE     BLKPARAM_IS_USER_OFFSET + 1
 
 extern struct blkparam blk_op;
 
index d2ce6cf..0d7bd40 100644 (file)
@@ -132,8 +132,17 @@ void devide_read_data(void) __naked
             ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
             ld b, #0                                ; setup count
             ld c, #IDE_REG_DATA                     ; setup port number
+#ifdef SWAPDEV
+           cp #2
+            jr nz, not_swapin
+            ld a, (_blk_op+BLKPARAM_SWAP_PAGE)     ; blkparam.swap_page
+            call map_for_swap
+            jr swapin
+not_swapin:
+#endif
             or a                                    ; test is_user
             call nz, map_process_always             ; map user memory first if required
+swapin:
             inir                                    ; transfer first 256 bytes
             inir                                    ; transfer second 256 bytes
             or a                                    ; test is_user
@@ -149,8 +158,17 @@ static void devide_write_data(void) __naked
             ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
             ld b, #0                                ; setup count
             ld c, #IDE_REG_DATA                     ; setup port number
+#ifdef SWAPDEV
+           cp #2
+            jr nz, not_swapout
+            ld a, (_blk_op+BLKPARAM_SWAP_PAGE)     ; blkparam.swap_page
+            call map_for_swap
+            jr swapout
+not_swapout:
+#endif
             or a                                    ; test is_user
             call nz, map_process_always             ; else map user memory first if required
+swapout:
             otir                                    ; transfer first 256 bytes
             otir                                    ; transfer second 256 bytes
             or a                                    ; test is_user
index 4dede83..06e9c32 100644 (file)
@@ -74,4 +74,5 @@
 #define SWAP_SIZE 0x40
 #define MAX_SWAPS 3            /* For now */
 
-#define swap_map(x)            ((uint8_t *)(x))
+/* All our pages get mapped into the top 16K bank for swapping use */
+#define swap_map(x)            ((uint8_t *)(x|0xC000))
index 19f5030..47a5156 100644 (file)
@@ -19,6 +19,7 @@
         .globl map_restore
        .globl map_process_save
        .globl map_kernel_restore
+       .globl map_for_swap
        .globl current_map
        .globl switch_bank
 
@@ -181,8 +182,18 @@ setallvectors:
        ld a, #7
        jp setvectors
 
+
+       ; Swap helper. Map the page in A into the address space such
+       ; that swap_map() gave the correct pointer to use. Undone by
+       ; a map_kernel_{restore}
+map_for_swap:
         ; bank switching procedure. On entrance:
         ;  A - bank number to set
+       push af
+       ld a, (current_map)
+       ld (ksave_map), a
+       pop af
+       ; Then fall through to set the bank up
 
 switch_bank:
        ; Write the store first, that way any interrupt will restore
@@ -196,11 +207,6 @@ switch_bank:
         ret
 
 
-;
-;      These are incomplete - or at least someone somewhere has to do the
-;      exchange hackery as we've only got a 16K window so can't flip 0x8000
-;      directly.
-;
 map_process:
         ld a, h
         or l
@@ -211,12 +217,11 @@ map_process:
        pop af
        ret
 
+;
+;      We always save here so that existing code works until we have a
+;      clear usage of save/restore forms across the kernel
+;
 map_process_save:
-       push af
-       ld a, (current_map)
-       ld (ksave_map), a
-       pop af
-
 map_process_always:
        push af
        ld a, (current_map)