From: Alan Cox Date: Fri, 6 Apr 2018 18:35:48 +0000 (+0100) Subject: cromemco: initial draft port X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=ac27e0abe130f5d714a9d4c1675673c70007d0dd;p=FUZIX.git cromemco: initial draft port No floppy driver yet and boot blocks are untested --- diff --git a/Kernel/platform-cromemco/Makefile b/Kernel/platform-cromemco/Makefile new file mode 100644 index 00000000..2e8ab09c --- /dev/null +++ b/Kernel/platform-cromemco/Makefile @@ -0,0 +1,31 @@ + +CSRCS = devtty.c devfd.c +CSRCS += devices.c main.c + +ASRCS = crt0.s cromemco.s +ASRCS += tricks.s commonmem.s + +AOBJS = $(ASRCS:.s=.rel) +COBJS = $(CSRCS:.c=.rel) + +OBJS = $(AOBJS) $(COBJS) + +JUNK = *.rel *.lst *.asm *.sym *.rst + +all: $(OBJS) + +$(AOBJS): %.rel: %.s + $(CROSS_AS) $(ASOPTS) $< + +$(COBJS): %.rel: %.c + $(CROSS_CC) $(CROSS_CCOPTS) -c $< + +clean: + rm -f $(OBJS) $(JUNK) core *~ + +image: + sdasz80 -o cloader-16fdc.s + sdldz80 -m -i cloader-16fdc.rel + makebin -s 256 cloader-16fdc.ihx > cloader-16fdc.tmp + dd if=cloader-16fdc.tmp of=cloader-16fdc.bin bs=1 skip=128 + diff --git a/Kernel/platform-cromemco/README b/Kernel/platform-cromemco/README new file mode 100644 index 00000000..7be076f8 --- /dev/null +++ b/Kernel/platform-cromemco/README @@ -0,0 +1,179 @@ +FUZIX on a Cromenco (no hard disk support right now - need docs for that and +suitable emulation!) + +We expect + +0 tuart / 4 FDC +4 fdc aux +5-9 times +32 tuart / parallel 36 +48 fdc +64 mmu +80 tuart / parallel 84 +255 front panel + + + + +The MMU settings we use are + +1 << n That bank 0-6 + +0x80 Turn on comon writing (write to all banks) + + +UARTs: TMS 5501 x 2 per board. These can do Z80 IM2 where the vector is +determined by A7-A5 of the IRQ (used as D7-D5 of the vector) + +R 0 Status + +7: set if tx buffer empty +6: set if rx data available +5: irq pending +4: start bit detected +3: full bit detected +2: serial receive line state +1: overrun (clear on read) +0: frame error (clear on valid rx) + +W 0 +7: 1 for one stop 0 for 2 +0-6 set baud rate (all 0 off) +0: 110 +1: 150 +2: 300 +3: 1200 +4: 2400 +5: 4800 +6: 9600 +(but see later) + +R 1 Data received + +W 1 Load tx + +W 2 cmd + +0: reset (self clears) +1: break send +2: IRQ on parallel msb +3: May respond to an IRQ by gating an RST + Low prevents gating instructions +4: Baud rate x8 +5: Test + + +R 3: Interrupt address (gives service priority order for events) + Each read clears a priority + + C7 timer 1 + CF timer 2 + D7 !sens + DF timer 3 + E7 rx data + EF tx data + F7 timer 4 + FF timer 5 (or none) + +W 3: Interrupt mask + +7: timer 5 +6: timer 4 +5: tx buffer empty +4: rx data ready +3: timer 3 +2: !sens +1: timer 2 +0: timer 1 + +R 4: + Read parallel input data captured after strobe +W 4: + Write parallel + + (Parallel will halt the CPU for the other end to respond .. !) + +W 5: timer 1 (decremented ever 64uS - longest interval 16.32ms) + +W 6: timer 2 (ditto) + +W 7: timer 3 (ditto) + +W 8: timer 4 (ditto) + +W 9: timer 5 (ditto) + + + + +The 4FDC has a uart at 0 (parallel out is used for disk control) +Disk (FD1771). 16FDC is same ports but a 1793 + +Parallel in is wired so that (16FDC) + D7 = DRQ/RTC (Jumper sets it to 512ms clock used with 5501 int) + D6 = Seek in progress + D3 = Switch 5 + D2 = Switch 6 + D1 = Switch 7 + D0 = Switch 8 + +4FDC has only D7 (DRQ) optional - default off, D6 seek in progress + +64FDC + D7 = DRQ/RTC + D6 = 1 + D5 = ? + D4-D0 Switch 5/1-4 + + +16FDC out + D6 clear to eject (not always supported) + D5 set to disconnect drive select (shared disk configurations) + D4 clear for fast step mode (8" drives), set once seek complete sent + D3 clear to force drive to track 0 (restore) + D2 clear activates control OUT (test pin) + D1 side select (0 for second side of 2 sided media) + +4FDC out + D6: eject left + D5: eject right + D4: clear for fast seek + D3: cler for restore + D2: clear activates daisy chain + +64FDC out + D5: drive select override (as 16FDC) + D2: control out (as 16FDC) + D1: side select (as 16FDC) + +(hex) +R 30 status +W 30 command +R 31 track +W 31 track +R 32 sector +W 32 sector +R 33 data +W 33 data +R 34 flags + D7: !DRQ + D6: !BOOT (0 SW3 set to boot) + D5 HEADLOAD (Drive sect if high on 64FDC) + D4 Zero mean switch inhibit init is on (16FDC) + D3 motor is on (16FDC) on = 1 + D2 motor timeout (16FDC) timedout = 1 + D1 autowait timeout if 1 + D0: End of Job +W 34 control + D7: autowait - 34H will hold CPU in wait until DRQ or EOJ or RESET + D6: double density (4FDC not ??) + D5: motor on + D4: 1 = 8" (fast step) 0 = 5.25 (slow step) + D3-D0 - drive select (only one at a time) + +W 40 Disables boot rom as a side effect + + +W 40 bank select + + diff --git a/Kernel/platform-cromemco/cloader-16fdc.s b/Kernel/platform-cromemco/cloader-16fdc.s new file mode 100644 index 00000000..285e5d57 --- /dev/null +++ b/Kernel/platform-cromemco/cloader-16fdc.s @@ -0,0 +1,116 @@ + .area ASEG(ABS) + .org 0x80 +; +; Loader for Fuzix on a Cromenco 16FDC +; +; The kernel is written in blocks 1+ SS/SD with no magic +; involved. We have 128 bytes, but fortunately a ROM helper +; +; +; Memory map +; 0x0000-0x002E Stack +; 0x0060-0x007F Used by the boot ROM +; 0x0080-0x00FF This boot block +; 0x0100-0xBFFF Free RAM +; 0xC000-0xCFFF Boot ROM (until we out to 0x40) +; 0xD000-0xFFFF May be RAM but may also be ROM shadows +; + +set_side .equ 0xC003 +set_track .equ 0xC006 +set_sector .equ 0xC009 +set_buffer .equ 0xC00C +disk_restore .equ 0xC00F +disk_seek .equ 0xC012 +disk_read .equ 0xC015 +disk_write .equ 0xC018 +setup_uart .equ 0xC01B +char_input .equ 0xC01E +char_ready .equ 0xC021 +line_input .equ 0xC024 +char_output .equ 0xC027 +newline_output .equ 0xC02A + + .globl start + .globl endc + .globl end + .globl msg +; Carry set, drive in A +start: + push af + ld hl,#boot + call tout + ld hl,#0xFC + pop af + ld (hl),a ; boot drive + inc hl + ld a,#16 + ld (hl),a ; controller type (16FDC) + inc hl + ld bc,(0x7E) ; features and feature save for boot disk + ld (hl),c + inc hl + ld (hl),b + inc hl ; now 0x100 + xor a + ld b,a + call set_side + ld a,(0x6E) ; sectors per track + inc a + ld c,a + ld a,#1 ; sector 2 + ld de,#128 +trackloop: + push af + ld a,b + call set_track + pop af +secloop: + inc a + call set_sector + call set_buffer + ex af,af' ; shorter than pushing them + exx + call disk_seek + call disk_read + jr c, crap + exx + add hl,de + ld a,h + cp #0xC0 + jr z,go + ex af,af' + cp c + jr nz, secloop + inc b + xor a + jr trackloop +go: + ld a,(0x100) + cp #0xC3 + jr z, 0x100 +crap: + ld hl, #fail + call tout + jp 0xC000 + +tout: + ld a,(hl) + inc hl + or a + ret z + push hl + call char_output + pop hl + jr tout + +msg: +boot: .asciz 'Boot' +fail: .ascii ' failed' + .byte 13,10,0 + +endc: + .org 0xF8 + + .ascii 'FZSSSD' +end: diff --git a/Kernel/platform-cromemco/config.h b/Kernel/platform-cromemco/config.h new file mode 100644 index 00000000..fe8ec2df --- /dev/null +++ b/Kernel/platform-cromemco/config.h @@ -0,0 +1,39 @@ +/* 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 +/* 7 64K banks, 1 is kernel */ +#define MAX_MAPS 6 +#define MAP_SIZE 0xF000U + +/* Banks as reported to user space */ +#define CONFIG_BANKS 1 + +#define TICKSPERSEC 10 /* Ticks per second */ +#define PROGBASE 0x0000 /* also data base */ +#define PROGLOAD 0x0100 /* also data base */ +#define PROGTOP 0xED00 /* Top of program, base of U_DATA copy */ +#define PROC_SIZE 60 /* Memory needed per process */ + +#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 NBUFS 8 /* Number of block buffers */ +#define NMOUNTS 4 /* Number of mounts at a time */ + +#define platform_discard() diff --git a/Kernel/platform-cromemco/cromemco.s b/Kernel/platform-cromemco/cromemco.s new file mode 100644 index 00000000..25bb675f --- /dev/null +++ b/Kernel/platform-cromemco/cromemco.s @@ -0,0 +1,224 @@ +; +; Cromemco hardware support +; + + .module cromemco + + ; exported symbols + .globl init_early + .globl init_hardware + .globl _program_vectors + .globl platform_interrupt_all + + .globl map_kernel + .globl map_process + .globl map_process_always + .globl map_process_a + .globl map_save + .globl map_restore + + .globl _platform_reboot + + ; exported debugging tools + .globl _platform_monitor + .globl outchar + + ; imported symbols + .globl _ramsize + .globl _procmem + + .globl unix_syscall_entry + .globl null_handler + .globl nmi_handler + .globl interrupt_handler + .globl _doexit + .globl _inint + .globl kstack_top + .globl _panic + .globl _need_resched + .globl _ssig + + .globl outcharhex + .globl outhl, outde, outbc + .globl outnewline + .globl outstring + .globl outstringhex + + .include "kernel.def" + .include "../kernel.def" + +; ----------------------------------------------------------------------------- +; COMMON MEMORY BANK (0xF000 upwards) +; ----------------------------------------------------------------------------- + .area _COMMONMEM + +_platform_reboot: +_platform_monitor: + jr _platform_monitor +platform_interrupt_all: + ret + +; ----------------------------------------------------------------------------- +; KERNEL MEMORY BANK (below 0xF000, only accessible when the kernel is mapped) +; ----------------------------------------------------------------------------- + .area _CODE + +init_early: + ld a,#0x81 ; Every memory is in bank 7 + out (0x40),a ; MMU set + ld hl,#0xF000 ; Copy 4K to itself loading + ld d,h ; into into the other banks + ld e,l + ld b,#0x10 + ld c,l + ldir + ld a,#0x01 ; bank to the kernel bank + out (0x40),a + ret + +init_hardware: + ; set system RAM size + ld hl, #448 + ld (_ramsize), hl + ld hl, #(448-64) ; 64K for kernel + ld (_procmem), hl + + ld a, #156 ; ticks for 10Hz (9984uS per tick) + out (8), a ; 10Hz timer on + + ; set up interrupt vectors for the kernel (also sets up common memory in page 0x000F which is unused) + ld hl, #0 + push hl + call _program_vectors + pop hl + +; ld a, #0xfe ; Use FEFF (currently free) +; ld i, a +; im 2 ; set CPU interrupt mode + im 1 ; really should use a page and im2? + ret + + +;------------------------------------------------------------------------------ +; COMMON MEMORY PROCEDURES FOLLOW + + .area _COMMONMEM + + +_program_vectors: + ; we are called, with interrupts disabled, by both newproc() and crt0 + ; will exit with interrupts off + di ; just to be sure + pop de ; temporarily store return address + pop hl ; function argument -- base page number + push hl ; put stack back as it was + push de + + call map_process + + ; write zeroes across all vectors + ld hl, #0 + ld de, #1 + ld bc, #0x007f ; program first 0x80 bytes only + ld (hl), #0x00 + ldir + + ; now install the interrupt vector at 0x38 + ld hl, #interrupt_handler + ld (0x39), hl + + ld a,#0xC3 ; JP + ; set restart vector for UZI system calls + ld (0x0030), a ; (rst 30h is unix function call vector) + ld (0x0038), a ; (rst 38h) + ld hl, #unix_syscall_entry + ld (0x0031), hl + + ; now install the interrupt vector at 0x38 + ld hl, #interrupt_handler + ld (0x39), hl + + ; Set vector for jump to NULL + ld (0x0000), a + ld hl, #null_handler ; to Our Trap Handler + ld (0x0001), hl + + ld (0x0066), a ; Set vector for NMI + ld hl, #nmi_handler + ld (0x0067), hl + + ; falls through + + ; put the paging back as it was -- we're in kernel mode so this is predictable +map_kernel: + push af + ld a,#1 + out (0x40), a + ld (map_page), a ; map_page lives in kernel so be careful + pop af ; our common is r/o common so writes won't + ret ; cross a bank +map_process: + ld a, h + or l + jr z, map_kernel + ld a, (hl) +map_process_a: + ld (map_page),a ; save before we map out kernel + out (0x40), a + ret +map_process_always: + push af + ld a, (U_DATA__U_PAGE) + ld (map_page),a ; save before we map out kernel + out (0x40), a + pop af + ret +map_save: ; this is a bit naughty, but we know + push af ; map_save will always be followed by + ld a, #1 ; map_kernel so we do the map_kernel + out (0x40), a ; a shade early. + ld a, (map_page) ; then we can get the vars + ld (map_store), a + pop af + ret +map_restore: ; called in kernel map + push af + ld a, (map_store) + ld (map_page),a + out (0x40), a + pop af + ret +map_store: + .db 0 +map_page: + .db 0 + +; outchar: Wait for UART TX idle, then print the char in A +; destroys: AF +outchar: + push af +outcharl: + in a, (0x00) + bit 7,a + jr z, outcharl + pop af + out (0x01), a + ret + +; +; Low level pieces for floppy driver +; + .globl _fd_reset + .globl _fd_operation + .globl _fd_map + .globl _fd_cmd + +_fd_reset: + ret +_fd_operation: + ret +_fd_map: + .byte 0 +_fd_cmd: + .byte 0, 0, 0, 0, 0, 0, 0 + diff --git a/Kernel/platform-cromemco/crt0.s b/Kernel/platform-cromemco/crt0.s new file mode 100644 index 00000000..027a3034 --- /dev/null +++ b/Kernel/platform-cromemco/crt0.s @@ -0,0 +1,73 @@ +; 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 _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 + + ; startup code + .area _CODE +init: + di + ld sp, #kstack_top + + ; Configure memory map + call init_early + + ; move the common memory where it belongs + ld hl, #s__DATA + 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 + + ; Hardware setup + call init_hardware + + ; Call the C main routine + call _fuzix_main + + ; main shouldn't return, but if it does... + di +stop: halt + jr stop + diff --git a/Kernel/platform-cromemco/devfd.c b/Kernel/platform-cromemco/devfd.c new file mode 100644 index 00000000..04efa5d2 --- /dev/null +++ b/Kernel/platform-cromemco/devfd.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include + +#define MAX_DRIVE 4 + +#define OPDIR_NONE 0 +#define OPDIR_READ 1 +#define OPDIR_WRITE 2 + +#define FD_READ 0x80 /* 2797 needs 0x88, 1797 needs 0x80 */ +#define FD_WRITE 0xA0 /* Likewise A8 v A0 */ + +/* Extern as they live in common */ +extern uint8_t fd_map; +extern uint8_t fd_selected; +extern uint8_t fd_cmd[7]; + +static uint8_t fd_tab[MAX_DRIVE]; + +__sfr __at 0x04 fd_aux; +__sfr __at 0x30 fd_stcmd; +__sfr __at 0x31 fd_track; +__sfr __at 0x32 fd_sector; +__sfr __at 0x33 fd_data; +__sfr __at 0x34 fd_ctrlflag; + +/* 4 large disks (0 5" 1 8" 255 none */ + +uint8_t drivetype[4] = { 1, 1, 1, 1 }; + +/* + * We only support normal block I/O for the moment. + */ + +static uint8_t selmap[4] = { 0x01, 0x02, 0x04, 0x08 }; + +static const uint8_t skewtab[2][18] = { + /* Matches CDOS 5" skew for DSDD */ + { 1, 5, 9, 3, 7, 2, 6, 10, 4, 9 }, + /* No idea what CDOS uses for 8" DSDD right now */ + { 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 }, +}; + +static uint8_t live[4]; + +/* + * A note on disk formats and the Cromenco (and also emulator limits) + * + * Classic 8" SS/SD 26 sectors, 128 bytes/sector, 77 track + * software skewed + * Classic 5" SS/SD 18 sectors, 40 tracks otherwise as before + * + * Double sided use the same formats for SD but with two sides + * + * When we go to DD 8" goes to 16 512 byte sectors/track and + * 5" goes to 10 512 byte sectors/track + * + * The controller can do a lot more but the emulators don't always + * cope. In particular a 'correct' bootable disk is supposed to be + * SD on track 0 side 0 and can be DS/DD on the rest. + * + * Likewise the hardware can write PC format media in theory and + * do format level skewing at least for 5.25" disks + * + * Just to get us going - only do DSDD. + */ + +static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) +{ + int tries; + uint8_t err = 0; + uint8_t drive = minor & 3; + uint8_t *driveptr = fd_tab + drive; + uint8_t large = !(minor & 0x10); + const uint8_t *skew = skewtab[large]; /* skew table */ + + if(rawflag == 2) + goto bad2; + + fd_map = rawflag; + if (rawflag && d_blkoff(BLKSHIFT)) + return -1; + + /* Command to go to the controller after any seek is done */ + fd_cmd[0] = is_read ? FD_READ : FD_WRITE; + if (large) { + /* Track */ + fd_cmd[1] = udata.u_block / 16; + /* Sector */ + fd_cmd[2] = skew[udata.u_block % 16]; /* 1..n skewed */ + /* control */ + fd_cmd[6] = 0xF0; + } else { + fd_cmd[1] = udata.u_block / 10; + fd_cmd[2] = skew[udata.u_block % 10]; + fd_cmd[6] = 0xA0; + } + fd_cmd[6] |= (1 << drive); + /* Directon of xfer */ + fd_cmd[3] = is_read ? OPDIR_READ: OPDIR_WRITE; + /* Buffer */ + fd_cmd[4] = ((uint16_t)udata.u_dptr) & 0xFF; + fd_cmd[5] = ((uint16_t)udata.u_dptr) >> 8; + + /* FIXME: Sides. Really 32 sectors/track 16 each side */ + + while (udata.u_done < udata.u_nblock) { + if (large) { + fd_cmd[1] = udata.u_block / 16; + fd_cmd[2] = (udata.u_block % 16) + 1; + } else { + fd_cmd[1] = udata.u_block / 10; + fd_cmd[2] = (udata.u_block % 10) + 1; + } + for (tries = 0; tries < 4 ; tries++) { + err = fd_operation(driveptr); + if (err == 0) + break; + if (tries > 1) + fd_reset(driveptr); + } + if (tries == 4) + goto bad; + udata.u_block++; + udata.u_done++; + } + return udata.u_done << 9; +bad: + kprintf("fd%d: error %x\n", minor, err); +bad2: + udata.u_error = EIO; + return -1; +} + +/* We encode the minor has + 000[8/5][sd/dd][ss/ds][disk.2] */ + +int fd_open(uint8_t minor, uint16_t flag) +{ + uint8_t *dp = live + (minor & 3); + + flag; + if ((minor & 0xE0) || drivetype[minor] == 255) { + udata.u_error = ENODEV; + return -1; + } + /* Ensure we can't open the same physical disk in two modes at once */ + if (*dp != 0xFF) { + udata.u_error = EBUSY; + return -1; + } + *dp = minor; + return 0; +} + +int fd_close(uint8_t minor) +{ + live[minor & 3] = 0xFF; + return 0; +} + +int fd_read(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + flag; + return fd_transfer(minor, true, rawflag); +} + +int fd_write(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + flag;rawflag;minor; + return fd_transfer(minor, false, rawflag); +} + + \ No newline at end of file diff --git a/Kernel/platform-cromemco/devfd.h b/Kernel/platform-cromemco/devfd.h new file mode 100644 index 00000000..22ad8c49 --- /dev/null +++ b/Kernel/platform-cromemco/devfd.h @@ -0,0 +1,7 @@ +extern int fd_read(uint8_t minor, uint8_t rawflag, uint8_t flag); +extern int fd_write(uint8_t minor, uint8_t rawflag, uint8_t flag); +extern int fd_close(uint8_t minor); +extern int fd_open(uint8_t minor, uint16_t flag); + +extern void fd_reset(uint8_t *ptr); +extern int fd_operation(uint8_t *ptr); diff --git a/Kernel/platform-cromemco/devices.c b/Kernel/platform-cromemco/devices.c new file mode 100644 index 00000000..4b869a75 --- /dev/null +++ b/Kernel/platform-cromemco/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/fd Floppy disc block devices */ + /* TODO: add fd_ioctl and eject etc */ + { fd_open, fd_close, fd_read, fd_write, no_ioctl }, + /* 1: /dev/hd 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: none for now */ + { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 4: /dev/mem etc System devices (one offs) */ + { no_open, sys_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) +{ +} diff --git a/Kernel/platform-cromemco/devtty.c b/Kernel/platform-cromemco/devtty.c new file mode 100644 index 00000000..d62c5860 --- /dev/null +++ b/Kernel/platform-cromemco/devtty.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include + +char tbuf1[TTYSIZ]; +char tbuf2[TTYSIZ]; +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 uint8_t ttybase[NUM_DEV_TTY+1] = { + 0, 0, 32, 80 +}; + +static uint8_t ttypoll; + +/* Write to system console */ +void kputchar(char c) +{ + /* handle CRLF */ + if(c=='\n') + tty_putc(1, '\r'); + tty_putc(1, c); +} + +char tty_writeready(uint8_t minor) +{ + uint8_t r = ttybase[minor]; + r = in(r); + if (r & 0x80) + return 1; + return 0; +} + +void tty_putc(uint8_t minor, unsigned char c) +{ + uint8_t r = ttybase[minor]; + out(r + 1, c); +} + +void tty_sleeping(uint8_t minor) +{ + ttypoll |= 1 << minor; +} + +__sfr __at 0x08 timer4; + +void tty_irq(uint8_t minor) +{ + uint8_t r = ttybase[minor]; + uint8_t op; + while((op = in(r + 3)) != 0xFF) { + switch(op) { + case 0xE7: + /* should check in(r) for error bits */ + tty_inproc(minor, in(r + 1 )); + case 0xEF: + ttypoll &= ~(1 << minor); + wakeup(&ttydata[minor]); + case 0xF7: + if (minor == 1) { + timer_interrupt(); + timer4 = 156; + } + } + } +} + +static uint8_t baudbits[] = { + 1, + 1, + 1, + 1, /* 110 */ + 1, + 2, /* 150 */ + 4, /* 300 */ + 4, + 8, /* 1200 */ + 16, /* 2400 */ + 32, /* 4800 */ + 64, /* 9600 */ + /* x8 modes */ + 8, /* 19200 */ + 16, /* 38400 */ + 16, + 16 +}; + +void tty_setup(uint8_t minor) +{ + struct termios *t = &ttydata[minor].termios; + uint8_t baud = t->c_cflag & CBAUD; + uint8_t r = ttybase[minor]; + out(r, baudbits[baud] | (t->c_cflag & CSTOPB) ? 0 : 0x80); + /* Assume we keep to IM1 */ + if (baud <= B9600) + out(r + 2, 0x8); + else + out(r + 2, 0x18); + t->c_cflag |= CS8; + t->c_cflag &= ~PARENB; + /* Ok we could do sw parity .. */ +} + +/* For the moment */ +int tty_carrier(uint8_t minor) +{ + used(minor); + return 1; +} diff --git a/Kernel/platform-cromemco/devtty.h b/Kernel/platform-cromemco/devtty.h new file mode 100644 index 00000000..ddb0f422 --- /dev/null +++ b/Kernel/platform-cromemco/devtty.h @@ -0,0 +1 @@ +extern void tty_irq(uint8_t minor); diff --git a/Kernel/platform-cromemco/fuzix.lnk b/Kernel/platform-cromemco/fuzix.lnk new file mode 100644 index 00000000..886a5e12 --- /dev/null +++ b/Kernel/platform-cromemco/fuzix.lnk @@ -0,0 +1,36 @@ +-mwxuy +-i fuzix.ihx +-b _CODE=0x0100 +-b _COMMONMEM=0xF000 +-b _DISCARD=0xE000 +-l z80 +platform-cromemco/crt0.rel +platform-cromemco/commonmem.rel +platform-cromemco/cromemco.rel +platform-cromemco/main.rel +start.rel +version.rel +lowlevel-z80.rel +usermem_std-z80.rel +platform-cromemco/tricks.rel +timer.rel +kdata.rel +usermem.rel +platform-cromemco/devfd.rel +platform-cromemco/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 +devsys.rel +platform-cromemco/devtty.rel +-e diff --git a/Kernel/platform-cromemco/main.c b/Kernel/platform-cromemco/main.c new file mode 100644 index 00000000..8f83fac5 --- /dev/null +++ b/Kernel/platform-cromemco/main.c @@ -0,0 +1,34 @@ +#include +#include + +uaddr_t ramtop = PROGTOP; + +void pagemap_init(void) +{ + int i; + for (i = 1; i < 7; i++) + pagemap_add(1 << i); +} + +void platform_idle(void) +{ + /* halt ?? */ +} + +void platform_interrupt(void) +{ + tty_irq(1); + tty_irq(2); + tty_irq(3); +} + +/* 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-cromemco/target.mk b/Kernel/platform-cromemco/target.mk new file mode 100644 index 00000000..3bffcde0 --- /dev/null +++ b/Kernel/platform-cromemco/target.mk @@ -0,0 +1 @@ +export CPU = z80 diff --git a/Kernel/platform-cromemco/tricks.s b/Kernel/platform-cromemco/tricks.s new file mode 100644 index 00000000..ee50c077 --- /dev/null +++ b/Kernel/platform-cromemco/tricks.s @@ -0,0 +1,5 @@ + + .include "../kernel.def" + .include "kernel.def" + + .include "../lib/z80fixedbank.s"