From 0f6a81a33184162ebe730011a85f08e96563a881 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 20 Feb 2019 01:06:16 +0000 Subject: [PATCH] spx302: Initial code sketch for the SPX302/MPU302 conversion See https://www.retrobrewcomputers.org/doku.php?id=builderpages:plasmo:spx-mpu for more information about this system. This is just an initial set of buildable code. It needs a loader and debugging before we can get further --- Kernel/platform-spx302/Makefile | 51 +++++++ Kernel/platform-spx302/README | 81 ++++++++++ Kernel/platform-spx302/config.h | 47 ++++++ Kernel/platform-spx302/crt0.S | 33 +++++ Kernel/platform-spx302/devices.c | 39 +++++ Kernel/platform-spx302/devtty.c | 149 +++++++++++++++++++ Kernel/platform-spx302/devtty.h | 10 ++ Kernel/platform-spx302/fuzix.ld | 87 +++++++++++ Kernel/platform-spx302/kernel.def | 2 + Kernel/platform-spx302/libc.c | 52 +++++++ Kernel/platform-spx302/main.c | 81 ++++++++++ Kernel/platform-spx302/p68000.S | 203 ++++++++++++++++++++++++++ Kernel/platform-spx302/platform_ide.h | 42 ++++++ Kernel/platform-spx302/ppide_spx302.c | 42 ++++++ Kernel/platform-spx302/target.mk | 1 + Kernel/platform-spx302/tricks.S | 3 + 16 files changed, 923 insertions(+) create mode 100644 Kernel/platform-spx302/Makefile create mode 100644 Kernel/platform-spx302/README create mode 100644 Kernel/platform-spx302/config.h create mode 100644 Kernel/platform-spx302/crt0.S create mode 100644 Kernel/platform-spx302/devices.c create mode 100644 Kernel/platform-spx302/devtty.c create mode 100644 Kernel/platform-spx302/devtty.h create mode 100644 Kernel/platform-spx302/fuzix.ld create mode 100644 Kernel/platform-spx302/kernel.def create mode 100644 Kernel/platform-spx302/libc.c create mode 100644 Kernel/platform-spx302/main.c create mode 100644 Kernel/platform-spx302/p68000.S create mode 100644 Kernel/platform-spx302/platform_ide.h create mode 100644 Kernel/platform-spx302/ppide_spx302.c create mode 100644 Kernel/platform-spx302/target.mk create mode 100644 Kernel/platform-spx302/tricks.S diff --git a/Kernel/platform-spx302/Makefile b/Kernel/platform-spx302/Makefile new file mode 100644 index 00000000..0af36366 --- /dev/null +++ b/Kernel/platform-spx302/Makefile @@ -0,0 +1,51 @@ + +CSRCS = devtty.c +CSRCS += devices.c main.c libc.c ppide_spx302.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,%.o, $(DSRCS)) + +LSRCS = ../lib/68000exception.c +LOBJS = $(patsubst ../lib/%.c,%.o, $(LSRCS)) + +COBJS = $(CSRCS:.c=.o) +AOBJS = $(ASRCS:.S=.o) +OBJS = $(COBJS) $(AOBJS) $(DOBJS) $(LOBJS) + +CROSS_CCOPTS += -I../dev/ + +all: $(OBJS) + +$(COBJS): %.o: %.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +$(AOBJS): %.o: %.S + $(CROSS_AS) $(ASOPTS) $< -o $*.o + +$(DOBJS): %.o: ../dev/%.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +$(LOBJS): %.o: ../lib/%.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +tricks.S: ../lib/68000flat.S + +clean: + rm -f *.o fuzix.elf loader.elf loader.map loader.bin core *~ + +image: + $(CROSS_LD) -M -o fuzix.elf -T fuzix.ld \ + crt0.o \ + p68000.o ../start.o ../version.o ../lowlevel-68000.o \ + tricks.o main.o ../timer.o ../kdata.o 68000exception.o devices.o \ + ../devio.o ../filesys.o ../process.o ../inode.o ../syscall_fs.o \ + ../syscall_proc.o ../syscall_other.o ../mm.o ../flat.o \ + ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o \ + ../syscall_fs3.o ../syscall_exec32.o blkdev.o devide.o devide_discard.o \ + mbr.o ppide_spx302.o \ + ../usermem_std-68000.o devtty.o libc.o ../malloc.o \ + ../level2.o ../syscall_level2.o ../select.o > ../fuzix.map + m68k-uclinux-objcopy fuzix.elf -O binary ../fuzix.bin diff --git a/Kernel/platform-spx302/README b/Kernel/platform-spx302/README new file mode 100644 index 00000000..d158e897 --- /dev/null +++ b/Kernel/platform-spx302/README @@ -0,0 +1,81 @@ +Adapted Sonoplex MC68302 board + +https://retrobrewcomputers.org/doku.php?id=builderpages:plasmo:spx-mpu + +This a system with a 68302@16MHz, 2.25MB of flash (holding a boot ROM and CP/M +68K) as well as a monitor, 1MB of RAM (256K battery backed) a 68692 DUART +providing a console port, an 82C55 PIO and an RTC (not yet handled). + +There is a plug in board which provides a CF interface using the 82C55, and +interface points for the second DUART port and minimal SPI. + + +Memory Map + +When are loaded we have the 68302 internal I/O mapped at FFF000 and the +RAM mapped at 0. + +000000-0FFFFF RAM (1MB) +300000-300007 82C55 (odd side) +300000-300020 DUART (68692) (even side) +300040-30005F RTC72743 (odd side) + +Chip Selects + +0 Boot Flash 256K (1 wait) +1 RAM, 4MB mapping (0 wait) +2 400000, 1MB 1 wait (flash) +3 500000, 1MB 1 wait (flash) + +RAM is aliased in the low 1MB +GIMR is set to vector 80-9F +TMR1 is set to 10ms +The RTC is kicked into 24hr mode +DUART and TMR1 are the interrupt sources + +As we boot CP/M 68K from ROM we need to run from CP/M 68K as follows + +Binary header +601AH +Size of text.L +Size of data.L +Size of BSS.L +0.L (Sizeof syms) +0.L +0.L (beginning of text segment and start) +0.W (no reloc) +[text][data] + +Supervisor mode: + +MOVE.W #$3E,D0 +TRAP #2 + +returns in supervisor mode on the CP/M supervisor stack + + +The serial ports are mapped as follows + +tty1 The DB25 serial port +tty2 The port on the CF card +Future: +tty3-5 The SCC ports (these are wired as RS422/485) + +TODO + +Figure out the right rituals to get the CP/M 68K filesystem working in the +CP/M utils +Write a front end CP/M loader module that has the kernel as data and boots it +Test the console and timer drivers +Test IDE +Write RTC driver +Investigate the SPI state of affairs, see if we can get SD working +Reboot logic + +Longer Term + +SCC RS485 drivers (serial and/or networking ?) +Ethernet over SPI + +How to do swap ? + diff --git a/Kernel/platform-spx302/config.h b/Kernel/platform-spx302/config.h new file mode 100644 index 00000000..7fb99bd6 --- /dev/null +++ b/Kernel/platform-spx302/config.h @@ -0,0 +1,47 @@ +/* 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 + +#define CONFIG_32BIT +#define CONFIG_LEVEL_2 + +#define CONFIG_MULTI +#define CONFIG_FLAT +#define CONFIG_PARENT_FIRST +#define CONFIG_USERMEM_DIRECT +#define CONFIG_BANKS (65536/512) + +#define CONFIG_LARGE_IO_DIRECT(x) 1 + +#define CONFIG_SPLIT_UDATA +#define UDATA_SIZE 1024 +#define UDATA_BLKS 2 + +#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 2 +#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ + +/* Could be bigger but we need to add hashing first and it's not clearly + a win with a CF card anyway */ +#define NBUFS 16 /* Number of block buffers */ +#define NMOUNTS 8 /* Number of mounts at a time */ + +#define MAX_BLKDEV 2 + +#define CONFIG_IDE + +#define platform_copyright() + +#define BOOTDEVICENAMES "hd#" diff --git a/Kernel/platform-spx302/crt0.S b/Kernel/platform-spx302/crt0.S new file mode 100644 index 00000000..910e1d78 --- /dev/null +++ b/Kernel/platform-spx302/crt0.S @@ -0,0 +1,33 @@ +/* + * Need to wipe BSS etc once we figure out our preferred boot method + * + * On entry we are loaded at $0400 with the loader and the loaders + * supervisor stack a mystery. We are in supervisor mode and the rest + * is our problem. + */ + #include "../kernel-68000.def" + + .globl __end + .globl __bss_start + +.mri 1 + byte $15 + byte $05 + byte $C0 + byte $DE +start: + or #$0700,sr + move.l #__bss_start,a0 + move.l #__end,d0 + sub.l a0,d0 + lsr.l #2,d0 +wipebss: + clr.l (a0)+ + dbra d0,wipebss + + lea udata_block0+UBLOCK_SIZE,a7 + bsr init_early + bsr init_hardware + bsr fuzix_main + or #$0700,sr +stop: bra stop diff --git a/Kernel/platform-spx302/devices.c b/Kernel/platform-spx302/devices.c new file mode 100644 index 00000000..a1729bc0 --- /dev/null +++ b/Kernel/platform-spx302/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 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) - 1) + return false; + else + return true; +} + +void device_init(void) +{ + devide_init(); +} diff --git a/Kernel/platform-spx302/devtty.c b/Kernel/platform-spx302/devtty.c new file mode 100644 index 00000000..ecffc83b --- /dev/null +++ b/Kernel/platform-spx302/devtty.c @@ -0,0 +1,149 @@ +/* + * The SPX302 has multiple serial ports but the 68302 built in ones are + * wired for RS485 so for now ignore them. Some day they'll be handy for + * TCP/IP ;-) + * + * This wants rewriting once it is all stable so that the serial interrupt + * isn't masked by the kernel and drives queues. + */ +#include +#include +#include +#include +#include +#include + +static unsigned char tbuf1[TTYSIZ]; +static unsigned char tbuf2[TTYSIZ]; + +#define UART_MRA 0x00 +#define UART_SRA 0x02 +#define UART_CSRA 0x02 +#define UART_CRA 0x04 +#define UART_RHRA 0x06 +#define UART_THRA 0x06 +#define UART_IPCR 0x08 +#define UART_ACR 0x08 +#define UART_ISR 0x0A +#define UART_IMR 0x0A +#define UART_CTU 0x0C +#define UART_CTUR 0x0C +#define UART_CTL 0x0E +#define UART_CTLR 0x0E +#define UART_MRB 0x10 +#define UART_SRB 0x12 +#define UART_CSRB 0x12 +#define UART_CRB 0x14 +#define UART_RHRB 0x16 +#define UART_THRB 0x16 +#define UART_IVR 0x18 +#define UART_OPCR 0x1A +#define UART_STARTCTR 0x1C +#define UART_SETOPR 0x1C +#define UART_STOPCTR 0x1E +#define UART_CLROPR 0x1E + +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}, +}; + +static uint8_t sleeping; + +/* For now */ +static tcflag_t console_mask[4] = { + _ISYS, + _OSYS, + _CSYS, + _LSYS +}; + +tcflag_t *termios_mask[NUM_DEV_TTY + 1] = { + NULL, + console_mask, + console_mask +}; + +static volatile uint8_t *uart_base = (volatile uint8_t *)0x300020; + +#define GETB(x) (uart_base[(x)]) +#define PUTB(x,y) uart_base[(x)] = (y) + +/* Output for the system console (kprintf etc). Polled. */ +void kputchar(char c) +{ + if (c == '\n') { + while(!(GETB(UART_SRA) & 4)); + PUTB(UART_THRA, '\r'); + } + while(!(GETB(UART_SRA) & 4)); + PUTB(UART_THRA, c); +} + +ttyready_t tty_writeready(uint8_t minor) +{ + uint8_t c = GETB(0x10 * (minor - 1) + UART_SRA); + return (c & 4) ? TTY_READY_NOW : TTY_READY_SOON; /* TX DATA empty */ +} + +void tty_putc(uint8_t minor, unsigned char c) +{ + PUTB(0x10 * (minor - 1) + UART_THRA, c); +} + +void tty_setup(uint8_t minor, uint8_t flags) +{ + /* TODO */ +} + +int tty_carrier(uint8_t minor) +{ + return 1; +} + +void tty_sleeping(uint8_t minor) +{ + sleeping |= 1 << minor; +} + +void tty_data_consumed(uint8_t minor) +{ +} + +static void tty_interrupt(uint8_t r) +{ + if (r & 0x02) { + r = GETB(UART_RHRA); + tty_inproc(1,r); + } + if (r & 0x01) { + if (sleeping & 2) + tty_outproc(1); + } + if (r & 0x04) { + /* How to clear break int ? */ + } + if (r & 0x20) { + r = GETB(UART_RHRB); + tty_inproc(2,r); + } + if (r & 0x10) { + if (sleeping & 4) + tty_outproc(2); + } + if (r & 0x40) { + /* How to clear break int ? */ + } +} + +void duart_interrupt(void) +{ + uint8_t r = GETB(UART_ISR); + tty_interrupt(r); +} + +void platform_interrupt(void) +{ + timer_interrupt(); +} diff --git a/Kernel/platform-spx302/devtty.h b/Kernel/platform-spx302/devtty.h new file mode 100644 index 00000000..14c28c31 --- /dev/null +++ b/Kernel/platform-spx302/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-spx302/fuzix.ld b/Kernel/platform-spx302/fuzix.ld new file mode 100644 index 00000000..ea455a5f --- /dev/null +++ b/Kernel/platform-spx302/fuzix.ld @@ -0,0 +1,87 @@ +STARTUP(crt0.o) +OUTPUT_ARCH(m68k) + +SEARCH_DIR(.) + +MEMORY +{ + ram (rwx) : ORIGIN = 0x400, LENGTH = 0x80000-0x400 +} + +/* + * stick everything in ram (of course) + */ +SECTIONS +{ + .text : + { + CREATE_OBJECT_SYMBOLS + *(.text .text.*) + + . = ALIGN(0x4); + /* These are for running static constructors and destructors under ELF. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + *(.rodata .rodata.*) + + . = ALIGN(0x4); + *(.gcc_except_table) + + . = ALIGN(0x4); + *(.eh_frame) + + . = ALIGN(0x4); + __INIT_SECTION__ = . ; + LONG (0x4e560000) /* linkw %fp,#0 */ + *(.init) + SHORT (0x4e5e) /* unlk %fp */ + SHORT (0x4e75) /* rts */ + + . = ALIGN(0x4); + __FINI_SECTION__ = . ; + LONG (0x4e560000) /* linkw %fp,#0 */ + *(.fini) + SHORT (0x4e5e) /* unlk %fp */ + SHORT (0x4e75) /* rts */ + + . = ALIGN(0x4); + _etext = .; + *(.lit) + } > ram + + .data : + { + *(.got.plt) *(.got) + *(.shdata) + *(.data .data.*) + _edata = .; + } > ram + + .bss : + { + . = ALIGN(0x4); + __bss_start = . ; + *(.shbss) + *(.bss .bss.*) + *(COMMON) + _end = ALIGN (0x8); + __end = _end; + } > ram + + .stab 0 (NOLOAD) : + { + *(.stab) + } + + .stabstr 0 (NOLOAD) : + { + *(.stabstr) + } +} diff --git a/Kernel/platform-spx302/kernel.def b/Kernel/platform-spx302/kernel.def new file mode 100644 index 00000000..4b1466f7 --- /dev/null +++ b/Kernel/platform-spx302/kernel.def @@ -0,0 +1,2 @@ +#define DI_MASK $700 /* or bits for DI */ +#define EI_MASK $000 /* or bits for EI */ \ No newline at end of file diff --git a/Kernel/platform-spx302/libc.c b/Kernel/platform-spx302/libc.c new file mode 100644 index 00000000..f172e3b1 --- /dev/null +++ b/Kernel/platform-spx302/libc.c @@ -0,0 +1,52 @@ +#include "cpu.h" + +/* FIXME: use proper fast methods */ + +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 *memcpy32(void *d, const void *s, size_t sz) +{ + uint32_t *dp = d; + const uint32_t *sp = s; + sz >>= 2; + 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-spx302/main.c b/Kernel/platform-spx302/main.c new file mode 100644 index 00000000..29247225 --- /dev/null +++ b/Kernel/platform-spx302/main.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include + +uint16_t swap_dev = 0xFFFF; + +void platform_idle(void) +{ + /* Use STOP ? */ +} + +void do_beep(void) +{ +} + +/* + * MMU initialize + */ + +void map_init(void) +{ +} + +uaddr_t ramtop; +uint8_t need_resched; + +uint8_t platform_param(char *p) +{ + return 0; +} + +void platform_discard(void) +{ + /* We need to put discard last and then adjust _end */ +} + +void memzero(void *p, usize_t len) +{ + memset(p, 0, len); +} + +void pagemap_init(void) +{ + /* Linker provided end of kernel */ + extern uint8_t _end; + uint32_t e = (uint32_t)&_end; + kprintf("Kernel end %p\n", e); + /* Allocate the rest of memory to the userspace. We have 1MB. For now + ignore the battery backed area */ + kmemaddblk((void *)e, 0xC0000 - e); +} + +/* Udata and kernel stacks */ +/* We need an initial kernel stack and udata so the slot for init is + set up at compile time */ +u_block udata_block0; +static u_block *udata_block[PTABSIZE] = {&udata_block0,}; + +/* This will belong in the core 68K code once finalized */ + +void install_vdso(void) +{ + extern uint8_t vdso[]; + /* Should be uput etc */ + memcpy((void *)udata.u_codebase, &vdso, 0x40); +} + +uint8_t platform_udata_set(ptptr p) +{ + u_block **up = &udata_block[p - ptab]; + if (*up == NULL) { + *up = kmalloc(sizeof(struct u_block), 0); + if (*up == NULL) + return ENOMEM; + } + p->p_udata = &(*up)->u_d; + return 0; +} diff --git a/Kernel/platform-spx302/p68000.S b/Kernel/platform-spx302/p68000.S new file mode 100644 index 00000000..e53d7c5d --- /dev/null +++ b/Kernel/platform-spx302/p68000.S @@ -0,0 +1,203 @@ + +#include "../kernel-68000.def" + + .globl platform_reboot + .globl init_early + .globl init_hardware + .globl program_vectors + .globl outchar + .globl platform_monitor + .globl udata_block0 + .globl devide_read_data + .globl devide_write_data + +.mri 1 +platform_monitor: +platform_reboot: +; +; FIXME: remap ROM at 0 and get back to it +; + or #$0700,sr + bra platform_monitor + +init_early: + lea.l udata_block0,a5 ; udata ptr + move.l a5,udata_shadow ; shadow copy for entry/exit + rts + +; +; FIXME: could be in discard if we wanted +; +init_hardware: + ; set system RAM size(hardcode hacks for now) + move.w #768,d0 ; ignore the ramdisc + move.w d0,ramsize + sub.w #64,d0 ; Guess for kernel + move.w d0,procmem ; guesses for now + + bsr install_vectors + + /* We use Vector 0x81 for the DUART */ + move.l #duart_irq,$204 + /* and the timer.. */ + /* 0x89 is the 68302 10ms timer */ + move.l #timer_irq,$224 + + rts + +duart_irq: + movem.l a0/a1/a5/d0/d1,-(sp) + jsr duart_interrupt + move.w #2,$FFF818 ; clear interrupt flag + movem.l (sp)+,a0/a1/a5/d0/d1 + rte + +timer_irq: + ; C will save and restore a2+/d2+ + movem.l a0-a1/a5/d0-d1,-(sp) + move.l udata_shadow,a5 ; set up the register global + move.b #1,U_DATA__U_ININTERRUPT(a5) + ; Now ack the hardware interrupt + move.b #3,$FFF849 ; Timer A event register + move.w #$200,$FFF818 ; Interrupt service + jsr platform_interrupt + clr.b U_DATA__U_ININTERRUPT(a5) + + tst.b U_DATA__U_INSYS(a5) + bne no_preempt + tst.b need_resched + beq no_preempt + ; + ; Vanish into the scheduler. Some other task will pop back out + ; and eventually we'll re-appear here and continue. + ; + move.l U_DATA__U_PTAB(a5),a0 + ; We might be in STOPPED state in which case do not go back + ; to ready ! + cmp.b #P_RUNNING,P_TAB__P_STATUS_OFFSET(a0) + bne no_ready + move.b #P_READY,P_TAB__P_STATUS_OFFSET(a0) +no_ready: + bsr switchout +no_preempt: + tst.b U_DATA__U_CURSIG(a5) + beq no_signal + ; FIXME: this is ugly + movem.l (sp)+,a0-a1/a5/d0-d1 + move.w sr,-(sp) + move.w #0,-(sp) + movem.l a0-a6/d0-d7,-(sp) + move.l (sp),-(sp) + bsr exception + addq #4,sp + movem.l (sp)+,a0-a6/d0-d7 + addq #4,sp + rte +no_signal: + movem.l (sp)+,a0-a1/a5/d0-d1 + rte + +; +; Nothing to do in 68000 - all set up once at boot +; +program_vectors: + rts + +; +; We do no banking so we need to do nothing here. +; +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: +outcharw: + btst #2,$00C00002 + beq outcharw + move.b d0,$00C00006 + rts + +; +; ATA CF support via PPIDE +; + +#define PortA8255 $300001 +#define PortB8255 $300003 +#define PortC8255 $300005 +#define Port8255Ctrl $300007 + +; +; Need to look at the fixes on write for the V1 board reliability. +; +devide_read_data: + movem.l a2/d2/d3,-(sp) + ; Target address + move.l (blk_op),a0 + ; Set up constants for speed + lea.l PortC8255,a1 + lea.l PortA8255,a2 + move.b #$40,d1 + move.b #$48,d2 + ; 256 words + ; Just in case a user is trying to do a misaligned raw I/O + move.w a0,d0 + btst #0,d0 + bne doreadblock8 + move.w #255,d0 +readblock: + ; Waggle the control signals + move.b d1,(a1) + move.b d2,(a1) + ; 16bits split across two words + movep.w 0(a2),d3 + ; Store to the target buffer + move.w d3,(a0)+ + dbra d0,readblock + move.b d1,(a1) + movem.l (sp)+,a2/d2/d3 + rts + +doreadblock8: + move.l a3,-(sp) + lea.l PortB8255,a3 + move.w #255,d0 +readblock8: + ; Waggle the control signals + move.b d1,(a1) + move.b d2,(a1) + ; 16bits split across two words + move.b (a3),(a0)+ + move.b (a2),(a0)+ + dbra d0,readblock8 + move.b d1,(a1) + move.l (sp)+,a3 + movem.l (sp)+,a2/d2/d3 + rts + +; FIXME: can we use movep + +devide_write_data: + movem.l a2-a3/d2,-(sp) + move.l (blk_op),a0 + lea.l PortA8255,a1 + lea.l PortB8255,a2 + lea.l PortC8255,a3 + move.b #$40,d1 + move.b #$50,d2 + move.b #$80,Port8255Ctrl + move.w #255,d0 +writeblock: + move.b (a0)+,(a1) + move.b (a0)+,(a2) + move.b d1,(a3) + move.b d2,(a3) + move.b d1,(a3) + dbra d0,writeblock + move.b #$92,Port8255Ctrl + movem.l (sp)+,a2-a3/d2 + rts diff --git a/Kernel/platform-spx302/platform_ide.h b/Kernel/platform-spx302/platform_ide.h new file mode 100644 index 00000000..3249b0e7 --- /dev/null +++ b/Kernel/platform-spx302/platform_ide.h @@ -0,0 +1,42 @@ +/* + * Platform specific declarations for the ParPort IDE device. + * This tells the shared driver how the thing is wired up. In our case + * it's MMIO + */ + +#define PPIDE_BASE 0x300000 /* Base address of 8255A */ +#define IDE_REG_INDIRECT /* IDE registers are not directly connected to the CPU bus */ + +/* IDE control signal to 8255 port C mapping */ +#define PPIDE_A0_LINE 0x01 // Direct from 8255 to IDE interface +#define PPIDE_A1_LINE 0x02 // Direct from 8255 to IDE interface +#define PPIDE_A2_LINE 0x04 // Direct from 8255 to IDE interface +#define PPIDE_CS0_LINE 0x08 // Inverter between 8255 and IDE interface +#define PPIDE_CS1_LINE 0x10 // Inverter between 8255 and IDE interface +#define PPIDE_WR_LINE 0x20 // Inverter between 8255 and IDE interface +#define PPIDE_WR_BIT 5 // (1 << PPIDE_WR_BIT) = PPIDE_WR_LINE +#define PPIDE_RD_LINE 0x40 // Inverter between 8255 and IDE interface +#define PPIDE_RD_BIT 6 // (1 << PPIDE_RD_BIT) = PPIDE_RD_LINE +#define PPIDE_RST_LINE 0x80 // Inverter between 8255 and IDE interface + +/* 8255 configuration */ +#define PPIDE_PPI_BUS_READ 0x92 +#define PPIDE_PPI_BUS_WRITE 0x80 + +/* IDE register addresses */ +#define ide_reg_data (PPIDE_CS0_LINE) +#define ide_reg_error (PPIDE_CS0_LINE | PPIDE_A0_LINE) +#define ide_reg_features (PPIDE_CS0_LINE | PPIDE_A0_LINE) +#define ide_reg_sec_count (PPIDE_CS0_LINE | PPIDE_A1_LINE) +#define ide_reg_lba_0 (PPIDE_CS0_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE) +#define ide_reg_lba_1 (PPIDE_CS0_LINE | PPIDE_A2_LINE) +#define ide_reg_lba_2 (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A0_LINE) +#define ide_reg_lba_3 (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE) +#define ide_reg_devhead (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE) +#define ide_reg_command (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE) +#define ide_reg_status (PPIDE_CS0_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE) +#define ide_reg_altstatus (PPIDE_CS1_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE) +#define ide_reg_control (PPIDE_CS1_LINE | PPIDE_A2_LINE | PPIDE_A1_LINE | PPIDE_A0_LINE) + +#define ide_select(x) +#define ide_deselect() diff --git a/Kernel/platform-spx302/ppide_spx302.c b/Kernel/platform-spx302/ppide_spx302.c new file mode 100644 index 00000000..3fbc235e --- /dev/null +++ b/Kernel/platform-spx302/ppide_spx302.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#include + +#define ppi_port_a *((volatile uint8_t *)0xC00001) /* LSB */ +#define ppi_port_b *((volatile uint8_t *)0xC00003) /* MSB */ +#define ppi_port_c *((volatile uint8_t *)0xC00005) /* IDE Control */ +#define ppi_control *((volatile uint8_t *)0xC00007) /* 82C55 Control */ + +void ppide_init(void) +{ + ppi_control = PPIDE_PPI_BUS_READ; + ppi_port_c = ide_reg_status; +} + +uint8_t devide_readb(uint8_t regaddr) +{ + uint8_t r; + + /* note: ppi_control should contain PPIDE_PPI_BUS_READ already */ + ppi_port_c = regaddr; + ppi_port_c = regaddr | PPIDE_RD_LINE; /* begin /RD pulse */ + r = ppi_port_a; + ppi_port_c = regaddr; /* end /RD pulse */ + return r; +} + +void devide_writeb(uint8_t regaddr, uint8_t value) +{ + ppi_control = PPIDE_PPI_BUS_WRITE; + ppi_port_c = regaddr; + ppi_port_a = value; + ppi_port_b = 0; + ppi_port_c = regaddr | PPIDE_WR_LINE; + /* FIXME: check timing */ + ppi_port_c = regaddr; + ppi_control = PPIDE_PPI_BUS_READ; +} diff --git a/Kernel/platform-spx302/target.mk b/Kernel/platform-spx302/target.mk new file mode 100644 index 00000000..df1c235f --- /dev/null +++ b/Kernel/platform-spx302/target.mk @@ -0,0 +1 @@ +export CPU = 68000 diff --git a/Kernel/platform-spx302/tricks.S b/Kernel/platform-spx302/tricks.S new file mode 100644 index 00000000..b98eaa3d --- /dev/null +++ b/Kernel/platform-spx302/tricks.S @@ -0,0 +1,3 @@ +#include "../kernel-68000.def" + +#include "../lib/68000flat.S" -- 2.34.1