coco3: first stab at sd driver for Roger Taylor's coco on a nano
authorBrett Gordon <beretta42@gmail.com>
Mon, 30 Apr 2018 14:20:51 +0000 (10:20 -0400)
committerBrett Gordon <beretta42@gmail.com>
Mon, 30 Apr 2018 14:20:51 +0000 (10:20 -0400)
Kernel/platform-coco3/Makefile
Kernel/platform-coco3/devices.c
Kernel/platform-coco3/devrtsd.c [new file with mode: 0644]
Kernel/platform-coco3/devrtsd.h [new file with mode: 0644]
Kernel/platform-coco3/rtsd.s [new file with mode: 0644]

index a07f800..720fd6d 100644 (file)
@@ -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
index 71f632f..24737e7 100644 (file)
@@ -11,6 +11,7 @@
 #include <dwtime.h>
 #include <netdev.h>
 #include <devlpr.h>
+#include <devrtsd.h>
 
 
 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 (file)
index 0000000..b737d6c
--- /dev/null
@@ -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 <kernel.h>
+#include <kdata.h>
+#include <blkdev.h>
+#include <mbr.h>
+#include <devrtsd.h>
+#include <printf.h>
+
+
+
+#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 (file)
index 0000000..b780294
--- /dev/null
@@ -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 (file)
index 0000000..6a01e36
--- /dev/null
@@ -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