From f5fa99d8c2970f6635b064d6f0be7e2238e4e65b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 7 Feb 2019 23:39:59 +0000 Subject: [PATCH] rabbit: initial work on the JackRabbit (BL18x0) boards Not yet anything fully build and bootable --- Kernel/platform-rabbit2000/Makefile | 47 +++ Kernel/platform-rabbit2000/README | 115 ++++++++ Kernel/platform-rabbit2000/commonmem.s | 9 + Kernel/platform-rabbit2000/config.h | 60 ++++ Kernel/platform-rabbit2000/crt0.s | 107 +++++++ Kernel/platform-rabbit2000/devices.c | 40 +++ Kernel/platform-rabbit2000/devtty.c | 97 ++++++ Kernel/platform-rabbit2000/devtty.h | 10 + Kernel/platform-rabbit2000/fuzix.lnk | 40 +++ Kernel/platform-rabbit2000/interrupt.s | 120 ++++++++ Kernel/platform-rabbit2000/kernel.def | 11 + Kernel/platform-rabbit2000/main.c | 43 +++ Kernel/platform-rabbit2000/rabbit.h | 119 ++++++++ Kernel/platform-rabbit2000/rabbit.s | 390 +++++++++++++++++++++++++ Kernel/platform-rabbit2000/target.mk | 2 + Kernel/platform-rabbit2000/tricks.s | 5 + 16 files changed, 1215 insertions(+) create mode 100644 Kernel/platform-rabbit2000/Makefile create mode 100644 Kernel/platform-rabbit2000/README create mode 100644 Kernel/platform-rabbit2000/commonmem.s create mode 100644 Kernel/platform-rabbit2000/config.h create mode 100644 Kernel/platform-rabbit2000/crt0.s create mode 100644 Kernel/platform-rabbit2000/devices.c create mode 100644 Kernel/platform-rabbit2000/devtty.c create mode 100644 Kernel/platform-rabbit2000/devtty.h create mode 100644 Kernel/platform-rabbit2000/fuzix.lnk create mode 100644 Kernel/platform-rabbit2000/interrupt.s create mode 100644 Kernel/platform-rabbit2000/kernel.def create mode 100644 Kernel/platform-rabbit2000/main.c create mode 100644 Kernel/platform-rabbit2000/rabbit.h create mode 100644 Kernel/platform-rabbit2000/rabbit.s create mode 100644 Kernel/platform-rabbit2000/target.mk create mode 100644 Kernel/platform-rabbit2000/tricks.s diff --git a/Kernel/platform-rabbit2000/Makefile b/Kernel/platform-rabbit2000/Makefile new file mode 100644 index 00000000..fc94afb6 --- /dev/null +++ b/Kernel/platform-rabbit2000/Makefile @@ -0,0 +1,47 @@ +ASRCS = crt0.s tricks.s commonmem.s rabbit.s +CSRCS = devices.c main.c devtty.c +DISCARD_CSRCS = +DISCARD_DSRCS = ../dev/devsd_discard.c +DSRCS = ../dev/devsd.c ../dev/mbr.c ../dev/blkdev.c + +AOBJS = $(ASRCS:.s=.rel) +COBJS = $(CSRCS:.c=.rel) +DISCARD_COBJS = $(DISCARD_CSRCS:.c=.rel) +DISCARD_DOBJS = $(patsubst ../dev/%.c,%.rel, $(DISCARD_DSRCS)) +DOBJS = $(patsubst ../dev/%.c,%.rel, $(DSRCS)) +DAOBJS = $(patsubst ../dev/%.s,%.rel, $(DASRCS)) + +OBJS = $(AOBJS) $(COBJS) $(DOBJS) $(DAOBJS) $(DISCARD_DOBJS) $(DISCARD_COBJS) + +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) --codeseg COMMONMEM -c $< + +$(DOBJS): %.rel: ../dev/%.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +$(DAOBJS): %.rel: ../dev/%.s + $(CROSS_AS) $(ASOPTS) $@ $< + +$(DISCARD_COBJS): %.rel: %.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< + +$(DISCARD_DOBJS): %.rel: ../dev/%.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< + +clean: + rm -f $(OBJS) $(JUNK) core *~ fuzix.com + +# +# Compile up the boot block +# +image: + diff --git a/Kernel/platform-rabbit2000/README b/Kernel/platform-rabbit2000/README new file mode 100644 index 00000000..0fbfd63e --- /dev/null +++ b/Kernel/platform-rabbit2000/README @@ -0,0 +1,115 @@ +First sketches for the Rabbit 2000 + +Hardware BL18x0 'Jackrabbit' boards + + Rabbit 2000 @29.5 or 14.74MHz + 128K or 256K flash (256K on the 1800 only) + 128K SRAM (factory option for 512K) + + Serial A: control cable + Serial B: (we use for SPI instead) RS232 + Serial C: RS232 + Serial D: RS485 + + RTC and SRAM have battery backup + +PA0-PA7 Parallel I/O (Free unless doing slave stuff) +PB0/PB1 Serial clock (CLKA is connected to programming port) + CLKB is needed for SPI +PB2-7 Free if not using slave +PC0-PC7 Serial port outputs + 0-1 D to RS485 + 2-5 B and C to RS232 + 6-7 A to programming port +PD0-PD7 + 1-2 Control DA0 + 4 Control D1 (alt port B TX) + 5 RS485 data enable (alt port B RX) + 6-7 (Alt port A) +PE0-PE7 + 0 HV0 output control + 1 HV1 output control + 2 HV2 output control + 3 HV3 output control + 4-5 (INT0B/INT1B) + 6 A/D comparator output + 7 A/D comparator output + + + + + +The memory map of the R2K is fairly similar to the Z180 but not quite + +0000 Base segment +x000 Data segment +y000 Stack segment +E000 XPC + +The stack and data segment boundaries can be adjusted and the root segment +can even be vanished entirely as can stack or data. The E000-FFFF window +is however fixed and controlled by its own register (XPC) + +For simplicity try and get running with E000-FFFF as common. There are better +layouts but they are more complex. + +There are two further complications however + +1. The 20bit physical address gets fed into a memory interface unit which +in theory just sets the wait states and chip selects. However once you get +more than 1MB it starts getting used for other games as you can route all the +address lines to each RAM and use the chip selects as a kind of A20/A21 +address line and do further banking this way from software. For now we will +ignore this as it's usually on Rabbbit 3000 stuff that hits this. + +2. All but the early Rabbit 2000 chips support split I/D. In split I/D mode +the physical address can have either bit 16 or bit 19 inverted when accessing +data. bit 16 effectively requires a 128K chunk of memory suitably aligned. Bit +19 is intended for code from flash and data from RAM so is not of interest. + + +Rabbit 2000 CPU bugs/differences + +2000 No split ID, no 9bit serial helper + Must nop after some I/O operations + Cannot start tx/rx together for SPI + Wait state bugs (notably in LDxR) + +2000A Split I/D supported, 9bit serial added + Most instruction bugs fixed + Can start tx/rx together for SPI + LDIR broken differently (do not use with split I/D) + +2000B Rare special run. Differently buggy LDIR + +2000C Later edition. Adds early I/O enable + Fixes LDIR split I/D and breaks it differently + +In general then +- nop after I/O operations using ioo foo (HL) - all the logic ops and LD +- don't use LDxR + + + +Badly Documented Stuff + +GCSR register + +(0x10->0x9 is done going from 32Khz to main clock) +Write 0x10 to turn on the main oscillator 00010000 +Write 0x09 to switch the CPU onto it 00001001 +Write 0x05 to switch on /8 clock divider 00000101 +Write 0x14 to switch to 32Khz osc and disable 2Khz tick + 00011000 + +So my guess is + +bit 0 - set enabbles the tick +bit 4 - set enables the CPU to run on 32Khz +bit 3-2 control the clock + + +Serial oddity + +- to send a break switch the tty port off (disconnect from the port C/D) and +use the I/O bit interface to set/lower the bit! diff --git a/Kernel/platform-rabbit2000/commonmem.s b/Kernel/platform-rabbit2000/commonmem.s new file mode 100644 index 00000000..309b8b6a --- /dev/null +++ b/Kernel/platform-rabbit2000/commonmem.s @@ -0,0 +1,9 @@ +; +; Common on z80pack is at 0xF000 as defined by hardware. +; + + .module commonmem + + .area _COMMONMEM + + .include "../cpu-r2k/std-commonmem.s" diff --git a/Kernel/platform-rabbit2000/config.h b/Kernel/platform-rabbit2000/config.h new file mode 100644 index 00000000..65a9cc48 --- /dev/null +++ b/Kernel/platform-rabbit2000/config.h @@ -0,0 +1,60 @@ +/* We have an RTC */ +#undef CONFIG_RTC +/* And we can read ToD from it */ +#undef CONFIG_RTC_FULL +/* 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 +/* Fixed banking */ +#define CONFIG_BANK_FIXED +/* 2 32K banks, + 64K is kernel */ +/* When we run from flash we'll fix this to 2 x 64K */ +#define MAX_MAPS 2 +#define MAP_SIZE 0x8000U + +#define CONFIG_SD +#define SD_DRIVE_COUNT 1 +#define MAX_BLKDEV 1 + +/* Read processes and big I/O direct into process space */ +#define CONFIG_LARGE_IO_DIRECT(x) 1 + +/* Banks as reported to user space */ +#define CONFIG_BANKS 1 + +#define TICKSPERSEC 200 /* Ticks per second */ +#define PROGBASE 0x0000 /* also data base */ +#define PROGLOAD 0x0100 /* also data base */ +#define PROGTOP 0x7E00 /* Top of program, base of U_DATA copy */ +#define PROC_SIZE 40 /* Memory needed per process */ + +#define SWAP_SIZE 0x40 /* 48K in blocks (we actually don't need the low 256) */ +#define SWAPBASE 0x0000 /* We swap the lot in one, include the */ +#define SWAPTOP 0x8000 /* vectors so its a round number of sectors */ +#define MAX_SWAPS 16 /* The full drive would actually be 85! */ + +#define swap_map(x) ((uint8_t *)(x)) /* Simple zero based mapping */ + +#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 NULL /* Location of root dev name */ + +/* Device parameters */ +#define NUM_DEV_TTY 3 + +#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ +#define SWAPDEV (256 + 1) /* Device for swapping. (FIXME) */ +#define NBUFS 8 /* Number of block buffers */ +#define NMOUNTS 4 /* Number of mounts at a time */ + +#define platform_discard() +#define platform_copyright() diff --git a/Kernel/platform-rabbit2000/crt0.s b/Kernel/platform-rabbit2000/crt0.s new file mode 100644 index 00000000..a40a6917 --- /dev/null +++ b/Kernel/platform-rabbit2000/crt0.s @@ -0,0 +1,107 @@ + .module crt0 + + ; Segment order + ; Note: the code segments may be in flash + .area _CODE + .area _CODE2 + .area _CONST + .area _INITIALIZED + .area _DATA + .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 + .globl _kdataseg + + ; startup code + .area _CODE + + .include "kernel.def" + .include "../kernel-rabbit.def" +; +; For a RAM startup our configuration is +; +; Interrupts off +; Stack undefined +; +; DATASEG set from 0-DFFF +; XPC segment undefined but will be somewhere in the bootstrap +; as it will jump to 0 +; +; Physically mapped so that the kernel starts at ram address 0x0000 +; +; Serial console is configured, wait states and cs are set up validly +; +init: + ld sp, #kstack_top + + ; Learn our banks + + ; Will need extending when we start to run from flash + ioi + ld a,(DATASEG) + ld (_kdataseg),a + add a,#14 ; 56K on (our E000) + ld xpc,a ; We now have 64K linear physical + ; space + ; For now we don't move XPC, that will change eventually + + ; + ; our stack pointer is now valid (we can't do the above in + ; init_early as we have no sane stack) + ; + + ; Configure memory map + call init_early + + ; move the common memory where it belongs (our XPC is now valid) + ld hl, #s__DATA + ld de, #s__COMMONMEM + ld bc, #l__COMMONMEM + call doldir + ; and the discard + ld de, #s__DISCARD + ld bc, #l__DISCARD + call doldir + ; then zero the data area + ld hl, #s__DATA + ld de, #s__DATA + 1 + ld bc, #l__DATA - 1 + ld (hl), #0 + call doldir + + ; Hardware setup + call init_hardware + + ; Call the C main routine + call _fuzix_main + + ; main shouldn't return, but if it does... +stop: jr stop + +doldir: + ; the ldir instruction is broken in Rabbit 2000 series CPU + ; in differing ways depending upon the chip version. So just + ; skip using it. + ldi + jp lo,doldir + ret diff --git a/Kernel/platform-rabbit2000/devices.c b/Kernel/platform-rabbit2000/devices.c new file mode 100644 index 00000000..707b6649 --- /dev/null +++ b/Kernel/platform-rabbit2000/devices.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct devsw dev_tab[] = /* The device driver switch table */ +{ + /* 0: /dev/hd Hard disc block devices */ + { blkdev_open, no_close, blkdev_read, blkdev_write, blkdev_ioctl }, + /* 1: /dev/fd Floppy disc block devices: nope */ + { no_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 }, + /* 5: 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) +{ +#ifdef CONFIG_SD + devsd_init(); +#endif +} diff --git a/Kernel/platform-rabbit2000/devtty.c b/Kernel/platform-rabbit2000/devtty.c new file mode 100644 index 00000000..d223518e --- /dev/null +++ b/Kernel/platform-rabbit2000/devtty.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include + +#include "rabbit.h" + +static char tbuf1[TTYSIZ]; +static char tbuf2[TTYSIZ]; +static char tbuf3[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, tbuf3, tbuf3, TTYSIZ, 0, TTYSIZ/2 }, +}; + +static tcflag_t console_mask[4] = { + _ISYS, + _OSYS, + _CSYS, + _LSYS +}; + +/* Port B is owned by our SPI code */ +static uint8_t serial_map[4] = { 0, SADR-SADR, SCDR-SADR, SDDR-SADR }; + +/* TODO: stty support for the r2k ports */ +tcflag_t *termios_mask[NUM_DEV_TTY + 1] = { + NULL, + console_mask, + console_mask, +}; + +void tty_setup(uint8_t minor, uint8_t flags) +{ + minor; +} + +/* For the moment */ +int tty_carrier(uint8_t minor) +{ + minor; + return 1; +} + +/* + * Drain the interrupt queue + */ +void tty_pollirq(void) +{ + uint16_t c; + while((c = sera_get()) != 0xFF) + tty_inproc(1, c); + while((c = serc_get()) != 0xFF) + tty_inproc(2, c); + while((c = serd_get()) != 0xFF) + tty_inproc(3, c); +} + +void tty_putc(uint8_t minor, unsigned char c) +{ + out(SADR + serial_map[minor], c); +} + +void tty_sleeping(uint8_t minor) +{ + minor; +} + +void tty_data_consumed(uint8_t minor) +{ +} + +ttyready_t tty_writeready(uint8_t minor) +{ + uint8_t r = in(SASR + serial_map[minor]); + /* FIXME: should go IRQ driven */ + if (r & 4) + return TTY_READY_SOON; + else + return TTY_READY_NOW; +} + +/* kernel writes to system console -- never sleep! */ +void kputchar(char c) +{ + while(tty_writeready(TTYDEV) != TTY_READY_NOW); + tty_putc(TTYDEV & 0xFF, c); + if(c == '\n') { + while(tty_writeready(TTYDEV) != TTY_READY_NOW); + tty_putc(TTYDEV & 0xFF, '\r'); + } +} diff --git a/Kernel/platform-rabbit2000/devtty.h b/Kernel/platform-rabbit2000/devtty.h new file mode 100644 index 00000000..64a8d3de --- /dev/null +++ b/Kernel/platform-rabbit2000/devtty.h @@ -0,0 +1,10 @@ +extern void tty_pollirq(void); + +extern uint16_t sera_get(void); +extern void sera_setup(uint8_t set) __z88dk_fastcall; + +extern uint16_t serc_get(void); +extern void serc_setup(uint8_t set) __z88dk_fastcall; + +extern uint16_t serd_get(void); +extern void serd_setup(uint8_t set) __z88dk_fastcall; diff --git a/Kernel/platform-rabbit2000/fuzix.lnk b/Kernel/platform-rabbit2000/fuzix.lnk new file mode 100644 index 00000000..96b79135 --- /dev/null +++ b/Kernel/platform-rabbit2000/fuzix.lnk @@ -0,0 +1,40 @@ +-mwxuy +-i fuzix.ihx +-l r2k +-b _CODE=0x0100 +-b _COMMONMEM=0xF000 +-b _DISCARD=0xD800 +platform-rabbit2000/crt0.rel +platform-rabbit2000/commonmem.rel +platform-rabbit2000/rabbit.rel +platform-rabbit2000/main.rel +start.rel +version.rel +lowlevel-r2k.rel +usermem_std-r2k.rel +platform-rabbit2000/tricks.rel +timer.rel +kdata.rel +usermem.rel +platform-rabbit2000/devices.rel +devio.rel +filesys.rel +process.rel +inode.rel +syscall_exec16.rel +syscall_fs.rel +syscall_fs2.rel +syscall_fs3.rel +syscall_proc.rel +syscall_other.rel +tty.rel +mm.rel +bankfixed.rel +swap.rel +devsys.rel +platform-rabbit2000/devtty.rel +platform-rabbit2000/devsd.rel +platform-rabbit2000/devsd_discard.rel +platform-rabbit2000/mbr.rel +platform-rabbit2000/blkdev.rel +-e diff --git a/Kernel/platform-rabbit2000/interrupt.s b/Kernel/platform-rabbit2000/interrupt.s new file mode 100644 index 00000000..a5188058 --- /dev/null +++ b/Kernel/platform-rabbit2000/interrupt.s @@ -0,0 +1,120 @@ +; +; The interrupt page. We fold IIR and EIR together +; +; For interrupts we should never get we do the required +; irq clearing reads. +; + .module iir + + .area _IIR + + .globl unix_syscall_entry + .globl ticktock + +periodic: +eir0: ; If we use both we'll need to do some + ; thinking and maybe split this + jp ticktock + + .bndry 16 +eir1: + ipres + ret + + .bndry 16 + +rst10: + ret + + .bndry 16 + +rst18: + ret + + .bndry 16 + +rst20: + ret + + .bndry 16 + +rst28: + jp unix_syscall_entry + + .bndry 16 + +spare: + ret + .bindry 16 + +rst38: + ret + + .bndry 16 + +slave: + ipres + ret + + .bndry 16 + +spare2: + ret + + .bndry 16 + +timera: + push af + ioi ld a,(TACSR) + pop af + ipres + ret + + .bndry 16 + +timerb: + push af + ioi ld a,(TBCSR) + pop af + ipres + ret + + .bndry 16 + +seriala: + push af + ioi ld a,(SASR) + or a + jp m,sera_rx + jp sera_tx + + .bndry 16 + +; +; B is our SPI +; +serialb: + ipres + ret + + .bndry 16 + +serialc: + push af + ioi ld a,(SCSR) + or a + jp m,serc_rx + jp serc_tx + + + .bndry 16 + +seriald: + push af + ioi ld a,(SDSR) + or a + jp m,serd_rx + jp serd_tx + + + .bndry 16 diff --git a/Kernel/platform-rabbit2000/kernel.def b/Kernel/platform-rabbit2000/kernel.def new file mode 100644 index 00000000..718bf95a --- /dev/null +++ b/Kernel/platform-rabbit2000/kernel.def @@ -0,0 +1,11 @@ +; UZI mnemonics for memory addresses etc + +U_DATA .equ 0xE000 ; (this is struct u_data from kernel.h) +U_DATA__TOTALSIZE .equ 0x200 ; 256+256 bytes. + +U_DATA_STASH .equ 0xBE00 ; BE00-BFFF + +PROGBASE .equ 0x0000 +PROGLOAD .equ 0x0100 + +CONFIG_SWAP .equ 1 diff --git a/Kernel/platform-rabbit2000/main.c b/Kernel/platform-rabbit2000/main.c new file mode 100644 index 00000000..f727031e --- /dev/null +++ b/Kernel/platform-rabbit2000/main.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include + +uaddr_t ramtop = PROGTOP; + +void pagemap_init(void) +{ + int i; + for (i = 0; i < 2; i++) + pagemap_add(kdataseg + 16 + i << 3); /* In 32K chunks to get us going */ +} + +/* On idle we spin checking for the terminals. Gives us more responsiveness + for the polled ports */ +void platform_idle(void) +{ + /* We don't want an idle poll and IRQ driven tty poll at the same moment */ + irqflags_t irq = di(); + tty_pollirq(); + irqrestore(irq); +} + +void platform_interrupt(void) +{ + tty_pollirq(); + timer_interrupt(); +} + +/* Nothing to do for the map of init */ +void map_init(void) +{ +} + +uint8_t platform_param(char *p) +{ + used(p); + return 0; +} + diff --git a/Kernel/platform-rabbit2000/rabbit.h b/Kernel/platform-rabbit2000/rabbit.h new file mode 100644 index 00000000..fcfd7005 --- /dev/null +++ b/Kernel/platform-rabbit2000/rabbit.h @@ -0,0 +1,119 @@ +extern uint8_t kdataseg; + +extern void rabbit_spi_tx(uint8_t c) __z88dk_fastcall; +extern uint8_t rabbit_spi_rx(void); +extern void rabbit_spi_slow(void); +extern void rabbit_spi_fast(void); +extern void rabbit_read_rtc(uint8_t *ptr) __z88dk_fastcall; +extern void rabbit_bop_watchdog(uint8_t code) __z88dk_fastcall; + +#define GCSR 0x00 +#define RTCCR 0x01 +#define RTC0R 0x02 +#define RTC1R 0x03 +#define RTC2R 0x04 +#define RTC3R 0x05 +#define RTC4R 0x06 +#define RTC5R 0x07 +#define WDTCR 0x08 +#define WDTTR 0x09 +#define GCM0R 0x0A +#define GCM1R 0x0B +#define GOCR 0x0E +#define GCDR 0x0F +#define MMIDR 0x10 +#define STACKSEG 0x11 +#define DATASEG 0x12 +#define SEGSIZE 0x13 +#define MB0CR 0x14 +#define MB1CR 0x15 +#define MB2CR 0x16 +#define MB3CR 0x17 +#define SPD0R 0x20 +#define SPD1R 0x21 +#define SPD2R 0x22 +#define SPSR 0x23 +#define SPCR 0x24 +#define GCPU 0x2E +#define GREV 0x2F +#define PADR 0x30 +#define PBDR 0x40 +#define PCDR 0x50 +#define PCFR 0x55 +#define PDDR 0x60 +#define PDCR 0x64 +#define PDFR 0x65 +#define PDDCR 0x66 +#define PDDDR 0x67 +#define PDB0R 0x68 +#define PDB1R 0x69 +#define PDB2R 0x6A +#define PDB3R 0x6B +#define PDB4R 0x6C +#define PDB5R 0x6D +#define PDB6R 0x6E +#define PDB7R 0x6F +#define PEDR 0x70 +#define PECR 0x74 +#define PEFR 0x75 +#define PEDDR 0x77 +#define PEB0R 0x78 +#define PEB1R 0x79 +#define PEB2R 0x7A +#define PEB3R 0x7B +#define PEB4R 0x7C +#define PEB5R 0x7D +#define PEB6R 0x7E +#define PEB7R 0x7F +#define IB0CR 0x80 +#define IB1CR 0x81 +#define IB2CR 0x82 +#define IB3CR 0x83 +#define IB4CR 0x84 +#define IB5CR 0x85 +#define IB6CR 0x86 +#define IB7CR 0x87 +#define I0CR 0x98 +#define I1CR 0x99 +#define TACSR 0xA0 +#define TACR 0xA2 +#define TAT1R 0xA3 +#define TAT4R 0xA9 +#define TAT5R 0xAB +#define TAT6R 0xAD +#define TAT7R 0xAF +#define TBCSR 0xB0 +#define TBCR 0xB1 +#define TBM1R 0xB2 +#define TBL1R 0xB3 +#define TBM2R 0xB4 +#define TBL2R 0xB5 +#define TBCMR 0xBE +#define TBCLR 0xBF +#define SADR 0xC0 +#define SAAR 0xC1 +#define SALR 0xC2 +#define SASR 0xC3 +#define SACR 0xC4 +#define SBDR 0xD0 +#define SBAR 0xD1 +#define SBLR 0xD2 +#define SBSR 0xD3 +#define SBCR 0xD4 +#define SCDR 0xE0 +#define SCAR 0xE1 +#define SCLR 0xE2 +#define SCSR 0xE3 +#define SCCR 0xE4 +#define SDDR 0xF0 +#define SDAR 0xF1 +#define SDLR 0xF2 +#define SDSR 0xF3 +#define SDCR 0xF4 + +#define GREV_R2000 0x00 +#define GREV_R2000A 0x01 +#define GREV_R2000B 0x02 +#define GREV_R2000C 0x03 + +#define GCPU_R2000 0x01 diff --git a/Kernel/platform-rabbit2000/rabbit.s b/Kernel/platform-rabbit2000/rabbit.s new file mode 100644 index 00000000..779b7670 --- /dev/null +++ b/Kernel/platform-rabbit2000/rabbit.s @@ -0,0 +1,390 @@ +; +; Skeleton for Rabbit 2000 +; + .module rabbit + + .area _COMMONMEM + + .globl _platform_reboot + .globl _platform_monitor + + .include 'kernel.def' + .include '../kernel-rabbit.def' + +_platform_reboot: +_platform_monitor: + ; Force a hardware level reset using the watchdog + ld a,#0x53 + ioi + ld (WDTCR),a + jr _platform_monitor + + .globl platform_interrupt_all + +platform_interrupt_all: + ret + + .area _COMMONDATA + + .globl _int_disabled + +_int_disabled: + .db 1 + + + .area _CODE + + .globl init_early + .globl init_hardware + + .globl _ramsize + .globl _procmem + +init_early: + ret + +init_hardware: + ; FIXME: should get this from firmware + ld hl,#128 + ld (_ramsize),hl + ld de,#64 + or a,a + sbc hl,de + ld (_procmem),hl + ret + + .area _COMMONMEM + + .globl _program_vectors + +_program_vectors: + ret + + + .globl map_process + .globl map_process_always + .globl map_process_always_di + .globl map_process_a + .globl map_kernel + .globl map_kernel_di + .globl map_save_kernel + .globl map_restore + + .globl _kdataseg + +map_kernel: +map_kernel_di: + push af + ld a,(_kdataseg) + ioi + ld (DATASEG),a + pop af + ret + +map_process: +map_process_di: + ld a,h + or a,l + jr z, map_kernel + ld a,(hl) +map_process_a: + ioi + ld (DATASEG),a + ret +map_process_always: +map_process_always_di: + push af + ld a,(U_DATA__U_PAGE) + ioi + ld (DATASEG),a + pop af + ret +map_save_kernel: + push af + ioi + ld a, (DATASEG) + ld (map_store),a + ld a,(_kdataseg) + ioi + ld (DATASEG),a ; Must match map_kernel + pop af + ret +map_restore: + push af + ld a,(map_store) + ioi + ld (DATASEG),a + pop af + ret +map_store: + .db 0 +_kdataseg: + .db 0 + + .globl outchar + +outchar: + push af +outwait: + ioi + ld a, (SASR) + bit 2,a + jr nz,outwait + pop af + ioi + ld (SADR),a + ret + + .globl _spi_tx +; +; Low level Rabbit 2000 primitives to use Port B for SPI. +; +; Assumptions: The port is configured and the clock is set up +; properly. That is you have the serial pins enabled and you have +; timer A5 programmed and running. +; +; We don't support simultaneous rx/tx although the R2000 can do it +; at lower speeds with some mucking about. SD doesn't need the full +; duplex behaviour. +; +; Remember the bit ordering ! + + + .area _CODE + + .globl _rabbit_spi_tx + .globl _rabbit_spi_rx + .globl _rabbit_spi_slow + .globl _rabbit_spi_fast +; +_rabbit_spi_tx: + ; Finish any previous transaction activity + ioi + ld a,(SBSR) + bit 7,a + jr nz,_rabbit_spi_tx + ld a,l + ioi + ld (SBDR),a + ld a, #0x8C ; send, our clock (ie master) + ioi + ld (SBCR),a +txwait: ioi + ld a,(SBSR) + bit 3,a + jr nz,txwait +txwait2: ioi + ld a,(SBSR) + bit 2,a + jr nz,txwait2 + ret + +_rabbit_spi_rx: + ; Fire up the receiver and clock + ld a,#0x4C ; receive (using PC4, 0x5C is PD4) + ioi + ld (SBCR),a + ; Wait for the data byte to appear + ; This is bounded by the synchronous clock +rxwait: + ioi + ld a,(SBSR) + and a,#0x80 + jr z,rxwait + ioi + ld a,(SBDR) + ld l,a + ret + + +; +; Slow speed for probing +; +_rabbit_spi_slow: + ld a,#30 ; about 25KHz with a 29.5MHz clock + ioi + ld (TAT5R),a + ret + +; +; Set the timer for fast SPI. +; +; We are limited to about 7.5MHz +; +_rabbit_spi_fast: + xor a,a + ioi + ld(TAT5R),a + ret + +; +; Real time clock interface. This is a 48bit counter running at 32KHz +; +; Convention is that clock 0 is Jan 1 1980 +; +; The caller needs to ensure that they get two identical copies +; + + .globl _rabbit_read_rtc + +_rabbit_read_rtc: + ex de,hl ; C argument is the buffer + ld hl,#RTC0R + ioi + ld (hl),#0 + nop ; R2000 erratum + ipset3 + ioi + ldi + ioi + ldi + ioi + ldi + ioi + ldi + ioi + ldi + ioi + ldi + ipres + ret + +; +; Watchdog timer +; +; 0x5A = 2 second, 0x57 = 1 second, 0x59 = 500m, 0x53 = 250ms +; + .globl _rabbit_bop_watchdog + +_rabbit_bop_watchdog: + ld a,l + ioi + ld (WDTCR),a + ret +; +; Periodic interrupt. Annoyingly fixed at 2KHz it seems +; This is the same for all rabbit 2k so maybe it belongs in the +; lowlevel-rabbit code ? +; + .globl ticktock + + .globl _ticker + .globl interrupt_handler +ticktock: + push af + ioi + ld a,(GCSR) + push hl + ld hl,#_ticker + inc (hl) + jr z,tickwrap + pop hl + pop af + ipres + ret +tickwrap: ld (hl),#11 ; slightly off for 200/second but the rtc + ; will compensate just fine. We need the + ; speed for the serial queues + jp interrupt_handler + +; +; Serial queues. The basic logic for them is given in the manual +; We do a simple optimization - our queues never cross a page. With +; the free d we then read the char early +; +; Our platform interrupt will pick up the queue each timer tick +; + +.macro serial X Y + + .area _COMMONMEM + + .globl _ser'X'_q + .globl _ser'X'_rxbuf + +ser'X'_rx: + push hl + push de + ioi + ld a,(S'Y'DR) + ld d,a + ld hl,#_ser'X'_q + ld a,(hl) + ld e,a + inc hl + cp a,(hl) + jr z,ser'X'_rx_over + inc a + and a, #63 + dec hl + ld (hl),a + ipres + ; work around stupid linker bug + ld hl, #_ser'X'_rxbuf + ld l,e + ld (hl),d +ser'X'_rx_over: ; for now do nothing clever + pop de + pop hl + pop af + ret + +ser'X'_tx: ; really 'transmit and other...' + ; we don't do transmit interrupts yet but we + ; can't turn them off alone 8( + ioi + ld (S'Y'SR),a + pop af + ipres + ret + + .globl _ser'X'_setup + .globl _ser'X'_get + +; +; 00PPMMII +; +; PP 00 port C 01 port D 1X off +; MM 00 8bit 01 7bit 10 clocked ext, 11 clocked int +; II 00 no int 01 pri 1 10 pri 2 11 pri 3 +; +_ser'X'_setup: + ld a,l + ioi + ld (S'Y'CR),a + ret + +_ser'X'_get: + ld hl,#_ser'X'_q + ld a,(hl) ; out ptr + ld e,a + inc hl + inc a + cp a,(hl) ; in ptr + jr nz, ser'X'_empty + dec hl + ipset3 + ld (hl),a + ld hl,#_ser'X'_rxbuf ; work around dumb linker limit + ld l,e + ld l,(hl) + ld h,#0 + ipres + ret +ser'X'_empty: + ld hl,#0xffff + ret +_ser'X'_q: + .db 0 + .db 1 + + .area _SERIALBUF + +_ser'X'_rxbuf: .ds 64 + + .area _COMMONMEM +.endm + +serial a A +serial c C +serial d D diff --git a/Kernel/platform-rabbit2000/target.mk b/Kernel/platform-rabbit2000/target.mk new file mode 100644 index 00000000..6c5c8de1 --- /dev/null +++ b/Kernel/platform-rabbit2000/target.mk @@ -0,0 +1,2 @@ +export CPU = r2k + diff --git a/Kernel/platform-rabbit2000/tricks.s b/Kernel/platform-rabbit2000/tricks.s new file mode 100644 index 00000000..4aaa98a0 --- /dev/null +++ b/Kernel/platform-rabbit2000/tricks.s @@ -0,0 +1,5 @@ + + .include "../kernel.def" + .include "kernel.def" + + .include "../lib/r2kfixedbank.s" -- 2.34.1