From: Alan Cox Date: Thu, 21 May 2015 08:33:30 +0000 (+0100) Subject: swap: introduce swapping onto IDE, add the needed ZX128 bits X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=cbd005bac9bda66a4e1ee0288ee430466260c2d8;p=FUZIX.git swap: introduce swapping onto IDE, add the needed ZX128 bits 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. --- diff --git a/Kernel/dev/blkdev.c b/Kernel/dev/blkdev.c index 1475736a..603e9c5c 100644 --- a/Kernel/dev/blkdev.c +++ b/Kernel/dev/blkdev.c @@ -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; } diff --git a/Kernel/dev/blkdev.h b/Kernel/dev/blkdev.h index c1b5f326..ef00875b 100644 --- a/Kernel/dev/blkdev.h +++ b/Kernel/dev/blkdev.h @@ -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; diff --git a/Kernel/dev/devide.c b/Kernel/dev/devide.c index d2ce6cf8..0d7bd40c 100644 --- a/Kernel/dev/devide.c +++ b/Kernel/dev/devide.c @@ -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 diff --git a/Kernel/platform-zx128/config.h b/Kernel/platform-zx128/config.h index 4dede83d..06e9c320 100644 --- a/Kernel/platform-zx128/config.h +++ b/Kernel/platform-zx128/config.h @@ -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)) diff --git a/Kernel/platform-zx128/zx128.s b/Kernel/platform-zx128/zx128.s index 19f50303..47a51564 100644 --- a/Kernel/platform-zx128/zx128.s +++ b/Kernel/platform-zx128/zx128.s @@ -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)