Esempio n. 1
0
///////////////////////////////////////////////////////////////////////////////
//  SDMemWrite       - Write data to card from pSG scatter gather buffers
//  Input:  pMemCard - SD memory card structure
//          pSG      - Scatter Gather buffer structure from FATFS
//  Output:
//  Return: Status   - windows status code
//  Notes:  Writes to the card are split into groups of size TransferBlockSize
//          This is controlled by a registry entry for the driver.
///////////////////////////////////////////////////////////////////////////////
DWORD SDMemWrite( PSD_MEMCARD_INFO pMemCard, PSG_REQ pSG )
{
    DWORD  NumBlocks;
    DWORD  StartBlock;
    PUCHAR pBlockBuffer = NULL, pCardDataPtr = NULL;
    PUCHAR pSGBuffer = NULL;
    DWORD  status = ERROR_SUCCESS;
    DWORD  SGBufNum, SGBufLen, SGBufRemaining;
    DWORD  PartialStartBlock;
    DWORD  CardDataRemaining;

    DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDMemory: +SDMemWrite\r\n")));

    PREFAST_DEBUGCHK(pSG);

    // pSG is a sterile SG_REQ copy of the callers's SG_REQ; we can map the
    // embedded pointers back into it

    // validate the embedded sb_bufs
    for (ULONG ul = 0; ul < pSG->sr_num_sg; ul += 1) {
        if (
            (NULL == pSG->sr_sglist[ul].sb_buf) ||
            (0 == pSG->sr_sglist[ul].sb_buf)
        ) {
            status = ERROR_INVALID_PARAMETER;
            goto statusReturn;
        }
        pSG->sr_sglist[ul].sb_buf = (PUCHAR)MapCallerPtr(
            (LPVOID)pSG->sr_sglist[ul].sb_buf,
            pSG->sr_sglist[ul].sb_len);
        if (pSG->sr_sglist[ul].sb_buf == NULL) {
            status = ERROR_INVALID_PARAMETER;
            goto statusReturn;
        }
    }

    // validate the I/O request
    if ((pSG->sr_start > pSG->sr_start + pSG->sr_num_sec) 
        ||(pSG->sr_start + pSG->sr_num_sec) > pMemCard->DiskInfo.di_total_sectors) {
        status = ERROR_INVALID_PARAMETER;
        goto statusReturn;
    }

    // check card write protect status
    if (pMemCard->WriteProtected) {
        DEBUGMSG(SDMEM_ZONE_DISK_IO, (TEXT("SDMemWrite: Card is write protected\r\n")));
        status = ERROR_WRITE_PROTECT;
        goto statusReturn;
    }

    // get number of sectors
    StartBlock = pSG->sr_start;
    NumBlocks = pSG->sr_num_sec;

    DEBUGMSG(SDMEM_ZONE_DISK_IO, (TEXT("SDMemWrite: Writing blocks %d-%d\r\n"),
        StartBlock,
        StartBlock+NumBlocks-1));

    // calculate total buffer space of scatter gather buffers
    SGBufLen = 0;
    for (SGBufNum = 0; SGBufNum < pSG->sr_num_sg; SGBufNum++) {
        SGBufLen += pSG->sr_sglist[SGBufNum].sb_len;
    }

    // check total SG buffer space is enough for reqeusted transfer size
    if(SGBufLen < NumBlocks * SD_BLOCK_SIZE) {
        DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDMemWrite: SG Buffer space %d bytes less than block write size %d bytes\r\n"),
            SGBufLen,
            NumBlocks * SD_BLOCK_SIZE));
        status = ERROR_GEN_FAILURE;
        goto statusReturn;
    }

    // get block transfer buffer
    pBlockBuffer = (PUCHAR)SDAllocateFromMemList(pMemCard->hBufferList);

    // initialize some variables used in data copy
    SGBufNum = 0;
    SGBufRemaining = pSG->sr_sglist[SGBufNum].sb_len;
    pSGBuffer = pSG->sr_sglist[SGBufNum].sb_buf;

    // split the writes into groups of TransferBlockSize in size to avoid
    // hogging the SD Bus with large writes
    for(PartialStartBlock = StartBlock; PartialStartBlock < StartBlock+NumBlocks; PartialStartBlock += pMemCard->BlockTransferSize) {

        // some variables just used for copying
        DWORD PartialTransferSize;
        DWORD CopySize;

        pCardDataPtr = pBlockBuffer;

        PartialTransferSize = MIN(
            pMemCard->BlockTransferSize,
            StartBlock+NumBlocks-PartialStartBlock);

        // copy from pSG buffers to pBlockArray
        CardDataRemaining = PartialTransferSize*SD_BLOCK_SIZE;

        while (CardDataRemaining) {

            // get minimum of remaining size in SG buf and data left in pBlockBuffer
            CopySize = MIN(SGBufRemaining, CardDataRemaining);

            // copy that much data to block buffer
            if (0 == CeSafeCopyMemory(pCardDataPtr, pSGBuffer, CopySize)) {
                status = ERROR_INVALID_PARAMETER;
                goto statusReturn;
            }

            // update pointers and counts
            pSGBuffer += CopySize;
            pCardDataPtr += CopySize;
            CardDataRemaining -= CopySize;
            SGBufRemaining -= CopySize;

            // get the next SG Buffer if needed
            if (!SGBufRemaining && CardDataRemaining) {
                SGBufNum++;
                SGBufRemaining = pSG->sr_sglist[SGBufNum].sb_len;
                pSGBuffer = pSG->sr_sglist[SGBufNum].sb_buf;
            }
        }

        // write the data to the SD Card
        status = SDMemWriteMultiple(
            pMemCard,
            PartialStartBlock,
            PartialTransferSize,
            pBlockBuffer);

        if (status != ERROR_SUCCESS) {
            break;
        }
    }
statusReturn:

    // free the allocated block buffer
    if (pBlockBuffer) {
        SDFreeToMemList(pMemCard->hBufferList, pBlockBuffer);
    }

    // FATFS wants the status returned in the SG buffers also
    pSG->sr_status = status;

    DEBUGMSG(SDCARD_ZONE_FUNC, (TEXT("SDMemory: -SDMemWrite\r\n")));

    return status;
}
Esempio n. 2
0
//------------------------------------------------------------------------------
//
//  Function:  DMA_IOControl
//
//  This function sends a command to a device.
//
BOOL
DMA_IOControl(
    DWORD context, 
    DWORD code, 
    UCHAR *pInBuffer, 
    DWORD inSize, 
    UCHAR *pOutBuffer,
    DWORD outSize, 
    DWORD *pOutSize
    )
{
    BOOL rc = FALSE;
    Instance_t *pInstance = (Instance_t*)context;
    Device_t *pDevice = pInstance->pDevice;

    UNREFERENCED_PARAMETER(pOutSize);

    DEBUGMSG(ZONE_FUNCTION, (
        L"+DMA_IOControl(0x%08x, 0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x)\r\n",
        context, code, pInBuffer, inSize, pOutBuffer, outSize, pOutSize
        ));

    // Check if we get correct context
    if ((pInstance == NULL) || (pInstance->cookie != DMA_INSTANCE_COOKIE))
        {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
            L"Incorrect context paramer\r\n"
            ));
        goto cleanUp;
        }

    switch (code)
        { 
        case IOCTL_DMA_INTERRUPTDONE:
            {
            DmaControllerBase *pController;
            IOCTL_DMA_INTERRUPTDONE_IN *pContext;
            DEBUGMSG(ZONE_INFO, (L"DMA: IOCTL_DMA_INTERRUPTDONE\r\n"));

            if (pInBuffer == NULL || 
                inSize != sizeof(IOCTL_DMA_INTERRUPTDONE_IN))
                {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
                    L"IOCTL_DMA_INTERRUPTDONE invalid parameters\r\n"
                    ));
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }

            pContext = (IOCTL_DMA_INTERRUPTDONE_IN*)pInBuffer;
            switch (pContext->type)
                {
                case DMA_TYPE_SYSTEM:
                    pController = pDevice->pSystemController;
                    break;

                default:
                    SetLastError(ERROR_INVALID_PARAMETER);
                    goto cleanUp;               
                }
            EnterCriticalSection(&pDevice->cs);
            rc = pController->InterruptDone(pContext);
            LeaveCriticalSection(&pDevice->cs);
            }
            break;
            
        case IOCTL_DMA_RESERVE_CHANNEL:
            {
            DmaControllerBase *pController;
            IOCTL_DMA_RESERVE_IN *pDmaType;
            IOCTL_DMA_RESERVE_OUT *pContext;
            DEBUGMSG(ZONE_INFO, (L"DMA: IOCTL_DMA_RESERVE_CHANNEL\r\n"));
            
            // check for correct parameters
            if (pOutBuffer == NULL || outSize != sizeof(IOCTL_DMA_RESERVE_OUT) ||
                pInBuffer == NULL || inSize != sizeof(IOCTL_DMA_RESERVE_IN))
                {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
                    L"IOCTL_DMA_RESERVE_CHANNEL invalid parameters\r\n"
                    ));
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }

            // if successful allocate memory            
            pDmaType = (IOCTL_DMA_RESERVE_IN*)pInBuffer;
            pContext = (IOCTL_DMA_RESERVE_OUT*)pOutBuffer;
            switch (*pDmaType)
                {
                case DMA_TYPE_SYSTEM:
                    pController = pDevice->pSystemController;
                    break;

                default:
                    SetLastError(ERROR_INVALID_PARAMETER);
                    goto cleanUp;
                }

            // reset context information
            memset(pContext, 0, sizeof(IOCTL_DMA_RESERVE_OUT));

            // copy context information
            pContext->type = *pDmaType;
            EnterCriticalSection(&pDevice->cs);
            if (pController->ReserveChannel(pContext) == FALSE)
                {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
                    L"IOCTL_DMA_RESERVE_CHANNEL: failed\r\n"
                    ));
                LeaveCriticalSection(&pDevice->cs);
                break;
                }
            LeaveCriticalSection(&pDevice->cs);
            rc = TRUE;
            }            
            break;

        case IOCTL_DMA_RELEASE_CHANNEL:
            {
            DmaControllerBase *pController;
            IOCTL_DMA_RELEASE_IN *pContext;
            DEBUGMSG(ZONE_INFO, (L"DMA: IOCTL_DMA_RELEASE_CHANNEL\r\n"));

            if (pInBuffer == NULL || inSize != sizeof(IOCTL_DMA_RELEASE_IN))
                {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
                    L"IOCTL_DMA_RELEASE_CHANNEL invalid parameters\r\n"
                    ));
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }

            pContext = (IOCTL_DMA_RELEASE_IN*)pInBuffer;
            switch (pContext->type)
                {
                case DMA_TYPE_SYSTEM:
                    pController = pDevice->pSystemController;
                    break;

                default:
                    SetLastError(ERROR_INVALID_PARAMETER);
                    goto cleanUp;                
                }

            EnterCriticalSection(&pDevice->cs);
            pController->ReleaseChannel(pContext);
            LeaveCriticalSection(&pDevice->cs);
            rc = TRUE;
            }
            break;

        case IOCTL_DMA_REGISTER_EVENTHANDLE:
            {
            DmaControllerBase *pController;
            IOCTL_DMA_REGISTER_EVENTHANDLE_IN *pRegisterEvent;
            DEBUGMSG(ZONE_INFO, (L"DMA: IOCTL_DMA_REGISTER_EVENTHANDLE\r\n"));

            if (pInBuffer == NULL || inSize != sizeof(IOCTL_DMA_REGISTER_EVENTHANDLE_IN))
                {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
                    L"IOCTL_DMA_REGISTER_EVENTHANDLE invalid parameters\r\n"
                    ));
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }

            pRegisterEvent = (IOCTL_DMA_REGISTER_EVENTHANDLE_IN*)pInBuffer;

#if (_WINCEOSVER<600)
            pRegisterEvent->pContext = (DmaChannelContext_t*)MapCallerPtr(
                    pRegisterEvent->pContext, sizeof(DmaChannelContext_t)
                    );
#endif
            
            switch (pRegisterEvent->pContext->type)
                {
                case DMA_TYPE_SYSTEM:
                    pController = pDevice->pSystemController;
                    break;

                default:
                    SetLastError(ERROR_INVALID_PARAMETER);
                    goto cleanUp;                
                }

            EnterCriticalSection(&pDevice->cs);
            rc = pController->SetSecondaryInterruptHandler(
                    pRegisterEvent->pContext,
                    pRegisterEvent->hEvent,
                    pRegisterEvent->processId
                    );
            LeaveCriticalSection(&pDevice->cs);
            }
            break; 

        case IOCTL_DMA_DISABLESTANDBY:
            {
            DmaControllerBase *pController;
            IOCTL_DMA_DISABLESTANDBY_IN *pIoctlInput;
            DEBUGMSG(ZONE_INFO, (L"DMA: IOCTL_DMA_DISABLESTANDBY\r\n"));

            if (pInBuffer == NULL || inSize != sizeof(IOCTL_DMA_DISABLESTANDBY_IN))
                {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
                    L"IOCTL_DMA_DISABLESTANDBY invalid parameters\r\n"
                    ));
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }

            // Cast pInBuffer
            pIoctlInput = (IOCTL_DMA_DISABLESTANDBY_IN*)pInBuffer;
#if (_WINCEOSVER<600)
            pIoctlInput->pContext = (DmaChannelContext_t*)MapCallerPtr(
                    pIoctlInput->pContext, sizeof(DmaChannelContext_t)
                    );
#endif

            if (!pIoctlInput->bDelicatedChannel)
            {
            switch (pIoctlInput->pContext->type)
                {
                case DMA_TYPE_SYSTEM:
                    pController = pDevice->pSystemController;
                    break;

                default:
                    SetLastError(ERROR_INVALID_PARAMETER);
                    goto cleanUp;                
                    }
            }
            else
            {
                pController = pDevice->pSystemController;
                }

            EnterCriticalSection(&pDevice->cs);
            rc = pController->DisableStandby(
                    pIoctlInput->pContext,
                    pIoctlInput->bNoStandby
                    );
            LeaveCriticalSection(&pDevice->cs);
            }
            break;
            
        case IOCTL_DMA_REQUEST_DEDICATED_INTERRUPT:
            {
            SystemDmaController *pController;
            IOCTL_DMA_REQUEST_DEDICATED_INTERRUPT_OUT *pIoctlOutput;
            DEBUGMSG(ZONE_INFO, (L"DMA: IOCTL_DMA_REQUEST_DEDICATED_INTERRUPT\r\n"));

            if (pOutBuffer == NULL || outSize != sizeof(IOCTL_DMA_REQUEST_DEDICATED_INTERRUPT_OUT) ||
                pInBuffer == NULL || inSize != sizeof(IOCTL_DMA_REQUEST_DEDICATED_INTERRUPT_IN))
                {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
                    L"IOCTL_DMA_REQUEST_DEDICATED_INTERRUPT invalid parameters\r\n"
                    ));
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }

            // Cast pOutBuffer
            pIoctlOutput = (IOCTL_DMA_REQUEST_DEDICATED_INTERRUPT_OUT*)pOutBuffer;

            //assume this is a system interrupt
            pController = pDevice->pSystemController;
            
            EnterCriticalSection(&pDevice->cs);
            rc = pController->DI_ReserveInterrupt(
                                                *((DWORD*)pInBuffer), 
                                                &pIoctlOutput->IrqNum,
                                                &pIoctlOutput->DmaControllerPhysAddr,
                                                &pIoctlOutput->ffDmaChannels
                                              );
            LeaveCriticalSection(&pDevice->cs);
            }
            break;

        case IOCTL_DMA_RELEASE_DEDICATED_INTERRUPT:
            {
            SystemDmaController *pController;
            DEBUGMSG(ZONE_INFO, (L"DMA: IOCTL_DMA_RELEASE_DEDICATED_INTERRUPT\r\n"));

            if (pInBuffer == NULL || inSize != sizeof(IOCTL_DMA_RELEASE_DEDICATED_INTERRUPT_IN))
                {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: DMA_IOControl: "
                    L"IOCTL_DMA_RELEASE_DEDICATED_INTERRUPT invalid parameters\r\n"
                    ));
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }

            //assume this is a system interrupt
            pController = pDevice->pSystemController;
            
            EnterCriticalSection(&pDevice->cs);
            rc = pController->DI_ReleaseInterrupt(*((DWORD*)pInBuffer));
            LeaveCriticalSection(&pDevice->cs);
            }
            break;
            
        }

cleanUp:
    DEBUGMSG(ZONE_FUNCTION, (L"-DMA_IOControl(rc = %d)\r\n", rc));
    return rc;
}