From: Will Sowerbutts Date: Sat, 27 Dec 2014 02:38:45 +0000 (+0000) Subject: Kernel: Add N8VEM Mark 4 and DX-Designs P112 platforms X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=17e1ccfd04102f5b4817ca67831fe50da74ae494;p=FUZIX.git Kernel: Add N8VEM Mark 4 and DX-Designs P112 platforms --- diff --git a/Kernel/dev/devide.c b/Kernel/dev/devide.c new file mode 100644 index 00000000..7dac82d7 --- /dev/null +++ b/Kernel/dev/devide.c @@ -0,0 +1,373 @@ +/*-----------------------------------------------------------------------*/ +/* IDE interface driver */ +/* 2014-11-02 Will Sowerbutts (unreleased UZI-mark4) */ +/* 2014-12-22 WRS ported to Fuzix */ +/* 2014-12-25 WRS updated to also support P112 GIDE */ +/*-----------------------------------------------------------------------*/ + +/* Minor numbers + + The kernel identifies our storage devices with an 8-bit minor number. + + The top two bits of the minor identify the drive, allowing a maximum of four + drives, the current hardware supports only two but future controllers may + support more. + + The bottom six bits of the minor identify the slice number. Slice 0 + addresses "the whole drive", with no translation. Due to limitations within + the kernel only the first 32MB can currently be accessed through slice 0. + + Slice 0 is intended to be used primarily for writing a partition table to + the drive, although it can also be used to store a single Fuzix filesystem + on an unpartitioned disk. + + Slices 1+ are stored in a partition on the drive. The partition is stored in + a PC-style MBR partition table and must be a primary partition of type 0x5A. + Only the first suitable partition is found. Multiple filesystems are stored + in this partition by dividing it into 32MB slices. + + To create the required device nodes, use: + + mknod /dev/hda 60660 0 + mknod /dev/hdb 60660 64 + mknod /dev/hdc 60660 128 + mknod /dev/hdd 60660 192 + + mknod /dev/hda1 60660 1 + mknod /dev/hda2 60660 2 + mknod /dev/hda3 60660 3 + ... + mknod /dev/hda63 60660 63 + + mknod /dev/hdb1 60660 65 + mknod /dev/hdb2 60660 66 + mknod /dev/hdb3 60660 67 + ... + mknod /dev/hdb63 60660 127 + + mknod /dev/hdc1 60660 129 + mknod /dev/hdc2 60660 130 + mknod /dev/hdc3 60660 131 + ... + mknod /dev/hdc63 60660 191 + + mknod /dev/hdd1 60660 193 + mknod /dev/hdd2 60660 194 + mknod /dev/hdd3 60660 195 + ... + mknod /dev/hdd63 60660 255 +*/ + +#include +#include +#include +#include +#include +#include "devide.h" + +typedef struct { + unsigned char status; + unsigned char chs_first[3]; + unsigned char type; + unsigned char chs_last[3]; + unsigned long lba_first; + unsigned long lba_count; +} partition_table_entry_t; + +#define MBR_ENTRY_COUNT 4 +typedef struct { + unsigned char bootcode[446]; + partition_table_entry_t partition[MBR_ENTRY_COUNT]; + unsigned int signature; +} master_boot_record_t; + +#define DRIVE_COUNT 2 +static unsigned char ide_drives_present; /* bitmap */ +static unsigned long ide_partition_start[DRIVE_COUNT]; +static unsigned int ide_slice_count[DRIVE_COUNT]; + +__sfr __at IDE_REG_ALTSTATUS ide_reg_altstatus; +__sfr __at IDE_REG_COMMAND ide_reg_command; +__sfr __at IDE_REG_CONTROL ide_reg_control; +__sfr __at IDE_REG_DATA ide_reg_data; +__sfr __at IDE_REG_DEVHEAD ide_reg_devhead; +__sfr __at IDE_REG_ERROR ide_reg_error; +__sfr __at IDE_REG_FEATURES ide_reg_features; +__sfr __at IDE_REG_LBA_0 ide_reg_lba_0; +__sfr __at IDE_REG_LBA_1 ide_reg_lba_1; +__sfr __at IDE_REG_LBA_2 ide_reg_lba_2; +__sfr __at IDE_REG_LBA_3 ide_reg_lba_3; +__sfr __at IDE_REG_SEC_COUNT ide_reg_sec_count; +__sfr __at IDE_REG_STATUS ide_reg_status; + +static void devide_read_data(void *buffer, unsigned char ioport) __naked +{ + buffer; ioport; /* silence compiler warning */ + __asm + pop de ; return address + pop hl ; buffer address + pop bc ; IO port number (in c) + push bc ; restore stack + push hl + push de + + ld b, #0 ; setup count + inir ; first 256 bytes + inir ; second 256 bytes + ret + __endasm; +} + +static void devide_write_data(void *buffer, unsigned char ioport) __naked +{ + buffer; ioport; /* silence compiler warning */ + __asm + pop de ; return address + pop hl ; buffer address + pop bc ; IO port number (in c) + push bc ; restore stack + push hl + push de + + ld b, #0 ; setup count + otir ; first 256 bytes + otir ; second 256 bytes + ret + __endasm; +} + +static void devide_delay(void) +{ + timer_t timeout; + + timeout = set_timer_ms(25); + + while(!timer_expired(timeout)) + platform_idle(); +} + +static bool devide_wait(unsigned char bits) +{ + unsigned char status; + timer_t timeout; + + timeout = set_timer_ms(500); + + while(true){ + status = ide_reg_status; + + if((status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR | bits)) == bits) + return true; + + if((status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) == IDE_STATUS_ERROR){ + kprintf("ide error, status=%x\n", status); + return false; + } + + if(timer_expired(timeout)){ + kprintf("ide timeout, status=%x\n", status); + return false; + } + }; +} + +static bool devide_read_sector(unsigned char *buffer) +{ + if(!devide_wait(IDE_STATUS_DATAREQUEST)) + return false; + + devide_read_data(buffer, IDE_REG_DATA); + + return true; +} + +static bool devide_write_sector(unsigned char *buffer) +{ + if(!devide_wait(IDE_STATUS_DATAREQUEST)) + return false; + + devide_write_data(buffer, IDE_REG_DATA); + + if(!devide_wait(IDE_STATUS_READY)) + return false; + + return true; +} + +static int devide_transfer(uint8_t minor, bool is_read, uint8_t rawflag) +{ + unsigned char *target, *p; + unsigned long lba; + unsigned char drive; + + drive = minor >> 6; + minor = minor & 0x3F; + + if(rawflag == 0) { + target = udata.u_buf->bf_data; + lba = udata.u_buf->bf_blk; + }else + goto xferfail; + + /* minor 0 is the whole disk and requires no translation */ + if(minor > 0){ + /* minor 1+ are slices located within the partition */ + lba += (ide_partition_start[drive]); + lba += ((unsigned long)(minor-1) << 16); + } + +#if 0 + ide_reg_lba_3 = ((lba >> 24) & 0xF) | ((drive == 0) ? 0xE0 : 0xF0); // select drive, start loading LBA + ide_reg_lba_2 = (lba >> 16); + ide_reg_lba_1 = (lba >> 8); + ide_reg_lba_0 = lba; +#else + /* sdcc sadly unable to figure this out for itself yet */ + p = (unsigned char *)&lba; + ide_reg_lba_3 = (p[3] & 0x0F) | ((drive == 0) ? 0xE0 : 0xF0); // select drive, start loading LBA + ide_reg_lba_2 = p[2]; + ide_reg_lba_1 = p[1]; + ide_reg_lba_0 = p[0]; +#endif + ide_reg_sec_count = 1; + + if(is_read){ + ide_reg_command = IDE_CMD_READ_SECTOR; + if(!devide_read_sector(target)) + goto xferfail; + }else{ + ide_reg_command = IDE_CMD_WRITE_SECTOR; + if(!devide_write_sector(target)) + goto xferfail; + } + + return 1; +xferfail: + udata.u_error = EIO; + return -1; +} + +int devide_open(uint8_t minor, uint16_t flags) +{ + unsigned char drive; + flags; /* not used */ + + drive = minor >> 6; + minor = minor & 0x3F; + + if(ide_drives_present & (1 << drive) && (minor == 0 || minor < ide_slice_count[drive])) + return 0; + + udata.u_error = ENODEV; + return -1; +} + +int devide_read(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + flag; /* not used */ + return devide_transfer(minor, true, rawflag); +} + +int devide_write(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + flag; /* not used */ + return devide_transfer(minor, false, rawflag); +} + +void devide_init_drive(unsigned char drive) +{ + unsigned char *buffer, i, select; + master_boot_record_t *mbr; + + switch(drive){ + case 0: select = 0xE0; break; + case 1: select = 0xF0; break; + default: return; + } + + kprintf("hd%c: ", 'a' + drive); + ide_partition_start[drive] = 0; + ide_slice_count[drive] = 0; + + /* reset the drive */ + ide_reg_devhead = select; + ide_reg_control = 0x06; /* assert reset, no interrupts */ + devide_delay(); + ide_reg_control = 0x02; /* release reset, no interruptst */ + devide_delay(); + if(!devide_wait(IDE_STATUS_READY)) + return; + +#ifdef IDE_8BIT_ONLY + /* set 8-bit mode -- mostly only supported by CF cards */ + ide_reg_devhead = select; + if(!devide_wait(IDE_STATUS_READY)) + return; + ide_reg_features = 0x01; + ide_reg_command = IDE_CMD_SET_FEATURES; +#endif + + /* confirm drive has LBA support */ + if(!devide_wait(IDE_STATUS_READY)) + return; + ide_reg_command = IDE_CMD_IDENTIFY; + + /* allocate temporary sector buffer memory */ + buffer = (unsigned char *)tmpbuf(); + + if(!devide_read_sector(buffer)) + goto failout; + + if(!(buffer[99] & 0x02)){ + kputs("LBA unsupported.\n"); + goto failout; + } + + /* read first sector (looking for the partition table) */ + if(!devide_wait(IDE_STATUS_READY)) + goto failout; + + ide_reg_devhead = select; + ide_reg_lba_2 = 0; + ide_reg_lba_1 = 0; + ide_reg_lba_0 = 0; + ide_reg_sec_count = 1; + ide_reg_command = IDE_CMD_READ_SECTOR; + + if(!devide_read_sector(buffer)) + goto failout; + + /* if we get this far the drive is apparently present and functioning */ + ide_drives_present |= (1 << drive); + + /* check for MBR table signature */ + mbr = (master_boot_record_t*)buffer; + if(mbr->signature != 0xaa55){ + kputs("no partition table\n"); + goto failout; + } + + /* look for a fuzix partition (type 0x5A) */ + for(i=0; ipartition[i].type == 0x5A){ + ide_partition_start[drive] = mbr->partition[i].lba_first; + ide_slice_count[drive] = mbr->partition[i].lba_count >> 16; + break; + } + } + + kprintf("%d slices\n", ide_slice_count[drive]); + +failout: + brelse((bufptr)buffer); +} + +void devide_init(void) +{ + unsigned char d; + + ide_drives_present = 0; + + for(d=0; d + +Assumes an N8VEM Mark IV SBC fitted with 512KB RAM, with the RS232 port as +tty1, and the RS422 port as tty2. Does not yet support any ECB peripheral +boards. + +To build, edit ../Makefile to read: + +export TARGET= n8vem-mark4 +export CPU = z180 diff --git a/Kernel/platform-n8vem-mark4/commonmem.s b/Kernel/platform-n8vem-mark4/commonmem.s new file mode 100644 index 00000000..522503a8 --- /dev/null +++ b/Kernel/platform-n8vem-mark4/commonmem.s @@ -0,0 +1,9 @@ +; +; Common on z80pack is at 0xF000 as defined by hardware. +; + + .module commonmem + + .area _COMMONMEM + + .include "../cpu-z80/std-commonmem.s" diff --git a/Kernel/platform-n8vem-mark4/config.h b/Kernel/platform-n8vem-mark4/config.h new file mode 100644 index 00000000..e56ad57f --- /dev/null +++ b/Kernel/platform-n8vem-mark4/config.h @@ -0,0 +1,55 @@ +/* Enable to make ^Z dump the inode table for debug */ +#undef CONFIG_IDUMP +/* Enable to make ^A drop back into the monitor */ +#undef CONFIG_MONITOR +/* Profil syscall support (not yet complete) */ +#undef CONFIG_PROFIL +/* Multiple processes in memory at once */ +#define CONFIG_MULTI +/* Single tasking */ +#undef CONFIG_SINGLETASK +/* CP/M emulation */ +#undef CONFIG_CPM_EMU +/* Fixed banking */ +#define CONFIG_BANK_FIXED +/* 8 60K banks, 1 is kernel */ +#define MAX_MAPS 8 +#define MAP_SIZE 0xF000U + +/* Banks as reported to user space */ +#define CONFIG_BANKS 1 + +#define TICKSPERSEC 100U /* Ticks per second */ +#define PROGBASE 0x0000 /* also data base */ +#define PROGLOAD 0x0100 /* also data base */ +#define PROGTOP 0xF000 /* Top of program, base of U_DATA copy */ +#define PROC_SIZE 64 /* Memory needed per process */ + +/* WRS: this is probably wrong -- we want to swap the full 64K minus the common code */ +/* For now let's just use something and fix this up later when we have a swap device */ +#define SWAP_SIZE 0x7F /* 63.5K in blocks (which is the wrong number) */ +#define SWAPBASE 0x0000 /* start at the base of user mem */ +#define SWAPTOP 0xFF00 /* can we stop at the top? not sure how. let's stop short. */ +#define MAX_SWAPS 10 /* Well, that depends really, hmmmmmm. Pick a number, any number. */ + +#define BOOT_TTY (512 + 1)/* Set this to default device for stdio, stderr */ + /* In this case, the default is the first TTY device */ + +/* We need a tidier way to do this from the loader */ +#define CMDLINE (0x0081) /* Location of root dev name */ + +/* Device parameters */ +#define NUM_DEV_TTY 2 + +#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ +//#define SWAPDEV (256 + 1) /* Device for swapping. (z80pack drive J) */ +#define NBUFS 10 /* Number of block buffers */ +#define NMOUNTS 4 /* Number of mounts at a time */ + +/* Hardware parameters */ +#define Z180_IO_BASE 0x40 + +#define DEVICE_IDE /* enable if IDE interface present */ +#define IDE_REG_BASE 0x80 +#define IDE_8BIT_ONLY +#define IDE_REG_CS1_FIRST diff --git a/Kernel/platform-n8vem-mark4/cpmload.s b/Kernel/platform-n8vem-mark4/cpmload.s new file mode 100644 index 00000000..7d1dfa28 --- /dev/null +++ b/Kernel/platform-n8vem-mark4/cpmload.s @@ -0,0 +1,36 @@ +.module cpmload +.area _LOADER (ABS) + + ; CP/M will load us at 0x0100 + ; We want to relocate our payload (the kernel) and jump into it. + ; We put a small stub at the very bottom of memory, copy the kernel into + ; place above us, then jump into it. + + .org 0x100 + di + ; copy ourselves to the very bottom of memory -- 0x00 upwards + ld de, #0 + ld hl, #(doload) ; start of loader code + ld bc, #(endloader-doload) ; length of our loader + ldir ; copy copy copy! + ld hl, (load_address) + ld sp, hl ; stash copy of entry vector in SP for now + ex de, hl ; load_address to de + ld hl, #payload_start + ld bc, (load_length) + jp 0 ; jump and perform copy in low memory + + ; this code gets copied to .org 0 +doload: + ldir ; copy image into correct place + ld hl, #0 + add hl, sp ; recover entry vector + jp (hl) ; run image +endloader: ; end of code to copy + + ; the data is in a trailer, with a 6-byte header: +load_address: + .ds 2 +load_length: + .ds 2 +payload_start: diff --git a/Kernel/platform-n8vem-mark4/crt0.s b/Kernel/platform-n8vem-mark4/crt0.s new file mode 100644 index 00000000..98ac696f --- /dev/null +++ b/Kernel/platform-n8vem-mark4/crt0.s @@ -0,0 +1,72 @@ +; 2013-12-18 William R Sowerbutts + + .module crt0 + + ; Ordering of segments for the linker. + ; WRS: Note we list all our segments here, even though + ; we don't use them all, because their ordering is set + ; when they are first seen. + .area _CODE + .area _CODE2 + .area _CONST + .area _DATA + .area _INITIALIZED + .area _BSEG + .area _BSS + .area _HEAP + ; note that areas below here may be overwritten by the heap at runtime, so + ; put initialisation stuff in here + .area _INITIALIZER + .area _GSINIT + .area _GSFINAL + .area _DISCARD + .area _COMMONMEM + + ; imported symbols + .globl _fuzix_main + .globl init_early + .globl init_hardware + .globl s__INITIALIZER + .globl s__COMMONMEM + .globl l__COMMONMEM + .globl s__DISCARD + .globl l__DISCARD + .globl s__DATA + .globl l__DATA + .globl kstack_top + + ; startup code + .area _CODE +init: + di + ld sp, #kstack_top + + ; move the common memory where it belongs + ld hl, #s__INITIALIZER + ld de, #s__COMMONMEM + ld bc, #l__COMMONMEM + ldir + ; and the discard + ld de, #s__DISCARD + ld bc, #l__DISCARD + ldir + ; then zero the data area + ld hl, #s__DATA + ld de, #s__DATA + 1 + ld bc, #l__DATA - 1 + ld (hl), #0 + ldir + + ; Configure memory map + call init_early + + ; Hardware setup + call init_hardware + + ; Call the C main routine + call _fuzix_main + + ; fuzix_main() shouldn't return, but if it does... + di +stop: halt + jr stop diff --git a/Kernel/platform-n8vem-mark4/devices.c b/Kernel/platform-n8vem-mark4/devices.c new file mode 100644 index 00000000..2e861aa2 --- /dev/null +++ b/Kernel/platform-n8vem-mark4/devices.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include + +struct devsw dev_tab[] = /* The device driver switch table */ +{ +// minor open close read write ioctl +// ----------------------------------------------------------------- + /* 0: /dev/hd IDE-8 interface */ + { devide_open, no_close, devide_read, devide_write, no_ioctl }, + /* 1: /dev/sd SD interface */ + { no_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 2: /dev/tty serial ports */ + { tty_open, tty_close, tty_read, tty_write, tty_ioctl }, + /* 3: /dev/lpr Unused slot (pad to keep system devices at index 4) */ + { no_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 4: /dev/mem etc System devices (one offs) */ + { no_open, no_close, sys_read, sys_write, sys_ioctl }, + /* Pack to 7 with nxio if adding private devices and start at 8 */ +}; + +bool validdev(uint16_t dev) +{ + /* This is a bit uglier than needed but the right hand side is + a constant this way */ + if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) + 255) + return false; + else + return true; +} + +void device_init(void) +{ + devide_init(); +} diff --git a/Kernel/platform-n8vem-mark4/devtty.c b/Kernel/platform-n8vem-mark4/devtty.c new file mode 100644 index 00000000..ed2a2319 --- /dev/null +++ b/Kernel/platform-n8vem-mark4/devtty.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include "config.h" +#include + +char tbuf1[TTYSIZ]; +char tbuf2[TTYSIZ]; + +struct s_queue ttyinq[NUM_DEV_TTY+1] = { /* ttyinq[0] is never used */ + { NULL, NULL, NULL, 0, 0, 0 }, + { tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ/2 }, + { tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ/2 }, +}; + +void tty_setup(uint8_t minor) +{ + minor; +} + +/* For the moment */ +int tty_carrier(uint8_t minor) +{ + minor; + return 1; +} + +void tty_pollirq_asci0(void) +{ + while(ASCI_STAT0 & 0x80){ + tty_inproc(1, ASCI_RDR0); + } +} + +void tty_pollirq_asci1(void) +{ + while(ASCI_STAT1 & 0x80){ + tty_inproc(2, ASCI_RDR1); + } +} + +void tty_putc(uint8_t minor, unsigned char c) +{ + switch(minor){ + case 1: + while(!(ASCI_STAT0 & 2)); + ASCI_TDR0 = c; + break; + case 2: + while(!(ASCI_STAT1 & 2)); + ASCI_TDR1 = c; + break; + } +} + +bool tty_writeready(uint8_t minor) +{ + minor; + return 1; +} + +/* kernel writes to system console -- never sleep! */ +void kputchar(char c) +{ + tty_putc(1, c); + if(c == '\n') + tty_putc(1, '\r'); +} + diff --git a/Kernel/platform-n8vem-mark4/devtty.h b/Kernel/platform-n8vem-mark4/devtty.h new file mode 100644 index 00000000..3a499c0c --- /dev/null +++ b/Kernel/platform-n8vem-mark4/devtty.h @@ -0,0 +1,7 @@ +#ifndef __DEVTTY_DOT_H__ +#define __DEVTTY_DOT_H__ +void tty_putc(uint8_t minor, unsigned char c); +bool tty_writeready(uint8_t minor); +void tty_pollirq_asci0(void); +void tty_pollirq_asci1(void); +#endif diff --git a/Kernel/platform-n8vem-mark4/kernel.def b/Kernel/platform-n8vem-mark4/kernel.def new file mode 100644 index 00000000..e9606c07 --- /dev/null +++ b/Kernel/platform-n8vem-mark4/kernel.def @@ -0,0 +1,17 @@ +; UZI mnemonics for memory addresses etc + +U_DATA .equ 0xF000 ; (this is struct u_data from kernel.h) +U_DATA__TOTALSIZE .equ 0x300 ; 256+256+256 bytes. +NMOS_Z80 .equ 0 + +OS_BANK .equ 0x00 ; value from include/kernel.h + +; N8VEM Mark IV mnemonics +FIRST_RAM_BANK .equ 0x80 ; low 512K of physical memory is ROM/ECB window. +RAM_KB .equ 512 +Z180_IO_BASE .equ 0x40 +MARK4_IDE_BASE .equ 0x80 +MARK4_IDE_DATA .equ MARK4_IDE_BASE + +; No standard clock speed for the Mark IV board, but this is a common choice. +CPU_CLOCK_KHZ .equ 36864 ; 18.432MHz * 2 diff --git a/Kernel/platform-n8vem-mark4/main.c b/Kernel/platform-n8vem-mark4/main.c new file mode 100644 index 00000000..49aaed35 --- /dev/null +++ b/Kernel/platform-n8vem-mark4/main.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include "config.h" +#include + +uint16_t ramtop = PROGTOP; +extern unsigned char irqvector; + +void z180_timer_interrupt(void) +{ + unsigned char a; + + /* we have to read both of these registers in order to reset the timer */ + a = TIME_TMDR0L; + a = TIME_TCR; + + timer_interrupt(); +} + + +void pagemap_init(void) +{ + int i; + + /* N8VEM SBC Mark IV has RAM in the top 512K of physical memory. + * First 64K is used by the kernel. + * Each process gets the full 64K for now. + * Page size is 4KB. */ + for(i = 0x90; i < 0x100; i+=0x10) + pagemap_add(i); +} + +void platform_idle(void) +{ + /* Let's go to sleep while we wait for something to interrupt us; + * Makes the Mark IV's run LED go red, which amuses me greatly. */ + __asm + halt + __endasm; +} + +void platform_interrupt(void) +{ + switch(irqvector){ + case Z180_INT_TIMER0: + z180_timer_interrupt(); + return; + case Z180_INT_ASCI0: + tty_pollirq_asci0(); + return; + case Z180_INT_ASCI1: + tty_pollirq_asci1(); + return; + default: + return; + } +} + +void map_init(void) +{ + /* clone udata and stack into a regular process bank, return with common memory + for the new process loaded */ + copy_and_map_process(&init_process->p_page); + /* kernel bank udata (0x300 bytes) is never used again -- could be reused? */ +} diff --git a/Kernel/platform-n8vem-mark4/mark4.s b/Kernel/platform-n8vem-mark4/mark4.s new file mode 100644 index 00000000..8d9bdcc8 --- /dev/null +++ b/Kernel/platform-n8vem-mark4/mark4.s @@ -0,0 +1,178 @@ +; 2014-12-16 William R Sowerbutts +; N8VEM Mark IV SBC hardware specific code + + .module mark4 + .z180 + + ; exported symbols + .globl init_early + .globl init_hardware + .globl outchar + .globl outcharhex + .globl platform_interrupt_all + .globl _trap_monitor + + .globl map_kernel + .globl map_process_always + .globl map_save + .globl map_restore + ;.globl map_process_only + + ; imported symbols + .globl z180_init_hardware + .globl z180_init_early + .globl _ramsize + .globl _procmem + .globl outhl + .globl outnewline + + .include "kernel.def" + .include "../cpu-z180/z180.def" + .include "../kernel.def" + +; ----------------------------------------------------------------------------- +; Initialisation code +; ----------------------------------------------------------------------------- + .area _DISCARD + +init_early: + jp z180_init_early + +init_hardware: + ; set system RAM size + ld hl, #RAM_KB + ld (_ramsize), hl + ld hl, #(RAM_KB-64) ; 64K for kernel + ld (_procmem), hl + + ; enable ASCI interrupts + in0 a, (ASCI_STAT0) + or #0x08 ; enable ASCI0 receive interrupts + out0 (ASCI_STAT0), a + in0 a, (ASCI_ASEXT0) + and #0x7f ; disable RDRF interrupt inhibit + out0 (ASCI_ASEXT0), a + in0 a, (ASCI_STAT1) + or #0x08 ; enable ASCI1 receive interrupts + out0 (ASCI_STAT1), a + in0 a, (ASCI_ASEXT1) + and #0x7f ; disable RDRF interrupt inhibit + out0 (ASCI_ASEXT1), a + + jp z180_init_hardware + +; ----------------------------------------------------------------------------- +; COMMON MEMORY BANK (0xF000 upwards) +; ----------------------------------------------------------------------------- + .area _COMMONMEM + +; outchar: Wait for UART TX idle, then print the char in A +; destroys: AF +outchar: + push bc + ld b, a + ; wait for transmitter to be idle +ocloop: in0 a, (ASCI_STAT0) + bit 1, a ; and 0x02 + jr z, ocloop ; loop while busy + ; now output the char to serial port + ld a, b + out0 (ASCI_TDR0), a + pop bc + ret + +platform_interrupt_all: + ret + +map_kernel: ; map the kernel into the low 60K, leaves common memory unchanged + push af +.if DEBUGBANK + ld a, #'K' + call outchar +.endif + ld a, #(OS_BANK + FIRST_RAM_BANK) + out0 (MMU_BBR), a + pop af + ret + +; this "map_process" business makes no sense on mark4 since we'd switch stacks +; and the RET would thus lose its return address. oh damn. I suppose we could +; pop the stack address into hl, then jp (hl) or whatever. let's try and get by +; without it. +; +; map_process: ; if HL=0 call map_kernel, else map the full 64K in bank pointed to by HL +; ld a, h +; or l +; jr z, map_kernel +; ld a, (hl) +; out0 (MMU_BBR), a +; out0 (MMU_CBR), a +; ret + +; map_process_only: ; as map_process, but does not modify common memory +; ld a, h +; or l +; jr z, map_kernel +; ld a, (hl) +; out0 (MMU_BBR), a +; ret + +map_process_always: ; map the process into the low 60K based on current common mem (which is unchanged) + push af +.if DEBUGBANK + ld a, #'=' + call outchar +.endif + ld a, (U_DATA__U_PAGE) + out0 (MMU_BBR), a +.if DEBUGBANK + call outcharhex +.endif + ; MMU_CBR is left unchanged + pop af + ret + +map_save: ; save the current process/kernel mapping + push af + in0 a, (MMU_BBR) + ld (map_store), a + pop af + ret + +map_restore: ; restore the saved process/kernel mapping + push af +.if DEBUGBANK + ld a, #'-' + call outchar +.endif + ld a, (map_store) + out0 (MMU_BBR), a +.if DEBUGBANK + call outcharhex +.endif + pop af + ret + +_trap_monitor: + di + call outnewline + pop hl + call outhl + call outnewline + pop hl + call outhl + call outnewline + pop hl + call outhl + call outnewline + pop hl + call outhl + call outnewline + pop hl + call outhl + call outnewline + halt + jr _trap_monitor + +map_store: ; storage for map_save/map_restore + .db 0 diff --git a/Kernel/platform-n8vem-mark4/uzi.lnk b/Kernel/platform-n8vem-mark4/uzi.lnk new file mode 100644 index 00000000..c881d86a --- /dev/null +++ b/Kernel/platform-n8vem-mark4/uzi.lnk @@ -0,0 +1,36 @@ +-mwxuy +-i uzi.ihx +-b _CODE=0x0088 +-b _COMMONMEM=0xF000 +-b _DISCARD=0xE000 +-l z180 +platform-n8vem-mark4/crt0.rel +platform-n8vem-mark4/commonmem.rel +platform-n8vem-mark4/z180.rel +platform-n8vem-mark4/mark4.rel +platform-n8vem-mark4/main.rel +start.rel +version.rel +lowlevel-z180.rel +usermem_std-z180.rel +timer.rel +kdata.rel +usermem.rel +platform-n8vem-mark4/devices.rel +devio.rel +filesys.rel +process.rel +inode.rel +syscall_exec.rel +syscall_fs.rel +syscall_fs2.rel +syscall_proc.rel +syscall_other.rel +tty.rel +mm.rel +bankfixed.rel +swap.rel +devsys.rel +platform-n8vem-mark4/devtty.rel +platform-n8vem-mark4/devide.rel +-e diff --git a/Kernel/platform-n8vem-mark4/z180.s b/Kernel/platform-n8vem-mark4/z180.s new file mode 100644 index 00000000..7371295b --- /dev/null +++ b/Kernel/platform-n8vem-mark4/z180.s @@ -0,0 +1 @@ +.include "../cpu-z180/z180.s" diff --git a/Kernel/platform-p112/Makefile b/Kernel/platform-p112/Makefile new file mode 100644 index 00000000..702be274 --- /dev/null +++ b/Kernel/platform-p112/Makefile @@ -0,0 +1,33 @@ +CSRCS += devices.c main.c devtty.c +DSRCS = ../dev/devide.c + +ASRCS = crt0.s z180.s p112.s commonmem.s + +AOBJS = $(ASRCS:.s=.rel) +COBJS = $(CSRCS:.c=.rel) +DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS)) + +OBJS = $(AOBJS) $(COBJS) $(DOBJS) + +CROSS_CCOPTS += -I../dev/ + +JUNK = *.rel *.lst *.asm *.sym *.rst *.map *.ihx *.bin + +all: $(OBJS) + +$(AOBJS): %.rel: %.s + $(CROSS_AS) $(ASOPTS) $< + +$(COBJS): %.rel: %.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +$(DOBJS): %.rel: ../dev/%.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +clean: + rm -f $(OBJS) $(JUNK) core *~ fuzix.com + +z180.rel: z180.s kernel.def ../cpu-z180/z180.s + +image: + ../cpm-loader/makecpmloader ../cpm-loader/cpmload.bin ../fuzix.bin 0x88 fuzix.com diff --git a/Kernel/platform-p112/README b/Kernel/platform-p112/README new file mode 100644 index 00000000..2b4b9109 --- /dev/null +++ b/Kernel/platform-p112/README @@ -0,0 +1,11 @@ +This is UZI for the DX-Designs P112 +By Will Sowerbutts + +Assumes a P112 fitted with 1024KB RAM and G-IDE + +Only supported storage device at this time is the G-IDE + +To build, edit ../Makefile to read: + +export TARGET= p112 +export CPU = z180 diff --git a/Kernel/platform-p112/commonmem.s b/Kernel/platform-p112/commonmem.s new file mode 100644 index 00000000..522503a8 --- /dev/null +++ b/Kernel/platform-p112/commonmem.s @@ -0,0 +1,9 @@ +; +; Common on z80pack is at 0xF000 as defined by hardware. +; + + .module commonmem + + .area _COMMONMEM + + .include "../cpu-z80/std-commonmem.s" diff --git a/Kernel/platform-p112/config.h b/Kernel/platform-p112/config.h new file mode 100644 index 00000000..c5985ce3 --- /dev/null +++ b/Kernel/platform-p112/config.h @@ -0,0 +1,56 @@ +/* Enable to make ^Z dump the inode table for debug */ +#undef CONFIG_IDUMP +/* Enable to make ^A drop back into the monitor */ +#undef CONFIG_MONITOR +/* Profil syscall support (not yet complete) */ +#undef CONFIG_PROFIL +/* Multiple processes in memory at once */ +#define CONFIG_MULTI +/* Single tasking */ +#undef CONFIG_SINGLETASK +/* CP/M emulation */ +#undef CONFIG_CPM_EMU +/* Fixed banking */ +#define CONFIG_BANK_FIXED +/* 8 60K banks, 1 is kernel */ +#define MAX_MAPS 16 +#define MAP_SIZE 0xF000U + +/* Banks as reported to user space */ +#define CONFIG_BANKS 1 + +#define TICKSPERSEC 100U /* Ticks per second */ +#define PROGBASE 0x0000 /* also data base */ +#define PROGLOAD 0x0100 /* also data base */ +#define PROGTOP 0xF000 /* Top of program, base of U_DATA copy */ +#define PROC_SIZE 64 /* Memory needed per process */ + +/* WRS: this is probably wrong -- we want to swap the full 64K minus the common code */ +/* For now let's just use something and fix this up later when we have a swap device */ +#define SWAP_SIZE 0x7F /* 63.5K in blocks (which is the wrong number) */ +#define SWAPBASE 0x0000 /* start at the base of user mem */ +#define SWAPTOP 0xFF00 /* can we stop at the top? not sure how. let's stop short. */ +#define MAX_SWAPS 10 /* Well, that depends really, hmmmmmm. Pick a number, any number. */ + +#define BOOT_TTY (512 + 1)/* Set this to default device for stdio, stderr */ + /* In this case, the default is the first TTY device */ + +/* We need a tidier way to do this from the loader */ +#define CMDLINE (0x0081) /* Location of root dev name */ + +/* Device parameters */ +#define NUM_DEV_TTY 4 + +#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ +//#define SWAPDEV (256 + 1) /* Device for swapping. (z80pack drive J) */ +#define NBUFS 10 /* Number of block buffers */ +#define NMOUNTS 4 /* Number of mounts at a time */ + +/* Hardware parameters */ +#define Z180_IO_BASE 0x00 + +#define DEVICE_IDE /* enable if IDE interface present */ +#define IDE_REG_BASE 0x50 +#define IDE_REG_CS0_FIRST +#define IDE_REG_CS0_BASE (IDE_REG_BASE+0x00) +#define IDE_REG_CS1_BASE (IDE_REG_BASE+0x08) diff --git a/Kernel/platform-p112/crt0.s b/Kernel/platform-p112/crt0.s new file mode 100644 index 00000000..98ac696f --- /dev/null +++ b/Kernel/platform-p112/crt0.s @@ -0,0 +1,72 @@ +; 2013-12-18 William R Sowerbutts + + .module crt0 + + ; Ordering of segments for the linker. + ; WRS: Note we list all our segments here, even though + ; we don't use them all, because their ordering is set + ; when they are first seen. + .area _CODE + .area _CODE2 + .area _CONST + .area _DATA + .area _INITIALIZED + .area _BSEG + .area _BSS + .area _HEAP + ; note that areas below here may be overwritten by the heap at runtime, so + ; put initialisation stuff in here + .area _INITIALIZER + .area _GSINIT + .area _GSFINAL + .area _DISCARD + .area _COMMONMEM + + ; imported symbols + .globl _fuzix_main + .globl init_early + .globl init_hardware + .globl s__INITIALIZER + .globl s__COMMONMEM + .globl l__COMMONMEM + .globl s__DISCARD + .globl l__DISCARD + .globl s__DATA + .globl l__DATA + .globl kstack_top + + ; startup code + .area _CODE +init: + di + ld sp, #kstack_top + + ; move the common memory where it belongs + ld hl, #s__INITIALIZER + ld de, #s__COMMONMEM + ld bc, #l__COMMONMEM + ldir + ; and the discard + ld de, #s__DISCARD + ld bc, #l__DISCARD + ldir + ; then zero the data area + ld hl, #s__DATA + ld de, #s__DATA + 1 + ld bc, #l__DATA - 1 + ld (hl), #0 + ldir + + ; Configure memory map + call init_early + + ; Hardware setup + call init_hardware + + ; Call the C main routine + call _fuzix_main + + ; fuzix_main() shouldn't return, but if it does... + di +stop: halt + jr stop diff --git a/Kernel/platform-p112/devices.c b/Kernel/platform-p112/devices.c new file mode 100644 index 00000000..2e861aa2 --- /dev/null +++ b/Kernel/platform-p112/devices.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include + +struct devsw dev_tab[] = /* The device driver switch table */ +{ +// minor open close read write ioctl +// ----------------------------------------------------------------- + /* 0: /dev/hd IDE-8 interface */ + { devide_open, no_close, devide_read, devide_write, no_ioctl }, + /* 1: /dev/sd SD interface */ + { no_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 2: /dev/tty serial ports */ + { tty_open, tty_close, tty_read, tty_write, tty_ioctl }, + /* 3: /dev/lpr Unused slot (pad to keep system devices at index 4) */ + { no_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 4: /dev/mem etc System devices (one offs) */ + { no_open, no_close, sys_read, sys_write, sys_ioctl }, + /* Pack to 7 with nxio if adding private devices and start at 8 */ +}; + +bool validdev(uint16_t dev) +{ + /* This is a bit uglier than needed but the right hand side is + a constant this way */ + if(dev > ((sizeof(dev_tab)/sizeof(struct devsw)) << 8) + 255) + return false; + else + return true; +} + +void device_init(void) +{ + devide_init(); +} diff --git a/Kernel/platform-p112/devtty.c b/Kernel/platform-p112/devtty.c new file mode 100644 index 00000000..51e126dd --- /dev/null +++ b/Kernel/platform-p112/devtty.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include "config.h" +#include + +char tbuf1[TTYSIZ]; +char tbuf2[TTYSIZ]; +char tbuf3[TTYSIZ]; +char tbuf4[TTYSIZ]; + +struct s_queue ttyinq[NUM_DEV_TTY+1] = { /* ttyinq[0] is never used */ + { NULL, NULL, NULL, 0, 0, 0 }, + { tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ/2 }, + { tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ/2 }, + { tbuf3, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ/2 }, + { tbuf4, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ/2 }, +}; + +void tty_setup(uint8_t minor) +{ + minor; +} + +/* For the moment */ +int tty_carrier(uint8_t minor) +{ + minor; + return 1; +} + +void tty_pollirq_asci0(void) +{ + while(ASCI_STAT0 & 0x80){ + tty_inproc(1, ASCI_RDR0); + } +} + +void tty_pollirq_asci1(void) +{ + while(ASCI_STAT1 & 0x80){ + tty_inproc(2, ASCI_RDR1); + } +} + +void tty_pollirq_escc(void) +{ + unsigned char rr3; + ESCC_CTRL_A = 0x03; /* select read register 3 */ + rr3 = ESCC_CTRL_A; + + if(rr3 & 0x20){ /* channel A RX pending */ + tty_inproc(1, ESCC_DATA_A); + } + if(rr3 & 0x04){ /* channel B RX pending */ + tty_inproc(2, ESCC_DATA_B); + } + if(rr3 & (~0x24)){ + kputs("[escc hurts]"); + } + + ESCC_CTRL_A = 0x38; /* reset interrupt under service */ +} + +void tty_putc(uint8_t minor, unsigned char c) +{ + switch(minor){ + case 1: + while(!(ESCC_CTRL_A & 4)); + ESCC_DATA_A = c; + break; + case 2: + while(!(ESCC_CTRL_B & 4)); + ESCC_DATA_B = c; + break; + case 3: + while(!(ASCI_STAT0 & 2)); + ASCI_TDR0 = c; + break; + case 4: + while(!(ASCI_STAT1 & 2)); + ASCI_TDR1 = c; + break; + } +} + +bool tty_writeready(uint8_t minor) +{ + minor; + return 1; +} + +/* kernel writes to system console -- never sleep! */ +void kputchar(char c) +{ + tty_putc(1, c); + if(c == '\n') + tty_putc(1, '\r'); +} diff --git a/Kernel/platform-p112/devtty.h b/Kernel/platform-p112/devtty.h new file mode 100644 index 00000000..2a428de8 --- /dev/null +++ b/Kernel/platform-p112/devtty.h @@ -0,0 +1,8 @@ +#ifndef __DEVTTY_DOT_H__ +#define __DEVTTY_DOT_H__ +void tty_putc(uint8_t minor, unsigned char c); +bool tty_writeready(uint8_t minor); +void tty_pollirq_escc(void); +void tty_pollirq_asci0(void); +void tty_pollirq_asci1(void); +#endif diff --git a/Kernel/platform-p112/kernel.def b/Kernel/platform-p112/kernel.def new file mode 100644 index 00000000..e204fe8a --- /dev/null +++ b/Kernel/platform-p112/kernel.def @@ -0,0 +1,18 @@ +; UZI mnemonics for memory addresses etc + +U_DATA .equ 0xF000 ; (this is struct u_data from kernel.h) +U_DATA__TOTALSIZE .equ 0x300 ; 256+256+256 bytes. +NMOS_Z80 .equ 0 + +OS_BANK .equ 0x00 ; value from include/kernel.h + +; P112 +FIRST_RAM_BANK .equ 0x00 ; all memory is RAM on P112 +RAM_KB .equ 1024 +Z180_IO_BASE .equ 0x00 +P112_IDE_BASE .equ 0x50 +P112_IDE_DATA .equ (P112_IDE_BASE+0x08) + +; Believe most P112 kits shipped with 16MHz oscillators, I have tried faster +; (18.432MHz) but this made the machine unstable. +CPU_CLOCK_KHZ .equ 16000 ; 16MHz is the stock crystal diff --git a/Kernel/platform-p112/main.c b/Kernel/platform-p112/main.c new file mode 100644 index 00000000..baf4da28 --- /dev/null +++ b/Kernel/platform-p112/main.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include "config.h" + +uint16_t ramtop = PROGTOP; +extern unsigned char irqvector; + +void z180_timer_interrupt(void) +{ + unsigned char a; + + /* we have to read both of these registers in order to reset the timer */ + a = TIME_TMDR0L; + a = TIME_TCR; + + timer_interrupt(); +} + + +void pagemap_init(void) +{ + int i; + + /* N8VEM SBC Mark IV has RAM in the top 512K of physical memory. + * First 64K is used by the kernel. + * Each process gets the full 64K for now. + * Page size is 4KB. */ + for(i = 0x10; i < 0x100; i+=0x10){ + pagemap_add(i); + } +} + +void platform_idle(void) +{ + /* Let's go to sleep while we wait for something to interrupt us; + * Makes the Mark IV's run LED go red, which amuses me greatly. */ + __asm + halt + __endasm; +} + +void platform_interrupt(void) +{ + switch(irqvector){ + case Z180_INT0: + tty_pollirq_escc(); + return; + case Z180_INT_TIMER0: + z180_timer_interrupt(); + return; + case Z180_INT_ASCI0: + tty_pollirq_asci0(); + return; + case Z180_INT_ASCI1: + tty_pollirq_asci1(); + return; + default: + kprintf("[int:%d?]", irqvector); + return; + } +} + +void map_init(void) +{ + /* clone udata and stack into a regular process bank, return with common memory + for the new process loaded */ + copy_and_map_process(&init_process->p_page); + /* kernel bank udata (0x300 bytes) is never used again -- could be reused? */ +} diff --git a/Kernel/platform-p112/p112.s b/Kernel/platform-p112/p112.s new file mode 100644 index 00000000..0f9579c7 --- /dev/null +++ b/Kernel/platform-p112/p112.s @@ -0,0 +1,202 @@ +; 2014-12-24 William R Sowerbutts +; P112 hardware specific code + + .module p112 + .z180 + + ; exported symbols + .globl init_early + .globl init_hardware + .globl outchar + .globl outstring + .globl outcharhex + .globl platform_interrupt_all + .globl _trap_monitor + + .globl map_kernel + .globl map_process_always + .globl map_save + .globl map_restore + ;.globl map_process_only + + ; imported symbols + .globl z180_init_hardware + .globl z180_init_early + .globl _ramsize + .globl _procmem + .globl outhl + .globl outnewline + + .include "kernel.def" + .include "../cpu-z180/z180.def" + .include "../kernel.def" + +; ----------------------------------------------------------------------------- +; Initialisation code +; ----------------------------------------------------------------------------- + .area _DISCARD + +init_early: + ; P112: stop the floppy motor in case it is running + ld a, #0x0c + out0 (0x92), a + + ; unmap ROM + xor a + out0 (Z182_ROMBR), a + + in0 a, (Z182_SYSCONFIG) + or #0x08 ; disable ROM chip select (is this required as well as setting Z182_ROMBR?) + out0 (Z182_SYSCONFIG), a + + jp z180_init_early + +init_hardware: + ; set system RAM size + ld hl, #RAM_KB + ld (_ramsize), hl + ld hl, #(RAM_KB-64) ; 64K for kernel + ld (_procmem), hl + + ; enable ASCI interrupts + ; in0 a, (ASCI_STAT0) + ; or #0x08 ; enable ASCI0 receive interrupts + ; out0 (ASCI_STAT0), a + ; in0 a, (ASCI_ASEXT0) + ; and #0x7f ; disable RDRF interrupt inhibit + ; out0 (ASCI_ASEXT0), a + ; in0 a, (ASCI_STAT1) + ; or #0x08 ; enable ASCI1 receive interrupts + ; out0 (ASCI_STAT1), a + ; in0 a, (ASCI_ASEXT1) + ; and #0x7f ; disable RDRF interrupt inhibit + ; out0 (ASCI_ASEXT1), a + + ; enable ESCC interrupts + ld bc, #0x0114 ; write register 1, 0x14: enable receive interrupts only + call write_escc + ld bc, #0x0908 ; write register 9, 0x08: master interrupt enable + call write_escc + + jp z180_init_hardware + +write_escc: + out0 (ESCC_CTRL_A), b + out0 (ESCC_CTRL_A), c + out0 (ESCC_CTRL_B), b + out0 (ESCC_CTRL_B), c + ret + +; ----------------------------------------------------------------------------- +; COMMON MEMORY BANK (0xF000 upwards) +; ----------------------------------------------------------------------------- + .area _COMMONMEM + +; outchar: Wait for UART TX idle, then print the char in A +; destroys: AF +outchar: + push bc + ld b, a + ; wait for transmitter to be idle +ocloop: in0 a, (ESCC_CTRL_A) + and #0x04 ; test transmit buffer empty + jr z, ocloop + out0 (ESCC_DATA_A), b + pop bc + ret + +platform_interrupt_all: + ret + +map_kernel: ; map the kernel into the low 60K, leaves common memory unchanged + push af +.if DEBUGBANK + ld a, #'K' + call outchar +.endif + ld a, #(OS_BANK + FIRST_RAM_BANK) + out0 (MMU_BBR), a + pop af + ret + +; this "map_process" business makes no sense on mark4 since we'd switch stacks +; and the RET would thus lose its return address. oh damn. I suppose we could +; pop the stack address into hl, then jp (hl) or whatever. let's try and get by +; without it. +; +; map_process: ; if HL=0 call map_kernel, else map the full 64K in bank pointed to by HL +; ld a, h +; or l +; jr z, map_kernel +; ld a, (hl) +; out0 (MMU_BBR), a +; out0 (MMU_CBR), a +; ret + +; map_process_only: ; as map_process, but does not modify common memory +; ld a, h +; or l +; jr z, map_kernel +; ld a, (hl) +; out0 (MMU_BBR), a +; ret + +map_process_always: ; map the process into the low 60K based on current common mem (which is unchanged) + push af +.if DEBUGBANK + ld a, #'=' + call outchar +.endif + ld a, (U_DATA__U_PAGE) + out0 (MMU_BBR), a +.if DEBUGBANK + call outcharhex +.endif + ; MMU_CBR is left unchanged + pop af + ret + +map_save: ; save the current process/kernel mapping + push af + in0 a, (MMU_BBR) + ld (map_store), a + pop af + ret + +map_restore: ; restore the saved process/kernel mapping + push af +.if DEBUGBANK + ld a, #'-' + call outchar +.endif + ld a, (map_store) + out0 (MMU_BBR), a +.if DEBUGBANK + call outcharhex +.endif + pop af + ret + +_trap_monitor: + di + call outnewline + pop hl + call outhl + call outnewline + pop hl + call outhl + call outnewline + pop hl + call outhl + call outnewline + pop hl + call outhl + call outnewline + pop hl + call outhl + call outnewline + halt + jr _trap_monitor + +map_store: ; storage for map_save/map_restore + .db 0 diff --git a/Kernel/platform-p112/uzi.lnk b/Kernel/platform-p112/uzi.lnk new file mode 100644 index 00000000..42407dad --- /dev/null +++ b/Kernel/platform-p112/uzi.lnk @@ -0,0 +1,36 @@ +-mwxuy +-i uzi.ihx +-b _CODE=0x0088 +-b _COMMONMEM=0xF000 +-b _DISCARD=0xE000 +-l z180 +platform-p112/crt0.rel +platform-p112/commonmem.rel +platform-p112/z180.rel +platform-p112/p112.rel +platform-p112/main.rel +start.rel +version.rel +lowlevel-z180.rel +usermem_std-z180.rel +timer.rel +kdata.rel +usermem.rel +platform-p112/devices.rel +devio.rel +filesys.rel +process.rel +inode.rel +syscall_exec.rel +syscall_fs.rel +syscall_fs2.rel +syscall_proc.rel +syscall_other.rel +tty.rel +mm.rel +bankfixed.rel +swap.rel +devsys.rel +platform-p112/devtty.rel +platform-p112/devide.rel +-e diff --git a/Kernel/platform-p112/z180.s b/Kernel/platform-p112/z180.s new file mode 100644 index 00000000..7371295b --- /dev/null +++ b/Kernel/platform-p112/z180.s @@ -0,0 +1 @@ +.include "../cpu-z180/z180.s"