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)
#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
#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
//#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 */
+++ /dev/null
-/* Zeta SBC V2 RAM disk driver
- *
- * Implements a single RAM disk DEV_RD_PAGES size and
- * starting from DEV_RD_START page
- *
- * */
-
-#include <kernel.h>
-#include <kdata.h>
-#include <printf.h>
-
-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;
- }
-}
+++ /dev/null
-#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__ */
+++ /dev/null
- .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
-;=========================================================================
--- /dev/null
+/* Zeta SBC V2 memory driver
+ *
+ * 2017-01-03 William R Sowerbutts, based on RAM disk code by Sergey Kiselev
+ */
+
+#include <kernel.h>
+#include <kdata.h>
+#include <printf.h>
+#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;
+}
--- /dev/null
+ .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
+;=========================================================================
#include <devtty.h>
#include <ds1302.h>
#include "config.h"
+#include "devrd.h"
+
+/* Everything in here is discarded after init starts */
#ifdef CONFIG_PPIDE
#include <devide.h>
-
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;
* 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 */
{
}
-
void device_init(void)
{
ds1302_init();
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
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
; imported symbols
.globl _ramsize
.globl _procmem
+ .globl _init_hardware_c
.globl outhl
.globl outnewline
.globl interrupt_handler
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
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