]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
Multidrive support for mmc.c (working)
authorLeo C <erbl259-lmu@yahoo.de>
Sat, 22 Nov 2014 23:39:03 +0000 (00:39 +0100)
committerLeo C <erbl259-lmu@yahoo.de>
Sat, 22 Nov 2014 23:39:03 +0000 (00:39 +0100)
avr/mmc.c

index 2592c45f12b7fb644294a028f561f645fbf5b7b2..d780fef4657ddcb5db01a8823ad9ef249456d92b 100644 (file)
--- a/avr/mmc.c
+++ b/avr/mmc.c
 #include "diskio.h"
 //#include "debug.h"
 
+#define MAX_DRV                2
 
 /* Port Controls  (Platform dependent) */
 /* SD card socket connections */
 
+//#define SD_CD_0      SBIT(PORT,)             /* Card detect switch */
+//#define SD_CD_0_IN   SBIT(PIN,)
+//#define SD_CD_0_DDR  SBIT(DDR,)
+
+//#define SD_WP_0      SBIT(PORT,)             /* Write protect switch */
+//#define SD_WP_0_IN   SBIT(PIN,)
+//#define SD_WP_0_DDR  SBIT(DDR,)
+
+#define SD_CS_0                SBIT(PORTB,0)           /* Chip select pin */
+#define SD_CS_0_IN     SBIT(PINB,0)
+#define SD_CS_0_DDR    SBIT(DDRB,0)
+
 #define SD_CD_1                SBIT(PORTG,3)           /* Card detect switch */
 #define SD_CD_1_IN     SBIT(PING,3)
 #define SD_CD_1_DDR    SBIT(DDRG,3)
@@ -69,7 +82,7 @@ struct sdsock_stat_s {
 
 static
 struct sdsock_stat_s
-       socket[2] = {
+       socket[MAX_DRV] = {
                {.stat=STA_NOINIT},
                {.stat=STA_NOINIT}
        };
@@ -98,26 +111,30 @@ int wait_ready (void)      /* 1:OK, 0:Timeout */
 /*-----------------------------------------------------------------------*/
 
 static
-void deselect (void)
+void deselect(BYTE drv)
 {
 //     debug("*** enter deselect()\n");
-       SD_CS_1 = 1;
+       if (drv == 0)
+               SD_CS_0 = 1;
+       else
+               SD_CS_1 = 1;
        /* Dummy clock (TODO: force DO hi-z for multiple slave SPI) */
        spi_rcvr();
 //     debug("***  exit deselect()\n");
 }
 
-
-
 /*-----------------------------------------------------------------------*/
 /* Select the card and wait for ready                                    */
 /*-----------------------------------------------------------------------*/
 
 static
-int select (void)      /* 1:Successful, 0:Timeout */
+int select(BYTE drv)   /* 1:Successful, 0:Timeout */
 {
 //     debug("*** enter select()\n");
-       SD_CS_1 = 0;
+       if (drv == 0)
+               SD_CS_0 = 0;
+       else
+               SD_CS_1 = 0;
        /* Dummy clock (force DO enabled) */
        spi_rcvr();
 
@@ -125,7 +142,7 @@ int select (void)   /* 1:Successful, 0:Timeout */
 //             debug("***  exit select() == 1\n");
                return 1;       /* OK */
        }
-       deselect();
+       deselect(drv);
 //     debug("***  exit select() == 0\n");
 
        return 0;       /* Timeout */
@@ -138,56 +155,92 @@ int select (void) /* 1:Successful, 0:Timeout */
 /* is nothing to do in these functions and chk_power always returns 1.   */
 
 static
-void power_on(void)
+void power_on(BYTE drv)
 {
 //     debug("*** enter power_on()\n");
 
+       if (drv == 0) {
+#ifdef SD_PWR_0
+               SD_PWR_0_DDR = 1;       /* Turns on PWR pin as output */
+               SD_PWR_0 = 0;           /* Drives PWR pin high */
+
+               for (uint32_t to = get_timer(0); get_timer(to) < 30;)
+                       ; /* Wait for 30ms */
+#endif
+
+#ifdef SD_CD_0
+               /* Card detect, input with pullup */
+               SD_CD_0_DDR = 0;
+               SD_CD_0 = 1;
+#endif
+#ifdef SD_WP_0
+               SD_WP_0_DDR = 0;
+               SD_WP_0 = 1;
+#endif
+               SD_CS_0 = 1;
+               SD_CS_0_DDR = 1;
+       } else {
 #ifdef SD_PWR_1
-       SD_PWR_1_DDR = 1;       /* Turns on PWR pin as output */
-       SD_PWR_1 = 0;           /* Drives PWR pin high */
+               SD_PWR_1_DDR = 1;       /* Turns on PWR pin as output */
+               SD_PWR_1 = 0;           /* Drives PWR pin high */
 
-       for (uint32_t to = get_timer(0); get_timer(to) < 30;)
-               ; /* Wait for 30ms */
+               for (uint32_t to = get_timer(0); get_timer(to) < 30;)
+                       ; /* Wait for 30ms */
 #endif
 
 #ifdef SD_CD_1
-       /* Card detect, input with pullup */
-       SD_CD_1_DDR = 0;
-       SD_CD_1 = 1;
+               /* Card detect, input with pullup */
+               SD_CD_1_DDR = 0;
+               SD_CD_1 = 1;
 #endif
 #ifdef SD_WP_1
-       SD_WP_1_DDR = 0;
-       SD_WP_1 = 1;
+               SD_WP_1_DDR = 0;
+               SD_WP_1 = 1;
 #endif
-       SD_CS_1 = 1;
-       SD_CS_1_DDR = 1;
+               SD_CS_1 = 1;
+               SD_CS_1_DDR = 1;
+       }
 
 //     debug("***  exit power_on()\n");
 }
 
 static
-void power_off (void)
+void power_off(BYTE drv)
 {
 //     debug("*** enter power_off()\n");
-       select();               /* Wait for card ready */
-       deselect();
+       select(drv);            /* Wait for card ready */
+       deselect(drv);
 
+       if (drv == 0) {
+#ifdef SD_PWR_0
+               SD_PWR_0 = 1;           /* Socket power OFF */
+#endif
+       } else {
 #ifdef SD_PWR_1
-       SD_PWR_1 = 1;           /* Socket power OFF */
+               SD_PWR_1 = 1;           /* Socket power OFF */
 #endif
-       socket[0].stat |= STA_NOINIT;
+       }
+       socket[drv].stat |= STA_NOINIT;
 //     debug("***  exit power_off()\n");
 }
 
 #if 0
 static
-int chk_power(void) /* Socket power state: 0=off, 1=on */
+int chk_power(BYTE drv) /* Socket power state: 0=off, 1=on */
 {
+       if (drv == 0) {
+#ifdef SD_PWR_0
+               return SD_PWR_0 == 0;
+#else
+               return 1;
+#endif /* SD_PWR_PIN */
+       } else {
 #ifdef SD_PWR_1
-       return SD_PWR_1 == 0;
+               return SD_PWR_1 == 0;
 #else
-       return 1;
+               return 1;
 #endif /* SD_PWR_PIN */
+       }
 }
 #endif
 
@@ -267,8 +320,9 @@ int xmit_datablock (
 
 static
 BYTE send_cmd (                /* Returns R1 resp (bit7==1:Send failed) */
-       BYTE cmd,               /* Command index */
-                                        DWORD arg /* Argument */
+       BYTE drv,       /* Physical drive nmuber (0) */
+       BYTE cmd,       /* Command index */
+       DWORD arg       /* Argument */
 ) {
        union {
                DWORD as32;
@@ -280,15 +334,15 @@ BYTE send_cmd (           /* Returns R1 resp (bit7==1:Send failed) */
 
        if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
                cmd &= 0x7F;
-               res = send_cmd(CMD55, 0);
+               res = send_cmd(drv, CMD55, 0);
                if (res > 1)
                        return res;
        }
 
        /* Select the card and wait for ready except to stop multiple block read */
        if (cmd != CMD12) {
-               deselect();
-               if (!select())
+               deselect(drv);
+               if (!select(drv))
                        return 0xFF;
        }
 
@@ -336,53 +390,60 @@ DSTATUS disk_initialize (
 {
        BYTE n, cmd, ty, ocr[4];
 
-       if (drv)
+       if (drv >= MAX_DRV)
                return STA_NOINIT; /* Supports only single drive */
        if (socket[drv].stat & STA_NODISK)
                return socket[drv].stat; /* No card in the socket */
 
-       power_on(); /* Force socket power on */
+       power_on(drv); /* Force socket power on */
        FCLK_SLOW();
        for (n = 10; n; n--)
                spi_rcvr(); /* 80 dummy clocks */
 
        ty = 0;
-       if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
+       if (send_cmd(drv, CMD0, 0) == 1) { /* Enter Idle state */
                /* Init timeout timer */
                uint32_t timer = get_timer(0);
 
-               if (send_cmd(CMD8, 0x1AA) == 1) {       /* SDv2? */
-                       for (n = 0; n < 4; n++) ocr[n] = spi_rcvr();            /* Get trailing return value of R7 resp */
-                       if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
-                               while (get_timer(timer) < MMC_INIT_TO && send_cmd(ACMD41, 1UL << 30));  /* Wait for leaving idle state (ACMD41 with HCS bit) */
-                               if (get_timer(timer) < MMC_INIT_TO && send_cmd(CMD58, 0) == 0) {                /* Check CCS bit in the OCR */
-                                       for (n = 0; n < 4; n++) ocr[n] = spi_rcvr();
+               if (send_cmd(drv, CMD8, 0x1AA) == 1) {  /* SDv2? */
+                       /* Get trailing return value of R7 resp */
+                       for (n = 0; n < 4; n++)
+                               ocr[n] = spi_rcvr();
+                       if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
+                               /* The card can work at vdd range of 2.7-3.6V */
+                               while (get_timer(timer) < MMC_INIT_TO
+                                       && send_cmd(drv, ACMD41, 1UL << 30))
+                                       ; /* Wait for leaving idle state (ACMD41 with HCS bit) */
+                               if (get_timer(timer) < MMC_INIT_TO && send_cmd(drv, CMD58, 0) == 0) {
+                                       /* Check CCS bit in the OCR */
+                                       for (n = 0; n < 4; n++)
+                                               ocr[n] = spi_rcvr();
                                        ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;      /* SDv2 */
                                }
                        }
                } else {                                                        /* SDv1 or MMCv3 */
-                       if (send_cmd(ACMD41, 0) <= 1) {
+                       if (send_cmd(drv, ACMD41, 0) <= 1) {
                                ty = CT_SD1; cmd = ACMD41;      /* SDv1 */
                        } else {
                                ty = CT_MMC; cmd = CMD1;        /* MMCv3 */
                        }
 
                        /* Wait for leaving idle state */
-                       while (get_timer(timer) < MMC_INIT_TO && send_cmd(cmd, 0));
+                       while (get_timer(timer) < MMC_INIT_TO && send_cmd(drv, cmd, 0))
+                               ;
 
                        /* Set R/W block length to 512 */
-                       if (!(get_timer(timer) < MMC_INIT_TO) || send_cmd(CMD16, 512) != 0)
+                       if (!(get_timer(timer) < MMC_INIT_TO) || send_cmd(drv, CMD16, 512) != 0)
                                ty = 0;
                }
        }
        socket[drv].CardType = ty;
-       deselect();
+       deselect(drv);
 
        if (ty) { /* Initialization succeded */
                socket[drv].stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
-               FCLK_FAST();
        } else { /* Initialization failed */
-               power_off();
+               power_off(drv);
        }
 
        return socket[drv].stat;
@@ -393,10 +454,11 @@ DSTATUS disk_initialize (
 /*-----------------------------------------------------------------------*/
 
 DSTATUS disk_status (
-       BYTE drv                /* Physical drive nmuber (0) */
+       BYTE drv        /* Physical drive nmuber (0) */
 )
 {
-       if (drv) return STA_NOINIT;             /* Supports only single drive */
+       if (drv >= MAX_DRV)
+               return STA_NOINIT;
        return socket[drv].stat;
 }
 
@@ -405,30 +467,36 @@ DSTATUS disk_status (
 /*-----------------------------------------------------------------------*/
 
 DRESULT disk_read (
-       BYTE drv,                       /* Physical drive nmuber (0) */
-       BYTE *buff, /* Pointer to the data buffer to store read data */
-       DWORD sector, /* Start sector number (LBA) */
-       UINT count /* Sector count (1..255) */
+       BYTE drv,       /* Physical drive nmuber (0) */
+       BYTE *buff,     /* Pointer to the data buffer to store read data */
+       DWORD sector,   /* Start sector number (LBA) */
+       UINT count      /* Sector count (1..255) */
 )
 {
        BYTE cmd;
 
-       if (drv || !count) return RES_PARERR;
-       if (socket[drv].stat & STA_NOINIT) return RES_NOTRDY;
+       if (drv >= MAX_DRV || !count)
+               return RES_PARERR;
+       if (socket[drv].stat & STA_NOINIT)
+               return RES_NOTRDY;
 
-       if (!(socket[drv].CardType & CT_BLOCK)) sector *= 512;  /* Convert to byte address if needed */
+       /* Convert to byte address if needed */
+       if (!(socket[drv].CardType & CT_BLOCK))
+               sector *= 512;
+       FCLK_FAST();
 
-       cmd = count > 1 ? CMD18 : CMD17;                        /*  READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
-       if (send_cmd(cmd, sector) == 0) {
+       /*  READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
+       cmd = count > 1 ? CMD18 : CMD17;
+       if (send_cmd(drv, cmd, sector) == 0) {
                do {
                        if (!rcvr_datablock(buff, 512))
                                break;
                        buff += 512;
                } while (--count);
                if (cmd == CMD18)
-                       send_cmd(CMD12, 0);     /* STOP_TRANSMISSION */
+                       send_cmd(drv, CMD12, 0);        /* STOP_TRANSMISSION */
        }
-       deselect();
+       deselect(drv);
 
        return count ? RES_ERROR : RES_OK;
 }
@@ -439,35 +507,45 @@ DRESULT disk_read (
 
 #if _USE_WRITE
 DRESULT disk_write (
-               BYTE drv, /* Physical drive nmuber (0) */
-               const BYTE *buff, /* Pointer to the data to be written */
-               DWORD sector, /* Start sector number (LBA) */
-               UINT count /* Sector count (1..255) */
+       BYTE drv,       /* Physical drive nmuber (0) */
+       const BYTE *buff, /* Pointer to the data to be written */
+       DWORD sector,   /* Start sector number (LBA) */
+       UINT count      /* Sector count (1..255) */
 )
 {
-       if (drv || !count) return RES_PARERR;
-       if (socket[drv].stat & STA_NOINIT) return RES_NOTRDY;
-       if (socket[drv].stat & STA_PROTECT) return RES_WRPRT;
-
-       if (!(socket[drv].CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
-
-       if (count == 1) { /* Single block write */
-               if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
+       if (drv >= MAX_DRV || !count)
+               return RES_PARERR;
+       if (socket[drv].stat & STA_NOINIT)
+               return RES_NOTRDY;
+       if (socket[drv].stat & STA_PROTECT)
+               return RES_WRPRT;
+
+       /* Convert to byte address if needed */
+       if (!(socket[drv].CardType & CT_BLOCK))
+               sector *= 512;
+       FCLK_FAST();
+
+       if (count == 1) {
+               /* Single block write */
+               if ((send_cmd(drv, CMD24, sector) == 0) /* WRITE_BLOCK */
                                && xmit_datablock(buff, 0xFE))
                count = 0;
-       }
-       else { /* Multiple block write */
-               if (socket[drv].CardType & CT_SDC) send_cmd(ACMD23, count);
-               if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
+       } else {
+               /* Multiple block write */
+               if (socket[drv].CardType & CT_SDC)
+                       send_cmd(drv, ACMD23, count);
+               if (send_cmd(drv, CMD25, sector) == 0) {
+                       /* WRITE_MULTIPLE_BLOCK */
                        do {
-                               if (!xmit_datablock(buff, 0xFC)) break;
+                               if (!xmit_datablock(buff, 0xFC))
+                                       break;
                                buff += 512;
-                       }while (--count);
+                       } while (--count);
                        if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
-                       count = 1;
+                               count = 1;
                }
        }
-       deselect();
+       deselect(drv);
 
        return count ? RES_ERROR : RES_OK;
 }
@@ -488,21 +566,23 @@ DRESULT disk_ioctl (
        BYTE n, csd[16], *ptr = buff;
        DWORD csize;
 
-       if (drv)
+       if (drv >= MAX_DRV)
                return RES_PARERR;
 
        res = RES_ERROR;
 
-       if (socket[drv].stat & STA_NOINIT) return RES_NOTRDY;
+       if (socket[drv].stat & STA_NOINIT)
+               return RES_NOTRDY;
 
+       FCLK_FAST();
        switch (cmd) {
        case CTRL_SYNC :                /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
-               if (select())
+               if (select(drv))
                        res = RES_OK;
                break;
 
        case GET_SECTOR_COUNT: /* Get number of sectors on the disk (DWORD) */
-               if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
+               if ((send_cmd(drv, CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
                        if ((csd[0] >> 6) == 1) {       /* SDC ver 2.00 */
                                csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
                                *(DWORD*)buff = csize << 10;
@@ -517,7 +597,7 @@ DRESULT disk_ioctl (
 
        case GET_BLOCK_SIZE:    /* Get erase block size in unit of sector (DWORD) */
                if (socket[drv].CardType & CT_SD2) {    /* SDv2? */
-                       if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
+                       if (send_cmd(drv, ACMD13, 0) == 0) { /* Read SD status */
                                spi_rcvr();
                                if (rcvr_datablock(csd, 16)) { /* Read partial block */
                                        for (n = 64 - 16; n; n--)
@@ -527,7 +607,7 @@ DRESULT disk_ioctl (
                                }
                        }
                } else {                                        /* SDv1 or MMCv3 */
-                       if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
+                       if ((send_cmd(drv, CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
                                if (socket[drv].CardType & CT_SD1) {    /* SDv1 */
                                        *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
                                } else {                                        /* MMCv3 */
@@ -546,19 +626,19 @@ DRESULT disk_ioctl (
                break;
 
        case MMC_GET_CSD: /* Receive CSD as a data block (16 bytes) */
-               if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
+               if (send_cmd(drv, CMD9, 0) == 0 /* READ_CSD */
                && rcvr_datablock(ptr, 16))
                        res = RES_OK;
                break;
 
        case MMC_GET_CID: /* Receive CID as a data block (16 bytes) */
-               if (send_cmd(CMD10, 0) == 0 /* READ_CID */
+               if (send_cmd(drv, CMD10, 0) == 0 /* READ_CID */
                && rcvr_datablock(ptr, 16))
                        res = RES_OK;
                break;
 
        case MMC_GET_OCR: /* Receive OCR as an R3 resp (4 bytes) */
-               if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
+               if (send_cmd(drv, CMD58, 0) == 0) { /* READ_OCR */
                        for (n = 4; n; n--)
                                *ptr++ = spi_rcvr();
                        res = RES_OK;
@@ -566,7 +646,7 @@ DRESULT disk_ioctl (
                break;
 
        case MMC_GET_SDSTAT: /* Receive SD status as a data block (64 bytes) */
-               if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
+               if (send_cmd(drv, ACMD13, 0) == 0) { /* SD_STATUS */
                        spi_rcvr();
                        if (rcvr_datablock(ptr, 64))
                                res = RES_OK;
@@ -574,7 +654,7 @@ DRESULT disk_ioctl (
                break;
 
        case CTRL_POWER_OFF :   /* Power off */
-               power_off();
+               power_off(drv);
                socket[drv].stat |= STA_NOINIT;
                res = RES_OK;
                break;
@@ -583,7 +663,7 @@ DRESULT disk_ioctl (
                res = RES_PARERR;
        }
 
-       deselect();
+       deselect(drv);
 
        return res;
 }
@@ -599,20 +679,32 @@ void disk_timerproc (void)
        BYTE s;
 
        s = socket[0].stat;
+#ifdef SD_WP_0
+       if (SD_WP_0_IN == 0)                    /* Write protected */
+               s |= STA_PROTECT;
+       else                                    /* Write enabled */
+               s &= ~STA_PROTECT;
+#endif
+#ifdef SD_CD_0
+       if (SD_CD_0_IN == 0)                    /* Card inserted */
+               s &= ~STA_NODISK;
+       else                                    /* Socket empty */
+               s |= (STA_NODISK | STA_NOINIT);
+#endif
+       socket[0].stat = s;                     /* Update MMC status */
 
+       s = socket[1].stat;
 #ifdef SD_WP_1
        if (SD_WP_1_IN == 0)                    /* Write protected */
                s |= STA_PROTECT;
        else                                    /* Write enabled */
                s &= ~STA_PROTECT;
 #endif
-
 #ifdef SD_CD_1
        if (SD_CD_1_IN == 0)                    /* Card inserted */
                s &= ~STA_NODISK;
        else                                    /* Socket empty */
                s |= (STA_NODISK | STA_NOINIT);
 #endif
-
-       socket[0].stat = s;                     /* Update MMC status */
+       socket[1].stat = s;                     /* Update MMC status */
 }