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 */
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;
}
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 */
};
/* 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;
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
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
#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))
.globl map_restore
.globl map_process_save
.globl map_kernel_restore
+ .globl map_for_swap
.globl current_map
.globl switch_bank
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
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
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)