From: Alan Cox Date: Mon, 19 Dec 2016 20:46:16 +0000 (+0000) Subject: coco2cart: Initial patches from Brett Gordon for cocosdc X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=3148cc0da2651edf36890feb4e75075f0c0ac539;p=FUZIX.git coco2cart: Initial patches from Brett Gordon for cocosdc --- diff --git a/Kernel/Makefile b/Kernel/Makefile index 62de3010..8807045e 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -6,7 +6,7 @@ TARGET_LIST = platform-nc100 platform-micropack platform-pcw8256 platform-socz80 #export TARGET = bbcmicro #export TARGET = dragon #export TARGET = coco2 -#export TARGET = coco2cart +export TARGET = coco2cart #export TARGET = coco3 #export TARGET = dragon-nx32 #export TARGET = multicomp09 @@ -28,7 +28,7 @@ TARGET_LIST = platform-nc100 platform-micropack platform-pcw8256 platform-socz80 #export TARGET = v65 #export TARGET = v68 #export TARGET = v68-banked -export TARGET = z80pack +#export TARGET = z80pack #export TARGET = z80pack-lite #export TARGET = zeta-v2 #export TARGET = zx128 diff --git a/Kernel/platform-coco2cart/Makefile b/Kernel/platform-coco2cart/Makefile index 116aefef..79c46ede 100644 --- a/Kernel/platform-coco2cart/Makefile +++ b/Kernel/platform-coco2cart/Makefile @@ -2,7 +2,7 @@ CSRCS = devices.c main.c # Code that must be present for the bootstrap -CISRCS = mini_ide.c +CISRCS = mini_ide.c devsdc.c C3SRCS = libc.c devtty.c @@ -10,7 +10,8 @@ CDSRCS = discard.c mini_ide_discard.c DSRCS = ../dev/devdw.c -ASRCS = crt0.s coco2.s ide.s usermem.s bootstrap.s +ASRCS = crt0.s coco2.s ide.s usermem.s sdc.s +ASRCS += bootstrap.s bootstrap_sdc.s bootstrap_dw.s ASRCS += tricks.s commonmem.s drivewire.s video.s COBJS = $(CSRCS:.c=$(BINEXT)) @@ -54,7 +55,7 @@ clean: image: $(CROSS_LD) -o ../fuzix.bin -Map=../fuzix.map --script=fuzix.link \ --oformat=decb \ - crt0.o bootstrap.o commonmem.o coco2.o discard.o ../simple.o \ + crt0.o bootstrap_sdc.o commonmem.o coco2.o discard.o ../simple.o \ ../start.o ../version.o ../lowlevel-6809.o \ tricks.o main.o ../timer.o ../kdata.o devices.o \ drivewire.o devdw.o mini_ide.o mini_ide_discard.o ide.o \ @@ -62,7 +63,7 @@ image: ../syscall_proc.o ../syscall_other.o ../mm.o ../swap.o \ ../tty.o ../devsys.o ../usermem.o usermem.o ../syscall_fs2.o \ ../syscall_exec16.o devtty.o libc.o ../vt.o video.o ../syscall_fs3.o \ - ../font8x8.o + ../font8x8.o devsdc.o sdc.o ../tools/decb-image <../fuzix.bin fuzix.img dd if=fuzix.img of=fuzix.rom bs=1024 skip=48 count=16 dd if=fuzix.img of=fuzix.ide bs=256 skip=26 count=102 diff --git a/Kernel/platform-coco2cart/README b/Kernel/platform-coco2cart/README index 576dbf69..daf5e067 100644 --- a/Kernel/platform-coco2cart/README +++ b/Kernel/platform-coco2cart/README @@ -8,6 +8,7 @@ COCO or Dragon 64 with an IDE port, cartridge and 64K of RAM Supported hardware: IDE (Cloud9 or compatible set at FF50) with either built in cartridge RAM or separate cartridge + COCO SDC (in progress) Disk Layout =========== @@ -56,8 +57,11 @@ Needs the IDE patches TODO ==== +Fix use of CONFIG_LEGACY_EXEC in the devsdc driver + Make the boot loader robust (timeout handling) Add hash of code not just simple magic - so we know bits match +Merge coco and IDE boot code so it works out which is present Support for a real time clock and clock locking @@ -68,6 +72,8 @@ We have about 2K left to try and jam those bits in which might just about be enough to add support for very minimal MBR parsing and offsets. That would be a big improvement. +Automatically pick swap according to whether IDE or SDC is present. + To Test ======= diff --git a/Kernel/platform-coco2cart/bootstrap_sdc.s b/Kernel/platform-coco2cart/bootstrap_sdc.s new file mode 100644 index 00000000..1dd17152 --- /dev/null +++ b/Kernel/platform-coco2cart/bootstrap_sdc.s @@ -0,0 +1,119 @@ +;;; The ROM-resident fuzix loader for the CoCoSDC drive. Mostly copied from +;;; Alan's IDE booter. + +; +; Bootstrap for cartridge start up. For now load from block 1 (second +; block). We can refine this later. We do 51 block loads from block 1 +; for 1A00 to 7FFF and then copy 1A00 to 0100 for vectors +; +; Needs some kind of global timeout -> error handling +; +; +; Load block b +; + .module bootstrap + + .globl load_image + + .area .text + +;;; Load a sector from SDC +;;; takes: B - sector number, X = dest address +;;; returns: nothing +load_block: + clr <$ff49 ; put lba to sdc + clr <$ff4a ; + stb <$ff4b ; + ldb #$80 ; read sector op + stb <$ff48 ; + exg x,x ; wait a few cycles for sdc status reg + exg x,x ; to be valid. - 2 long noops + ldb #$2 ; wait till sdc is ready + ;; FIXME: test for failure in this loop +a@ bitb <$ff48 ; + beq a@ ; + ;; tranfer data + lda #128 ; 128 x 16 bits = 256 byte sectors + pshs a ; push count on stack +c@ ldd <$ff4a ; get 16bit data from drive + std ,x++ ; stick it in memory + dec ,s ; bump counter + bne c@ ; repeat + leas 1,s ; drop counter + ;; wait for return value + ldb #$1 + ;; FIXME: test for failure in the loop, also. +b@ bitb <$ff48 ; + bne b@ ; wait for busy + ;; FIXME: get return status here and test? + puls pc ; return + + + +load_image: + orcc #$50 + ldy #$0400 ; display at this point + lda #'G' ; + sta ,y+ ; + ldd #$ff43 ; set DP to io page + tfr a,dp ; good for size + speed + stb <$ff40 ; turn on SDC's LBA mode + ;; we have to wait maybe 12us before doing anything + ;; with the SDC now, but the code below should + ;; delay SDC access enough. + ;; load kernel + ldb #0 ; start block no (* 2 for 256 byte sectors) + lda #102 ; number of blocks (* 2 for 256 bytes sectors) + ldx #$1A00 ; dest address +load_loop: + pshs a,b + bsr load_block + lda #'*' + sta ,y+ + puls a,b + incb + deca + bne load_loop + ldx #$1A00 + ldu #$0100 +vec_copy: + ldd ,x++ + std ,u++ + cmpu #$0200 + bne vec_copy + + ldx #$1A00 + clra + clrb +ud_wipe: + std ,x++ + cmpx #$1C00 + bne ud_wipe + lda ,x+ + cmpa #$15 + bne wrong_err + lda ,x+ + cmpa #$C0 + bne wrong_err + rts + +wrong_err: + ldu #wrong + bra l2 +load_error: + ldu #fail +l2: bsr copy_str +l1: bra l1 + +copy_str: + lda ,u+ + beq endstr + sta ,y+ + bra copy_str +endstr: rts +fail: + .ascii "Fail" + .db 0 +wrong: + .ascii "Wrong image" + .db 0 diff --git a/Kernel/platform-coco2cart/config.h b/Kernel/platform-coco2cart/config.h index fbd29601..f566efa0 100644 --- a/Kernel/platform-coco2cart/config.h +++ b/Kernel/platform-coco2cart/config.h @@ -15,7 +15,7 @@ #define CONFIG_BANKS 1 /* And swapping */ -#define SWAPDEV 0x0 /* Uses part of IDE slice 0 */ +#define SWAPDEV 0x900 /* Uses part of IDE slice 0 */ #define SWAP_SIZE 0x40 /* 32K in 512 byte blocks */ #define SWAPBASE 0x8000 /* We swap the lot */ #define SWAPTOP 0xFE00 /* so it's a round number of 512 byte sectors */ @@ -24,6 +24,7 @@ /* Permit large I/O requests to bypass cache and go direct to userspace */ #define CONFIG_LARGE_IO_DIRECT +#define CONFIG_LEGACY_EXEC /* Video terminal, not a serial tty */ #define CONFIG_VT diff --git a/Kernel/platform-coco2cart/devices.c b/Kernel/platform-coco2cart/devices.c index 5c3689bd..3bcb457d 100644 --- a/Kernel/platform-coco2cart/devices.c +++ b/Kernel/platform-coco2cart/devices.c @@ -9,6 +9,7 @@ #include #include #include +#include #include struct devsw dev_tab[] = /* The device driver switch table */ @@ -31,6 +32,7 @@ struct devsw dev_tab[] = /* The device driver switch table */ { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl }, /* 8: /dev/dw DriveWire remote disk images */ { dw_open, no_close, dw_read, dw_write, no_ioctl }, + { no_open, no_close, sdc_read, sdc_write, no_ioctl }, }; bool validdev(uint16_t dev) @@ -46,4 +48,5 @@ bool validdev(uint16_t dev) void device_init(void) { ide_probe(); + devsdc_init(); } diff --git a/Kernel/platform-coco2cart/devsdc.c b/Kernel/platform-coco2cart/devsdc.c new file mode 100644 index 00000000..a5814a83 --- /dev/null +++ b/Kernel/platform-coco2cart/devsdc.c @@ -0,0 +1,167 @@ +/* + + CoCoSDC driver + (c)2015 Brett M. Gordon GPL2 + + * Needs work on extended SDC API stuff. + * init / mounting stuff really needs to set/update blkdev structure for size + * need to get rawmode=1 and 2 working. + +*/ + +#include +#include +#include +#include +#include +#include + + +#define SDC_REG_BASE 0xff40 +#define SDC_REG_CTL (SDC_REG_BASE+0x00 ) +#define SDC_REG_DATA (SDC_REG_BASE+0x02 ) +#define SDC_REG_FCTL (SDC_REG_BASE+0x03 ) +#define SDC_REG_CMD (SDC_REG_BASE+0x08 ) +#define SDC_REG_STAT (SDC_REG_BASE+0x08 ) +#define SDC_REG_PARAM1 (SDC_REG_BASE+0x09 ) +#define SDC_REG_PARAM2 (SDC_REG_BASE+0x0a ) +#define SDC_REG_PARAM3 (SDC_REG_BASE+0x0b ) + +#define SDC_BUSY 0x01 +#define SDC_READY 0x02 +#define SDC_FAIL 0x80 + + + +#define sdc_reg_ctl *((volatile uint8_t *)SDC_REG_CTL) +#define sdc_reg_data *((volatile uint8_t *)SDC_REG_DATA) +#define sdc_reg_fctl *((volatile uint8_t *)SDC_REG_FCTL) +#define sdc_reg_cmd *((volatile uint8_t *)SDC_REG_CMD) +#define sdc_reg_stat *((volatile uint8_t *)SDC_REG_STAT) +#define sdc_reg_param1 *((volatile uint8_t *)SDC_REG_PARAM1) +#define sdc_reg_param2 *((volatile uint8_t *)SDC_REG_PARAM2) +#define sdc_reg_param3 *((volatile uint8_t *)SDC_REG_PARAM3) + + +/* Assembler glue */ + +extern void sdc_read_data(uint8_t *p); +extern void sdc_write_data(uint8_t *p); +extern uint8_t sdcpage; + +/* a "simple" internal function pointer to which transfer + routine to use. The is_read var might be better stored + in a way that the asm helpers could do self modifying. +*/ +typedef void (*sdc_transfer_function_t)( unsigned char *addr); + + + +/* blkdev method: transfer sectors */ +static uint8_t sdc_transfer(uint8_t minor, bool is_read, uint8_t rawflag) +{ + uint8_t nb = udata.u_nblock; /* our return value, preset to failure */ + uint32_t lba; /* holds 32 bit lsn */ + uint8_t *ptr = ((uint8_t *)&lba)+1; /* points to 24 bit lba in blk op */ + uint8_t t; /* temporarory sdc status holder */ + uint8_t cmd; /* holds SDC command value */ + sdc_transfer_function_t fptr; /* holds which xfer routine we want */ + + if (rawflag == 1 && d_blkoff(9) ) + return -1; + + /* pass rawflag to assembler */ + sdcpage = rawflag; + + + /* we get 256 bytes per lba in SDC so convert */ + udata.u_nblock *= 2; + lba = udata.u_block * 2; + ptr[0] |= (minor & 0x7f) << 1; + + /* setup cmd pointer and command value from blk_op */ + if( is_read ){ + cmd = 0x80; + fptr = sdc_read_data; + } + else{ + cmd = 0xa0; + fptr = sdc_write_data; + } + + /* apply our drive value 0 or 1*/ + if( minor & 0x80 ) + cmd++; + + while(udata.u_nblock--){ + /* load up registers */ + sdc_reg_param1 = ptr[0]; + sdc_reg_param2 = ptr[1]; + sdc_reg_param3 = ptr[2]; + sdc_reg_cmd= cmd; + asm("\texg x,x\n"); /* delay 16us minimum */ + asm("\texg x,x\n"); + /* wait till SDC is ready */ + do{ + t=sdc_reg_stat; + if( t & SDC_FAIL ) goto fail; + } while( ! (t & SDC_READY) ); + /* do our low-level xfer function */ + fptr( udata.u_dptr ); + /* and wait will ready again, and test for failure */ + do{ + t=sdc_reg_stat; + if( t & SDC_FAIL ) goto fail; + }while ( t & SDC_BUSY ); + /* increment our blk_op values for next 256 bytes sector */ + udata.u_dptr += 256; + lba++; + } + /* Huzzah! success! */ + return nb; + /* Boo! failure */ + fail: sdc_reg_ctl = 0x00; + udata.u_error = EIO; + return -1; +} + + +int sdc_read(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + return sdc_transfer(minor, true, rawflag); +} + +int sdc_write(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + return sdc_transfer(minor, false, rawflag); +} + + + + + +__attribute__((section(".discard"))) +/* Returns true if SDC hardware seems to exist */ +bool devsdc_exist() +{ + uint8_t t; + sdc_reg_data=0x64; + t=sdc_reg_fctl; + sdc_reg_data=0x00; + if( (sdc_reg_fctl ^ t) == 0x60 ) return -1; + else return 0; +} + +__attribute__((section(".discard"))) +/* Call this to initialize SDC/blkdev interface */ +void devsdc_init() +{ + kputs("SDC: "); + if( devsdc_exist() ){ + /* turn on uber-secret SDC LBA mode*/ + sdc_reg_ctl = 0x43; + kputs("Ok.\n"); + } + else kprintf("Not Found.\n"); +} + diff --git a/Kernel/platform-coco2cart/devsdc.h b/Kernel/platform-coco2cart/devsdc.h new file mode 100644 index 00000000..5c671465 --- /dev/null +++ b/Kernel/platform-coco2cart/devsdc.h @@ -0,0 +1,8 @@ + + +extern int sdc_open(uint8_t minor, uint16_t flag); +extern int sdc_read(uint8_t minor, uint8_t rawflag, uint8_t flag); +extern int sdc_write(uint8_t minor, uint8_t rawflag, uint8_t flag); +extern int sdc_ioctl(uint8_t minor, uarg_t request, char *data); + +extern uint8_t sdc_present; diff --git a/Kernel/platform-coco2cart/drivewire.s b/Kernel/platform-coco2cart/drivewire.s index 85962feb..1dfba906 100644 --- a/Kernel/platform-coco2cart/drivewire.s +++ b/Kernel/platform-coco2cart/drivewire.s @@ -220,11 +220,11 @@ lprrtw: .db 0x23 ; request for time ; Used by DWRead and DWWrite IntMasks equ $50 -NOINTMASK equ 1 +NOINTMASK equ 0 ; Hardcode these for now so that we can use below files unmodified H6309 equ 0 -BECKER equ 1 +BECKER equ 0 ARDUINO equ 0 JMCPBCK equ 0 BAUD38400 equ 0 diff --git a/Kernel/platform-coco2cart/sdc.s b/Kernel/platform-coco2cart/sdc.s new file mode 100644 index 00000000..e69de29b