⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcifuction_haero.c

📁 一个 PCI 驱动,实现PC 机与 PCI9045 的通信
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (pDevice == NULL)
        return ApiInvalidHandle;

    pIoNode = IoPoolGetNode();

    pIoNode->IoBuffer.DmaData.DmaChannel = dmaChannel;
    
    /*************************************************************
     * If the ReturnCode field is non-zero, the driver will
     * assume a NULL descriptor and will, therefore, not
     * modify the DMA mode parameters/registers.  It will assume
     * these are already setup correctly.
     *************************************************************/

    if (pDmaChannelDesc == NULL)
        pIoNode->IoBuffer.DmaData.ReturnCode = 1234;
    else
    {
        pIoNode->IoBuffer.DmaData.ReturnCode     = 0;
        pIoNode->IoBuffer.DmaData.DmaChannelDesc = *pDmaChannelDesc;    
    }

    DeviceIoControl(
        hDevice,
        PLX_IOCTL_DMA_SGL_OPEN,
        &(pIoNode->IoBuffer),
        sizeof(IOCTLDATA),
        &(pIoNode->IoBuffer),
        sizeof(IOCTLDATA),
        NULL,
        &(pIoNode->Overlapped)
        );

    rc = pIoNode->IoBuffer.DmaData.ReturnCode;

    IoPoolReleaseNode(
        pIoNode
        );

    // Build the DMA I/O buffers list if it hasn't been done
    if (pDevice->pDmaList == NULL)
    {
        DmaListBuild(
            pDevice
            );
    }

    return rc;
}

RETURN_CODE PlxIntrAttach(HANDLE    hDevice,PLX_INTR  intrTypes,HANDLE   *pEventHdl)
{
    IO_NODE     *pEvent;
    DEVICE_NODE *pDevice;


    if (pEventHdl == NULL)
        return ApiNullParam;

    // Verify the handle
    pDevice = DeviceListFind(
                  hDevice
                  );

    if (pDevice == NULL)
        return ApiInvalidHandle;

    // Check to see if the Event handle has been allocated already
    if (*pEventHdl != NULL)
    {
        pEvent = IoListFindByEventHandle(
                     pDevice->pEventList,
                     *pEventHdl
                     );
    }
    else
    {
        pEvent = NULL;
    }

    // Allocate resources if Event handle not previously used
    if (pEvent == NULL)
    {
        // Create the event
        *pEventHdl = CreateEvent(
                         NULL,          // Not inheritable to child processes
                         TRUE,          // Manual reset?
                         FALSE,         // Intial state
                         NULL
                         );

        if (*pEventHdl == NULL)
            return ApiInsufficientResources;

        // Save the resources for later release
        pEvent = IoListAdd(&(pDevice->pEventList),*pEventHdl);
        if (pEvent == NULL)
        {
            CloseHandle(*pEventHdl);
            return ApiInsufficientResources;
        }
    }


    // Fill in the I/O parameters
    pEvent->IoBuffer.MiscData.IntrInfo   = intrTypes;
    pEvent->IoBuffer.MiscData.ReturnCode = ApiSuccess;

    /*************************************************************
     * Since this is an Overlapped message, the request will not
     * complete it until the interrupt or an error occurs.  In
     * that case, the return code is only valid in error conditions,
     * so we cannot rely on it; therefore, it is set beforehand.
     *************************************************************/

    // Send message to driver
    DeviceIoControl(
        hDevice,
        PLX_IOCTL_INTR_ATTACH,
        &(pEvent->IoBuffer),
        sizeof(IOCTLDATA),
        &(pEvent->IoBuffer),
        sizeof(IOCTLDATA),  
        NULL,
        &(pEvent->Overlapped)
        );

    return pEvent->IoBuffer.MiscData.ReturnCode;
}

RETURN_CODE PlxDmaSglTransfer(HANDLE  hDevice,DMA_CHANNEL dmaChannel,DMA_TRANSFER_ELEMENT *pDmaData,BOOLEAN  returnImmediate)
{
    DWORD        StatusCode;
    IO_NODE     *pDmaNode;
    DEVICE_NODE *pDevice;


    if (pDmaData == NULL)
        return ApiNullParam;

    // Verify the handle
    pDevice = DeviceListFind(
                  hDevice
                  );
    if (pDevice == NULL)
        return ApiInvalidHandle;

    pDmaNode = DmaListGetNode(pDevice,(unsigned char)DmaIndex(dmaChannel));

    if (pDmaNode == NULL)
        return ApiDmaChannelUnavailable;

    // Copy parameter information
    pDmaNode->IoBuffer.DmaData.DmaChannel  = dmaChannel;
    pDmaNode->IoBuffer.DmaData.TransBlock1 = *pDmaData;
    pDmaNode->IoBuffer.DmaData.ReturnCode  = ApiSuccess;

    /*************************************************************
     * Since this is an Asynchronous operation, the request will not
     * complete it until the interrupt or an error occurs.  In
     * that case, the return code is only valid in error conditions,
     * so we cannot rely on it; therefore, it is set beforehand.
     *************************************************************/

    DeviceIoControl(
        hDevice,
        PLX_IOCTL_DMA_SGL_TRANSFER,
        &(pDmaNode->IoBuffer),
        sizeof(IOCTLDATA),
        &(pDmaNode->IoBuffer),
        sizeof(IOCTLDATA),
        NULL,
        &(pDmaNode->Overlapped)
        );

    // Don't wait for completion if requested not to
    if (returnImmediate)
        return pDmaNode->IoBuffer.DmaData.ReturnCode;

    if (pDmaNode->IoBuffer.DmaData.ReturnCode != ApiSuccess)
        return pDmaNode->IoBuffer.DmaData.ReturnCode;

    StatusCode = WaitForSingleObject(
                     pDmaNode->Overlapped.hEvent, 
                     MAX_DMA_TIMEOUT
                     );

    switch (StatusCode)
    {
        case WAIT_OBJECT_0:
            return pDmaNode->IoBuffer.DmaData.ReturnCode;

        case WAIT_TIMEOUT:
            return ApiPciTimeout;

        case WAIT_FAILED:
            return ApiFailed;
    }

    return ApiFailed;
}

RETURN_CODE PlxDmaSglChannelClose(HANDLE hDevice,DMA_CHANNEL dmaChannel)
{
    IO_NODE     *pIoNode;
    RETURN_CODE  rc;


    // Verify the handle
    if (DeviceListFind(
            hDevice
            ) == NULL)
    {
        return ApiInvalidHandle;
    }

    pIoNode = IoPoolGetNode();

    pIoNode->IoBuffer.DmaData.DmaChannel = dmaChannel;

    DeviceIoControl(
        hDevice,
        PLX_IOCTL_DMA_SGL_CLOSE,
        &(pIoNode->IoBuffer),
        sizeof(IOCTLDATA),
        &(pIoNode->IoBuffer),
        sizeof(IOCTLDATA),
        NULL,
        &(pIoNode->Overlapped)
        );

    rc = pIoNode->IoBuffer.DmaData.ReturnCode;

    IoPoolReleaseNode(
        pIoNode
        );

    return rc;
}

DEVICE_NODE *DeviceListFind(HANDLE hDevice)
{
    DEVICE_NODE *pCurrentDevice;


    LockGlobals();

    pCurrentDevice = pDeviceList;

    // Search for the node in the Device List
    while (pCurrentDevice != NULL)
    {
        if (pCurrentDevice->Handle == hDevice)
        {
            UnlockGlobals();
            return pCurrentDevice;
        }

        pCurrentDevice = pCurrentDevice->pNext;
    }

    UnlockGlobals();

    return NULL;
}

BOOLEAN DmaListBuild(DEVICE_NODE *pDevice)
{
    unsigned char        i;
    IO_NODE  *pNewDma;
    IO_NODE  *pDmaList;


    LockGlobals();

    for (i=0; i<MAX_DMA_CHANNELS; i++)
    {
        // Allocate a new node
        pNewDma = (IO_NODE *)malloc(sizeof(IO_NODE));

        if (pNewDma == NULL)
        {
            UnlockGlobals();
            return FALSE;
        }

        // Clear the overlapped structure
        memset(
            &(pNewDma->Overlapped),
            0,
            sizeof(OVERLAPPED)
            );

        // Allocate the Event handle
        pNewDma->Overlapped.hEvent =
            CreateEvent(
                NULL,          // Not inheritable to child processes
                TRUE,          // Manual reset?
                FALSE,         // Intial state
                NULL
                );
        if (pNewDma->Overlapped.hEvent == NULL)
        {
            UnlockGlobals();
            free(
                pNewDma
                );
            return FALSE;
        }

        // Clear the next pointer
        pNewDma->pNext = NULL;

        // Add node to the list
        if (pDevice->pDmaList == NULL)
            pDevice->pDmaList = pNewDma;
        else
            pDmaList->pNext = pNewDma;

        pDmaList = pNewDma;
    }

    UnlockGlobals();

    return TRUE;
}

IO_NODE * DmaListGetNode(DEVICE_NODE *pDevice,unsigned char  index)
{
    unsigned char       i;
    IO_NODE *pDmaNode;


    i = 0;

    LockGlobals();

    pDmaNode = pDevice->pDmaList;

    while (pDmaNode != NULL)
    {
        if (i == index)
        {
            UnlockGlobals();
            return pDmaNode;
        }

        i++;
        pDmaNode = pDmaNode->pNext;
    }

    UnlockGlobals();

    return NULL;
}

IO_NODE * IoListFindByEventHandle(IO_NODE *pIoList,HANDLE   hEvent)
{
    LockGlobals();

    // Search for the node in the list
    while (pIoList != NULL)
    {
        if (pIoList->Overlapped.hEvent == hEvent)
        {
            UnlockGlobals();
            return pIoList;
        }

        pIoList = pIoList->pNext;
    }

    UnlockGlobals();

    return NULL;
}

IO_NODE * IoListAdd(IO_NODE **pIoList,HANDLE    hEvent)
{
    IO_NODE *pNewNode;
    IO_NODE *pCurrNode;


    // Allocate a new node
    pNewNode = (IO_NODE *)malloc(sizeof(IO_NODE));
    
    if (pNewNode == NULL)
    {
        UnlockGlobals();
        return NULL;
    }

    // Clear the overlapped structure
    memset(
        &(pNewNode->Overlapped),
        0,
        sizeof(OVERLAPPED)
        );

    // Save the Event handle
    pNewNode->Overlapped.hEvent = hEvent;
    pNewNode->pNext             = NULL;

    LockGlobals();

    if (*pIoList != NULL)
    {
        pCurrNode = *pIoList;

        while (pCurrNode->pNext != NULL)
        {
            pCurrNode = pCurrNode->pNext;
        }

        // Add node to the list
        pCurrNode->pNext = pNewNode;
    }
    else
    {
        *pIoList = pNewNode;
    }

    UnlockGlobals();

    return pNewNode;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -