c5509_mmc.c
上传用户:dahaojd
上传日期:2008-01-29
资源大小:14357k
文件大小:31k
源码类别:

DSP编程

开发平台:

C/C++

  1. /*
  2.  *  Copyright 2003 by Texas Instruments Incorporated.
  3.  *  All rights reserved. Property of Texas Instruments Incorporated.
  4.  *  Restricted rights to use, duplicate or disclose this code are
  5.  *  granted through contract.
  6.  *  
  7.  */
  8. /* "@(#) DDK 1.11.00.00 11-04-03 (ddk-b13)" */
  9. /*
  10.  * 
  11.  *  ======== c5509_mmc.c ========    
  12.  *
  13.  *
  14.  */
  15. #include <std.h>
  16. #include <hwi.h>
  17. #include <que.h>
  18. #include <iom.h>
  19. #include <c5509_mmc.h>
  20. /*  Native Mode Defines  */
  21. #define ENABLECLKPIN       1
  22. #define DAT3EDGEDETECTION  0
  23. /*  Number of Data Blocks */
  24. #define NBLK               1
  25. /*  Command Register Defines  */
  26. #define CMDDCLR            0x8000
  27. #define CMDDATA            0x2000
  28. #define CMDWRITE           0x0800
  29. /*  MMCST0 (Status Register 0)
  30.  *  Register fields prefixed with register name: ST0
  31.  */
  32. #define ST0WPED            0x1000
  33. #define ST0DATED           0x0800
  34. #define ST0DRRDY           0x0400
  35. #define ST0DXRDY           0x0200
  36. #define ST0SPIERR          0x0100
  37. #define ST0CRCRS           0x0080
  38. #define ST0CRCRD           0x0040
  39. #define ST0CRCWR           0x0020
  40. #define ST0TOUTRS          0x0010
  41. #define ST0TOUTRD          0x0008
  42. #define ST0RSPDNE          0x0004
  43. #define ST0BSYDNE          0x0002
  44. #define ST0DATDNE          0x0001
  45. /*  MMC IE Register Values
  46.  *  These defines are used to capture the interrupts that
  47.  *  are enabled in the corresponding operations being
  48.  *  performed on the MMC
  49.  */
  50. #define REGVALMMCIEREAD    MMC_MMCCIE_RMK(1,1,1,1,1,1,1,1,0,1,1)
  51. #define REGVALMMCIEWRITE   MMC_MMCCIE_RMK(1,0,1,0,1,1,0,1,1,0,0)
  52. #define REGVALMMCIESTATUS  MMC_MMCCIE_RMK(1,1,1,1,1,0,0,0,0,1,0)
  53. /*
  54.  *  MMC State Defines
  55.  *  These will be used to indicate the current state of a
  56.  *  request in the overall state machine.
  57.  *  Namespace definition for C5509_MMC_RdWrObj::stateParameter.
  58.  *  Internal states prefixed with IST.
  59.  */
  60. #define ISTBASEVALUE       0x1000  /* Base value for this namespace */
  61. #define ISTINVALID         (ISTBASEVALUE + 0)
  62.                                    /*
  63.                                     * Applicable to stateParameter
  64.                                     * and atomicStatus
  65.                                     */
  66. #define ISTSENDREAD        (ISTBASEVALUE + 1)
  67. #define ISTSENDWRITE       (ISTBASEVALUE + 2)
  68. #define ISTGETSTATUS       (ISTBASEVALUE + 3)
  69. #define ISTDATADONEREAD    (ISTBASEVALUE + 4)
  70. #define ISTDATADONEWRITE   (ISTBASEVALUE + 5)
  71. /*
  72.  *  Namespace definition for C5509_MMC_RdWrObj::atomicStatus.
  73.  */
  74. #define ISTATOMICWRITE     (ISTBASEVALUE + 6)
  75. #define ISTATOMICREAD      (ISTBASEVALUE + 7)
  76. /*  Read and Write sector length (in WORDs)  */
  77. #define SECLEN            C5509_MMC_SECLEN
  78. /*  CPU interrupt number for MMC  */
  79. #define INT7                7   /* DEV 0 */
  80. #define INT13              13   /* DEV 1 */
  81. /*  Operating Voltage 3.2-3.4V  */
  82. #define OPVOLTAGE          0x00300000
  83. #define CALLBACK(chan,packet,result)                                    
  84.             do {                                                        
  85.                 (packet)->status = (result);                            
  86.                 ((chan)->callback)((Ptr)(chan)->callbackArg, (packet)); 
  87.             } while(0)
  88. /* Driver Functions */
  89. static Int mdBindDev(Ptr* devp, Int devid, Ptr devParams);
  90. static Int mdControlChan(Ptr chanp, Uns cmd, Ptr arg);
  91. static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode, 
  92.                 Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
  93. static Int mdDeleteChan(Ptr chanp);
  94. static Int mdSubmitChan(Ptr chanp, IOM_Packet *pPacket);
  95. /*  Helper Functions */
  96. static Int abortFlush(C5509_MMC_ChanObj *pChan, Uns cmd, IOM_Packet *pPacket);
  97. static Void issueReadWrite(IOM_Packet *pPacket, C5509_MMC_DevObj *ptrState);
  98. static Void handlerReadWrite(IOM_Packet *pPacket, 
  99.                 C5509_MMC_DevObj *ptrState, Uns error);
  100. /* MMC ISR */
  101. static Void isrMMC(Ptr ptrAttr);
  102. /*  MMC Reset Functions  */
  103. static Int initMMC(C5509_MMC_DevObj *ptrState, C5509_MMC_DevParams *mmcParams);
  104. static Int resetMMC(C5509_MMC_DevObj *ptrState);
  105. static Int reinitializeMMC(C5509_MMC_DevObj *ptrState);
  106. /*
  107.  * Public Mini Driver interface table.
  108.  */
  109. IOM_Fxns C5509_MMC_FXNS =
  110. {
  111.     &mdBindDev,
  112.     IOM_UNBINDDEVNOTIMPL,
  113.     &mdControlChan,
  114.     &mdCreateChan,
  115.     &mdDeleteChan,
  116.     &mdSubmitChan,
  117. };
  118. /*
  119.  *  ======== mdBindDev ========
  120.  *
  121.  *  Creates an instance of MMC device. Will be called to bind the device.
  122.  */
  123. static Int mdBindDev(Ptr* devp, Int devid, Ptr devParams)
  124. {
  125.     C5509_MMC_DevObj    *mmcHandle;
  126.     C5509_MMC_DevParams *mmcParams;
  127.     HWI_Attrs           attrs;
  128.     Int                 i;
  129.     
  130.     mmcParams = (C5509_MMC_DevParams *)devParams;
  131.     mmcHandle = (C5509_MMC_DevObj *)(*devp);
  132.     
  133.     if (*devp == NULL) {
  134.         return (IOM_EBADIO);
  135.     }
  136.     if (devParams == NULL) {
  137.         return (IOM_EBADARGS);  /* requires device params */
  138.     }
  139.     /* Check the version number */
  140.     if(mmcParams->versionId != C5509_MMC_VERSION_1){
  141.         return(IOM_EBADARGS);
  142.     }
  143.     /*  Fill up mmcHandle with mmcParams  */
  144.     mmcHandle->mmcDevNum = devid; /* MMC controller 0 or 1 */
  145.     /*  Copy structure containing all driver config parameters.  */
  146.     mmcHandle->drvrParams = mmcParams->drvrParams;
  147.     mmcHandle->blockLen = mmcParams->devParams.blockLen;
  148.     mmcHandle->currPacket = NULL;
  149.     mmcHandle->cslMMC = NULL;
  150.     mmcHandle->chOpenCount = 0;
  151.     
  152.     /*  Set all available channels as free  */
  153.     for (i = 0; i < mmcHandle->drvrParams.noChan; i++) {
  154.         mmcHandle->drvrParams.pChan[i].inUse = FALSE;
  155.     }
  156.     
  157.     /*  Reset the MMC before using it  */
  158.     if (initMMC (mmcHandle, mmcParams) != IOM_COMPLETED) {
  159.         return (IOM_EBADIO);
  160.     }
  161.     
  162.     /*  Create the pending request queue */
  163.     QUE_new (&mmcHandle->pendList);
  164.     
  165.     /*  Enable the MMC Interrupt  */
  166.     attrs.ier0mask = mmcParams->ier0Mask;
  167.     attrs.ier1mask = mmcParams->ier1Mask;
  168.     attrs.arg = (Arg)(*devp);
  169.     HWI_dispatchPlug ((devid == 0) ? INT7 : INT13, (Fxn)isrMMC, &attrs);
  170.     /* Successfully initialized, so return */
  171.     return (IOM_COMPLETED);
  172. }
  173. /*
  174.  *  ======== mdControlChan ========
  175.  * 
  176.  *  The Mini driver control function. 
  177.  *  Currently supports 2 commands - querying media type and 
  178.  *  reinitializing the MMC (after unplug/plug)
  179.  */
  180. static Int mdControlChan(Ptr chanp, Uns cmd, Ptr arg)
  181. {
  182.     C5509_MMC_ChanObj   *mmcChan;
  183.     
  184.     mmcChan = (C5509_MMC_ChanObj *)chanp;
  185.     switch (cmd) {
  186.         case MEDIA_CTRL_GETMEDIATYPE:
  187.             *(Int *)arg = C5509_MMC_MEDIATYPE;
  188.             return (IOM_COMPLETED);
  189.         case MEDIA_CTRL_REINITIALIZE:
  190.             if (reinitializeMMC (mmcChan->pHandle) != IOM_COMPLETED) {
  191.                 *(Int *)arg = MEDIA_NOTPRESENT;
  192.             }
  193.             else {
  194.                 *(Int *)arg = MEDIA_PRESENT;
  195.             }
  196.             return (IOM_COMPLETED);
  197.         default:
  198.             return (IOM_ENOTIMPL);
  199.     }
  200. }
  201. /*
  202.  *  ======== mdCreateChan ========
  203.  *
  204.  *  Creates an instance of channel object which will be used 
  205.  *  in future for sending commands on a particular channel 
  206.  */
  207.  
  208. static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode, 
  209.                         Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
  210. {
  211.     C5509_MMC_DevObj    *mmcHandle;
  212.     C5509_MMC_ChanObj   *mmcChan;
  213.     Int                 i;
  214.     Int                 found;
  215.     Uns                 intrMask;
  216.      
  217.     mmcHandle = (C5509_MMC_DevObj *)devp;
  218.     found = -1;
  219.     if (mode != IOM_INOUT) {
  220.         return (IOM_EBADMODE);
  221.     }
  222.     
  223.     /*
  224.      *  inUse is not really checked in the ISR - so this serialization is
  225.      *  primarily to avoid multiple application-level threads of control
  226.      *  to gain access to the same resource
  227.      */
  228.     intrMask = HWI_disable();
  229.     /*  Checking for free channels  */
  230.     for (i = 0; i < mmcHandle->drvrParams.noChan; i++) {
  231.         if (mmcHandle->drvrParams.pChan[i].inUse == FALSE) {
  232.             found = i;
  233.             mmcHandle->drvrParams.pChan[i].inUse = TRUE;
  234.             if (mmcHandle->chOpenCount == 0) {
  235.                 IRQ_enable ((mmcHandle->mmcDevNum == 0) ? INT7 : INT13);
  236.             }
  237.             mmcHandle->chOpenCount++;
  238.             break;
  239.         }
  240.     }
  241.     
  242.     HWI_restore (intrMask);
  243.     /*  If no Channel is free, return error  */
  244.     if (found == -1) {
  245.         return (IOM_EALLOC);
  246.     }
  247.     
  248.     /*  Allocate the channel and mark it as INUSE.  */
  249.     mmcChan = &(mmcHandle->drvrParams.pChan[found]);
  250.     mmcChan->mode = mode;
  251.     mmcChan->pHandle = mmcHandle;
  252.     mmcChan->callback = cbFxn; 
  253.     mmcChan->callbackArg = cbArg;
  254.     
  255.     *chanp = &(mmcHandle->drvrParams.pChan[found]);
  256.     
  257.     return (IOM_COMPLETED);
  258. }
  259. /*
  260.  *  ======== mdSubmitChan ========
  261.  *  
  262.  *  This function provides read,write,abort and flush 
  263.  *  functionality to the application. 
  264.  */
  265.  
  266. static Int mdSubmitChan(Ptr chanp, IOM_Packet *pPacket)
  267. {
  268.     C5509_MMC_ChanObj    *mmcChan;
  269.     C5509_MMC_RdWrObj    *mediaStr;
  270.     C5509_MMC_RdWrObj    *currStr;
  271.     Int                  status;
  272.     Uns                  intrMask;
  273.     
  274.     mmcChan = (C5509_MMC_ChanObj *)chanp;
  275.     mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
  276.     mediaStr->pChan = (C5509_MMC_ChanObj *)chanp;
  277.     
  278.     switch (pPacket->cmd) {
  279.         case IOM_READ:
  280.         case IOM_WRITE:
  281.         
  282.             /*  initialize mediastr */
  283.             mediaStr->count = 0;
  284.             mediaStr->atomicStatus = ISTINVALID;
  285.             mediaStr->stateParameter = ISTINVALID;
  286.             if (pPacket->cmd == IOM_WRITE && mediaStr->length != SECLEN) {
  287.                 pPacket->cmd = IOM_READ;
  288.                 mediaStr->atomicStatus = ISTATOMICREAD;
  289.                 mediaStr->stateParameter = ISTGETSTATUS;
  290.             }
  291.             intrMask = HWI_disable();
  292.             /*  Que this request if already currPacket has something */
  293.             if (mmcChan->pHandle->currPacket != NULL) {
  294.                 QUE_enqueue (&mmcChan->pHandle->pendList, pPacket);
  295.                 HWI_restore (intrMask);
  296.             }
  297.             else { 
  298.                 /* since there is nothing pending, process this request */
  299.                 mmcChan->pHandle->currPacket = pPacket;
  300.                 HWI_restore (intrMask);
  301.                 mediaStr->stateParameter = ISTGETSTATUS;
  302.                 _MMC_MMCCIE_SET (mmcChan->pHandle->mmcDevNum,
  303.                     REGVALMMCIESTATUS);
  304.                 MMC_sendCmd (mmcChan->pHandle->cslMMC, MMC_SEND_STATUS,
  305.                     mmcChan->pHandle->drvrParams.mmcCardId,
  306.                     MMC_STUFF_BITS, 0);
  307.             }
  308.             return (IOM_PENDING);
  309.         
  310.         case IOM_FLUSH:
  311.         case IOM_ABORT:
  312.             pPacket->addr = (C5509_MMC_ChanObj *)mmcChan;
  313.             intrMask = HWI_disable();
  314.             if (mmcChan->pHandle->currPacket != NULL) {
  315.                 currStr = (C5509_MMC_RdWrObj *)
  316.                                 mmcChan->pHandle->currPacket->addr;
  317.                 /* 
  318.                  *  if queue is empty and current packet is not for this 
  319.                  *  channel, then just return 
  320.                  */
  321.                 if (QUE_empty (&mmcChan->pHandle->pendList) &&
  322.                         currStr->pChan != mediaStr->pChan) {
  323.                     status = IOM_COMPLETED;
  324.                     goto FLUSHDONE;
  325.                 }
  326.             }
  327.             else {
  328.                 /*  
  329.                  *  this means current packet is null, 
  330.                  *  check if the queue is empty, if so return
  331.                  */
  332.                 if (QUE_empty (&mmcChan->pHandle->pendList)) {
  333.                     status = IOM_COMPLETED;
  334.                     goto FLUSHDONE;
  335.                 }
  336.             }
  337.         
  338.             status = abortFlush (mmcChan, pPacket->cmd, pPacket);
  339. FLUSHDONE:
  340.             HWI_restore (intrMask);
  341.             return (status);
  342.             
  343.         default:
  344.             return (IOM_ENOTIMPL);
  345.     }
  346. }
  347. /*
  348.  *  ======== mdDeleteChan ========
  349.  *
  350.  *  Deletes an instance of a channel object
  351.  */
  352.  
  353. static Int mdDeleteChan(Ptr chanp)
  354. {
  355.     C5509_MMC_ChanObj   *mmcChan;
  356.     Uns                 intrMask;
  357.     
  358.     mmcChan = (C5509_MMC_ChanObj *)chanp;
  359.     
  360.     intrMask = HWI_disable();
  361.     /*  Set the channel as free.  */
  362.     mmcChan->inUse = FALSE;
  363.     mmcChan->pHandle->chOpenCount--;
  364.     if (mmcChan->pHandle->chOpenCount == 0) {
  365.         IRQ_disable ((mmcChan->pHandle->mmcDevNum == 0) ? INT7 : INT13);
  366.     }
  367.     
  368.     HWI_restore (intrMask);
  369.     return (IOM_COMPLETED);
  370. }
  371.  
  372. /*
  373.  *  ======== abortFlush ========
  374.  * 
  375.  *  This function takes care of performing abort and flush operations
  376.  *  on a given channel.
  377.  *  This function is called with interrupts disabled.
  378.  */
  379. static Int abortFlush(C5509_MMC_ChanObj *mmcChan, Uns cmd, IOM_Packet *pPack)
  380. {
  381.     QUE_Elem           *qelem;
  382.     QUE_Elem           *tempElem;
  383.     QUE_Elem           *waitElem;
  384.     IOM_Packet         *pPacket;
  385.     C5509_MMC_RdWrObj  *mediaStr;
  386.     Int                retval;
  387.     waitElem = NULL;
  388.     
  389.     /* Unless a WRITE is pending in case of FLUSH this would not change */
  390.     retval = IOM_COMPLETED;
  391.     /* get pointer to first element in the queue */
  392.     qelem = QUE_head (&mmcChan->pHandle->pendList);
  393.     
  394.     /* 
  395.      *  Traverse through the request queue and identify
  396.      *  the request for this particular channel. 
  397.      *  For abort command, complete all the requests with
  398.      *  an error status and remove them from the queue.
  399.      *  For flush command, complete all read requests with
  400.      *  error status and remove them from the queue.
  401.      */
  402.     while (qelem != &mmcChan->pHandle->pendList) {
  403.         pPacket = (IOM_Packet *)qelem;
  404.         mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
  405.         if (mediaStr->pChan == mmcChan) {
  406.             if ((cmd == IOM_FLUSH && pPacket->cmd == IOM_READ &&
  407.                     mediaStr->atomicStatus != ISTATOMICREAD) ||
  408.                     cmd == IOM_ABORT) {
  409.                 Int    status;
  410.                 if (cmd == IOM_FLUSH) {
  411.                     status = IOM_FLUSHED;
  412.                 }
  413.                 else {
  414.                     status = IOM_ABORTED;
  415.                 }
  416.                 tempElem = qelem;
  417.                 qelem = QUE_next (qelem);
  418.                 QUE_remove (tempElem);
  419.                 CALLBACK (mediaStr->pChan, pPacket, status);
  420.                 continue;
  421.             }
  422.             /*  This element tracks the last pending write in the queue  */
  423.             waitElem = qelem;
  424.         }
  425.         qelem = QUE_next(qelem);
  426.     }
  427.     /*
  428.      *  Now insert IOM_FLUSH packet in the queue so that it is processed
  429.      *  after all write-requests have completed
  430.      */
  431.     if (waitElem == NULL) {
  432.         pPacket = mmcChan->pHandle->currPacket;
  433.         mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
  434.         /*
  435.          *  If a write operation is in progress on the current channel,
  436.          *  wait for it to complete.
  437.          */
  438.         if ((mediaStr->pChan == mmcChan) &&
  439.                 ((pPacket->cmd == IOM_WRITE) ||
  440.                  (pPacket->cmd == IOM_READ
  441.                     && mediaStr->atomicStatus == ISTATOMICREAD))) {
  442.             waitElem = QUE_head (&mmcChan->pHandle->pendList);
  443.             QUE_insert (waitElem, pPack);
  444.             retval = IOM_PENDING;
  445.         }
  446.     }
  447.     else {
  448.         waitElem = QUE_next (waitElem);
  449.         QUE_insert (waitElem, pPack);
  450.         retval = IOM_PENDING;
  451.     }
  452.     
  453.     /*
  454.      * if pPack is queued, it would be queued with pPack->status
  455.      * as IOM_PENDING, which is also sematically correct
  456.      */
  457.     pPack->status = retval;
  458.     
  459.     return (retval);
  460. }
  461. /*
  462.  *  ======== issueReadWrite ========
  463.  *  
  464.  *  Function for issuing the Read and Write Command
  465.  *  Called from the ISR - in interrupt context.
  466.  */
  467. static Void issueReadWrite(IOM_Packet *pPacket, C5509_MMC_DevObj *ptrState)
  468. {
  469.     C5509_MMC_RdWrObj  *mediaStr;
  470.     LgUns              address;
  471.     LgUns              sectorNumber;
  472.     MdUns              track;
  473.     
  474.     mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
  475.     sectorNumber = mediaStr->sectorNumber;
  476.     address = sectorNumber << 9;
  477.     if (pPacket->cmd == IOM_WRITE) {
  478.         if ((mediaStr->length == SECLEN) || mediaStr->offset == 0) {
  479.             track = mediaStr->buf[0];
  480.         }
  481.         else {
  482.             /* in this case, atomicStatus == ISTATOMICWRITE */
  483.             track = mediaStr->pChan->pHandle->buf[0];
  484.         }
  485.         /* check if the byte-order needs to change */
  486.         if (ptrState->drvrParams.byteOrder == MEDIA_BYTESWAP) {
  487.             track = MEDIA_SWAPBYTES (track);
  488.         }
  489.         /* load the data transmission register with the first word */
  490.         _MMC_MMCDXR_SET (mediaStr->pChan->pHandle->mmcDevNum, track);
  491.     }
  492.     
  493.     /*  Set the Number of Blocks needed to be read, in this case it is 1 */
  494.     _MMC_MMCNBLK_SET (mediaStr->pChan->pHandle->mmcDevNum, NBLK);
  495.     
  496.     /*  Set the Block Length  */
  497.     _MMC_MMCBLEN_SET (mediaStr->pChan->pHandle->mmcDevNum,
  498.                       mediaStr->pChan->pHandle->blockLen);
  499.     
  500.     /*  Set the value of ARGL  */
  501.     _MMC_MMCARGL_SET (mediaStr->pChan->pHandle->mmcDevNum,
  502.                       (MdUns)(address & 0xFFFF));
  503.     
  504.     /*  Set the value of ARGH  */
  505.     _MMC_MMCARGH_SET (mediaStr->pChan->pHandle->mmcDevNum,
  506.                       (MdUns)((address >> 16) & 0xFFFF));
  507.     
  508.     /*  Check for COMMAND and send a READ or WRITE command.  */
  509.     if (pPacket->cmd == IOM_WRITE) {
  510.         _MMC_MMCCMD_SET (mediaStr->pChan->pHandle->mmcDevNum,
  511.             MMC_WRITE_BLOCK | CMDDATA | CMDDCLR | CMDWRITE);
  512.     }
  513.     else if (pPacket->cmd == IOM_READ) {
  514.         _MMC_MMCCMD_SET (mediaStr->pChan->pHandle->mmcDevNum,
  515.             MMC_READ_SINGLE_BLOCK | CMDDATA | CMDDCLR);
  516.     }
  517. }
  518. /*
  519.  *  ======== handlerReadWrite ========
  520.  *  
  521.  *  Read and Write Data from and to the MMC 
  522.  *  Called from the ISR - in interrupt context.
  523.  */
  524. static Void handlerReadWrite(IOM_Packet *pPacket,
  525.                              C5509_MMC_DevObj *ptrState, Uns error)
  526. {
  527.     C5509_MMC_ChanObj *afChan;
  528.     C5509_MMC_RdWrObj *mediaStr;
  529.     MdUns             k; 
  530.     Int               newRequest = 0;
  531.     Int               track = 0;
  532.     Int               flag = 1;
  533.     
  534.     mediaStr  = (C5509_MMC_RdWrObj *)pPacket->addr;
  535.     
  536.     /* 
  537.      *  afChan is used to store the channel pointer as it 
  538.      *  is not provided in the request for ABORT and FLUSH.
  539.      *  So we need to store it so that it can be used to 
  540.      *  call the callback function, in case of ABORT and FLUSH.
  541.      */
  542.     afChan = mediaStr->pChan;
  543.     if (pPacket->cmd == IOM_READ) {
  544.         k = _MMC_MMCDRR_GET (ptrState->mmcDevNum);
  545.         
  546.         /*  Loading the buffer with the new data.  */
  547.         if (mediaStr->count < SECLEN) {
  548.             if (mediaStr->count >= mediaStr->offset && 
  549.                 mediaStr->count < (mediaStr->length + mediaStr->offset)) {
  550.                 if (mediaStr->atomicStatus != ISTATOMICREAD) {
  551.                     if (ptrState->drvrParams.byteOrder == MEDIA_BYTESWAP) {
  552.                         mediaStr->buf[mediaStr->count - mediaStr->offset] =
  553.                                                             MEDIA_SWAPBYTES(k);
  554.                     }
  555.                     else {
  556.                         mediaStr->buf[mediaStr->count - mediaStr->offset] = k;
  557.                     }
  558.                 }
  559.             }
  560.             else if (mediaStr->atomicStatus == ISTATOMICREAD) {
  561.                 ptrState->buf[mediaStr->count] = k;
  562.             }
  563.         }
  564.         
  565.         /*  Incrementing the count of words read by one.  */
  566.         mediaStr->count++; 
  567.         
  568.         /*  
  569.          *  If the entire sector has been read, set the 
  570.          *  stateParameter to ISTDATADONEREAD
  571.          */
  572.         if (mediaStr->count >= SECLEN) {
  573.             mediaStr->stateParameter = ISTDATADONEREAD;
  574.         }
  575.         
  576.         /*  State where the request will call the callback.  */
  577.         if (mediaStr->count > SECLEN) {
  578.             if (error) {
  579.                 /*  Re-set the cmd, if it had been changed earlier */
  580.                 pPacket->cmd = (mediaStr->atomicStatus == ISTATOMICREAD)
  581.                                ? IOM_WRITE
  582.                                : IOM_READ;
  583.                 CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO); 
  584.                 /*  No further requests are scheduled - await reset */
  585.                 ptrState->currPacket = NULL;
  586.                 return;
  587.             }
  588.             if (mediaStr->atomicStatus == ISTATOMICREAD) {
  589.                 pPacket->cmd = IOM_WRITE;
  590.                 mediaStr->atomicStatus = ISTATOMICWRITE;
  591.                 mediaStr->count = 0;
  592.                 newRequest = 1;
  593.             }
  594.             else if (mediaStr->atomicStatus != ISTATOMICREAD) {
  595.                 CALLBACK (mediaStr->pChan, pPacket, IOM_COMPLETED); 
  596.                 ptrState->currPacket =
  597.                         (IOM_Packet *)QUE_dequeue (&ptrState->pendList);
  598.                 if ((QUE_Elem *)ptrState->currPacket != &ptrState->pendList) {
  599.                     newRequest = 1;
  600.                 }
  601.                 else {
  602.                     ptrState->currPacket = NULL;
  603.                 }
  604.             }
  605.         }
  606.     }
  607.     else if (pPacket->cmd == IOM_WRITE) {
  608.         /*  
  609.          *  If the entire sector has been written to, set the 
  610.          *  stateParameter to ISTDATADONEWRITE.
  611.          */
  612.         if (mediaStr->count >= SECLEN) {
  613.             mediaStr->stateParameter = ISTDATADONEWRITE;
  614.         }
  615.         /*  State where the request will call the callback.  */
  616.         if (mediaStr->count > SECLEN) {
  617.             if (error) {
  618.                 CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO); 
  619.                 /*  No further requests are scheduled - await reset */
  620.                 ptrState->currPacket = NULL;
  621.                 return;
  622.             }
  623.             CALLBACK (mediaStr->pChan, pPacket, IOM_COMPLETED); 
  624.             ptrState->currPacket = (IOM_Packet *)QUE_dequeue (&ptrState->pendList);
  625.             if ((QUE_Elem *)ptrState->currPacket != &ptrState->pendList) {
  626.                 newRequest = 1;
  627.             }
  628.             else {
  629.                 ptrState->currPacket = NULL;
  630.             }
  631.             
  632.             flag = 0;
  633.         }
  634.         if (flag) {
  635.             if (mediaStr->atomicStatus == ISTATOMICWRITE) {
  636.                 if (mediaStr->count >= mediaStr->offset &&
  637.                         mediaStr->count < (mediaStr->length +
  638.                                            mediaStr->offset)) {
  639.                     track = mediaStr->buf[mediaStr->count - mediaStr->offset];
  640.                 }
  641.                 else {
  642.                     track = ptrState->buf[mediaStr->count];
  643.                 }
  644.             }
  645.             else {
  646.                 track = mediaStr->buf[mediaStr->count];
  647.             }
  648.             if (ptrState->drvrParams.byteOrder == MEDIA_BYTESWAP) {
  649.                 track = MEDIA_SWAPBYTES (track);
  650.             }
  651.             _MMC_MMCDXR_SET (ptrState->mmcDevNum, track);
  652.             mediaStr->count++; 
  653.         }
  654.     }
  655.     
  656.     /*  
  657.      *  Checking for new requests in the request queue. 
  658.      *  In case of ABORT and FLUSH call the callback, else 
  659.      *  execute the request.
  660.      */
  661.     if (newRequest == 1) {
  662.         if ((ptrState->currPacket->cmd == IOM_ABORT) ||
  663.                 (ptrState->currPacket->cmd == IOM_FLUSH)) {
  664.             afChan = (C5509_MMC_ChanObj *)ptrState->currPacket->addr;
  665.             CALLBACK (afChan, ptrState->currPacket, IOM_COMPLETED); 
  666.             ptrState->currPacket = (IOM_Packet *)QUE_dequeue (&ptrState->pendList);
  667.             if ((QUE_Elem *)ptrState->currPacket != &ptrState->pendList) {
  668.                 newRequest = 1;
  669.             }
  670.             else {
  671.                 newRequest = 0;
  672.                 ptrState->currPacket = NULL;
  673.             }
  674.         }
  675.         
  676.         if (newRequest == 1) {
  677.             mediaStr = (C5509_MMC_RdWrObj *)ptrState->currPacket->addr;
  678.             mediaStr->stateParameter = ISTGETSTATUS;
  679.             _MMC_MMCCIE_SET (ptrState->mmcDevNum, REGVALMMCIESTATUS);
  680.             MMC_sendCmd (ptrState->cslMMC,MMC_SEND_STATUS,
  681.                 mediaStr->pChan->pHandle->drvrParams.mmcCardId,
  682.                 MMC_STUFF_BITS, 0);
  683.         }
  684.     }
  685. }
  686. /*
  687.  *  ======== isrMMC ========
  688.  *  
  689.  *  Interrupt handler for MMC
  690.  */
  691. static Void isrMMC(Ptr ptrAttr)
  692. {
  693.     C5509_MMC_DevObj  *ptrState = (C5509_MMC_DevObj *)ptrAttr;
  694.     IOM_Packet        *pPacket = ptrState->currPacket;
  695.     C5509_MMC_RdWrObj *mediaStr;
  696.     volatile Uns      regST0;
  697.     Uns               busy;
  698.     Uns               error;
  699.     
  700.     error = 0;
  701.     if (pPacket == NULL) {
  702.         return;
  703.     }
  704.     
  705.     mediaStr = (C5509_MMC_RdWrObj *)pPacket->addr;
  706.     regST0 = _MMC_MMCST0_GET (ptrState->mmcDevNum);
  707.     
  708.     switch (mediaStr->stateParameter) {
  709.        
  710.         case ISTGETSTATUS:
  711.                /*
  712.                 *  Check busy incase of RSPDNE.
  713.                 *  If busy resend MMC_SEND_STATUS else we proceed.
  714.                 */
  715.             if (regST0 & ST0RSPDNE) { 
  716.                 busy = ((_MMC_MMCRSP6_GET (ptrState->mmcDevNum) >> 8) & 1);
  717.                 if (!busy) {
  718.                     MMC_sendCmd (ptrState->cslMMC, MMC_SEND_STATUS, 
  719.                         mediaStr->pChan->pHandle->drvrParams.mmcCardId,
  720.                         MMC_STUFF_BITS, 0);
  721.                 }
  722.                 else {
  723.                     if (pPacket->cmd == IOM_READ) {
  724.                         _MMC_MMCCIE_SET (ptrState->mmcDevNum,
  725.                             REGVALMMCIEREAD);
  726.                         mediaStr->stateParameter = ISTSENDREAD;
  727.                         issueReadWrite (pPacket, ptrState);
  728.                     }
  729.                     else if (pPacket->cmd == IOM_WRITE) {
  730.                         _MMC_MMCCIE_SET (ptrState->mmcDevNum,
  731.                             REGVALMMCIEWRITE);
  732.                         regST0 = _MMC_MMCST0_GET (ptrState->mmcDevNum);
  733.                         mediaStr->stateParameter = ISTSENDWRITE;
  734.                         issueReadWrite (pPacket, ptrState);
  735.                     }
  736.                 }
  737.             }
  738.             else if (regST0 & ST0TOUTRS) {
  739.                 CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO); 
  740.                 ptrState->currPacket = NULL;
  741.             }
  742.             break;
  743.         
  744.         case ISTSENDREAD:
  745.             if (regST0 & ST0DRRDY) {
  746.                 _MMC_MMCST0_SET (ptrState->mmcDevNum, 0x0000);
  747.                 handlerReadWrite (pPacket, ptrState, error);
  748.             }
  749.             else if (regST0 & (ST0CRCRD | ST0CRCRS | ST0TOUTRD | ST0TOUTRS)) {
  750.                 CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO); 
  751.                 ptrState->currPacket = NULL;
  752.             }
  753.             break;
  754.         
  755.         case ISTSENDWRITE:
  756.             if (regST0 & ST0DXRDY) {
  757.                 handlerReadWrite (pPacket, ptrState, error);
  758.             }
  759.             else if (regST0 & (ST0CRCWR | ST0TOUTRS)) {
  760.                 CALLBACK (mediaStr->pChan, pPacket, IOM_EBADIO); 
  761.                 ptrState->currPacket = NULL;
  762.             }    
  763.             break;
  764.         
  765.         case ISTDATADONEREAD:
  766.             /*  Check if DATA done bit is set.  */
  767.             if (!(regST0 & ST0DATDNE) && (regST0 & ST0CRCRD)) {
  768.                 error = 1;
  769.             }
  770.             handlerReadWrite (pPacket, ptrState, error); 
  771.             break;
  772.             
  773.         case ISTDATADONEWRITE:
  774.             /*  Check if DATA done bit is set.  */
  775.             if (!(regST0 & ST0DATDNE) && (regST0 & ST0DRRDY)) {
  776.                 error = 1;
  777.             }
  778.             handlerReadWrite (pPacket, ptrState, error);
  779.             break;
  780.         default:
  781.             break;
  782.     } 
  783.     return;
  784. }
  785. /*
  786.  *  ======== resetMMC ========
  787.  *  
  788.  *  Resets the cards and selects it. This is a helper function called
  789.  *  by initMMC() and reinitializeMMC().
  790.  */
  791. static Int resetMMC(C5509_MMC_DevObj *ptrState)
  792. {
  793.     /*  Sets the operational voltage range.  */
  794.     if (MMC_sendOpCond (ptrState->cslMMC, OPVOLTAGE)) {
  795.         return (IOM_EBADIO);
  796.     }
  797.     
  798.     /*  Send broadcast command to all cards to identify themselves.  */
  799.     if (!MMC_sendAllCID (ptrState->cslMMC, &ptrState->cslMMC->cards->cid)) {
  800.         return (IOM_EBADIO);
  801.     }
  802.     
  803.     /*  Set the relative address.  */
  804.     if (!MMC_setRca (ptrState->cslMMC, ptrState->cslMMC->cards, 
  805.             ptrState->drvrParams.mmcCardId)) {
  806.         return (IOM_EBADIO);
  807.     }
  808.     
  809.     /*  Select the card.  */
  810.     if (!MMC_selectCard (ptrState->cslMMC, ptrState->cslMMC->cards)) {
  811.         return (IOM_EBADIO);
  812.     }
  813.     return (IOM_COMPLETED);
  814. }
  815. /*
  816.  *  ======== initMMC ========
  817.  *  
  818.  *  Initialization of the device takes place here, this is called during
  819.  *  bind dev. Initializes and selects a given card.
  820.  */
  821. static Int initMMC(C5509_MMC_DevObj *ptrState, C5509_MMC_DevParams *mmcParams)
  822. {
  823.     Int               retval;
  824.     Uns               intrMask;
  825.     volatile LgUns    delay = 30000;
  826.     
  827.     intrMask = HWI_disable ();
  828.     /*  Reserves the MMC device, specified by mmcDevNumber.  */
  829.     ptrState->cslMMC = MMC_open (ptrState->mmcDevNum);
  830.     if (ptrState->cslMMC == NULL) {
  831.         HWI_restore (intrMask);
  832.         return (IOM_EBADIO);
  833.     }
  834.     ptrState->cslMMC->cards = &ptrState->cslCards;
  835.     
  836.     /*  All except these two parameters are supplied by the application.  */
  837.     mmcParams->devParams.dat3EdgeDetection = DAT3EDGEDETECTION; 
  838.     mmcParams->devParams.enableClkPin = ENABLECLKPIN; 
  839.     
  840.     /*  Initialize the controller in native mode.  */
  841.     MMC_setupNative (ptrState->cslMMC, &mmcParams->devParams);
  842.     
  843.     /*  Send a broadcast GO_IDLE command.  */
  844.     MMC_sendGoIdle (ptrState->cslMMC);
  845.     
  846.     /*  Sufficient delay is needed for the MMC to reset.  */
  847.     while (delay--) {
  848.     }
  849.     if ((retval = resetMMC (ptrState)) != IOM_COMPLETED) {
  850.         MMC_close (ptrState->cslMMC);
  851.         ptrState->cslMMC = (MMC_Handle)NULL;
  852.     }
  853.     /*  Look at logic carefully before adding a statement here.  */
  854.     HWI_restore (intrMask);
  855.     return (retval);
  856. }
  857. /*
  858.  *  ======== reinitializeMMC ========
  859.  *  
  860.  *  Re-initializes the MMC and selects the card.
  861.  *  This function should be called whenever the MMC in UnPlugged
  862.  *  and plugged back.
  863.  */
  864.  
  865. static inline Int reinitializeMMC(C5509_MMC_DevObj *ptrState)
  866. {
  867.     Int    retval;
  868.     Uns    intrMask;
  869.     intrMask = HWI_disable ();
  870.     retval = resetMMC (ptrState);
  871.     HWI_restore (intrMask);
  872.     return (retval);
  873. }
  874. /*
  875.  *  ======== C5509_MMC_init ========
  876.  *  
  877.  *  Initialization function.
  878.  */
  879. Void C5509_MMC_init()
  880. {
  881. }