| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758 |
- /****************************************************************************
- * This file is part of the MMC device driver.
- *
- * Copyright (c) 2004 by Michael Fischer. All rights reserved.
- *
- * Thanks to Sylvain Bissonnette for some of his low level functions.
- * Take a look at www.microsyl.com (Led Sign with MMC MemoryCard)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the author nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- ****************************************************************************
- * History:
- *
- * 10.10.04 mifi First Version
- ****************************************************************************/
- #define __MMCDRV_C__
- #define LOG_MODULE LOG_MMCDRV_MODULE
- #include <stdio.h>
- #include <string.h>
- #include <sys/timer.h>
- #include <sys/thread.h>
- #include <sys/event.h>
- #include <sys/heap.h>
- #include "typedefs.h"
- #include "portio.h"
- #include "mmcdrv.h"
- #include "vs10xx.h"
- #include "led.h"
- #include "log.h"
- #include "spidrv.h"
- /*==========================================================*/
- /* DEFINE: All Structures and Common Constants */
- /*==========================================================*/
- #define MMC_MAX_SUPPORTED_DEVICE 1
- /*
- * Drive Flags
- */
- #define MMC_SUPPORT_LBA 0x0001
- #define MMC_SUPPORT_LBA48 0x0002
- #define MMC_READ_ONLY 0x4000
- #define MMC_READY 0x8000
- #define Delay_1ms(_x) NutDelay(_x)
- #define SPIDDR DDRB
- #define SPIPORT PORTB
- #define SPIPIN PINB
- /*
- PragmaLab: disable PIN-defines (already defined in 'portio.h'
- #define SCLK 0x02
- #define MOSI 0x04
- #define MISO 0x08
- #define CS 0x20
- #define ENABLE 0x40
- end PragmaLab
- */
- #define MMC_RESET 0
- #define MMC_INIT 1
- #define MMC_READ_CSD 9
- #define MMC_READ_CID 10
- typedef struct _drive
- {
- /*
- * Interface values
- */
- WORD wFlags;
- BYTE bDevice;
- /*
- * LBA value
- */
- DWORD dTotalSectors;
- WORD wSectorSize;
- } DRIVE;
- /*==========================================================*/
- /* DEFINE: Definition of all local Data */
- /*==========================================================*/
- static HANDLE hMMCSemaphore;
- static DRIVE sDrive[MMC_MAX_SUPPORTED_DEVICE];
- static MMC_MOUNT_FUNC *pUserMountFunc;
- static MMC_MOUNT_FUNC *pUserUnMountFunc;
- /*==========================================================*/
- /* DEFINE: Definition of all local Procedures */
- /*==========================================================*/
- /************************************************************/
- /* MMCLock */
- /************************************************************/
- static void MMCLock(void)
- {
- NutEventWait(&hMMCSemaphore, 0);
- } /* MMCLock */
- /************************************************************/
- /* MMCFree */
- /************************************************************/
- static void MMCFree(void)
- {
- NutEventPost(&hMMCSemaphore);
- } /* MMCFree */
- /************************************************************/
- /* MMCSemaInit */
- /************************************************************/
- static void MMCSemaInit(void)
- {
- NutEventPost(&hMMCSemaphore);
- } /* MMCSemaInit */
- /************************************************************
- * int MMCDataToken(void)
- *
- * - pings the card until it gets data token
- * - returns one byte of read info (data token)
- ************************************************************/
- static BYTE MMCDataToken(void)
- {
- WORD i = 0xffff;
- BYTE Byte = 0xff;
- while ((Byte != 0xfe) && (--i))
- {
- Byte = SPIgetByte();
- }
- return(Byte);
- } /* MMCDataToken */
- /************************************************************
- * unsigned char MMCGet(void)
- *
- * - pings the card until it gets a non-0xff value
- * - returns one byte of read info
- ************************************************************/
- static BYTE MMCGet(void)
- {
- WORD i = 0xffff;
- BYTE Byte = 0xff;
- while ((Byte == 0xff) && (--i))
- {
- Byte = SPIgetByte();
- }
- return(Byte);
- } /* MMCGet */
- /************************************************************
- * void MMCCommand(unsigned char command, unsigned int px, unsigned int py)
- *
- * - send one byte of 0xff, then issue command + params + (fake) crc
- * - eat up the one command of nothing after the CRC
- ************************************************************/
- static void MMCCommand(unsigned char command, unsigned int px, unsigned int py)
- {
- SPIselect(SPI_DEV_MMC);
- SPIputByte(0xff);
- SPIputByte(command | 0x40);
- SPIputByte((unsigned char)((px >> 8)&0x0ff)); /* high byte of param y */
- SPIputByte((unsigned char)(px & 0x00ff)); /* low byte of param y */
- SPIputByte((unsigned char)((py >> 8)&0x0ff)); /* high byte of param x */
- SPIputByte((unsigned char)(py & 0x00ff)); /* low byte of param x */
- SPIputByte(0x95); /* correct CRC for first command in SPI */
- /* after that CRC is ignored, so no problem with */
- /* always sending 0x95 */
- SPIputByte(0xff);
- } /* MMCCommand */
- /************************************************************/
- /* GetCSD */
- /************************************************************/
- static int GetCSD (DRIVE *pDrive)
- {
- int i;
- int nError = MMC_ERROR;
- BYTE bData[16];
- WORD wREAD_BL_LEN;
- WORD wC_SIZE;
- WORD wC_SIZE_MULT;
- WORD wDummy;
- DWORD dTotalSectors = 0;
- MMCCommand(MMC_READ_CSD, 0, 0);
- if (MMCDataToken() != 0xfe)
- {
- LogMsg_P(LOG_ERR, PSTR("error during CSD read"));
- }
- else
- {
- for (i=0; i<16; i++)
- {
- bData[i] = SPIgetByte();
- }
- SPIputByte(0xff); /* checksum -> don't care about it for now */
- SPIputByte(0xff); /* checksum -> don't care about it for now */
- SPIdeselect();
- /*
- * Get the READ_BL_LEN
- */
- wREAD_BL_LEN = (1 << (bData[5] & 0x0F));
- /*
- * Get the C_SIZE
- */
- wC_SIZE = (bData[6] & 0x03);
- wC_SIZE = wC_SIZE << 10;
- wDummy = bData[7];
- wDummy = wDummy << 2;
- wC_SIZE |= wDummy;
- wDummy = (bData[8] & 0xC0);
- wDummy = wDummy >> 6;
- wC_SIZE |= wDummy;
- /*
- * Get the wC_SIZE_MULT
- */
- wC_SIZE_MULT = (bData[9] & 0x03);
- wC_SIZE_MULT |= wC_SIZE_MULT << 1;
- wDummy = (bData[10] & 0x80);
- wDummy = wDummy >> 7;
- wC_SIZE_MULT |= wDummy;
- wC_SIZE_MULT = (1 << (wC_SIZE_MULT+2));
- dTotalSectors = wC_SIZE+1;
- dTotalSectors *= wC_SIZE_MULT;
- pDrive->dTotalSectors = dTotalSectors;
- pDrive->wSectorSize = wREAD_BL_LEN;
- nError = MMC_OK;
- }
- return(nError);
- } /* GetCSD */
- #if 0
- /************************************************************/
- /* GetCID */
- /************************************************************/
- static void GetCID(void)
- {
- int i;
- BYTE bData[16];
- MMCCommand(MMC_READ_CID, 0, 0);
- if (MMCDataToken() != 0xfe)
- {
- printf("MMC: error during CID read\n");
- }
- else
- {
- printf("MMC: CID read\n");
- }
- for (i=0; i<16; i++)
- {
- bData[i] = SPIgetByte();
- }
- SPIputByte(0xff); /* checksum -> don't care about it for now */
- SPIputByte(0xff); /* checksum -> don't care about it for now */
- SPIdeselect();
- printf("MMC: Product Name: %c%c%c%c%c%c\n",
- bData[3], bData[4], bData[5],
- bData[6], bData[7], bData[8]);
- } /* GetCID */
- #endif
- /************************************************************/
- /* InitMMCCard */
- /* */
- /* - flushes card receive buffer */
- /* - selects card */
- /* - sends the reset command */
- /* - sends the initialization command, waits for card ready */
- /************************************************************/
- static int InitMMCCard(void)
- {
- WORD i;
- /* PragmaLab: disable initit of PINS and SPI, already done in 'SystemInitIO()'
- SPIDDR = SCLK + MOSI + CS;
- SPIPORT = 0x00;
- Delay_1ms(250);
- Delay_1ms(250);
- SPIPORT |= CS;
- SPCR = (1 << SPE) | (1 << MSTR); // enable SPI as master, set clk divider
- // set to max speed
- Delay_1ms(250);
- SPIdeselect();
- // start off with 80 bits of high data with card deselected
- PragmaLab: why send dummy bytes with card DEselected? This messes up the VS10XX init */
- for (i = 0; i < 10; i++)
- {
- SPIputByte(0xff);
- }
- /*end PragmaLab */
- /* send CMD0 - go to idle state */
- MMCCommand(MMC_RESET, 0, 0);
- if (MMCGet() != 1)
- {
- SPIdeselect();
- return(MMC_ERROR); // MMC Not detected
- }
- /* send CMD1 until we get a 0 back, indicating card is done initializing */
- i = 0xffff;
- while ((SPIgetByte() != 0) && (--i))
- {
- MMCCommand(MMC_INIT, 0, 0);
- }
- if (i == 0)
- {
- SPIdeselect();
- return(MMC_ERROR); // Init Fail
- }
- SPIdeselect();
- return(MMC_OK);
- } /* InitMMCCard */
- /************************************************************/
- /* ReadSectors */
- /************************************************************/
- static int ReadSectors(DRIVE *pDrive, BYTE *pBuffer, DWORD dStartSector, WORD wSectorCount)
- {
- int nError = MMC_OK;
- int nSector;
- WORD wDataCount;
- DWORD dReadSector;
- pDrive = pDrive;
- for (nSector=0; nSector<wSectorCount; nSector++)
- {
- dReadSector = dStartSector + nSector;
- MMCCommand(17,(dReadSector>>7) & 0xffff, (dReadSector<<9) & 0xffff);
- if (MMCDataToken() != 0xfe)
- {
- nError = MMC_ERROR;
- SPIdeselect();
- break;
- }
- for (wDataCount=0; wDataCount<512; wDataCount++)
- { /* read the sector */
- *pBuffer = SPIgetByte();
- pBuffer++;
- }
- SPIputByte(0xff); /* checksum -> don't care about it for now */
- SPIputByte(0xff); /* checksum -> don't care about it for now */
- SPIdeselect();
- }
- return(nError);
- } /* ReadSectors */
- #if (MMC_SUPPORT_WRITE == 1)
- /************************************************************/
- /* WriteSectors */
- /************************************************************/
- static BYTE WriteSectors(DRIVE *pDrive, BYTE *pBuffer, DWORD dStartSector, WORD wSectorCount)
- {
- int nError = MMC_OK;
- int nSector;
- WORD wDataCount;
- DWORD dWriteSector;
- pDrive = pDrive;
- for (nSector=0; nSector<wSectorCount; nSector++)
- {
- dWriteSector = dStartSector + nSector;
- MMCCommand(24, (dWriteSector>>7)& 0xffff, (dWriteSector<<9)& 0xffff);
- if (MMCGet() == 0xff)
- {
- nError = MMC_ERROR;
- SPIdeselect();
- break;
- }
- SPIputByte(0xfe); // Send Start Byte
- for (wDataCount=0; wDataCount<512; wDataCount++)
- { /* read the sector */
- SPIputByte(*pBuffer);
- pBuffer++;
- }
- SPIputByte(0xff); /* checksum -> don't care about it for now */
- SPIputByte(0xff); /* checksum -> don't care about it for now */
- SPIputByte(0xff); /* Read "data response byte" */
- wDataCount = 0xffff;
- while ((SPIgetByte() == 0x00) && (--wDataCount)); /* wait for write finish */
- if (wDataCount == 0)
- {
- nError = MMC_ERROR;
- SPIdeselect();
- break;
- }
- SPIdeselect();
- }
- return(nError);
- }
- #endif /* WriteSectors */
- /*==========================================================*/
- /* DEFINE: All code exported */
- /*==========================================================*/
- /************************************************************/
- /* MMCInit */
- /************************************************************/
- int MMCInit(int nMMCMode, MMC_MOUNT_FUNC *pMountFunc,
- MMC_MOUNT_FUNC *pUnMountFunc)
- {
- int nError = MMC_OK;
- BYTE bIndex;
- nMMCMode = nMMCMode;
- pUserMountFunc = pMountFunc;
- pUserUnMountFunc = pUnMountFunc;
- for (bIndex=0; bIndex<MMC_MAX_SUPPORTED_DEVICE; bIndex++)
- {
- memset((BYTE *) & sDrive[bIndex], 0x00, sizeof(DRIVE));
- sDrive[bIndex].bDevice = bIndex;
- }
- MMCSemaInit();
- nError = InitMMCCard();
- if (nError == MMC_OK)
- {
- sDrive[MMC_DRIVE_C].wFlags = MMC_READY;
- //GetCID();
- }
- return(nError);
- } /* MMCInit */
- /************************************************************/
- /* MMCMountAllDevices */
- /************************************************************/
- int MMCMountAllDevices(int nMMCMode, BYTE *pSectorBuffer)
- {
- int nError = MMC_ERROR;
- DRIVE *pDrive;
- nMMCMode = nMMCMode;
- pDrive = NULL;
- MMCLock();
- pDrive = &sDrive[MMC_DRIVE_C];
- if (pDrive->wFlags & MMC_READY)
- {
- nError = GetCSD(pDrive);
- }
- MMCFree();
- if (nError == MMC_OK)
- {
- nError = MMCReadSectors(MMC_DRIVE_C, pSectorBuffer, 0, 1);
- }
- return(nError);
- } /* MMCMountDevice */
- /************************************************************/
- /* MMCGetSectorSize */
- /************************************************************/
- int MMCGetSectorSize(BYTE bDevice)
- {
- int nSectorSize;
- DRIVE *pDrive;
- nSectorSize = 0;
- MMCLock();
- if (bDevice >= MMC_MAX_SUPPORTED_DEVICE)
- {
- nSectorSize = 0;
- }
- else
- {
- pDrive = &sDrive[bDevice];
- nSectorSize = pDrive->wSectorSize;
- }
- MMCFree();
- return(nSectorSize);
- } /* MMCGetSectorSize */
- /************************************************************/
- /* MMCIsCDROMDevice */
- /************************************************************/
- int MMCIsCDROMDevice(BYTE bDevice)
- {
- return(FALSE);
- } /* MMCIsCDROMDevice */
- /************************************************************/
- /* MMCIsZIPDevice */
- /************************************************************/
- int MMCIsZIPDevice(BYTE bDevice)
- {
- return(FALSE);
- } /* MMCIsZIPDevice */
- /************************************************************/
- /* MMCUnMountDevice */
- /************************************************************/
- int MMCUnMountDevice(BYTE bDevice)
- {
- return(MMC_OK);
- } /* MMCUnMountDevice */
- /************************************************************/
- /* MMCGetTotalSectors */
- /************************************************************/
- DWORD MMCGetTotalSectors(BYTE bDevice)
- {
- DWORD dwTotalSectors;
- DRIVE *pDrive;
- dwTotalSectors = 0;
- MMCLock();
- if (bDevice >= MMC_MAX_SUPPORTED_DEVICE)
- {
- dwTotalSectors = 0;
- }
- else
- {
- pDrive = &sDrive[bDevice];
- dwTotalSectors = pDrive->dTotalSectors;
- //dwTotalSectors -= 64;
- }
- MMCFree();
- return(dwTotalSectors);
- } /* MMCGetTotalSectors */
- /************************************************************/
- /* MMCReadSectors */
- /************************************************************/
- int MMCReadSectors(BYTE bDevice, void *pData, DWORD dwStartSector, WORD wSectorCount)
- {
- int nError;
- WORD wReadCount;
- DRIVE *pDrive = 0;
- BYTE *pByte;
- nError = MMC_OK;
- MMCLock();
- if (bDevice >= MMC_MAX_SUPPORTED_DEVICE)
- {
- nError = MMC_DRIVE_NOT_FOUND;
- }
- else
- {
- pDrive = &sDrive[bDevice];
- if ((pDrive->wFlags & MMC_READY) == 0)
- {
- nError = MMC_DRIVE_NOT_FOUND;
- }
- else
- {
- if ((dwStartSector + wSectorCount) > pDrive->dTotalSectors)
- {
- nError = MMC_PARAM_ERROR;
- }
- }
- }
- if (nError == MMC_OK)
- {
- pByte = (BYTE *)pData;
- if (wSectorCount != 1)
- {
- while (wSectorCount > 0)
- {
- if (wSectorCount < 256)
- {
- wReadCount = wSectorCount;
- }
- else
- {
- wReadCount = 256;
- }
- nError = ReadSectors(pDrive, pByte, dwStartSector, wReadCount);
- if (nError != MMC_OK)
- {
- break;
- }
- dwStartSector += wReadCount;
- wSectorCount -= wReadCount;
- pByte += (wReadCount * pDrive->wSectorSize);
- }
- }
- else
- {
- nError = ReadSectors(pDrive, pByte, dwStartSector, 1);
- }
- }
- MMCFree();
- return(nError);
- } /* MMCReadSectors */
- #if (MMC_SUPPORT_WRITE == 1)
- /************************************************************/
- /* MMCWriteSectors */
- /************************************************************/
- int MMCWriteSectors(BYTE bDevice, void *pData,
- DWORD dwStartSector, WORD wSectorCount)
- {
- int nError;
- WORD wWriteCount;
- DRIVE *pDrive = 0;
- BYTE *pByte;
- nError = MMC_OK;
- MMCLock();
- if (bDevice >= MMC_MAX_SUPPORTED_DEVICE)
- {
- nError = MMC_DRIVE_NOT_FOUND;
- }
- else
- {
- pDrive = &sDrive[bDevice];
- if ((dwStartSector + wSectorCount) > pDrive->dTotalSectors)
- {
- nError = MMC_PARAM_ERROR;
- }
- if ((pDrive->wFlags & MMC_READY) == 0)
- {
- nError = MMC_DRIVE_NOT_FOUND;
- }
- if (pDrive->wFlags & MMC_READ_ONLY)
- {
- nError = MMC_NOT_SUPPORTED;
- }
- }
- if (nError == MMC_OK)
- {
- pByte = (BYTE *) pData;
- while (wSectorCount > 0)
- {
- if (wSectorCount < 256)
- {
- wWriteCount = wSectorCount;
- }
- else
- {
- wWriteCount = 256;
- }
- nError = WriteSectors(pDrive, pByte, dwStartSector, wWriteCount);
- if (nError != MMC_OK)
- {
- break;
- }
- dwStartSector += wWriteCount;
- wSectorCount -= wWriteCount;
- pByte += (wWriteCount * MMC_SECTOR_SIZE);
- }
- }
- MMCFree();
- return(nError);
- } /* MMCWriteSectors */
- #endif
|