From 4c1b174510f7f7c715d43cd1d6bc62c50285353c Mon Sep 17 00:00:00 2001 From: Will Sowerbutts Date: Sun, 8 Jan 2017 23:00:43 +0000 Subject: [PATCH] Kernel: zeta-v2: Implement /dev/rd and new /dev/mem This implements the new /dev/mem and /dev/rd drivers for the zeta-v2 platform. --- Kernel/platform-zeta-v2/Makefile | 8 +- Kernel/platform-zeta-v2/config.h | 18 ++- Kernel/platform-zeta-v2/devrd.c | 119 ------------------- Kernel/platform-zeta-v2/devrd.h | 10 -- Kernel/platform-zeta-v2/devrd_hw.s | 57 --------- Kernel/platform-zeta-v2/devrd_zeta2.c | 47 ++++++++ Kernel/platform-zeta-v2/devrd_zeta2_hw.s | 141 +++++++++++++++++++++++ Kernel/platform-zeta-v2/discard.c | 13 ++- Kernel/platform-zeta-v2/fuzix.lnk | 2 + Kernel/platform-zeta-v2/kernel.def | 2 - Kernel/platform-zeta-v2/zeta-v2.s | 9 +- 11 files changed, 218 insertions(+), 208 deletions(-) delete mode 100644 Kernel/platform-zeta-v2/devrd.c delete mode 100644 Kernel/platform-zeta-v2/devrd.h delete mode 100644 Kernel/platform-zeta-v2/devrd_hw.s create mode 100644 Kernel/platform-zeta-v2/devrd_zeta2.c create mode 100644 Kernel/platform-zeta-v2/devrd_zeta2_hw.s diff --git a/Kernel/platform-zeta-v2/Makefile b/Kernel/platform-zeta-v2/Makefile index 9d87e961..20526e10 100644 --- a/Kernel/platform-zeta-v2/Makefile +++ b/Kernel/platform-zeta-v2/Makefile @@ -1,11 +1,11 @@ ASRCS = crt0.s tricks.s commonmem.s zeta-v2.s monitor.s -ASRCS += ds1302-n8vem.s devrd_hw.s -CSRCS = devices.c main.c devtty.c devrd.c ppide.c +ASRCS += ds1302-n8vem.s devrd_zeta2_hw.s +CSRCS = devices.c main.c devtty.c devrd_zeta2.c ppide.c DISCARD_CSRCS = discard.c devtty_discard.c DISCARD_DSRCS = ../dev/ds1302_discard.c ../dev/devide_discard.c DSRCS = ../dev/devfd.c ../dev/devsd.c ../dev/mbr.c ../dev/blkdev.c -DSRCS += ../dev/ds1302.c ../dev/devide.c -DASRCS = ../dev/devfd_hw.s +DSRCS += ../dev/ds1302.c ../dev/devide.c ../dev/devrd.c +DASRCS = ../dev/devfd_hw.s ../dev/devrd_hw.s AOBJS = $(ASRCS:.s=.rel) COBJS = $(CSRCS:.c=.rel) diff --git a/Kernel/platform-zeta-v2/config.h b/Kernel/platform-zeta-v2/config.h index df016d75..0e7cbebe 100644 --- a/Kernel/platform-zeta-v2/config.h +++ b/Kernel/platform-zeta-v2/config.h @@ -14,8 +14,8 @@ #define CONFIG_BANK16 /* Permit large I/O requests to bypass cache and go direct to userspace */ #define CONFIG_LARGE_IO_DIRECT -/* 32 x 16K pages, 3 pages for kernel, 16 pages for RAM disk */ -#define MAX_MAPS 13 +/* 32 x 16K pages, 3 pages for kernel, whatever the RAM disk uses */ +#define MAX_MAPS (32 - 3 - DEV_RD_RAM_PAGES) /* Banks as reported to user space */ #define CONFIG_BANKS 4 @@ -41,7 +41,7 @@ #define NBUFS 10 /* Number of block buffers */ #define NMOUNTS 4 /* Number of mounts at a time */ -#define MAX_BLKDEV 4 /* 1 ROM disk, 1 RAM disk, 1 floppy, 1 SD card */ +#define MAX_BLKDEV 4 /* 1 ROM disk, 1 RAM disk, 1 floppy, 1 PPIDE */ /* On-board DS1302, we can read the time of day from it */ #define CONFIG_RTC @@ -57,10 +57,16 @@ //#define CONFIG_PPP /* #define CONFIG_PPP to enable as tty3 */ /* Device parameters */ +#define CONFIG_DEV_MEM /* enable /dev/mem driver */ + #define CONFIG_RAMDISK /* enable memory-backed disk driver */ -#define NUM_DEV_RD 1 -#define DEV_RD_PAGES 16 /* size of the RAM disk in pages */ -#define DEV_RD_START 48 /* first page used by the RAM disk */ +#define DEV_RD_ROM_PAGES 28 /* size of the ROM disk in 16KB pages (max 32, any unused pages are at the start of the ROM) */ +#define DEV_RD_RAM_PAGES 0 /* size of the RAM disk in 16KB pages */ + +#define DEV_RD_ROM_START ((uint32_t)(32-DEV_RD_ROM_PAGES) << 14) /* first byte used by the ROM disk */ +#define DEV_RD_RAM_START ((uint32_t)(64-DEV_RD_RAM_PAGES) << 14) /* first byte used by the RAM disk */ +#define DEV_RD_ROM_SIZE ((uint32_t)DEV_RD_ROM_PAGES << 14) /* size of the ROM disk */ +#define DEV_RD_RAM_SIZE ((uint32_t)DEV_RD_RAM_PAGES << 14) /* size of the RAM disk */ #ifdef CONFIG_PPP /* SD card in ParPortProp */ diff --git a/Kernel/platform-zeta-v2/devrd.c b/Kernel/platform-zeta-v2/devrd.c deleted file mode 100644 index d6a76e5b..00000000 --- a/Kernel/platform-zeta-v2/devrd.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Zeta SBC V2 RAM disk driver - * - * Implements a single RAM disk DEV_RD_PAGES size and - * starting from DEV_RD_START page - * - * */ - -#include -#include -#include - -extern uint8_t src_page; /* source page number */ -extern uint8_t dst_page; /* destination page number */ -extern uint16_t src_offset; /* offset of the data in the source page */ -extern uint16_t dst_offset; /* offset of the data in the destination page */ -extern uint16_t cpy_count; /* data transfer length */ -extern uint8_t kernel_pages[]; /* kernel's page table */ - -int ramdisk_transfer(bool is_read, uint8_t minor, uint8_t rawflag); -int page_copy(void); /* assembler code */ - -int rd_read(uint8_t minor, uint8_t rawflag, uint8_t flag) -{ - flag; - return ramdisk_transfer(true, minor, rawflag); -} - -int rd_write(uint8_t minor, uint8_t rawflag, uint8_t flag) -{ - flag; - return ramdisk_transfer(false, minor, rawflag); -} - -int ramdisk_transfer(bool is_read, uint8_t minor, uint8_t rawflag) -{ - blkno_t block; - int block_xfer; /* r/w return value (number of 512 byte blocks transferred) */ - uint32_t rd_addr; - uint16_t buffer_addr; - usize_t xfer_count; - - if (minor >= NUM_DEV_RD) { - udata.u_error = ENXIO; - return -1; - } - - if (rawflag) { /* rawflag == 1, read to or write from user space */ - xfer_count = udata.u_count; - buffer_addr = (uint16_t) udata.u_base; - block = udata.u_offset >> 9; - block_xfer = xfer_count >> 9; - } else { /* rawflag == 0, read to or write from kernel space */ - xfer_count = 512; - buffer_addr = (uint16_t) udata.u_buf->bf_data; - block = udata.u_buf->bf_blk; - block_xfer = 1; - } - - if (block > (DEV_RD_PAGES * 16 * 2)) { /* block beyond RAM disk end? */ - udata.u_error = EIO; - return -1; - } - - /* calculate physical address of the RAM drive data */ - /* rd_addr = block * 512 + DEV_RD_START * 16K; */ - rd_addr = ((unsigned long) block << 9) + DEV_RD_START * 16384UL; - while (xfer_count > 0) { - if (is_read) { - /* RAM disk page number = rd_addr / 16K */ - src_page = rd_addr >> 14; - /* offset within RAM disk page */ - src_offset = rd_addr & 0x3FFF; - /* destination page number */ - if (rawflag) - dst_page = ((uint8_t *) &udata.u_page)[buffer_addr >> 14]; - else - dst_page = kernel_pages[buffer_addr >> 14]; - /* offset in the destination page */ - dst_offset = buffer_addr & 0x3FFF; - } else { - /* source page number */ - if (rawflag) - src_page = ((uint8_t *) &udata.u_page)[buffer_addr >> 14]; - else - src_page = kernel_pages[buffer_addr >> 14]; - /* offset in the source page */ - src_offset = buffer_addr & 0x3FFF; - /* RAM disk page number = rd_addr / 16K */ - dst_page = rd_addr >> 14; - /* offset within RAM disk page */ - dst_offset = rd_addr & 0x3FFF; - } - cpy_count = xfer_count; - if (cpy_count > 16384 - src_offset) - cpy_count = 16384 - src_offset; - if (cpy_count > 16384 - dst_offset) - cpy_count = 16384 - dst_offset; -#ifdef DEBUG - kprintf("page_cpy(src_page=%x, src_offset=%x, dst_page=%x, dst_offset=%x, cpy_count=%x)\n", src_page, src_offset, dst_page, dst_offset, cpy_count); -#endif - page_copy(); - xfer_count -= cpy_count; - buffer_addr += cpy_count; - rd_addr += cpy_count; - } - - return block_xfer; -} - - -int rd_open(uint8_t minor) -{ - if(minor < NUM_DEV_RD){ - return 0; - } else { - udata.u_error = EIO; - return -1; - } -} diff --git a/Kernel/platform-zeta-v2/devrd.h b/Kernel/platform-zeta-v2/devrd.h deleted file mode 100644 index e54a1546..00000000 --- a/Kernel/platform-zeta-v2/devrd.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __DEVRD_DOT_H__ -#define __DEVRD_DOT_H__ - -/* public interface */ -int rd_read(uint8_t minor, uint8_t rawflag, uint8_t flag); -int rd_write(uint8_t minor, uint8_t rawflag, uint8_t flag); -int rd_init(void); -int rd_open(uint8_t minor, uint16_t flag); - -#endif /* __DEVRD_DOT_H__ */ diff --git a/Kernel/platform-zeta-v2/devrd_hw.s b/Kernel/platform-zeta-v2/devrd_hw.s deleted file mode 100644 index 750ce9e1..00000000 --- a/Kernel/platform-zeta-v2/devrd_hw.s +++ /dev/null @@ -1,57 +0,0 @@ - .module devrd_hw - - ; imported symbols - from zeta-v2.s - .globl map_kernel,mpgsel_cache - - ; exported symbols (used by devrd.c) - .globl _page_copy - .globl _src_page, _src_offset, _dst_page, _dst_offset, _cpy_count - - .include "kernel.def" - - .area _COMMONMEM - -;========================================================================= -; _page_copy - Copy data from one physical page to another -; Inputs: -; _src_page - page number of the source page (uint8_t) -; _src_offset - offset in the source page (uint16_t) -; _dst_page - page number of the destination page (uint8_t) -; _dst_offset - offset in the destination page (uint16_t) -; _cpy_count - number of bytes to copy (uint16_t) -; Outputs: -; Data copied -; Destroys AF, BC, DE, HL -;========================================================================= -_page_copy: - ld a,(_src_page) - ld (mpgsel_cache+1),a ; save the mapping - out (MPGSEL_1),a ; map source page to bank #1 - ld a,(_dst_page) - ld (mpgsel_cache+2),a ; save the mapping - out (MPGSEL_2),a ; map destination page to bank #2 - ld hl,(_src_offset) ; load offset in source page - ld a,#0x40 ; add bank #1 offset - 0x4000 - add h ; to the source offset - ld h,a - ld de,(_dst_offset) - ld a,#0x80 ; add bank #2 offset - 0x8000 - add d ; to the destination offset - ld d,a - ld bc,(_cpy_count) ; bytes to copy - ldir ; do the copy - call map_kernel ; map the kernel - ret - -; variables -_src_page: - .db 0 -_dst_page: - .db 0 -_src_offset: - .dw 0 -_dst_offset: - .dw 0 -_cpy_count: - .dw 0 -;========================================================================= diff --git a/Kernel/platform-zeta-v2/devrd_zeta2.c b/Kernel/platform-zeta-v2/devrd_zeta2.c new file mode 100644 index 00000000..2dd5e9e4 --- /dev/null +++ b/Kernel/platform-zeta-v2/devrd_zeta2.c @@ -0,0 +1,47 @@ +/* Zeta SBC V2 memory driver + * + * 2017-01-03 William R Sowerbutts, based on RAM disk code by Sergey Kiselev + */ + +#include +#include +#include +#define DEVRD_PRIVATE +#include "devrd.h" + +void rd_page_copy(void); // devrd_zeta2_hw.s + +void rd_platform_copy(void) +{ + uint16_t ocount, count, maxcpy; + + ocount = count = rd_cpy_count; + + while(true){ + /* ensure transfer will not span a 16KB bank boundary */ + if(count > 1){ + maxcpy = ((uint16_t)rd_src_address) & 0x3FFF; + if((rd_dst_address & 0x3FFF) > maxcpy) + maxcpy = rd_dst_address & 0x3FFF; + maxcpy = 0x4000 - maxcpy; + if(rd_cpy_count > maxcpy) + rd_cpy_count = maxcpy; + } +#ifdef DEBUG + kprintf("rd_transfer: src=0x%lx, dst=0x%x(%s) reverse=%d count=%d\n", + rd_src_address, rd_dst_address, rd_dst_userspace?"user":"kern", + rd_reverse, rd_cpy_count); +#endif + rd_page_copy(); + + count -= rd_cpy_count; + if(!count) + break; + + rd_dst_address += rd_cpy_count; + rd_src_address += rd_cpy_count; + rd_cpy_count = count; + } + + rd_cpy_count = ocount; +} diff --git a/Kernel/platform-zeta-v2/devrd_zeta2_hw.s b/Kernel/platform-zeta-v2/devrd_zeta2_hw.s new file mode 100644 index 00000000..05b2f861 --- /dev/null +++ b/Kernel/platform-zeta-v2/devrd_zeta2_hw.s @@ -0,0 +1,141 @@ + .module devrd_hw + + ; imported symbols + .globl map_kernel, mpgsel_cache, _kernel_pages + .globl _rd_platform_copy + + ; exported symbols + .globl _rd_page_copy + .globl _rd_cpy_count + .globl _rd_reverse + .globl _rd_dst_userspace + .globl _rd_dst_address + .globl _rd_src_address + .globl _devmem_read + .globl _devmem_write + + .include "../kernel.def" + .include "kernel.def" + + .area _CODE +_devmem_write: + ld a, #1 + ld (_rd_reverse), a ; 1 = write + jr _devmem_go + +_devmem_read: + xor a + ld (_rd_reverse), a ; 0 = read + inc a +_devmem_go: + ld (_rd_dst_userspace), a ; 1 = userspace + ; load the other parameters + ld hl, (U_DATA__U_BASE) + ld (_rd_dst_address), hl + ld hl, (U_DATA__U_OFFSET) + ld (_rd_src_address), hl + ld hl, (U_DATA__U_OFFSET+2) + ld (_rd_src_address+2), hl + ld hl, (U_DATA__U_COUNT) + ld (_rd_cpy_count), hl + ; for single byte transfers we can optimise away the outer loop + dec l ; test for HL=1 + ld a, h + or l + jp nz, _rd_platform_copy ; > 1 byte, do it the hard way + call _rd_page_copy ; transfer single byte + ld hl, #1 ; return with HL set appropriately + ret + + .area _COMMONMEM +;========================================================================= +; _rd_page_copy - Copy data from one physical page to another +; See notes in devrd.h for input parameters +;========================================================================= +_rd_page_copy: + ; split rd_src_address into page and offset -- it's limited to 20 bits (max 0xFFFFF) + ; example address 0x000ABCDE + ; in memory it is stored: DE BC 0A 00 + ; offset would be 0x0ABCDE & 0x3FFF = 0x3CDE + ; page would be 0x0ABCDE >> 14 = 0x2A + + ; compute source page number + ld a,(_rd_src_address+1) ; load 0xBC -> B + ld b, a + ld a,(_rd_src_address+2) ; load 0x0A -> A + rl b ; grab the top bit into carry + rla ; shift accumulator left, load carry bit at the bottom + rl b ; and again + rla ; now A is the page number (0x2A) + + ; map source page + ld (mpgsel_cache+1),a ; save the mapping + out (MPGSEL_1),a ; map source page to bank #1 + + ; compute source page offset, store in DE + ld a,(_rd_src_address+1) + and #0x3F ; mask to 16KB + or #0x40 ; add offset for bank 1 + ld d, a + ld a,(_rd_src_address+0) + ld e, a ; now offset is in DE + + ; compute destination page index (addr 0xABCD >> 14 = 0x02) + ld a,(_rd_dst_address+1) ; load top 8 bits + and #0xc0 ; mask off top 2 bits + rlca ; rotate into lower 2 bits + rlca + ld b, #0 + ld c, a ; store in l + + ; look up page number + ld a,(_rd_dst_userspace) ; are we loading into userspace memory? + or a + jr nz, rd_translate_userspace + ld hl, #_kernel_pages ; get kernel page table + jr rd_do_translate +rd_translate_userspace: + ld hl, #U_DATA__U_PAGE ; get user process page table +rd_do_translate: + add hl, bc ; add index to base ptr (uint8_t *) + ld a, (hl) ; load the page number from the page table + + ; map destination page + ld (mpgsel_cache+2),a ; save the mapping + out (MPGSEL_2),a ; map destination page to bank #2 + + ; compute destination page offset, store in HL + ld a,(_rd_dst_address+1) + and #0x3F ; mask to 16KB + or #0x80 ; add offset for bank #2 + ld h, a + ld a, (_rd_dst_address+0) + ld l, a ; now offset is in HL + + ; load byte count + ld bc,(_rd_cpy_count) ; bytes to copy + + ; check if reversed + ld a, (_rd_reverse) + or a + jr nz, go + ex de,hl ; reverse if necessary +go: + ldir ; do the copy + jp map_kernel ; map back the kernel + +; variables +_rd_cpy_count: + .dw 0 ; uint16_t +_rd_reverse: + .db 0 ; bool +_rd_dst_userspace: + .db 0 ; bool +_rd_dst_address: + .dw 0 ; uint16_t +_rd_src_address: + .db 0 ; uint32_t + .db 0 + .db 0 + .db 0 +;========================================================================= diff --git a/Kernel/platform-zeta-v2/discard.c b/Kernel/platform-zeta-v2/discard.c index 4081d80b..ce78eff8 100644 --- a/Kernel/platform-zeta-v2/discard.c +++ b/Kernel/platform-zeta-v2/discard.c @@ -4,13 +4,21 @@ #include #include #include "config.h" +#include "devrd.h" + +/* Everything in here is discarded after init starts */ #ifdef CONFIG_PPIDE #include - void ppide_init(void); #endif +void init_hardware_c(void) +{ + ramsize = 512; + procmem = 512 - 64 - (DEV_RD_RAM_PAGES<<4); +} + void pagemap_init(void) { int i; @@ -21,7 +29,7 @@ void pagemap_init(void) * Page 35 is the common area * Pages starting from DEV_RD_START are used by RAM disk */ - for (i = 32 + 4; i < DEV_RD_START; i++) + for (i = 32 + 4; i < (DEV_RD_RAM_START >> 14); i++) pagemap_add(i); /* finally add the common area */ @@ -32,7 +40,6 @@ void map_init(void) { } - void device_init(void) { ds1302_init(); diff --git a/Kernel/platform-zeta-v2/fuzix.lnk b/Kernel/platform-zeta-v2/fuzix.lnk index 07628427..02a96899 100644 --- a/Kernel/platform-zeta-v2/fuzix.lnk +++ b/Kernel/platform-zeta-v2/fuzix.lnk @@ -18,6 +18,8 @@ platform-zeta-v2/devfd.rel platform-zeta-v2/devfd_hw.rel platform-zeta-v2/devrd.rel platform-zeta-v2/devrd_hw.rel +platform-zeta-v2/devrd_zeta2.rel +platform-zeta-v2/devrd_zeta2_hw.rel platform-zeta-v2/devices.rel devio.rel filesys.rel diff --git a/Kernel/platform-zeta-v2/kernel.def b/Kernel/platform-zeta-v2/kernel.def index ae762f1b..c1ac107f 100644 --- a/Kernel/platform-zeta-v2/kernel.def +++ b/Kernel/platform-zeta-v2/kernel.def @@ -3,8 +3,6 @@ U_DATA .equ 0xF000 ; (this is struct u_data from kernel.h) U_DATA__TOTALSIZE .equ 0x300 ; 256+256+256 bytes. Z80_TYPE .equ 0 ; just an old good Z80 -;RAM_KB .equ 512 -RAM_KB .equ 256 USE_FANCY_MONITOR .equ 1 ; disabling this saves around approx 0.5KB PROGBASE .equ 0x0000 diff --git a/Kernel/platform-zeta-v2/zeta-v2.s b/Kernel/platform-zeta-v2/zeta-v2.s index 6fdce980..03ba17f6 100644 --- a/Kernel/platform-zeta-v2/zeta-v2.s +++ b/Kernel/platform-zeta-v2/zeta-v2.s @@ -21,6 +21,7 @@ ; imported symbols .globl _ramsize .globl _procmem + .globl _init_hardware_c .globl outhl .globl outnewline .globl interrupt_handler @@ -130,11 +131,6 @@ foundpage: ret init_hardware: - ld hl, #RAM_KB ; set system RAM size - ld (_ramsize), hl - ld hl,#(RAM_KB-64) ; 64K for kernel - ld (_procmem), hl - ; program vectors for the kernel ld hl, #0 push hl @@ -186,8 +182,7 @@ init_partial_uart: ld a,h ; get bits 15-8 of int. vectors table ld i,a ; load to I register im 2 ; set Z80 CPU interrupt mode 2 - - ret + jp _init_hardware_c ; pass control to C, which returns for us ;========================================================================= ; Kernel code -- 2.34.1