Exemplo n.º 1
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuShBufferIoctl -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtuShBufferIoctl(
    DtuDeviceData*  pDvcData, 
    DtFileObject*  pFile, 
    DtIoctlObject*  pIoctl)
{
    DtStatus  Status = DT_STATUS_OK;
    char*  pIoctlStr;           // Mnemonic string for Command
    UInt  InReqSize = 0;        // Required length of input buffer
    UInt  OutReqSize = 0;       // Required length of output buffer
    Int  Index;
    DtuShBuffer*  pShBuffer = NULL;
    DtuIoctlShBufCmdInput*  pShBufCmdInput = 
                                           (DtuIoctlShBufCmdInput*)pIoctl->m_pInputBuffer;
    
    InReqSize = OFFSETOF(DtuIoctlShBufCmdInput, m_Data);
    
    
    // Check if we can read m_Cmd
    if (pIoctl->m_InputBufferSize < OFFSETOF(DtuIoctlShBufCmdInput, m_Data))
        return DT_STATUS_INVALID_PARAMETER;

    switch (pShBufCmdInput->m_Cmd)
    {
    case DTU_SH_BUF_CMD_INIT:
        pIoctlStr = "DTU_SH_BUF_CMD_INIT";
        InReqSize += sizeof(DtuIoctlShBufCmdInitInput);
        // We expect an output buffer size, but will be checked later
        OutReqSize = 0;
        break;

    case DTU_SH_BUF_CMD_CLOSE:
        pIoctlStr = "DTU_HP_BUF_CMD_CLOSE";
        // We expect no output buffer
        OutReqSize = 0;
        break;

    default:
        pIoctlStr = "??UNKNOWN VPDCMD CODE??";
        Status = DT_STATUS_NOT_SUPPORTED;
    }

    if (DT_SUCCESS(Status))
    {
        // Check buffer sizes
        if (pIoctl->m_InputBufferSize < InReqSize)
        {
            DtDbgOut(ERR, SHBUF, "%s: INPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, 
                                                        pIoctl->m_InputBufferSize, InReqSize);
            return DT_STATUS_INVALID_PARAMETER;
        }
        if (pIoctl->m_OutputBufferSize < OutReqSize)
        {
            DtDbgOut(ERR, SHBUF, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, 
                                                      pIoctl->m_OutputBufferSize, OutReqSize);
            return DT_STATUS_INVALID_PARAMETER;
        }

        DtDbgOut(MAX, SHBUF, "%s: In=%d (Rq=%d), Out=%d (Rq=%d)", pIoctlStr,
                pIoctl->m_InputBufferSize, InReqSize, pIoctl->m_OutputBufferSize, OutReqSize);
    }

    if (pShBufCmdInput->m_BufferIndex != 0)
    {
        DtDbgOut(ERR, SHBUF, "%s: OUTPUT BUFFER TOO SMALL Size=%d Req=%d", pIoctlStr, 
                                                      pIoctl->m_OutputBufferSize, OutReqSize);
        return DT_STATUS_INVALID_PARAMETER;
    }
    
    // The bytes written will be updated if needed. Set the default value here.
    pIoctl->m_OutputBufferBytesWritten = OutReqSize;

    // Lookup the shared buffer structure
    // Check if the PortIndex is from the NonIpPort
    Status = DtuGetNonIpPortIndex(pDvcData, pShBufCmdInput->m_PortIndex, &Index);
    if (!DT_SUCCESS(Status))
        return DT_STATUS_NOT_FOUND;
    pShBuffer = &pDvcData->m_pNonIpPorts[Index].m_SharedBuffer;

    if (DT_SUCCESS(Status))
    {
        switch (pShBufCmdInput->m_Cmd)
        {
        case DTU_SH_BUF_CMD_INIT:
            {
                char*  pBuffer;
                UInt  Size;
                DtPageList*  pPageList = NULL;
#if defined(WINBUILD)
                DtPageList  PageList;
                PMDL  pMdl;
                NTSTATUS  NtStatus;
                // Retrieve MDL and virtual buffer from request object
                NtStatus = WdfRequestRetrieveOutputWdmMdl(pIoctl->m_WdfRequest, &pMdl);
                if (NtStatus != STATUS_SUCCESS)
                {
                    DtDbgOut(ERR, SHBUF, "WdfRequestRetrieveOutputWdmMdl error: %08x", 
                                                                                NtStatus);
                    Status = DT_STATUS_OUT_OF_RESOURCES;
                }
                if (DT_SUCCESS(Status))
                {
                    pBuffer = MmGetMdlVirtualAddress(pMdl);
                    if (pBuffer == NULL)
                    {
                        DtDbgOut(ERR, SHBUF, "DTU_SH_BUF_CMD_INIT: DT_STATUS_OUT_OF_MEMORY");
                        Status = DT_STATUS_OUT_OF_MEMORY;
                    }
                    Size = MmGetMdlByteCount(pMdl);

                    // Build pagelist object for user space buffer
                    pPageList = &PageList;
                    pPageList->m_BufType = DT_BUFTYPE_USER;
                    pPageList->m_OwnedByOs = TRUE;
                    pPageList->m_pMdl = pMdl;
                    pPageList->m_pVirtualKernel = NULL;
                }
#else // LINBUILD
                Size = (UInt)pShBufCmdInput->m_Data.m_Init.m_BufferSize;
#if defined(LIN32)
                pBuffer = (char*)(UInt32)pShBufCmdInput->m_Data.m_Init.m_BufferAddr;
#else
                pBuffer = (char*)(UInt64)pShBufCmdInput->m_Data.m_Init.m_BufferAddr;
#endif
#endif
                if (DT_SUCCESS(Status))
                {
                    Status = DtuShBufferInit(pShBufCmdInput, pFile, pPageList, pBuffer, 
                                                        Size, DT_BUFTYPE_USER, pShBuffer);
                    if (!DT_SUCCESS(Status))
                        DtDbgOut(ERR, SHBUF, "DtuShBufferInit failed");
                }
            }
            break;
        case DTU_SH_BUF_CMD_CLOSE:
            if (pDvcData->m_pNonIpPorts!=NULL && 
                                   pDvcData->m_pNonIpPorts[0].m_State==DTU3_STATE_READ351)
            {
                pDvcData->m_pNonIpPorts[0].m_NextState = DTU3_STATE_DET_VIDSTD;
                DtEventSet(&pDvcData->m_pNonIpPorts[0].m_StateChanged);
                DtEventWait(&pDvcData->m_pNonIpPorts[0].m_StateChangeCmpl, -1);
            }
            else  if (pDvcData->m_pNonIpPorts!=NULL && 
                                  pDvcData->m_pNonIpPorts[0].m_State==DTU3_STATE_WRITE315)
            {
                pDvcData->m_pNonIpPorts[0].m_NextState = DTU3_STATE_IDLE;
                DtEventSet(&pDvcData->m_pNonIpPorts[0].m_StateChanged);
                DtEventWait(&pDvcData->m_pNonIpPorts[0].m_StateChangeCmpl, -1);
            }
            Status = DtuShBufferClose(pShBuffer);
            break;
        default:
            Status = DT_STATUS_NOT_SUPPORTED;
        }
    }

    // If we failed, no data has te be copied to user space
    if (!DT_SUCCESS(Status))
    {
        pIoctl->m_OutputBufferBytesWritten = 0;
        if (Status == DT_STATUS_NOT_SUPPORTED)
            DtDbgOut(MIN, SHBUF, "ShBufCmd=0x%x: NOT SUPPORTED", pShBufCmdInput->m_Cmd);
    }
    return Status;
}
Exemplo n.º 2
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtuEventsGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
// Return a pending event. This functions blocks if no events are pending.
//
DtStatus  DtuEventsGet(
    DtuDeviceData*  pDvcData,
    DtFileObject*  pFile, 
    UInt*  pEventType, 
    UInt*  pValue1,
    UInt*  pValue2,
    Bool  Wait)
{
    DtStatus  Result = DT_STATUS_OK;
    DtuEvents*  pDtuEvents;

    if (pFile==NULL || pEventType==NULL || pValue1==NULL || pValue2==NULL)
        return DT_STATUS_INVALID_PARAMETER;

    // Get corresponding events object
    pDtuEvents = DtuEventsGetEventsObject(pDvcData, pFile);
    if (pDtuEvents == NULL)
        Result = DT_STATUS_NOT_FOUND;

    if (DT_SUCCESS(Result))
    {
        DtEventReset(&pDtuEvents->m_PendingEvent);

        if (Wait && pDtuEvents->m_NumPendingEvents==0 && !pDtuEvents->m_CancelInProgress) 
        {
            DtDbgOut(MAX, EVENTS, "Waiting for event");
        
            // Wait for event to be triggered
            DtEventWait(&pDtuEvents->m_PendingEvent, -1);
        }

        // The next request will be rejected by the IoCtl function, so we can reset
        // the Cancel state here.
        if (pDtuEvents->m_CancelInProgress)
            Result = DT_STATUS_CANCELLED;
        pDtuEvents->m_CancelInProgress = FALSE;

        DtSpinLockAcquire(&pDtuEvents->m_Lock);
        
        // Return pending events
        if (pDtuEvents->m_NumPendingEvents != 0)
        {  
            *pEventType = pDtuEvents->m_PendingEvents[0].m_EventType;
            *pValue1 = pDtuEvents->m_PendingEvents[0].m_EventValue1;
            *pValue2 =  pDtuEvents->m_PendingEvents[0].m_EventValue2;
            DtDbgOut(MAX, EVENTS, "Event #%d. Type: %d, Value1: %d, Value2: %d", 
                         pDtuEvents->m_NumPendingEvents, *pEventType, *pValue1, *pValue2);
            pDtuEvents->m_NumPendingEvents--;

            if (pDtuEvents->m_NumPendingEvents != 0)
            {   
                // Remove the old event
                DtMemMove(&pDtuEvents->m_PendingEvents[0],
                                       &pDtuEvents->m_PendingEvents[1],
                                       sizeof(DtuEvent) * pDtuEvents->m_NumPendingEvents);
            }
        } else {
            *pEventType = 0;
            *pValue1 = 0;
            *pValue2 = 0;
            if (Result == DT_STATUS_OK)
                Result = DT_STATUS_REQUEUE; // No pending events
            DtDbgOut(MAX, EVENTS, "Event #%d. No event", pDtuEvents->m_NumPendingEvents);
        }
    
        DtSpinLockRelease(&pDtuEvents->m_Lock);

        // Decrement refcount
        DtuEventsUnrefEventsObject(pDvcData, pDtuEvents);
    }
    
    return Result;
}
Exemplo n.º 3
0
Arquivo: Uart.c Projeto: levic/dektec
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaUartWrite -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
//
DtStatus  DtaUartRead(
    DtaUartPort*  pUart,
    UInt8*  pBuf,
    Int  BytesToRead,
    Int  Timeout,
    Int*  pNumBytesRead)
{
    DtStatus  Status = DT_STATUS_OK; 
    Int  NumBytesAvail, NumCanRead, FifoSize, i;
    Int Idx = 0;
    volatile UInt8* pFwbRegs = pUart->m_pFwbRegs;
#ifdef WINBUILD
    LARGE_INTEGER  StartTime, CurTime;
#else
    struct timespec  StartTime, CurTime;
#endif
    Int  TimeElapsed;
    Int  OrigTimeout = Timeout;

    *pNumBytesRead = 0;
    
    // Check timeout
    if (Timeout < -1)
        return DT_STATUS_INVALID_PARAMETER;


#ifdef WINBUILD
    KeQueryTickCount(&StartTime);
#else
    getnstimeofday(&StartTime);
#endif

    FifoSize = DtaFwbRegRead(pFwbRegs,  &pUart->m_pFwbUart->Config_RxFifoSize);
    NumBytesAvail = DtaFwbRegRead(pFwbRegs, &pUart->m_pFwbUart->RxStat_FifoLoad);
    do
    {
        NumCanRead = (BytesToRead < NumBytesAvail) ? BytesToRead : NumBytesAvail;
        // Read available data from FIFO
        for (i=0; i<NumCanRead; i++)
            pBuf[Idx++] = (UInt8)DtaFwbRegRead(pFwbRegs, &pUart->m_pFwbUart->RxData);

        BytesToRead -= NumCanRead;
        *pNumBytesRead += NumCanRead;

        // Ready?
        if (BytesToRead==0 || Timeout==0)
            break;

        // Wait for data available event
        DtEventReset(&pUart->m_RxEvent);
        if (BytesToRead < FifoSize/2)
            DtaFwbRegWrite(pFwbRegs, &pUart->m_pFwbUart->RxCtrl_DataIdleIntEnable, 1);
        else
            DtaFwbRegWrite(pFwbRegs, &pUart->m_pFwbUart->RxCtrl_HalfFullIntEnable, 1);
        Status = DtEventWait(&pUart->m_RxEvent, Timeout);
        if (!DT_SUCCESS(Status))
            break;

        // Check how much is availble now
        NumBytesAvail = DtaFwbRegRead(pFwbRegs, &pUart->m_pFwbUart->RxStat_FifoLoad);

        if (Timeout == -1)
            continue;

#ifdef WINBUILD
        KeQueryTickCount(&CurTime);
        TimeElapsed = (Int)((CurTime.QuadPart - StartTime.QuadPart)*KeQueryTimeIncrement()
                                                                                 / 10000);
#else
        getnstimeofday(&CurTime);
        TimeElapsed = DtDivide64(((CurTime.tv_sec-StartTime.tv_sec)*1000000000LL
                                   + (CurTime.tv_nsec-StartTime.tv_nsec)), 1000000, NULL);
#endif

        Timeout = OrigTimeout - TimeElapsed;
    } while (Timeout > 0);
    
    // Reception ready
    DtaFwbRegWrite(pFwbRegs, &pUart->m_pFwbUart->RxCtrl_DataIdleIntEnable, 0);
    DtaFwbRegWrite(pFwbRegs, &pUart->m_pFwbUart->RxCtrl_HalfFullIntEnable, 0);

    // A timeout is not an error in this case. Let userspace deal with the fact that
    // the read operation is not complete.
    if (Status == DT_STATUS_TIMEOUT)
        Status = DT_STATUS_OK;

    return Status;
}