- /*
- * 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;
- mediaStr->stateParameter = ISTINVALID;
- if (pPacket->cmd == IOM_WRITE && mediaStr->length != SECLEN) {
- pPacket->cmd = IOM_READ;
- mediaStr->atomicStatus = ISTATOMICREAD;
- mediaStr->stateParameter = ISTGETSTATUS;
- }
- intrMask = HWI_disable();
- /* Que this request if already currPacket has something */
- if (mmcChan->pHandle->currPacket != NULL) {
- QUE_enqueue (&mmcChan->pHandle->pendList, pPacket);
- HWI_restore (intrMask);
- }
- else {
- /* since there is nothing pending, process this request */
- mmcChan->pHandle->currPacket = pPacket;
- HWI_restore (intrMask);
- mediaStr->stateParameter = ISTGETSTATUS;
- _MMC_MMCCIE_SET (mmcChan->pHandle->mmcDevNum,
- REGVALMMCIESTATUS);
- MMC_sendCmd (mmcChan->pHandle->cslMMC, MMC_SEND_STATUS,
- mmcChan->pHandle->drvrParams.mmcCardId,
- MMC_STUFF_BITS, 0);
- }
- return (IOM_PENDING);
- case IOM_FLUSH:
- case IOM_ABORT:
- pPacket->addr = (C5509_MMC_ChanObj *)mmcChan;
- intrMask = HWI_disable();
- if (mmcChan->pHandle->currPacket != NULL) {
- currStr = (C5509_MMC_RdWrObj *)
- mmcChan->pHandle->currPacket->addr;
- /*
- * if queue is empty and current packet is not for this
- * channel, then just return
- */
- if (QUE_empty (&mmcChan->pHandle->pendList) &&
- currStr->pChan != mediaStr->pChan) {
- status = IOM_COMPLETED;
- goto FLUSHDONE;
- }
- }
- else {
- /*
- * this means current packet is null,
- * check if the queue is empty, if so return
- */
- if (QUE_empty (&mmcChan->pHandle->pendList)) {
- status = IOM_COMPLETED;
- goto FLUSHDONE;
- }
- }
- status = abortFlush (mmcChan, pPacket->cmd, pPacket);
- FLUSHDONE:
- HWI_restore (intrMask);
- return (status);
- default:
- return (IOM_ENOTIMPL);
- }
- }
- /*
- * ======== mdDeleteChan ========
- *
- * Deletes an instance of a channel object
- */
- static Int mdDeleteChan(Ptr chanp)
- {
- C5509_MMC_ChanObj *mmcChan;
- Uns intrMask;
- mmcChan = (C5509_MMC_ChanObj *)chanp;
- intrMask = HWI_disable();
- /* Set the channel as free. */
- mmcChan->inUse = FALSE;
- mmcChan->pHandle->chOpenCount--;
- if (mmcChan->pHandle->chOpenCount == 0) {
- IRQ_disable ((mmcChan->pHandle->mmcDevNum == 0) ? INT7 : INT13);
- }
- HWI_restore (intrMask);
- return (IOM_COMPLETED);
- }
- /*
- * ======== abortFlush ========
- *
- * This function takes care of performing abort and flush operations
- * on a given channel.
- * This function is called with interrupts disabled.
- */
- static Int abortFlush(C5509_MMC_ChanObj *mmcChan, Uns cmd, IOM_Packet *pPack)
- {
- QUE_Elem *qelem;
- QUE_Elem *tempElem;
- QUE_Elem *waitElem;
- IOM_Packet *pPacket;
- C5509_MMC_RdWrObj *mediaStr;
- Int retval;
- waitElem = NULL;
- /* Unless a WRITE is pending in case of FLUSH this would not change */
- retval = IOM_COMPLETED;
- /* get pointer to first element in the queue */
- qelem = QUE_head (&mmcChan->pHandle->pendList);
- /*
- * Traverse through the request queue and identify
- * the request for this particular channel.
- * For abort command, complete all the requests with
- * an error status and remove them from the queue.
- * For flush command, complete all read requests with
- * error status and remove them from the queue.
- */
- while (qelem != &mmcChan->pHandle->pendList) {
- pPacket = (IOM_Packet *)qelem;
- mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
- if (mediaStr->pChan == mmcChan) {
- if ((cmd == IOM_FLUSH && pPacket->cmd == IOM_READ &&
- mediaStr->atomicStatus != ISTATOMICREAD) ||
- cmd == IOM_ABORT) {
- Int status;
- if (cmd == IOM_FLUSH) {
- status = IOM_FLUSHED;
- }
- else {
- status = IOM_ABORTED;
- }
- tempElem = qelem;
- qelem = QUE_next (qelem);
- QUE_remove (tempElem);
- CALLBACK (mediaStr->pChan, pPacket, status);
- continue;
- }
- /* This element tracks the last pending write in the queue */
- waitElem = qelem;
- }
- qelem = QUE_next(qelem);
- }
- /*
- * Now insert IOM_FLUSH packet in the queue so that it is processed
- * after all write-requests have completed
- */
- if (waitElem == NULL) {
- pPacket = mmcChan->pHandle->currPacket;
- mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
- /*
- * If a write operation is in progress on the current channel,
- * wait for it to complete.
- */
- if ((mediaStr->pChan == mmcChan) &&
- ((pPacket->cmd == IOM_WRITE) ||
- (pPacket->cmd == IOM_READ
- && mediaStr->atomicStatus == ISTATOMICREAD))) {
- waitElem = QUE_head (&mmcChan->pHandle->pendList);
- QUE_insert (waitElem, pPack);
- retval = IOM_PENDING;
- }
- }
- else {
- waitElem = QUE_next (waitElem);
- QUE_insert (waitElem, pPack);
- retval = IOM_PENDING;
- }
- /*
- * if pPack is queued, it would be queued with pPack->status
- * as IOM_PENDING, which is also sematically correct
- */
- pPack->status = retval;
- return (retval);
- }
- /*
- * ======== issueReadWrite ========
- *
- * Function for issuing the Read and Write Command
- * Called from the ISR - in interrupt context.
- */
- static Void issueReadWrite(IOM_Packet *pPacket, C5509_MMC_DevObj *ptrState)
- {
- C5509_MMC_RdWrObj *mediaStr;
- LgUns address;
- LgUns sectorNumber;
- MdUns track;
- mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
- sectorNumber = mediaStr->sectorNumber;
- address = sectorNumber << 9;
- if (pPacket->cmd == IOM_WRITE) {
- if ((mediaStr->length == SECLEN) || mediaStr->offset == 0) {
- track = mediaStr->buf[0];
- }
- else {
- /* in this case, atomicStatus == ISTATOMICWRITE */
- track = mediaStr->pChan->pHandle->buf[0];
- }
- /* check if the byte-order needs to change */
- if (ptrState->drvrParams.byteOrder == MEDIA_BYTESWAP) {
- track = MEDIA_SWAPBYTES (track);
- }
- /* load the data transmission register with the first word */
- _MMC_MMCDXR_SET (mediaStr->pChan->pHandle->mmcDevNum, track);
- }
- /* Set the Number of Blocks needed to be read, in this case it is 1 */
- _MMC_MMCNBLK_SET (mediaStr->pChan->pHandle->mmcDevNum, NBLK);
- /* Set the Block Length */
- _MMC_MMCBLEN_SET (mediaStr->pChan->pHandle->mmcDevNum,
- mediaStr->pChan->pHandle->blockLen);
- /* Set the value of ARGL */
- _MMC_MMCARGL_SET (mediaStr->pChan->pHandle->mmcDevNum,
- (MdUns)(address & 0xFFFF));
- /* Set the value of ARGH */
- _MMC_MMCARGH_SET (mediaStr->pChan->pHandle->mmcDevNum,
- (MdUns)((address >> 16) & 0xFFFF));
- /* Check for COMMAND and send a READ or WRITE command. */
- if (pPacket->cmd == IOM_WRITE) {
- _MMC_MMCCMD_SET (mediaStr->pChan->pHandle->mmcDevNum,
- MMC_WRITE_BLOCK | CMDDATA | CMDDCLR | CMDWRITE);
- }
- else if (pPacket->cmd == IOM_READ) {
- _MMC_MMCCMD_SET (mediaStr->pChan->pHandle->mmcDevNum,
- MMC_READ_SINGLE_BLOCK | CMDDATA | CMDDCLR);
- }
- }
- /*
- * ======== handlerReadWrite ========
- *
- * Read and Write Data from and to the MMC
- * Called from the ISR - in interrupt context.
- */
- static Void handlerReadWrite(IOM_Packet *pPacket,
- C5509_MMC_DevObj *ptrState, Uns error)
- {
- C5509_MMC_ChanObj *afChan;
- C5509_MMC_RdWrObj *mediaStr;
- MdUns k;
- Int newRequest = 0;
- Int track = 0;
- Int flag = 1;
- mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
- /*
- * afChan is used to store the channel pointer as it
- * is not provided in the request for ABORT and FLUSH.
- * So we need to store it so that it can be used to
- * call the callback function, in case of ABORT and FLUSH.
- */
- afChan = mediaStr->pChan;
- if (pPacket->cmd == IOM_READ) {
- k = _MMC_MMCDRR_GET (ptrState->mmcDevNum);
- /* Loading the buffer with the new data. */
- if (mediaStr->count < SECLEN) {
- if (mediaStr->count >= mediaStr->offset &&
- mediaStr->count < (mediaStr->length + mediaStr->offset)) {
- if (mediaStr->atomicStatus != ISTATOMICREAD) {
- if (ptrState->drvrParams.byteOrder == MEDIA_BYTESWAP) {
- mediaStr->buf[mediaStr->count - mediaStr->offset] =
- MEDIA_SWAPBYTES(k);
- }
- else {
- mediaStr->buf[mediaStr->count - mediaStr->offset] = k;
- }
- }
- }
- else if (mediaStr->atomicStatus == ISTATOMICREAD) {
- ptrState->buf[mediaStr->count] = k;
- }
- }
- /* Incrementing the count of words read by one. */
- mediaStr->count++;
- /*
- * If the entire sector has been read, set the
- * stateParameter to ISTDATADONEREAD
- */
- if (mediaStr->count >= SECLEN) {
- mediaStr->stateParameter = ISTDATADONEREAD;
- }
- /* State where the request will call the callback. */
- if (mediaStr->count > SECLEN) {
- if (error) {
- /* Re-set the cmd, if it had been changed earlier */
- pPacket->cmd = (mediaStr->atomicStatus == ISTATOMICREAD)
- ? IOM_WRITE
- : IOM_READ;
- CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO);
- /* No further requests are scheduled - await reset */
- ptrState->currPacket = NULL;
- return;
- }
- if (mediaStr->atomicStatus == ISTATOMICREAD) {
- pPacket->cmd = IOM_WRITE;
- mediaStr->atomicStatus = ISTATOMICWRITE;
- mediaStr->count = 0;
- newRequest = 1;
- }
- else if (mediaStr->atomicStatus != ISTATOMICREAD) {
- CALLBACK (mediaStr->pChan, pPacket, IOM_COMPLETED);
- ptrState->currPacket =
- (IOM_Packet *)QUE_dequeue (&ptrState->pendList);
- if ((QUE_Elem *)ptrState->currPacket != &ptrState->pendList) {
- newRequest = 1;
- }
- else {
- ptrState->currPacket = NULL;
- }
- }
- }
- }
- else if (pPacket->cmd == IOM_WRITE) {
- /*
- * If the entire sector has been written to, set the
- * stateParameter to ISTDATADONEWRITE.
- */
- if (mediaStr->count >= SECLEN) {
- mediaStr->stateParameter = ISTDATADONEWRITE;
- }
- /* State where the request will call the callback. */
- if (mediaStr->count > SECLEN) {
- if (error) {
- CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO);
- /* No further requests are scheduled - await reset */
- ptrState->currPacket = NULL;
- return;
- }
- CALLBACK (mediaStr->pChan, pPacket, IOM_COMPLETED);
- ptrState->currPacket = (IOM_Packet *)QUE_dequeue (&ptrState->pendList);
- if ((QUE_Elem *)ptrState->currPacket != &ptrState->pendList) {
- newRequest = 1;
- }
- else {
- ptrState->currPacket = NULL;
- }
- flag = 0;
- }
- if (flag) {
- if (mediaStr->atomicStatus == ISTATOMICWRITE) {
- if (mediaStr->count >= mediaStr->offset &&
- mediaStr->count < (mediaStr->length +
- mediaStr->offset)) {
- track = mediaStr->buf[mediaStr->count - mediaStr->offset];
- }
- else {
- track = ptrState->buf[mediaStr->count];
- }
- }
- else {
- track = mediaStr->buf[mediaStr->count];
- }
- if (ptrState->drvrParams.byteOrder == MEDIA_BYTESWAP) {
- track = MEDIA_SWAPBYTES (track);
- }
- _MMC_MMCDXR_SET (ptrState->mmcDevNum, track);
- mediaStr->count++;
- }
- }
- /*
- * Checking for new requests in the request queue.
- * In case of ABORT and FLUSH call the callback, else
- * execute the request.
- */
- if (newRequest == 1) {
- if ((ptrState->currPacket->cmd == IOM_ABORT) ||
- (ptrState->currPacket->cmd == IOM_FLUSH)) {
- afChan = (C5509_MMC_ChanObj *)ptrState->currPacket->addr;
- CALLBACK (afChan, ptrState->currPacket, IOM_COMPLETED);
- ptrState->currPacket = (IOM_Packet *)QUE_dequeue (&ptrState->pendList);
- if ((QUE_Elem *)ptrState->currPacket != &ptrState->pendList) {
- newRequest = 1;
- }
- else {
- newRequest = 0;
- ptrState->currPacket = NULL;
- }
- }
- if (newRequest == 1) {
- mediaStr = (C5509_MMC_RdWrObj *)ptrState->currPacket->addr;
- mediaStr->stateParameter = ISTGETSTATUS;
- _MMC_MMCCIE_SET (ptrState->mmcDevNum, REGVALMMCIESTATUS);
- MMC_sendCmd (ptrState->cslMMC,MMC_SEND_STATUS,
- mediaStr->pChan->pHandle->drvrParams.mmcCardId,
- MMC_STUFF_BITS, 0);
- }
- }
- }
- /*
- * ======== isrMMC ========
- *
- * Interrupt handler for MMC
- */
- static Void isrMMC(Ptr ptrAttr)
- {
- C5509_MMC_DevObj *ptrState = (C5509_MMC_DevObj *)ptrAttr;
- IOM_Packet *pPacket = ptrState->currPacket;
- C5509_MMC_RdWrObj *mediaStr;
- volatile Uns regST0;
- Uns busy;
- Uns error;
- error = 0;
- if (pPacket == NULL) {
- return;
- }
- mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
- regST0 = _MMC_MMCST0_GET (ptrState->mmcDevNum);
- switch (mediaStr->stateParameter) {
- case ISTGETSTATUS:
- /*
- * Check busy incase of RSPDNE.
- * If busy resend MMC_SEND_STATUS else we proceed.
- */
- if (regST0 & ST0RSPDNE) {
- busy = ((_MMC_MMCRSP6_GET (ptrState->mmcDevNum) >> 8) & 1);
- if (!busy) {
- MMC_sendCmd (ptrState->cslMMC, MMC_SEND_STATUS,
- mediaStr->pChan->pHandle->drvrParams.mmcCardId,
- MMC_STUFF_BITS, 0);
- }
- else {
- if (pPacket->cmd == IOM_READ) {
- _MMC_MMCCIE_SET (ptrState->mmcDevNum,
- REGVALMMCIEREAD);
- mediaStr->stateParameter = ISTSENDREAD;
- issueReadWrite (pPacket, ptrState);
- }
- else if (pPacket->cmd == IOM_WRITE) {
- _MMC_MMCCIE_SET (ptrState->mmcDevNum,
- REGVALMMCIEWRITE);
- regST0 = _MMC_MMCST0_GET (ptrState->mmcDevNum);
- mediaStr->stateParameter = ISTSENDWRITE;
- issueReadWrite (pPacket, ptrState);
- }
- }
- }
- else if (regST0 & ST0TOUTRS) {
- CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO);
- ptrState->currPacket = NULL;
- }
- break;
- case ISTSENDREAD:
- if (regST0 & ST0DRRDY) {
- _MMC_MMCST0_SET (ptrState->mmcDevNum, 0x0000);
- handlerReadWrite (pPacket, ptrState, error);
- }
- else if (regST0 & (ST0CRCRD | ST0CRCRS | ST0TOUTRD | ST0TOUTRS)) {
- CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO);
- ptrState->currPacket = NULL;
- }
- break;
- case ISTSENDWRITE:
- if (regST0 & ST0DXRDY) {
- handlerReadWrite (pPacket, ptrState, error);
- }
- else if (regST0 & (ST0CRCWR | ST0TOUTRS)) {
- CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO);
- ptrState->currPacket = NULL;
- }
- break;
- case ISTDATADONEREAD:
- /* Check if DATA done bit is set. */
- if (!(regST0 & ST0DATDNE) && (regST0 & ST0CRCRD)) {
- error = 1;
- }
- handlerReadWrite (pPacket, ptrState, error);
- break;
- case ISTDATADONEWRITE:
- /* Check if DATA done bit is set. */
- if (!(regST0 & ST0DATDNE) && (regST0 & ST0DRRDY)) {
- error = 1;
- }
- handlerReadWrite (pPacket, ptrState, error);
- break;
- default:
- break;
- }
- return;
- }
- /*
- * ======== resetMMC ========
- *
- * Resets the cards and selects it. This is a helper function called
- * by initMMC() and reinitializeMMC().
- */
- static Int resetMMC(C5509_MMC_DevObj *ptrState)
- {
- /* Sets the operational voltage range. */
- if (MMC_sendOpCond (ptrState->cslMMC, OPVOLTAGE)) {
- return (IOM_EBADIO);
- }
- /* Send broadcast command to all cards to identify themselves. */
- if (!MMC_sendAllCID (ptrState->cslMMC, &ptrState->cslMMC->cards->cid)) {
- return (IOM_EBADIO);
- }
- /* Set the relative address. */
- if (!MMC_setRca (ptrState->cslMMC, ptrState->cslMMC->cards,
- ptrState->drvrParams.mmcCardId)) {
- return (IOM_EBADIO);
- }
- /* Select the card. */
- if (!MMC_selectCard (ptrState->cslMMC, ptrState->cslMMC->cards)) {
- return (IOM_EBADIO);
- }
- return (IOM_COMPLETED);
- }
- /*
- * ======== initMMC ========
- *
- * Initialization of the device takes place here, this is called during
- * bind dev. Initializes and selects a given card.
- */
- static Int initMMC(C5509_MMC_DevObj *ptrState, C5509_MMC_DevParams *mmcParams)
- {
- Int retval;
- Uns intrMask;
- volatile LgUns delay = 30000;
- intrMask = HWI_disable ();
- /* Reserves the MMC device, specified by mmcDevNumber. */
- ptrState->cslMMC = MMC_open (ptrState->mmcDevNum);
- if (ptrState->cslMMC == NULL) {
- HWI_restore (intrMask);
- return (IOM_EBADIO);
- }
- ptrState->cslMMC->cards = &ptrState->cslCards;
- /* All except these two parameters are supplied by the application. */
- mmcParams->devParams.dat3EdgeDetection = DAT3EDGEDETECTION;
- mmcParams->devParams.enableClkPin = ENABLECLKPIN;
- /* Initialize the controller in native mode. */
- MMC_setupNative (ptrState->cslMMC, &mmcParams->devParams);
- /* Send a broadcast GO_IDLE command. */
- MMC_sendGoIdle (ptrState->cslMMC);
- /* Sufficient delay is needed for the MMC to reset. */
- while (delay--) {
- }
- if ((retval = resetMMC (ptrState)) != IOM_COMPLETED) {
- MMC_close (ptrState->cslMMC);
- ptrState->cslMMC = (MMC_Handle)NULL;
- }
- /* Look at logic carefully before adding a statement here. */
- HWI_restore (intrMask);
- return (retval);
- }
- /*
- * ======== reinitializeMMC ========
- *
- * Re-initializes the MMC and selects the card.
- * This function should be called whenever the MMC in UnPlugged
- * and plugged back.
- */
- static inline Int reinitializeMMC(C5509_MMC_DevObj *ptrState)
- {
- Int retval;
- Uns intrMask;
- intrMask = HWI_disable ();
- retval = resetMMC (ptrState);
- HWI_restore (intrMask);
- return (retval);
- }
- /*
- * ======== C5509_MMC_init ========
- *
- * Initialization function.
- */
- Void C5509_MMC_init()
- {
- }