From: Brett Gordon Date: Mon, 30 Apr 2018 14:20:51 +0000 (-0400) Subject: coco3: first stab at sd driver for Roger Taylor's coco on a nano X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=a263ff77819e301bcdfc1e1beadc89235bbfde04;p=FUZIX.git coco3: first stab at sd driver for Roger Taylor's coco on a nano --- diff --git a/Kernel/platform-coco3/Makefile b/Kernel/platform-coco3/Makefile index a07f8002..720fd6d8 100644 --- a/Kernel/platform-coco3/Makefile +++ b/Kernel/platform-coco3/Makefile @@ -1,6 +1,6 @@ CSRCS = ttydw.c mbr.c dwtime.c -CSRCS += devices.c main.c libc.c devsdc.c devlpr.c +CSRCS += devices.c main.c libc.c devsdc.c devlpr.c devrtsd.c CDSRCS = ../dev/devide_discard.c ../dev/devsd_discard.c @@ -8,7 +8,7 @@ DSRCS = ../dev/devdw.c ../dev/blkdev.c ../dev/devide.c ../dev/devsd.c NSRCS = ../dev/net/net_native.c -ASRCS = coco3.s crt0.s ide.s sd.s +ASRCS = coco3.s crt0.s ide.s sd.s rtsd.s ASRCS += tricks.s commonmem.s usermem_gime.s drivewire.s sdc.s videoll.s COBJS = $(CSRCS:.c=$(BINEXT)) @@ -62,6 +62,11 @@ DRIVERS += devsd.o devsd_discard.o sd.o CROSS_CC += -DCONFIG_COCOSDFPGA endif +ifdef COCO_SDNANO +DRIVERS += devrtsd.o rtsd.o +CROSS_CC += -DCONFIG_COCOSDNANO +endif + ifdef COCO_BECKER ASOPTS = --defsym BECKER=1 else diff --git a/Kernel/platform-coco3/devices.c b/Kernel/platform-coco3/devices.c index 71f632fe..24737e71 100644 --- a/Kernel/platform-coco3/devices.c +++ b/Kernel/platform-coco3/devices.c @@ -11,6 +11,7 @@ #include #include #include +#include struct devsw dev_tab[] = /* The device driver switch table */ @@ -54,6 +55,9 @@ void device_init(void) #endif #ifdef CONFIG_COCOSDC devsdc_init( ); +#endif +#ifdef CONFIG_COCOSDNANO + devrtsd_init(); #endif if ( ! dw_init() ) dwtime_init( ); diff --git a/Kernel/platform-coco3/devrtsd.c b/Kernel/platform-coco3/devrtsd.c new file mode 100644 index 00000000..b737d6c9 --- /dev/null +++ b/Kernel/platform-coco3/devrtsd.c @@ -0,0 +1,108 @@ +/* + + Roger Taylor's CoCo On a Chip SD card driver + (for use with firmware > 031618) + + Fixme: these routines need to fail gracefully. +*/ + + +#include +#include +#include +#include +#include +#include + + + +#define sdc_data *((volatile uint8_t *) 0xff70) +#define sdc_status *((volatile uint8_t *) 0xff71) +#define SDC_ST_RTS 0x80 +#define SDC_ST_BUSY 0x40 +#define SDC_ST_SBUSY 0x20 +#define SDC_ST_VALID 0x10 +#define SDC_ST_MOUNT 0x08 +#define SDC_ST_CLASS 0x04 +#define SDC_ST_WBUSY 0x01 +#define sdc_command *((volatile uint8_t *) 0xff71) +#define SDC_CMD_READ 0x00 +#define SDC_CMD_WRITE 0x10 +#define SDC_CMD_RESET 0x30 +#define SDC_CMD_MOUNT 0x20 +#define SDC_CMD_DIRECT 0xC0 +#define SDC_CMD_IMAGE 0x80 +#define SDC_CMD_GMOUNT 0x40 +#define sdc_lsn_high *((volatile uint8_t *) 0xff72) +#define sdc_lsn_mid *((volatile uint8_t *) 0xff73) +#define sdc_lsn_low *((volatile uint8_t *) 0xff74) + +typedef void (*sdc_transfer_function_t)(unsigned char *addr); + + +/* blkdev method: flush drive */ +int devrtsd_flush( void ) +{ + return 0; +} + +/* blkdev method: transfer sectors */ +uint8_t devrtsd_transfer(void) +{ + int i = 2; + uint8_t *ptr; + sdc_transfer_function_t fptr; + uint8_t cmd; + + /* convert to 256 byte sector LBA */ + blk_op.lba *= 2; + + if (blk_op.is_read){ + cmd = SDC_CMD_READ; + fptr = devrtsd_read; + } + else { + cmd = SDC_CMD_WRITE; + fptr = devrtsd_write; + } + + cmd |= blk_op.blkdev->driver_data; + ptr=((uint8_t *)(&blk_op.lba))+1; + while (i--){ + /* set lsn */ + sdc_lsn_high = ptr[0]; + sdc_lsn_mid = ptr[1]; + sdc_lsn_low = ptr[2]; + /* wait for ready */ + while (sdc_status & (SDC_ST_BUSY | SDC_ST_SBUSY) ); + /* send command */ + sdc_command = cmd; + /* xfer data */ + fptr( blk_op.addr ); + /* wait for ready */ + while (sdc_status & (SDC_ST_BUSY | SDC_ST_SBUSY) ); + blk_op.lba++; + blk_op.addr += 256; + } + return 1; +} + +__attribute__((section(".discard"))) +/* blkdev method: initalize device */ +void devrtsd_init( void ) +{ + blkdev_t *blk; + int i; + + kputs("RTSD: "); + /* fixme: add some device checking/reporting here */ + for (i = 0; i < 4; i++) { + blk = blkdev_alloc(); + blk->driver_data = i; + blk->transfer = devrtsd_transfer; + blk->flush = devrtsd_flush; + /* assume max 24 bit size? (how big are images?) */ + blk->drive_lba_count = 16777216; + } + kputs("Ok.\n"); +} diff --git a/Kernel/platform-coco3/devrtsd.h b/Kernel/platform-coco3/devrtsd.h new file mode 100644 index 00000000..b780294c --- /dev/null +++ b/Kernel/platform-coco3/devrtsd.h @@ -0,0 +1,4 @@ + +void devrtsd_init( void ); +void devrtsd_read( unsigned char *addr ); +void devrtsd_write( unsigned char *addr ); diff --git a/Kernel/platform-coco3/rtsd.s b/Kernel/platform-coco3/rtsd.s new file mode 100644 index 00000000..6a01e36b --- /dev/null +++ b/Kernel/platform-coco3/rtsd.s @@ -0,0 +1,46 @@ +;;; Low level common memory transfer routine +;;; for Roger Taylor's CoCo On A Chip SD + + +;;; imported + .globl blk_op + +;;; exported + .globl _devrtsd_write + .globl _devrtsd_read + +DATA equ $ff70 +STATUS equ $ff71 + + + section .common + +;;; fixme: unroll loops +_devrtsd_write + pshs u + ldu #DATA ; set Y to point at data reg a + clra + jsr blkdev_rawflg ; map memory based on blkopt flag +a@ ldb STATUS + lsrb + bcs a@ + ldb ,x+ ; get 2 data bytes from source + stb ,u ; send data to controller + deca ; decrement loop counter + bne a@ ; loop until all chunks written + jsr blkdev_unrawflg ; reset memory + puls u,pc ; return + +_devrtsd_read + pshs u + ldu #DATA ; set Y to point to data reg a + clra + jsr blkdev_rawflg ; map memory based on blkopt flag +a@ ldb STATUS + bpl a@ + ldb ,u + stb ,x+ + deca ; decrement loop counter + bne a@ ; loop if more chunks to read + jsr blkdev_unrawflg ; reset memory + puls u,pc ; return \ No newline at end of file