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; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // 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