VOID natpReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext ) { PFILTER_ADAPTER pAdapt; pAdapt = (PFILTER_ADAPTER)ProtocolBindingContext; if(1 == InterlockedIncrement(&pAdapt->RcvCompleteProcessing)) natpFlushReceiveQueue(pAdapt); if ( (pAdapt->MiniportHandle != NULL) && (pAdapt->IndicateRcvComplete)){ switch (pAdapt->Medium){ case NdisMedium802_3: NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle); break; default: break; } } pAdapt->IndicateRcvComplete = FALSE; InterlockedDecrement(&pAdapt->RcvCompleteProcessing); }
VOID PtReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext ) /*++ Routine Description: Called by the adapter below us when it is done indicating a batch of received packets. Arguments: ProtocolBindingContext Pointer to our adapter structure. Return Value: None --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; if ((pAdapt->MiniportHandle != NULL) && pAdapt->IndicateRcvComplete) { switch (pAdapt->Medium) { case NdisMedium802_3: case NdisMediumWan: NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle); break; case NdisMedium802_5: NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle); break; case NdisMediumFddi: //NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle); break; default: ASSERT(FALSE); break; } } pAdapt->IndicateRcvComplete = FALSE; }
void NIC_DRIVER_OBJECT::DriverReceiveIndication( int nCurr, PVOID pVoid, int nLength) { NdisMEthIndicateReceive( m_NdisHandle, (PNDIS_HANDLE)nCurr, (char*)pVoid, ETH_HEADER_SIZE, ((char*)pVoid + ETH_HEADER_SIZE), nLength - ETH_HEADER_SIZE, nLength - ETH_HEADER_SIZE); NdisMEthIndicateReceiveComplete(m_NdisHandle); return; }
// Process the received packet void NeoWrite(void *buf) { UINT num, i, size; void *packet_buf; // Validate arguments if (buf == NULL) { return; } // Number of packets num = NEO_NUM_PACKET(buf); if (num > NEO_MAX_PACKET_EXCHANGE) { // Number of packets is too many return; } if (num == 0) { // No packet return; } if (ctx->Halting != FALSE) { // Halting return; } if (ctx->Opened == FALSE) { // Not connected return; } for (i = 0;i < num;i++) { PACKET_BUFFER *p = ctx->PacketBuffer[i]; size = NEO_SIZE_OF_PACKET(buf, i); if (size > NEO_MAX_PACKET_SIZE) { size = NEO_MAX_PACKET_SIZE; } if (size < NEO_PACKET_HEADER_SIZE) { size = NEO_PACKET_HEADER_SIZE; } packet_buf = NEO_ADDR_OF_PACKET(buf, i); // Buffer copy NeoCopy(p->Buf, packet_buf, size); if (g_is_win8 == false) { // Adjust the buffer size NdisAdjustBufferLength(p->NdisBuffer, size); // Set the packet information NDIS_SET_PACKET_STATUS(p->NdisPacket, NDIS_STATUS_RESOURCES); NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE); } else { NdisMEthIndicateReceive(ctx->NdisMiniport, ctx, p->Buf, NEO_PACKET_HEADER_SIZE, ((UCHAR *)p->Buf) + NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE); NdisMEthIndicateReceiveComplete(ctx->NdisMiniport); } } // Notify that packets have received ctx->Status.NumPacketRecv += num; if (g_is_win8 == false) { NdisMIndicateReceivePacket(ctx->NdisMiniport, ctx->PacketBufferArray, num); } }
/*************************************************************************** Routine Description: This is the real interrupt handler for receive/overflow interrupt. Called when a receive interrupt is received. It first indicates all packets on the card and finally indicates ReceiveComplete(). Arguments: Adapter - Pointer to the adapter block. Return Value: TRUE if done with all receives, else FALSE. *****************************************************************************/ BOOLEAN R6040RcvDpc(IN PR6040_ADAPTER Adapter) { // Status of a received packet. INDICATE_STATUS IndicateStatus = INDICATE_OK; // Guess at where the packet is located PUCHAR PacketLoc; // Flag to tell when the receive process is complete BOOLEAN Done = TRUE; PUCHAR rxd; USHORT rxstatus; int total_len; do { // Code to fix a loop we got into where the card had been removed, // Now, the NDIS unbind routine calls our shutdown // handler which sets a flag if (Adapter->ShuttingDown) { RETAILMSG(R6040DBG, (TEXT("R6040RcvDpc(): Shutdown detected\r\n"))); break; } // Default to not indicating NdisMEthIndicateReceiveComplete Adapter->IndicateReceiveDone = FALSE; // A packet was found on the card, indicate it. Adapter->ReceivePacketCount++; rxd = Adapter->Rx_ring[Adapter->Rx_desc_add].VirtualAddr; READMEM16(rxd + DS_STATUS, rxstatus); READMEM16(rxd + DS_LEN, total_len); total_len -= 4; /* Skip CRC 4 byte */ /* OWN bit=1, no packet coming */ if (rxstatus & 0x8000) { IndicateStatus = SKIPPED; //RETAILMSG(R6040DBG, (TEXT("R6040RcvDpc(): no packet coming \r\n"))); break; } //RETAILMSG(R6040DBG, (TEXT("R6040RcvDpc(): total_len = %d\r\n"), total_len)); Adapter->Rx_desc_add++; // Adapter->Rx_free_cnt++; // Copy the data to the network stack PacketLoc = rxd + BUF_START; Adapter->PacketHeaderLoc = PacketLoc; // Indicate the packet to the wrapper IndicateStatus = R6040IndicatePacket(Adapter , total_len); if (IndicateStatus != CARD_BAD) { Adapter->FramesRcvGood++; } // Handle when the card is unable to indicate good packets if (IndicateStatus == CARD_BAD) { RETAILMSG(R6040DBG, (TEXT("R6040RcvDpc(): CARD_BAD: R: <%x %x %x %x> \r\n"), Adapter->PacketHeader[0], Adapter->PacketHeader[1], Adapter->PacketHeader[2], Adapter->PacketHeader[3])); // Start off with receive interrupts disabled. Adapter->NicInterruptMask = MIER_RXENDE | MIER_TXENDE; // Reset the adapter CardReset(Adapter); // Since the adapter was just reset, stop indicating packets. break; } /* Rx data already copy to the upper buffer, now can reuse RX descriptor */ WRITEMEM16(rxd + DS_STATUS, 0x8000); /* Reuse RX descriptor */ /* Signal RX ready */ // NdisRawWritePortUshort( Adapter->IoPAddr + NIC_CONTROL0,Adapter->MacControl); /* Move to next RX descriptor */ if (Adapter->Rx_desc_add >= MAX_RX_DESCRIPTORS) { Adapter->Rx_desc_add = 0; Done = FALSE; Adapter->ReceivePacketCount = 0; // break; } // Finally, indicate ReceiveComplete to all protocols which received packets if (Adapter->IndicateReceiveDone) { NdisDprReleaseSpinLock(&Adapter->RcvLock); NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle); NdisDprAcquireSpinLock(&Adapter->RcvLock); Adapter->IndicateReceiveDone = FALSE; } }while (TRUE); return (Done); }
VOID NTAPI MiniportHandleInterrupt ( IN NDIS_HANDLE MiniportAdapterContext ) { PRTL_ADAPTER adapter = (PRTL_ADAPTER)MiniportAdapterContext; ULONG txStatus; UCHAR command; PPACKET_HEADER nicHeader; PETH_HEADER ethHeader; NdisDprAcquireSpinLock(&adapter->Lock); NDIS_DbgPrint(MAX_TRACE, ("Interrupts pending: 0x%x\n", adapter->InterruptPending)); // // Handle a link change // if (adapter->LinkChange) { NdisDprReleaseSpinLock(&adapter->Lock); NdisMIndicateStatus(adapter->MiniportAdapterHandle, adapter->MediaState == NdisMediaStateConnected ? NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0); NdisMIndicateStatusComplete(adapter->MiniportAdapterHandle); NdisDprAcquireSpinLock(&adapter->Lock); adapter->LinkChange = FALSE; } // // Handle a TX interrupt // if (adapter->InterruptPending & (R_I_TXOK | R_I_TXERR)) { while (adapter->TxFull || adapter->DirtyTxDesc != adapter->CurrentTxDesc) { NdisRawReadPortUlong(adapter->IoBase + R_TXSTS0 + (adapter->DirtyTxDesc * sizeof(ULONG)), &txStatus); if (!(txStatus & (R_TXS_STATOK | R_TXS_UNDERRUN | R_TXS_ABORTED))) { // // Not sent yet // break; } NDIS_DbgPrint(MAX_TRACE, ("Transmission for desc %d complete: 0x%x\n", adapter->DirtyTxDesc, txStatus)); if (txStatus & R_TXS_STATOK) { adapter->TransmitOk++; } else { adapter->TransmitError++; } adapter->DirtyTxDesc++; adapter->DirtyTxDesc %= TX_DESC_COUNT; adapter->InterruptPending &= ~(R_I_TXOK | R_I_TXERR); adapter->TxFull = FALSE; } } // // Handle a good RX interrupt // if (adapter->InterruptPending & (R_I_RXOK | R_I_RXERR)) { for (;;) { NdisRawReadPortUchar(adapter->IoBase + R_CMD, &command); if (command & R_CMD_RXEMPTY) { // // The buffer is empty // adapter->InterruptPending &= ~(R_I_RXOK | R_I_RXERR); break; } adapter->ReceiveOffset %= RECEIVE_BUFFER_SIZE; NDIS_DbgPrint(MAX_TRACE, ("Looking for a packet at offset 0x%x\n", adapter->ReceiveOffset)); nicHeader = (PPACKET_HEADER)(adapter->ReceiveBuffer + adapter->ReceiveOffset); if (!(nicHeader->Status & RSR_ROK)) { // // Receive failed // NDIS_DbgPrint(MIN_TRACE, ("Receive failed: 0x%x\n", nicHeader->Status)); if (nicHeader->Status & RSR_FAE) { adapter->ReceiveAlignmentError++; } else if (nicHeader->Status & RSR_CRC) { adapter->ReceiveCrcError++; } adapter->ReceiveError++; goto NextPacket; } NDIS_DbgPrint(MAX_TRACE, ("Indicating %d byte packet to NDIS\n", nicHeader->PacketLength - RECV_CRC_LENGTH)); ethHeader = (PETH_HEADER)(nicHeader + 1); NdisMEthIndicateReceive(adapter->MiniportAdapterHandle, NULL, (PVOID)(ethHeader), sizeof(ETH_HEADER), (PVOID)(ethHeader + 1), nicHeader->PacketLength - sizeof(ETH_HEADER) - RECV_CRC_LENGTH, nicHeader->PacketLength - sizeof(ETH_HEADER) - RECV_CRC_LENGTH); adapter->ReceiveOk++; NextPacket: adapter->ReceiveOffset += nicHeader->PacketLength + sizeof(PACKET_HEADER); adapter->ReceiveOffset = (adapter->ReceiveOffset + 3) & ~3; NdisRawWritePortUshort(adapter->IoBase + R_CAPR, adapter->ReceiveOffset - 0x10); if (adapter->InterruptPending & (R_I_RXOVRFLW | R_I_FIFOOVR)) { // // We can only clear these interrupts once CAPR has been reset // NdisRawWritePortUshort(adapter->IoBase + R_IS, R_I_RXOVRFLW | R_I_FIFOOVR); adapter->InterruptPending &= ~(R_I_RXOVRFLW | R_I_FIFOOVR); } } NdisMEthIndicateReceiveComplete(adapter->MiniportAdapterHandle); } NdisDprReleaseSpinLock(&adapter->Lock); }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexHandleInterrupt // // Description: // This routine is the deferred processing // routine for all adapter interrupts. // // Input: // acb - Our Driver Context for this adapter or head. // // Output: // None // // Called By: // Miniport Wrapper // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VOID NetFlexHandleInterrupt( IN NDIS_HANDLE MiniportAdapterContext ) { USHORT sifint_reg; USHORT tmp_reg; USHORT ReceivesProcessed = 0; PACB acb = (PACB) MiniportAdapterContext; // // Read the SifInt // NdisRawReadPortUshort( acb->SifIntPort, &sifint_reg); while (sifint_reg & SIFINT_SYSINT) { // // Ack the interrupt // sifint_reg &= ~SIFINT_SYSINT; NdisRawWritePortUshort( acb->SifIntPort, sifint_reg); // // mask off the int code // sifint_reg &= INT_CODES; // // See if there are any recieves to do... // if (acb->acb_rcv_head->RCV_CSTAT & RCSTAT_COMPLETE) { // // Increment the interrupt count. // acb->acb_int_count++; // // yes, do them... // acb->handled_interrupts++; ReceivesProcessed += acb->ProcessReceiveHandler(acb); } // // See if there are any transmits to do... // NetFlexProcessXmit(acb); switch (sifint_reg) { case INT_SCBCLEAR: acb->acb_scbclearout = FALSE; // // Is the SCB really clear? // // If the SCB is clear, send a SCB command off now. // Otherwise, if we are not currently waiting for an SCB clear // interrupt, signal the adapter to send us a SCB clear interrupt // when it is done with the SCB. // if (acb->acb_scb_virtptr->SCB_Cmd == 0) { NetFlexSendNextSCB(acb); } else if ((acb->acb_xmit_whead) || (acb->acb_rcv_whead) || (acb->acb_scbreq_next)) { acb->acb_scbclearout = TRUE; NdisRawWritePortUshort( acb->SifIntPort, (USHORT)SIFINT_SCBREQST); } break; case INT_COMMAND: NetFlexCommand(acb); // // Do we have any commands to complete? // if (acb->acb_confirm_qhead != NULL) { NetFlexProcessMacReq(acb); } break; case INT_ADPCHECK: // // Read the Adapter Check Status @ 1.05e0 // NdisRawWritePortUshort(acb->SifAddrxPort, (USHORT) 1); NdisRawWritePortUshort(acb->SifAddrPort, (USHORT) 0x5e0); NdisRawReadPortUshort( acb->SifDIncPort, &tmp_reg); DebugPrint(1,("NF(%d): Adapter Check - 0x%x\n",acb->anum,tmp_reg)); // // Reset has failed, errorlog an entry. // NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_ADAPTER_CHECK_ERROR, 2, NETFLEX_ADAPTERCHECK_ERROR_CODE, tmp_reg ); // // Set the variables up showing that the hardware has an unrecoverable // error. // acb->acb_state = AS_HARDERROR; break; case INT_RINGSTAT: NetFlexRingStatus(acb); break; case INT_RECEIVE: break; case INT_TRANSMIT: // // If we reached the end of the xmit lists, // then the xmit status will indicate COMMAND_COMPLETE. // The transmiter will be stalled until another transmit // command is issued with a valid list. // if (acb->acb_ssb_virtptr->SSB_Status & XSTAT_LERROR) { // // We have a list error... // NetFlexTransmitStatus(acb); } default: break; } // // Issue a ssb clear. After this we may see SIFCMD interrupts. // NdisRawWritePortUshort(acb->SifIntPort, SIFINT_SSBCLEAR); // // Read the SifInt // NdisRawReadPortUshort(acb->SifIntPort, &sifint_reg); } // // Processed any receives which need IndicateReceiveComplete? // if (ReceivesProcessed) { if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5) { // Token Ring // NdisMTrIndicateReceiveComplete(acb->acb_handle); } else { // Ethernet // NdisMEthIndicateReceiveComplete(acb->acb_handle); } } }
VOID NetFlexDeferredTimer( IN PVOID SystemSpecific1, IN PACB acb, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3 ) { USHORT ReceivesProcessed = 0; USHORT sifint_reg; UINT IntAve; // // Indicate that a timer has expired. // DebugPrint(3,("NF(%d) - Defered Timer Expired!\n",acb->anum)); // // If we are resetting, get out... // if (acb->acb_state == AS_RESETTING) { return; } // // See if there are any recieves to do... // if (acb->acb_rcv_head->RCV_CSTAT & RCSTAT_COMPLETE) { // // Increment the interrupt count. // acb->acb_int_count++; // yes, do them... // ReceivesProcessed = acb->ProcessReceiveHandler(acb); } // // See if there are any transmits to do... // NetFlexProcessXmit(acb); // // Processed any receives which need IndicateReceiveComplete? // if (ReceivesProcessed) { if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5) { // Token Ring // NdisMTrIndicateReceiveComplete(acb->acb_handle); } else { // Ethernet // NdisMEthIndicateReceiveComplete(acb->acb_handle); } } if ( ++acb->timer_run_count >= RatioCheckCount ) { acb->timer_run_count = 0; #ifdef ALLOW_DISABLE_DYNAMIC_RATIO if ( EnableDynamicRatio ) { #endif #ifdef NEW_DYNAMIC_RATIO // // Should we increase the ratio? // if ( acb->handled_interrupts > RaiseIntThreshold) { acb->current_run_down = 0; if (acb->XmitIntRatio == 1) { if ( ++acb->current_run_up > RunThreshold ) { #ifdef XMIT_INTS acb->XmitIntRatio = acb->acb_maxtrans; #endif acb->acb_gen_objs.interrupt_ratio_changes++; acb->current_run_up = 0; DebugPrint(1,("NF(%d) - RcvIntRatio = %d\n",acb->anum,acb->RcvIntRatio)); } } } // // Or, should we decrease it? // else //if ( acb->handled_interrupts < LowerIntThreshold ) { acb->current_run_up = 0; if (acb->XmitIntRatio != 1) { if ( ++acb->current_run_down > RunThreshold ) { #ifdef XMIT_INTS acb->XmitIntRatio = 1; #endif acb->acb_gen_objs.interrupt_ratio_changes++; acb->current_run_down = 0; DebugPrint(1,("NF(%d) - RcvIntRatio = %d\n",acb->anum,acb->RcvIntRatio)); } } } #else // !defined(NEW_DYNAMIC_RATIO) if ( acb->XmitIntRatio != 1 ) { if ( acb->handled_interrupts < sw21 ) { if ( ++acb->current_run > RunThreshold ) { #ifdef XMIT_INTS acb->XmitIntRatio = 1; #endif acb->RcvIntRatio = 1; acb->acb_gen_objs.interrupt_ratio_changes++; acb->current_run = 0; acb->sw24 += 3; acb->cleartime = 0; } } else { acb->current_run = 0; } } else { if ( acb->handled_interrupts > sw24 ) { if ( ++acb->current_run > RunThreshold ) { #ifdef XMIT_INTS acb->XmitIntRatio = ratio; #endif acb->RcvIntRatio = ratio; acb->acb_gen_objs.interrupt_ratio_changes++; acb->current_run = 0; } } else { acb->current_run = 0; } } #ifdef DYNAMIC_RATIO_HISTORY acb->IntHistory[acb->Hndx] = acb->handled_interrupts; acb->RatioHistory[acb->Hndx] = (UCHAR)acb->RcvIntRatio; if ( ++acb->Hndx >= 1024 ) { acb->Hndx = 0; } #endif // // The switchover value to turbo gets incremented each time // we drop to normal mode. We reset this value every x seconds. // This will prevent the driver from toggling rapidly between // turbo <-> normal mode. // if ( ++acb->cleartime > 50 ) { acb->sw24 = sw24; acb->cleartime = 0; } #endif // !NEW_DYNAMIC_RATIO #ifdef ALLOW_DISABLE_DYNAMIC_RATIO } else { #ifdef XMIT_INTS acb->XmitIntRatio = ratio; #endif acb->RcvIntRatio = ratio; } #endif // ALLOW_DISABLE_DYNAMIC_RATIO acb->acb_gen_objs.interrupt_count = acb->handled_interrupts; acb->handled_interrupts = 0; } // // Set the timer... // NdisMSetTimer(&acb->DpcTimer, 10); } // NetFlexDeferredTimer