Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fuzix kernel Z180 support, p112 and n8vem-mark4 platforms, other minor fixes #30

Merged
merged 15 commits into from
Dec 27, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions Kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ export SUBVERSION = "ac1"

UNAME_S := $(shell uname -s)

ifeq ($(CPU),z80)
ifneq (,$(filter $(CPU),z80 z180)) # matches CPU = z80 or z180
export CROSS_AS=sdasz80
export CROSS_LD=sdldz80
export CROSS_CC=sdcc
#export CROSS_CCOPTS=-c --std-sdcc99 --no-std-crt0 -mz80 -I$(ROOT_DIR)/cpu-z80 -I$(ROOT_DIR)/platform-$(TARGET) -I$(ROOT_DIR)/include --max-allocs-per-node 1000000 --opt-code-size --Werror --stack-auto --constseg CONST
#export CROSS_CCOPTS=-c --std-sdcc99 --no-std-crt0 -mz80 -I$(ROOT_DIR)/cpu-z80 -I$(ROOT_DIR)/platform-$(TARGET) -I$(ROOT_DIR)/include --max-allocs-per-node 200000 --opt-code-size --Werror --stack-auto --constseg CONST
export CROSS_CCOPTS=-c --std-sdcc99 --no-std-crt0 -mz80 -I$(ROOT_DIR)/cpu-z80 -I$(ROOT_DIR)/platform-$(TARGET) -I$(ROOT_DIR)/include --max-allocs-per-node 30000 --opt-code-size --Werror --stack-auto --constseg CONST
export CROSS_CCOPTS=-c --std-sdcc99 --no-std-crt0 -m$(CPU) -I$(ROOT_DIR)/cpu-$(CPU) -I$(ROOT_DIR)/platform-$(TARGET) -I$(ROOT_DIR)/include --max-allocs-per-node 30000 --opt-code-size --Werror --stack-auto --constseg CONST
#export CROSS_CCOPTS+=--nostdlib --nostdinc -Isdcclib/include
export CROSS_CC_SEG2=--codeseg CODE2
export CROSS_CC_SEGDISC=--codeseg DISCARD --constseg DISCARD
Expand All @@ -30,9 +30,9 @@ export BINEXT = .rel
# to look in the usual places !)
#
ifeq ($(UNAME_S),Darwin)
export LIBZ80=/usr/local/share/sdcc/lib/z80
export LIBZ80=/usr/local/share/sdcc/lib/$(CPU)
else
export LIBZ80=/usr/share/sdcc/lib/z80
export LIBZ80=/usr/share/sdcc/lib/$(CPU)
endif
else ifeq ($(CPU),6502)
export CROSS_AS=ca65
Expand Down Expand Up @@ -110,10 +110,14 @@ all: fuzix.bin
.SUFFIXES: # delete the default suffixes
.SUFFIXES: .c .s .rel

usermem_std-z180.rel: usermem_std-z180.s usermem_std-z80.s

lowlevel-z180.rel: lowlevel-z180.s lowlevel-z80.s

target:
-rm platform
-rm -f platform
ln -sf platform-$(TARGET) platform
$(MAKE) -C platform-$(TARGET)
+make -C platform-$(TARGET)

$(C1OBJS): %$(BINEXT): %.c
$(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG1) $<
Expand Down Expand Up @@ -154,23 +158,26 @@ tools/decbdragon: tools/decbdragon.c

tools/bintomdv: tools/bintomdv.c

cpm-loader/cpmload.bin: cpm-loader/cpmload.s cpm-loader/makecpmloader.c
+make -C cpm-loader

tools/makejv3: tools/makejv3.c

ifeq ($(CPU), z80)
ifneq (,$(filter $(CPU),z80 z180)) # matches CPU = z80 or z180
uzi.ihx: target $(OBJS) platform-$(TARGET)/uzi.lnk
$(CROSS_LD) -n -k $(LIBZ80) -f platform-$(TARGET)/uzi.lnk

fuzix.bin: uzi.ihx tools/analysemap tools/memhogs tools/binman tools/bintomdv
fuzix.bin: uzi.ihx tools/analysemap tools/memhogs tools/binman tools/bintomdv cpm-loader/cpmload.bin
tools/analysemap <uzi.map
-cp hogs.txt hogs.txt.old
tools/memhogs <uzi.map |sort -nr >hogs.txt
head -5 hogs.txt
makebin -s 65536 -p uzi.ihx >uzi.tmp
tools/binman uzi.tmp uzi.map fuzix.bin
$(MAKE) -C platform-$(TARGET) image
+make -C platform-$(TARGET) image
else
fuzix.bin: target $(OBJS) tools/decbdragon
$(MAKE) -C platform-$(TARGET) image
+make -C platform-$(TARGET) image
endif

clean:
Expand Down
3 changes: 1 addition & 2 deletions Kernel/bankfixed.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <kernel.h>
#include <timer.h>
#include <kdata.h>
#include <printf.h>

Expand Down Expand Up @@ -39,7 +38,7 @@ int pagemap_alloc(ptptr p)
/* Realloc is trivial - we can't do anything useful */
int pagemap_realloc(uint16_t size)
{
if (size >= MAP_SIZE)
if (size > MAP_SIZE)
return ENOMEM;
return 0;
}
Expand Down
11 changes: 11 additions & 0 deletions Kernel/cpm-loader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
all: makecpmloader cpmload.bin

makecpmloader: makecpmloader.c

cpmload.bin: cpmload.s
$(CROSS_AS) $(ASOPTS) cpmload.s
sdldz80 -nmi cpmload.rel
makebin -p cpmload.ihx > cpmload.bin

clean:
rm -f *~ *.rst *.lst *.asm *.bin *.sym *.rel *.map *.ihx makecpmloader
38 changes: 38 additions & 0 deletions Kernel/cpm-loader/cpmload.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
; 2014-12-21 Will Sowerbutts

.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 4-byte header:
load_address:
.ds 2
load_length:
.ds 2
payload_start:
160 changes: 160 additions & 0 deletions Kernel/cpm-loader/makecpmloader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>

/*
* 2014-12-21 William R Sowerbutts
*
* Create a CP/M program which boots Fuzix.
*
* The CP/M executable file contains a small loader program, followed by some
* data describing where the kernel should be loaded, and then the kernel
* itself.
*
* When run, the CP/M program copies a small (20 byte) program to the very
* start of memory, which then copies the kernel to the correct address and
* executes it.
*
*
* Syntax: makecpmloader <loader> <kernel> <address> <output>
*
* loader -- normally cpmload.bin, assembled from cpmload.s
* kernel -- fuzix.bin from the Fuzix build process
* address -- the kernel's load address (normally 0x88)
* output -- output file name
*
*/

#define LOADER_TRIM 0x100 /* CP/M loads us at 0x100 */
#define MAX_LOADER_LENGTH 0x200 /* Loader should really be teeny tiny */
#define MAX_KERNEL_LENGTH 0x10000 /* Kernel can't be larger than 64KB ... yet ... */
#define BYTESWAP16(x) (((x>>8) & 0xFF) | ((x & 0xFF) << 8))

char loader_data[MAX_LOADER_LENGTH];
char kernel_data[MAX_KERNEL_LENGTH];

struct loader_trailer {
unsigned short load_address;
unsigned short load_length;
};

int load_file(const char *filename, char *buffer, int buffer_len)
{
int fd, length, r;

fd = open(filename, O_RDONLY);

if(fd < 0){
fprintf(stderr, "Cannot open \"%s\": %s\n", filename, strerror(errno));
return -1;
}

length = 0;
while(1){
r = read(fd, &buffer[length], buffer_len - length);
if(r == 0) /* EOF */
break;
else if(r > 0)
length += r;
else{
fprintf(stderr, "Cannot read \"%s\": %s\n", filename, strerror(errno));
close(fd);
return -1;
}
if(length == buffer_len){
fprintf(stderr, "Out of buffer space reading \"%s\"\n", filename);
close(fd);
return -1;
}
}

close(fd);
return length;
}

int parse_int(char *str)
{
int base = 10;
long val;
char *end;

end = str;
if(strncasecmp(end, "0x", 2) == 0){
base = 16;
end = end + 2;
}

val = strtol(end, &end, base);

if(*end == 0 && *str != 0)
return val;
else{
fprintf(stderr, "Cannot parse load address \"%s\"\n", str);
return -1;
}
}

int main(int argc, char **argv)
{
int loader_length;
int load_address;
int kernel_length;
int fd;
struct loader_trailer trailer;

if(argc < 5){
fprintf(stderr, "%s [loader] [kernel] [address] [output]\n", argv[0]);
return 1;
}

loader_length = load_file(argv[1], loader_data, MAX_LOADER_LENGTH);
if(loader_length < 0)
return 1;
if(loader_length <= LOADER_TRIM){
fprintf(stderr, "Loader image is too small\n");
return 1;
}

kernel_length = load_file(argv[2], kernel_data, MAX_KERNEL_LENGTH);
if(kernel_length < 0)
return 1;

load_address = parse_int(argv[3]);

if(load_address < 0 || load_address > 0xFFFF){
fprintf(stderr, "Bad load address.\n");
return 1;
}

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
trailer.load_length = kernel_length;
trailer.load_address = load_address;
#else
trailer.load_length = BYTESWAP16(kernel_length);
trailer.load_address = BYTESWAP16(load_address);
#endif

fd = open(argv[4], O_WRONLY | O_CREAT | O_TRUNC, 0666);
if(fd < 0){
fprintf(stderr, "Cannot open \"%s\": %s\n", argv[4], strerror(errno));
return 1;
}

if(write(fd, &loader_data[LOADER_TRIM], loader_length - LOADER_TRIM) != (loader_length - LOADER_TRIM) ||
write(fd, &trailer, sizeof(trailer)) != sizeof(trailer) ||
write(fd, kernel_data, kernel_length) != kernel_length){
fprintf(stderr, "Write to \"%s\" failed: %s\n", argv[4], strerror(errno));
close(fd);
unlink(argv[4]);
return 1;
}

close(fd);

return 0;
}
1 change: 1 addition & 0 deletions Kernel/cpu-z180/cpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "../cpu-z80/cpu.h"
71 changes: 71 additions & 0 deletions Kernel/cpu-z180/z180.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
; ASCI serial ports
ASCI_CNTLA0 .equ (Z180_IO_BASE+0x00) ; ASCI control register A channel 0
ASCI_CNTLA1 .equ (Z180_IO_BASE+0x01) ; ASCI control register A channel 1
ASCI_CNTLB0 .equ (Z180_IO_BASE+0x02) ; ASCI control register B channel 0
ASCI_CNTLB1 .equ (Z180_IO_BASE+0x03) ; ASCI control register B channel 0
ASCI_STAT0 .equ (Z180_IO_BASE+0x04) ; ASCI status register channel 0
ASCI_STAT1 .equ (Z180_IO_BASE+0x05) ; ASCI status register channel 1
ASCI_TDR0 .equ (Z180_IO_BASE+0x06) ; ASCI transmit data reg, channel 0
ASCI_TDR1 .equ (Z180_IO_BASE+0x07) ; ASCI transmit data reg, channel 1
ASCI_RDR0 .equ (Z180_IO_BASE+0x08) ; ASCI receive data reg, channel 0
ASCI_RDR1 .equ (Z180_IO_BASE+0x09) ; ASCI receive data reg, channel 0
ASCI_ASEXT0 .equ (Z180_IO_BASE+0x12) ; ASCI extension register channel 0
ASCI_ASEXT1 .equ (Z180_IO_BASE+0x13) ; ASCI extension register channel 1
ASCI_ASTC0L .equ (Z180_IO_BASE+0x1A) ; ASCI time constant register channel 0 low
ASCI_ASTC0H .equ (Z180_IO_BASE+0x1B) ; ASCI time constant register channel 0 high
ASCI_ASTC1L .equ (Z180_IO_BASE+0x1C) ; ASCI time constant register channel 1 low
ASCI_ASTC1H .equ (Z180_IO_BASE+0x1D) ; ASCI time constant register channel 1 high

; Z180 MMU
MMU_CBR .equ (Z180_IO_BASE+0x38) ; common1 base register
MMU_BBR .equ (Z180_IO_BASE+0x39) ; bank base register
MMU_CBAR .equ (Z180_IO_BASE+0x3A) ; common/bank area register

; Z180 DMA engine
DMA_SAR0L .equ (Z180_IO_BASE+0x20) ; DMA source address reg, channel 0L
DMA_SAR0H .equ (Z180_IO_BASE+0x21) ; DMA source address reg, channel 0H
DMA_SAR0B .equ (Z180_IO_BASE+0x22) ; DMA source address reg, channel 0B
DMA_DAR0L .equ (Z180_IO_BASE+0x23) ; DMA dest address reg, channel 0L
DMA_DAR0H .equ (Z180_IO_BASE+0x24) ; DMA dest address reg, channel 0H
DMA_DAR0B .equ (Z180_IO_BASE+0x25) ; DMA dest address reg, channel 0B
DMA_BCR0L .equ (Z180_IO_BASE+0x26) ; DMA byte count reg, channel 0L
DMA_BCR0H .equ (Z180_IO_BASE+0x27) ; DMA byte count reg, channel 0H
DMA_MAR1L .equ (Z180_IO_BASE+0x28) ; DMA memory address reg, channel 1L
DMA_MAR1H .equ (Z180_IO_BASE+0x29) ; DMA memory address reg, channel 1H
DMA_MAR1B .equ (Z180_IO_BASE+0x2A) ; DMA memory address reg, channel 1B
DMA_IAR1L .equ (Z180_IO_BASE+0x2B) ; DMA I/O address reg, channel 1L
DMA_IAR1H .equ (Z180_IO_BASE+0x2C) ; DMA I/O address reg, channel 1H
DMA_BCR1L .equ (Z180_IO_BASE+0x2E) ; DMA byte count reg, channel 1L
DMA_BCR1H .equ (Z180_IO_BASE+0x2F) ; DMA byte count reg, channel 1H
DMA_DSTAT .equ (Z180_IO_BASE+0x30) ; DMA status register
DMA_DMODE .equ (Z180_IO_BASE+0x31) ; DMA mode register
DMA_DCNTL .equ (Z180_IO_BASE+0x32) ; DMA/WAIT control register

; Z180 Timer
TIME_TMDR0L .equ (Z180_IO_BASE+0x0C) ; Timer data register, channel 0L
TIME_TMDR0H .equ (Z180_IO_BASE+0x0D) ; Timer data register, channel 0H
TIME_RLDR0L .equ (Z180_IO_BASE+0x0E) ; Timer reload register, channel 0L
TIME_RLDR0H .equ (Z180_IO_BASE+0x0F) ; Timer reload register, channel 0H
TIME_TCR .equ (Z180_IO_BASE+0x10) ; Timer control register
TIME_TMDR1L .equ (Z180_IO_BASE+0x14) ; Timer data register, channel 1L
TIME_TMDR1H .equ (Z180_IO_BASE+0x15) ; Timer data register, channel 1H
TIME_RLDR1L .equ (Z180_IO_BASE+0x16) ; Timer reload register, channel 1L
TIME_RLDR1H .equ (Z180_IO_BASE+0x17) ; Timer reload register, channel 1H
TIME_FRC .equ (Z180_IO_BASE+0x18) ; Timer Free running counter

; Z180 Interrupts
INT_IL .equ (Z180_IO_BASE+0x33) ; Interrupt vector low register
INT_ITC .equ (Z180_IO_BASE+0x34) ; Interrupt vector low register

; ESCC serial ports (Z80182)
ESCC_CTRL_A .equ 0xE0 ; ESCC Channel A control register
ESCC_DATA_A .equ 0xE1 ; ESCC Channel A data register
ESCC_CTRL_B .equ 0xE2 ; ESCC Channel B control register
ESCC_DATA_B .equ 0xE3 ; ESCC Channel B data register

Z182_SYSCONFIG .equ 0xEF ; System Configuration Register
Z182_ROMBR .equ 0xE8 ; ROMBR register

; Debugging
DEBUGBANK .equ 0
DEBUGCOMMON .equ 0
Loading