📄 c5509_mmc.c
字号:
/*
* Copyright 2003 by Texas Instruments Incorporated.
* All rights reserved. Property of Texas Instruments Incorporated.
* Restricted rights to use, duplicate or disclose this code are
* granted through contract.
*
*/
/* "@(#) DDK 1.11.00.00 11-04-03 (ddk-b13)" */
/*
*
* ======== c5509_mmc.c ========
*
*
*/
#include <std.h>
#include <hwi.h>
#include <que.h>
#include <iom.h>
#include <c5509_mmc.h>
/* Native Mode Defines */
#define ENABLECLKPIN 1
#define DAT3EDGEDETECTION 0
/* Number of Data Blocks */
#define NBLK 1
/* Command Register Defines */
#define CMDDCLR 0x8000
#define CMDDATA 0x2000
#define CMDWRITE 0x0800
/* MMCST0 (Status Register 0)
* Register fields prefixed with register name: ST0
*/
#define ST0WPED 0x1000
#define ST0DATED 0x0800
#define ST0DRRDY 0x0400
#define ST0DXRDY 0x0200
#define ST0SPIERR 0x0100
#define ST0CRCRS 0x0080
#define ST0CRCRD 0x0040
#define ST0CRCWR 0x0020
#define ST0TOUTRS 0x0010
#define ST0TOUTRD 0x0008
#define ST0RSPDNE 0x0004
#define ST0BSYDNE 0x0002
#define ST0DATDNE 0x0001
/* MMC IE Register Values
* These defines are used to capture the interrupts that
* are enabled in the corresponding operations being
* performed on the MMC
*/
#define REGVALMMCIEREAD MMC_MMCCIE_RMK(1,1,1,1,1,1,1,1,0,1,1)
#define REGVALMMCIEWRITE MMC_MMCCIE_RMK(1,0,1,0,1,1,0,1,1,0,0)
#define REGVALMMCIESTATUS MMC_MMCCIE_RMK(1,1,1,1,1,0,0,0,0,1,0)
/*
* MMC State Defines
* These will be used to indicate the current state of a
* request in the overall state machine.
* Namespace definition for C5509_MMC_RdWrObj::stateParameter.
* Internal states prefixed with IST.
*/
#define ISTBASEVALUE 0x1000 /* Base value for this namespace */
#define ISTINVALID (ISTBASEVALUE + 0)
/*
* Applicable to stateParameter
* and atomicStatus
*/
#define ISTSENDREAD (ISTBASEVALUE + 1)
#define ISTSENDWRITE (ISTBASEVALUE + 2)
#define ISTGETSTATUS (ISTBASEVALUE + 3)
#define ISTDATADONEREAD (ISTBASEVALUE + 4)
#define ISTDATADONEWRITE (ISTBASEVALUE + 5)
/*
* Namespace definition for C5509_MMC_RdWrObj::atomicStatus.
*/
#define ISTATOMICWRITE (ISTBASEVALUE + 6)
#define ISTATOMICREAD (ISTBASEVALUE + 7)
/* Read and Write sector length (in WORDs) */
#define SECLEN C5509_MMC_SECLEN
/* CPU interrupt number for MMC */
#define INT7 7 /* DEV 0 */
#define INT13 13 /* DEV 1 */
/* Operating Voltage 3.2-3.4V */
#define OPVOLTAGE 0x00300000
#define CALLBACK(chan,packet,result) \
do { \
(packet)->status = (result); \
((chan)->callback)((Ptr)(chan)->callbackArg, (packet)); \
} while(0)
/* Driver Functions */
static Int mdBindDev(Ptr* devp, Int devid, Ptr devParams);
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr arg);
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
static Int mdDeleteChan(Ptr chanp);
static Int mdSubmitChan(Ptr chanp, IOM_Packet *pPacket);
/* Helper Functions */
static Int abortFlush(C5509_MMC_ChanObj *pChan, Uns cmd, IOM_Packet *pPacket);
static Void issueReadWrite(IOM_Packet *pPacket, C5509_MMC_DevObj *ptrState);
static Void handlerReadWrite(IOM_Packet *pPacket,
C5509_MMC_DevObj *ptrState, Uns error);
/* MMC ISR */
static Void isrMMC(Ptr ptrAttr);
/* MMC Reset Functions */
static Int initMMC(C5509_MMC_DevObj *ptrState, C5509_MMC_DevParams *mmcParams);
static Int resetMMC(C5509_MMC_DevObj *ptrState);
static Int reinitializeMMC(C5509_MMC_DevObj *ptrState);
/*
* Public Mini Driver interface table.
*/
IOM_Fxns C5509_MMC_FXNS =
{
&mdBindDev,
IOM_UNBINDDEVNOTIMPL,
&mdControlChan,
&mdCreateChan,
&mdDeleteChan,
&mdSubmitChan,
};
/*
* ======== mdBindDev ========
*
* Creates an instance of MMC device. Will be called to bind the device.
*/
static Int mdBindDev(Ptr* devp, Int devid, Ptr devParams)
{
C5509_MMC_DevObj *mmcHandle;
C5509_MMC_DevParams *mmcParams;
HWI_Attrs attrs;
Int i;
mmcParams = (C5509_MMC_DevParams *)devParams;
mmcHandle = (C5509_MMC_DevObj *)(*devp);
if (*devp == NULL) {
return (IOM_EBADIO);
}
if (devParams == NULL) {
return (IOM_EBADARGS); /* requires device params */
}
/* Check the version number */
if(mmcParams->versionId != C5509_MMC_VERSION_1){
return(IOM_EBADARGS);
}
/* Fill up mmcHandle with mmcParams */
mmcHandle->mmcDevNum = devid; /* MMC controller 0 or 1 */
/* Copy structure containing all driver config parameters. */
mmcHandle->drvrParams = mmcParams->drvrParams;
mmcHandle->blockLen = mmcParams->devParams.blockLen;
mmcHandle->currPacket = NULL;
mmcHandle->cslMMC = NULL;
mmcHandle->chOpenCount = 0;
/* Set all available channels as free */
for (i = 0; i < mmcHandle->drvrParams.noChan; i++) {
mmcHandle->drvrParams.pChan[i].inUse = FALSE;
}
/* Reset the MMC before using it */
if (initMMC (mmcHandle, mmcParams) != IOM_COMPLETED) {
return (IOM_EBADIO);
}
/* Create the pending request queue */
QUE_new (&mmcHandle->pendList);
/* Enable the MMC Interrupt */
attrs.ier0mask = mmcParams->ier0Mask;
attrs.ier1mask = mmcParams->ier1Mask;
attrs.arg = (Arg)(*devp);
HWI_dispatchPlug ((devid == 0) ? INT7 : INT13, (Fxn)isrMMC, &attrs);
/* Successfully initialized, so return */
return (IOM_COMPLETED);
}
/*
* ======== mdControlChan ========
*
* The Mini driver control function.
* Currently supports 2 commands - querying media type and
* reinitializing the MMC (after unplug/plug)
*/
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr arg)
{
C5509_MMC_ChanObj *mmcChan;
mmcChan = (C5509_MMC_ChanObj *)chanp;
switch (cmd) {
case MEDIA_CTRL_GETMEDIATYPE:
*(Int *)arg = C5509_MMC_MEDIATYPE;
return (IOM_COMPLETED);
case MEDIA_CTRL_REINITIALIZE:
if (reinitializeMMC (mmcChan->pHandle) != IOM_COMPLETED) {
*(Int *)arg = MEDIA_NOTPRESENT;
}
else {
*(Int *)arg = MEDIA_PRESENT;
}
return (IOM_COMPLETED);
default:
return (IOM_ENOTIMPL);
}
}
/*
* ======== mdCreateChan ========
*
* Creates an instance of channel object which will be used
* in future for sending commands on a particular channel
*/
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
{
C5509_MMC_DevObj *mmcHandle;
C5509_MMC_ChanObj *mmcChan;
Int i;
Int found;
Uns intrMask;
mmcHandle = (C5509_MMC_DevObj *)devp;
found = -1;
if (mode != IOM_INOUT) {
return (IOM_EBADMODE);
}
/*
* inUse is not really checked in the ISR - so this serialization is
* primarily to avoid multiple application-level threads of control
* to gain access to the same resource
*/
intrMask = HWI_disable();
/* Checking for free channels */
for (i = 0; i < mmcHandle->drvrParams.noChan; i++) {
if (mmcHandle->drvrParams.pChan[i].inUse == FALSE) {
found = i;
mmcHandle->drvrParams.pChan[i].inUse = TRUE;
if (mmcHandle->chOpenCount == 0) {
IRQ_enable ((mmcHandle->mmcDevNum == 0) ? INT7 : INT13);
}
mmcHandle->chOpenCount++;
break;
}
}
HWI_restore (intrMask);
/* If no Channel is free, return error */
if (found == -1) {
return (IOM_EALLOC);
}
/* Allocate the channel and mark it as INUSE. */
mmcChan = &(mmcHandle->drvrParams.pChan[found]);
mmcChan->mode = mode;
mmcChan->pHandle = mmcHandle;
mmcChan->callback = cbFxn;
mmcChan->callbackArg = cbArg;
*chanp = &(mmcHandle->drvrParams.pChan[found]);
return (IOM_COMPLETED);
}
/*
* ======== mdSubmitChan ========
*
* This function provides read,write,abort and flush
* functionality to the application.
*/
static Int mdSubmitChan(Ptr chanp, IOM_Packet *pPacket)
{
C5509_MMC_ChanObj *mmcChan;
C5509_MMC_RdWrObj *mediaStr;
C5509_MMC_RdWrObj *currStr;
Int status;
Uns intrMask;
mmcChan = (C5509_MMC_ChanObj *)chanp;
mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
mediaStr->pChan = (C5509_MMC_ChanObj *)chanp;
switch (pPacket->cmd) {
case IOM_READ:
case IOM_WRITE:
/* initialize mediastr */
mediaStr->count = 0;
mediaStr->atomicStatus = ISTINVALID;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -