📄 c5509_mmc.c
字号:
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -