From 2eb3e9540d90899a3c46c6f5b723d6a2fd0d1c88 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 26 Aug 2016 22:01:25 +0100 Subject: [PATCH] v68: initial bits of 68000 development tree Nothing to see here yet --- Kernel/platform-v68/Makefile | 42 ++++++++++++++++ Kernel/platform-v68/README | 3 ++ Kernel/platform-v68/config.h | 43 +++++++++++++++++ Kernel/platform-v68/crt0.S | 19 ++++++++ Kernel/platform-v68/device.h | 6 +++ Kernel/platform-v68/devices.c | 40 ++++++++++++++++ Kernel/platform-v68/devtty.c | 65 +++++++++++++++++++++++++ Kernel/platform-v68/devtty.h | 10 ++++ Kernel/platform-v68/libc.c | 40 ++++++++++++++++ Kernel/platform-v68/main.c | 77 ++++++++++++++++++++++++++++++ Kernel/platform-v68/p68000.S | 61 +++++++++++++++++++++++ Kernel/platform-v68/platform_ide.h | 18 +++++++ Kernel/platform-v68/target.mk | 1 + Kernel/platform-v68/tricks.S | 73 ++++++++++++++++++++++++++++ 14 files changed, 498 insertions(+) create mode 100644 Kernel/platform-v68/Makefile create mode 100644 Kernel/platform-v68/README create mode 100644 Kernel/platform-v68/config.h create mode 100644 Kernel/platform-v68/crt0.S create mode 100644 Kernel/platform-v68/device.h create mode 100644 Kernel/platform-v68/devices.c create mode 100644 Kernel/platform-v68/devtty.c create mode 100644 Kernel/platform-v68/devtty.h create mode 100644 Kernel/platform-v68/libc.c create mode 100644 Kernel/platform-v68/main.c create mode 100644 Kernel/platform-v68/p68000.S create mode 100644 Kernel/platform-v68/platform_ide.h create mode 100644 Kernel/platform-v68/target.mk create mode 100644 Kernel/platform-v68/tricks.S diff --git a/Kernel/platform-v68/Makefile b/Kernel/platform-v68/Makefile new file mode 100644 index 00000000..4e61033d --- /dev/null +++ b/Kernel/platform-v68/Makefile @@ -0,0 +1,42 @@ + +CSRCS = devtty.c +CSRCS += devices.c main.c libc.c + +ASRCS = p68000.S crt0.S +ASRCS += tricks.S + +DSRCS = ../dev/devide.c ../dev/mbr.c ../dev/blkdev.c ../dev/devide_discard.c +DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS)) + +COBJS = $(CSRCS:.c=$(BINEXT)) +AOBJS = $(ASRCS:.S=.o) +OBJS = $(COBJS) $(AOBJS) + +CROSS_CCOPTS += -I../dev/ + +JUNK = $(CSRCS:.c=.o) $(ASRCS:.S=.o) + +all: $(OBJS) + +$(COBJS): %.o: %.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +$(AOBJS): %.o: %.S + $(CROSS_AS) $(ASOPTS) $< -o $*.o + +$(DOBJS): %.rel: ../dev/%.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +clean: + rm -f $(OBJS) $(JUNK) core *~ + +image: + $(CROSS_LD) -M -o ../fuzix.bin \ + crt0.o \ + p68000.o ../start.o ../version.o ../lowlevel-68000.o \ + tricks.o main.o ../timer.o ../kdata.o devices.o \ + ../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \ + ../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o ../buddy.o \ + ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o \ + ../syscall_fs3.o ../syscall_exec32.o \ + ../usermem_std-68000.o devtty.o libc.o ../malloc.o > ../fuzix.map diff --git a/Kernel/platform-v68/README b/Kernel/platform-v68/README new file mode 100644 index 00000000..e03ad8dc --- /dev/null +++ b/Kernel/platform-v68/README @@ -0,0 +1,3 @@ +Development subtree for the v68 virtual platform and general 68000 +bootstrap work. There is a lot to do before anything remotely useful will +happen. diff --git a/Kernel/platform-v68/config.h b/Kernel/platform-v68/config.h new file mode 100644 index 00000000..37b09b49 --- /dev/null +++ b/Kernel/platform-v68/config.h @@ -0,0 +1,43 @@ +/* Enable to make ^Z dump the inode table for debug */ +#define 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 - for now while we get it booting */ +#undef CONFIG_SINGLETASK +/* Buddy based MMU */ +#define CONFIG_BUDDY_MMU +#define BUDDY_NUMLEVEL 9 /* 1 MByte */ +#define BUDDY_BLOCKBITS 12 /* 4K pages */ +#define BUDDY_BLOCKSIZE 4096 +/* FIXME: these should be dynamic */ +#define BUDDY_BASE ((uint8_t *)0x00000) /* Manage the low 1MB */ +#define BUDDY_START ((uint8_t *)0x10000) /* First usable 64K */ +#define BUDDY_TOP ((uint8_t *)0x80000) /* End at 512K - should be 7FFFF ? */ +#define BUDDY_TABLE BUDDY_START /* Pull the table from the pool */ +#define BUDDY_TREESIZE 511 /* 1MB in 4K pages */ + +#define CONFIG_32BIT +#define CONFIG_BANKS 1 /* FIXME */ +#define CONFIG_USERMEM_BUDDY /* TODO */ + +#define TICKSPERSEC 100 /* Ticks per second */ + +#define BOOT_TTY (512 + 1) /* Set this to default device for stdio, stderr */ + /* In this case, the default is the first TTY device */ + /* Temp FIXME set to serial port for debug ease */ + +/* We need a tidier way to do this from the loader */ +#define CMDLINE NULL /* Location of root dev name */ + +/* Device parameters */ +#define NUM_DEV_TTY 1 +#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ +#define NBUFS 20 /* Number of block buffers */ +#define NMOUNTS 6 /* Number of mounts at a time */ + +/* Programs run under MMU with zero base */ +#define PROGBASE 0 diff --git a/Kernel/platform-v68/crt0.S b/Kernel/platform-v68/crt0.S new file mode 100644 index 00000000..65a4e325 --- /dev/null +++ b/Kernel/platform-v68/crt0.S @@ -0,0 +1,19 @@ +/* + * Need to wipe BSS etc once we figure out our preferred boot method + * + * On entry we are loaded at $2000 with the loader and the loaders + * supervisor stack below us. We are in supervisor mode and the rest + * is our problem. + */ + .globl _start +.mri 1 + +start: + or #$0700,sr + /* FIXME: hard coded ugly */ + move.l #uarea_block+508,a7 + bsr init_early + bsr init_hardware + bsr fuzix_main + or #$0700,sr +stop: bra stop diff --git a/Kernel/platform-v68/device.h b/Kernel/platform-v68/device.h new file mode 100644 index 00000000..6f4c1e26 --- /dev/null +++ b/Kernel/platform-v68/device.h @@ -0,0 +1,6 @@ +#ifndef __DEVICE_DOT_H__ +#define __DEVICE_DOT_H__ + +extern void mod_control(uint8_t set, uint8_t clr); + +#endif /* __DEVICE_DOT_H__ */ diff --git a/Kernel/platform-v68/devices.c b/Kernel/platform-v68/devices.c new file mode 100644 index 00000000..53aa3c40 --- /dev/null +++ b/Kernel/platform-v68/devices.c @@ -0,0 +1,40 @@ +#include +#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 Disc block devices */ + { blkdev_open, no_close, blkdev_read, blkdev_write, blkdev_ioctl }, + /* 1: /dev/fd Hard disc block devices (absent) */ + { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 2: /dev/tty TTY devices */ + { tty_open, tty_close, tty_read, tty_write, tty_ioctl }, + /* 3: /dev/lpr Printer devices */ + { 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-v68/devtty.c b/Kernel/platform-v68/devtty.c new file mode 100644 index 00000000..5d398ad0 --- /dev/null +++ b/Kernel/platform-v68/devtty.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include + +volatile uint8_t *uart_data = (volatile uint8_t *)0xF03000; /* UART data */ +volatile uint8_t *uart_status = (volatile uint8_t *)0xF03010; /* UART status */ + +unsigned char tbuf1[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}, +}; + +/* Output for the system console (kprintf etc) */ +void kputchar(char c) +{ + if (c == '\n') + tty_putc(1, '\r'); + tty_putc(1, c); +} + +ttyready_t tty_writeready(uint8_t minor) +{ + uint8_t c = *uart_status; + return (c & 2) ? TTY_READY_NOW : TTY_READY_SOON; /* TX DATA empty */ +} + +void tty_putc(uint8_t minor, unsigned char c) +{ + *uart_data = c; /* Data */ +} + +void tty_setup(uint8_t minor) +{ +} + +int tty_carrier(uint8_t minor) +{ + return 1; +} + +void tty_sleeping(uint8_t minor) +{ +} + +/* Currently run off the timer */ +void tty_interrupt(void) +{ + uint8_t r = *uart_status; + if (r & 0x2) { + r = *uart_data; + tty_inproc(2,r); + } +} + +void platform_interrupt(void) +{ + timer_interrupt(); + tty_interrupt(); +} diff --git a/Kernel/platform-v68/devtty.h b/Kernel/platform-v68/devtty.h new file mode 100644 index 00000000..14c28c31 --- /dev/null +++ b/Kernel/platform-v68/devtty.h @@ -0,0 +1,10 @@ +#ifndef __DEVTTY_DOT_H__ +#define __DEVTTY_DOT_H__ + +#define KEY_ROWS 8 +#define KEY_COLS 7 +extern uint8_t keymap[8]; +extern uint8_t keyboard[8][7]; +extern uint8_t shiftkeyboard[8][7]; + +#endif diff --git a/Kernel/platform-v68/libc.c b/Kernel/platform-v68/libc.c new file mode 100644 index 00000000..e718087e --- /dev/null +++ b/Kernel/platform-v68/libc.c @@ -0,0 +1,40 @@ +#include "cpu.h" + +void *memcpy(void *d, const void *s, size_t sz) +{ + unsigned char *dp = d; + const unsigned char *sp = s; + while(sz--) + *dp++=*sp++; + return d; +} + +void *memset(void *d, int c, size_t sz) +{ + unsigned char *p = d; + while(sz--) + *p++ = c; + return d; +} + +size_t strlen(const char *p) +{ + const char *e = p; + while(*e++); + return e-p-1; +} + +int memcmp(const void *a, const void *b, size_t n) +{ + const uint8_t *ap = a; + const uint8_t *bp = b; + while(n--) { + if (*ap < *bp) + return -1; + if (*ap != *bp) + return 1; + ap++; + bp++; + } + return 0; +} diff --git a/Kernel/platform-v68/main.c b/Kernel/platform-v68/main.c new file mode 100644 index 00000000..ba9456e6 --- /dev/null +++ b/Kernel/platform-v68/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include + +void platform_idle(void) +{ + /* FIXME: disable IRQ, run tty interrupt, re-enable ? */ +} + +void do_beep(void) +{ +} + +/* + * MMU initialize + */ + +void pagemap_init(void) +{ + /* Allocate the buddy tables and init them */ + buddy_init(); +} + +void map_init(void) +{ +} + +u_block uarea_block[PTABSIZE]; +uaddr_t ramtop; + +/* Offsets into the buddy map for each level, byte aligned */ +const uint16_t buddy_level[BUDDY_NUMLEVEL] = { + 0, /* 256 4K pages */ + 256, /* 128 8K pages */ + 384, /* 64 16K pages */ + 448, /* 32 32K pages */ + 480, /* 16 64K pages */ + 496, /* 8 128K pages */ + 504, /* 4 256K pages */ + 508, /* 2 512K pages */ + 510, /* 1 1MB page */ +}; + +/* + * We can do our fork handling in C for once. The only oddity here is + * the fixups to run parent first and avoid needless memory thrashing + */ +int16_t dofork(ptptr p) +{ + /* Child and parent udata pointers */ + struct u_data *uc = &uarea_block[p - ptab].u_d; + struct u_data *up = udata_ptr; + uint32_t *csp = (uint32_t *)(uc + 1); + uint32_t *psp = up->u_sp; + /* Duplicate the memory maps */ + if (pagemap_fork(p)) + return -1; + /* Duplicate the udata */ + memcpy(&uc, &up, sizeof(struct u_data)); + /* Use the child udata for initializing the child */ + udata_ptr = uc; + newproc(p); + udata_ptr = up; + /* And return as the parent. The child will return via the + fork return path */ + /* FIXME: stack setup needs correcting */ +//FIXME *--csp = fork_return; + uc->u_sp = csp; + /* Copy the saved register state over - must match switchin */ + memcpy(csp - 14, psp - 14, 4 * 14); + /* Return as the parent and run it first (backwards to most ports) */ + p->p_status = P_READY; + udata.u_ptab->p_status = P_RUNNING; + return p->p_pid; +} diff --git a/Kernel/platform-v68/p68000.S b/Kernel/platform-v68/p68000.S new file mode 100644 index 00000000..33b86722 --- /dev/null +++ b/Kernel/platform-v68/p68000.S @@ -0,0 +1,61 @@ +/* + * Lots left to fill in + */ + + .globl trap_reboot + .globl init_early + .globl init_hardware + .globl program_vectors + .globl outchar + .globl trap_monitor + .globl uarea_block + +.mri 1 +trap_reboot: +trap_monitor: + or #0700,sr + bra trap_monitor + +init_early: + lea.l uarea_block,a5 ; udata ptr + rts + +init_hardware: + ; set system RAM size(hadcode hacks for now) + move.w #512,d0 + move.w d0,ramsize + sub.w #64,d0 ; Guess for kernel + move.w d0,procmem ; guesses for now + rts + +; +; Nothing to do in 68000 - all set up once at boot +; +program_vectors: + rts + +; +; TODO +; +map_process_always: +map_process: +map_kernel: +map_restore: +map_save: + rts + +; outchar: Wait for UART TX idle, then print the char in d0 + +outchar: + move.w d0,-(sp) +outcharw: + move.b $00F03010,d0 + btst #1,d0 + beq outcharw + move.w (sp)+,d0 + move.b d0,$00F03000 + rts + +.section data + +kernel_flag: byte 1 diff --git a/Kernel/platform-v68/platform_ide.h b/Kernel/platform-v68/platform_ide.h new file mode 100644 index 00000000..6e9d56c8 --- /dev/null +++ b/Kernel/platform-v68/platform_ide.h @@ -0,0 +1,18 @@ +#define IDE_IS_MMIO 1 /* MMIO IDE */ + +#define IDE_REG_DATA 0x00F01000 +#define IDE_REG_ERROR 0x00F01002 +#define IDE_REG_FEATURES 0x00F01002 +#define IDE_REG_SEC_COUNT 0x00F01004 +#define IDE_REG_LBA_0 0x00F01006 +#define IDE_REG_LBA_1 0x00F01008 +#define IDE_REG_LBA_2 0x00F0100A +#define IDE_REG_LBA_3 0x00F0100C +#define IDE_REG_DEVHEAD 0x00F0100C +#define IDE_REG_STATUS 0x00F0100E +#define IDE_REG_COMMAND 0x00F0100E +#define IDE_REG_ALTSTATUS 0x00F01010 +#define IDE_REG_CONTROL 0x00F01010 + +#define ide_select(x) +#define ide_deselect() diff --git a/Kernel/platform-v68/target.mk b/Kernel/platform-v68/target.mk new file mode 100644 index 00000000..df1c235f --- /dev/null +++ b/Kernel/platform-v68/target.mk @@ -0,0 +1 @@ +export CPU = 68000 diff --git a/Kernel/platform-v68/tricks.S b/Kernel/platform-v68/tricks.S new file mode 100644 index 00000000..a73349a7 --- /dev/null +++ b/Kernel/platform-v68/tricks.S @@ -0,0 +1,73 @@ +#include "../kernel-68000.def" + + +.globl switchout,switchin,dofork + +.mri 1 + +; Switchout switches out the current process, finds another that is READY, +; possibly the same process, and switches it in. When a process is +; restarted after calling switchout, it thinks it has just returned +; from switchout(). +; +; This function can have no arguments or auto variables. +switchout: + or #$0700,sr + bsr chksigs + ; save machine state + + clr.w -(sp) ; return code set here is ignored, but _switchin can + ; return from either _switchout OR _dofork, so they must both write + ; U_DATA__U_SP with the following on the stack: + movem.l a0-a4/a6/d0-d7,-(sp) ; FIXME: trim to callee saves + move.l sp,U_DATA__U_SP(a5) ; this is where the SP is restored in _switchin + + ; set _inint to false + clr.b inint + + ; find another process to run (may select this one again) + bsr getproc + + move.l a0,-(sp) ; CHECK compiler call/return rules + bsr switchin + + ; we should never get here + bra trap_monitor + +badswitchmsg: ascii "_switchin: FAIL" + byte 13,10,0 +swapped: ascii "_switchin: SWAPPED" + byte 13,10,0 + +switchin: + or #$0700,sr + move.l 4(sp),a0 ; task to switch to + move.l P_TAB__P_UDATA_OFFSET(a0),a5 + + ; check u_data->u_ptab matches what we wanted + move.l 4(sp),d0 + cmp.l U_DATA__U_PTAB(a5),d0 + bne switchinfail + + ; wants optimising up a bit + move.b #P_RUNNING,P_TAB__P_STATUS_OFFSET(a0) + + ; runticks = 0 + clr.w runticks + + ; restore machine state + move.l U_DATA__U_SP(a5),sp + movem.l (sp)+,a0-a4/a6/d0-d7 ; FIXME: trim to callee saves here too + + tst.b inint + beq keepoff ; in ISR, leave interrupts off + and #$F8FF,sr +keepoff: + rts ; return with interrupts on + +switchinfail: + bsr outa0hex + lea badswitchmsg,a0 + bsr outstring + ; something went wrong and we didn't switch in what we asked for + bra trap_monitor -- 2.34.1