NTSTATUS NICStartRecv( IN PFDO_DATA FdoData ) /*++ Routine Description: Start the receive unit if it's not in a ready state Assumption: This function is called with the Rcv SPINLOCK held. Arguments: FdoData Pointer to our FdoData Return Value: NT Status code --*/ { PMP_RFD pMpRfd; NTSTATUS status = STATUS_SUCCESS; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "---> NICStartRecv\n"); ASSERT(!IsListEmpty(&FdoData->RecvList)); // // Get the MP_RFD head // pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList); NICHandleRecvInterrupt(FdoData); ASSERT(!IsListEmpty(&FdoData->RecvList)); // // Get the new MP_RFD head // pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList); exit: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<--- NICStartRecv, Status=%x\n", status); return status; }
VOID NICEvtInterruptDpc( IN WDFINTERRUPT WdfInterrupt, IN WDFOBJECT WdfDevice ) /*++ Routine Description: DPC callback for ISR. Arguments: WdfInterrupt - Handle to the framework interrupt object WdfDevice - Associated device object. Return Value: --*/ { PFDO_DATA fdoData = NULL; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "--> NICEvtInterruptDpc\n"); fdoData = FdoGetData(WdfDevice); WdfSpinLockAcquire(fdoData->RcvLock); NICHandleRecvInterrupt(fdoData); WdfSpinLockRelease(fdoData->RcvLock); // // Handle send interrupt // WdfSpinLockAcquire(fdoData->SendLock); NICHandleSendInterrupt(fdoData); WdfSpinLockRelease(fdoData->SendLock); // // Check if any queued Sends need to be reprocessed. // NICCheckForQueuedSends(fdoData); // // Start the receive unit if it had stopped // WdfSpinLockAcquire(fdoData->RcvLock); NICStartRecv(fdoData); WdfSpinLockRelease(fdoData->RcvLock); // // Re-enable the interrupt (disabled in MPIsr) // WdfInterruptSynchronize( WdfInterrupt, NICEnableInterrupt, fdoData); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "<-- NICEvtInterruptDpc\n"); }
NTSTATUS NICStartRecv( IN PFDO_DATA FdoData ) /*++ Routine Description: Start the receive unit if it's not in a ready state Assumption: This function is called with the Rcv SPINLOCK held. Arguments: FdoData Pointer to our FdoData Return Value: NT Status code --*/ { PMP_RFD pMpRfd; NTSTATUS status; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "---> NICStartRecv\n"); // // If the receiver is ready, then don't try to restart. // if (NIC_IS_RECV_READY(FdoData)) { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Receive unit already active\n"); return STATUS_SUCCESS; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Re-start receive unit...\n"); ASSERT(!IsListEmpty(&FdoData->RecvList)); // // Get the MP_RFD head // pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList); // // If more packets are received, clean up RFD chain again // if (NIC_RFD_GET_STATUS(pMpRfd->HwRfd)) { NICHandleRecvInterrupt(FdoData); ASSERT(!IsListEmpty(&FdoData->RecvList)); // // Get the new MP_RFD head // pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList); } // // Wait for the SCB to clear before we set the general pointer // if (!WaitScb(FdoData)) { status = STATUS_DEVICE_DATA_ERROR; goto exit; } if (FdoData->DevicePowerState > PowerDeviceD0) { status = STATUS_DEVICE_DATA_ERROR; goto exit; } // // Set the SCB General Pointer to point the current Rfd // FdoData->CSRAddress->ScbGeneralPointer = pMpRfd->HwRfdPhys; // // Issue the SCB RU start command // status = D100IssueScbCommand(FdoData, SCB_RUC_START, FALSE); if (status == STATUS_SUCCESS) { // wait for the command to be accepted if (!WaitScb(FdoData)) { status = STATUS_DEVICE_DATA_ERROR; } } exit: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<--- NICStartRecv, Status=%x\n", status); return status; }