//********************************************************************** //********************************************************************** // // File Name: INT.C // // Program Name: NetFlex NDIS 3.0 Miniport Driver // // Companion Files: None // // Function: This module contains the NetFlex Miniport Driver // interface routines called by the Wrapper and the // configuration manager. // // (c) Compaq Computer Corporation, 1992,1993,1994 // // This file is licensed by Compaq Computer Corporation to Microsoft // Corporation pursuant to the letter of August 20, 1992 from // Gary Stimac to Mark Baber. // // History: // // 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver // // // //*********************************************************************** /*-------------------------------------*/ /* Include all general companion files */ /*-------------------------------------*/ #include #include "tmsstrct.h" #include "macstrct.h" #include "adapter.h" #include "protos.h" //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexISR // // Description: // This routine is the ISR for this Netflx mac driver. // This routine determines if the interrupt is for it // and if so, it clears the system interrupt bit of // the sifint register. // // Input: // Context - Our Driver Context for this adapter or head. // // Output: // Returns TRUE if the interrupt belongs to the // adapter and returns FALSE if it does not // belong to the adapter. // // Called By: // Miniport Wrapper // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VOID NetFlexISR( OUT PBOOLEAN InterruptRecognized, OUT PBOOLEAN QueueDpc, IN PVOID Context ) { PACB acb; USHORT sifint_reg; USHORT actl_reg; acb = (PACB) Context; // // Read the Sifint register. // NdisRawReadPortUshort( acb->SifIntPort, &sifint_reg); // // See if the System Interrupt bit is set. If it is, this is an // interrupt for us. // if (sifint_reg & SIFINT_SYSINT) { // // Acknowledge and Clear Int // if (!acb->InterruptsDisabled) { actl_reg = acb->actl_reg & ~ACTL_SINTEN; NdisRawWritePortUshort(acb->SifActlPort, actl_reg); DebugPrint(3,("NF(%d)(D)\n",acb->anum)); acb->InterruptsDisabled = TRUE; // // Return that we recognize it // *InterruptRecognized = TRUE; *QueueDpc = TRUE; } else { // // It appears that a second head is generating // the interrupt, and we have a DPC queued to // process our int, return that we don't recognize it // so that the oterh head's isr gets called... // *InterruptRecognized = FALSE; *QueueDpc = FALSE; } } else { // Return that we don't recognize it // *InterruptRecognized = FALSE; *QueueDpc = FALSE; } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexDeferredTimer // // Description: // This routine is called every 10ms to check to see // if there is any receives or transmits which need // to be cleaned up since we don't require an interrupt // for each frame. // // Input: // acb - Our Driver Context for this adapter or head. // // Output: // None. // // Called By: // Miniport Wrapper via acb->DpcTimer // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #ifdef NEW_DYNAMIC_RATIO UINT MaxIntRatio = 4; // // New Threshold for xmit disabled case. // UINT RaiseIntThreshold = 26; // // Run threshold of 1.5 seconds instead of 200msecs. // UINT RunThreshold = 15; UINT RatioCheckCount = 10; #else UINT sw24 = 220; UINT sw21 = 40; #endif #ifdef ALLOW_DISABLE_DYNAMIC_RATIO BOOLEAN EnableDynamicRatio = TRUE; UINT ratio = 1; #endif 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 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // 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); } } } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexRingStatus // // Description: // This routine does the clean up work necessary // when a ring status occurs. // // Input: // acb - Our Driver Context for this adapter or head. // // Output: // None // // Called By: // NetFlexHandleInterrupt // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VOID NetFlexRingStatus( PACB acb ) { USHORT value; ULONG RingStatus = 0; value = acb->acb_ssb_virtptr->SSB_Status; DebugPrint(1,("NF(%d): RingStatus value = %x\n",acb->anum, value)); // // Determine the reason for the ring interrupt. // if (value & RING_STATUS_SIGNAL_LOSS) { RingStatus |= NDIS_RING_SIGNAL_LOSS; DebugPrint(1,("NF(%d): RING_STATUS_SIGNAL_LOSS\n",acb->anum)); // // Have we already reported the error? // if (!acb->SentRingStatusLog && ((acb->acb_lastringstatus & RING_STATUS_SIGNAL_LOSS) == 0)) { // no, so send one. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_SIGNAL_LOSS_ERROR, 3, NETFLEX_RINGSTATUS_ERROR_CODE, (ULONG) acb->acb_baseaddr, (ULONG) value ); acb->SentRingStatusLog = TRUE; } } if (value & RING_STATUS_HARD_ERROR) { RingStatus |= NDIS_RING_HARD_ERROR; DebugPrint(1,("NF(%d): RING_STATUS_HARD_ERROR\n",acb->anum)); } if (value & RING_STATUS_SOFT_ERROR) { RingStatus |= NDIS_RING_SOFT_ERROR; DebugPrint(1,("NF(%d): RING_STATUS_SOFT_ERROR\n",acb->anum)); } if (value & RING_STATUS_XMIT_BEACON) { RingStatus |= NDIS_RING_TRANSMIT_BEACON; DebugPrint(1,("NF(%d): RING_STATUS_XMIT_BEACON\n",acb->anum)); } if (value & RING_STATUS_LOBE_WIRE_FAULT) { RingStatus |= NDIS_RING_LOBE_WIRE_FAULT; DebugPrint(1,("NF(%d): RING_STATUS_LOBE_WIRE_FAULT\n",acb->anum)); // // Have we already reported the error? // if (!acb->SentRingStatusLog && ((acb->acb_lastringstatus & NDIS_RING_LOBE_WIRE_FAULT) == 0)) { // no, so send one. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_LOBE_FAILUE_ERROR, 3, NETFLEX_RINGSTATUS_ERROR_CODE, (ULONG) acb->acb_baseaddr, (ULONG) value ); acb->SentRingStatusLog = TRUE; } } if (value & (RING_STATUS_AUTO_REMOVE_1 | RING_STATUS_REMOVE_RECEIVED)) { if (value & RING_STATUS_AUTO_REMOVE_1) { RingStatus |= NDIS_RING_AUTO_REMOVAL_ERROR; DebugPrint(1,("NF(%d): RING_STATUS_AUTO_REMOVE_1\n",acb->anum)); } if (value & RING_STATUS_REMOVE_RECEIVED) { RingStatus |= NDIS_RING_REMOVE_RECEIVED; DebugPrint(1,("NF(%d): RING_STATUS_REMOVE_RECEIVED\n",acb->anum)); } // // Have we already reported the error? // if ((acb->acb_lastringstatus & (RING_STATUS_AUTO_REMOVE_1 | RING_STATUS_REMOVE_RECEIVED )) == 0) { // no, so send one. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_REMOVE_RECEIVED_ERROR, 3, NETFLEX_RINGSTATUS_ERROR_CODE, (ULONG) acb->acb_baseaddr, (ULONG) value ); } } if (value & RING_STATUS_OVERFLOW) { RingStatus |= NDIS_RING_COUNTER_OVERFLOW; DebugPrint(1,("NF(%d): RING_STATUS_OVERFLOW\n",acb->anum)); } if (value & RING_STATUS_SINGLESTATION) { RingStatus |= NDIS_RING_SINGLE_STATION; DebugPrint(1,("NF(%d): RING_STATUS_SINGLESTATION\n",acb->anum)); } if (value & RING_STATUS_RINGRECOVERY) { RingStatus |= NDIS_RING_RING_RECOVERY; DebugPrint(1,("NF(%d): RING_STATUS_RINGRECOVERY\n",acb->anum)); } // // Save the Ring Status // acb->acb_lastringstatus = RingStatus; // // Indicate to the filter the ring status. // NdisMIndicateStatus( acb->acb_handle, NDIS_STATUS_RING_STATUS, &RingStatus, sizeof(ULONG) ); // // Tell the filter that we have completed the ring status. // NdisMIndicateStatusComplete(acb->acb_handle); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexCommand // // Description: // This routine looks at the current SSB struct // and places the corresponding request on the // Request Confirm Queue. If the command that // has completed is an open, a receive and // transmit command are issued. // // Input: // acb - Our Driver Context for this adapter or head. // // Output: // None // // Called By: // NetFlexHandleInterrupt // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VOID NetFlexCommand( PACB acb ) { PSCBREQ scbreq; PMACREQ macreq; PTR_OBJS trobjs; PETH_OBJS ethobjs; SHORT value,i; PUSHORT tempptr; NDIS_STATUS Status; #if (DBG || DBGPRINT) // // I wanted to know if I'm getting bad commands // if (acb->acb_ssb_virtptr->SSB_Cmd == TMS_CMDREJECT) { DebugPrint(0,("NF(%d): Command rejected\n",acb->anum)); DebugPrint(0,("NF(%d): SSB Status %x\n",acb->anum,SWAPS(acb->acb_ssb_virtptr->SSB_Status))); DebugPrint(0,("NF(%d): SSB Ptr %x\n",acb->anum,SWAPL(acb->acb_ssb_virtptr->SSB_Ptr))); } else if (acb->acb_ssb_virtptr->SSB_Status != SSB_GOOD) { DebugPrint(0,("NF(%d): Bad status %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Status)); DebugPrint(0,("NF(%d): cmd is %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Cmd)); } #endif // // Get the scb request associated with the completed request. // Status = NetFlexDequeue_TwoPtrQ_Head( (PVOID *)&(acb->acb_scbreq_head), (PVOID *)&(acb->acb_scbreq_tail), (PVOID *)&scbreq ); if (Status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NF(%d) NetFlexCommand - dequeue scbreq failed!\n",acb->anum)); return; } // // If we have a Macreq to place on the confirm q. Do this now. // macreq = scbreq->req_macreq; if (macreq) { // // If the command had a problem, save the failure reason and // exit out of the routine. Otherwise, save the success code // and see if the completed command is an open or a read error log. // if (acb->acb_ssb_virtptr->SSB_Cmd == TMS_CMDREJECT) { DebugPrint(0,("NF(%d): Command rejected\n",acb->anum)); DebugPrint(0,("NF(%d): SSB Status %x\n",acb->anum,SWAPS(acb->acb_ssb_virtptr->SSB_Status))); DebugPrint(0,("NF(%d): SSB Ptr %x\n",acb->anum,SWAPL(acb->acb_ssb_virtptr->SSB_Ptr))); macreq->req_status = NDIS_STATUS_FAILURE; } else if (acb->acb_ssb_virtptr->SSB_Status != SSB_GOOD) { DebugPrint(0,("NF(%d): Bad status %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Status)); DebugPrint(0,("NF(%d): cmd is %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Cmd)); if ((acb->acb_ssb_virtptr->SSB_Cmd == TMS_OPEN) && (acb->acb_ssb_virtptr->SSB_Status & SSB_OPENERR) ) { macreq->req_status = NDIS_STATUS_TOKEN_RING_OPEN_ERROR; macreq->req_info = (PVOID)(acb->acb_ssb_virtptr->SSB_Status >> 8); } else { macreq->req_status = NDIS_STATUS_FAILURE; } } else if (acb->acb_ssb_virtptr->SSB_Cmd == TMS_READLOG) { acb->acb_logbuf_valid = TRUE; // // Fill in the appropriate fields with the information // given by the log buffer. // if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5) { // TOKEN RING trobjs = (PTR_OBJS)(acb->acb_spec_objs); trobjs->REL_Congestion += ((PREL)(acb->acb_logbuf_virtptr))->REL_Congestion; trobjs->REL_LineError += ((PREL)(acb->acb_logbuf_virtptr))->REL_LineError; trobjs->REL_LostError += ((PREL)(acb->acb_logbuf_virtptr))->REL_LostError; trobjs->REL_BurstError += ((PREL)(acb->acb_logbuf_virtptr))->REL_BurstError; trobjs->REL_ARIFCIError += ((PREL)(acb->acb_logbuf_virtptr))->REL_ARIFCIError; trobjs->REL_Congestion += ((PREL)(acb->acb_logbuf_virtptr))->REL_Congestion; trobjs->REL_CopiedError += ((PREL)(acb->acb_logbuf_virtptr))->REL_CopiedError; trobjs->REL_TokenError += ((PREL)(acb->acb_logbuf_virtptr))->REL_TokenError; } else { // ETHERNET ethobjs = (PETH_OBJS)(acb->acb_spec_objs); ethobjs->RSL_AlignmentErr = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_AlignmentErr); ethobjs->RSL_1_Collision = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_1_Collision); ethobjs->RSL_FrameCheckSeq = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_FrameCheckSeq); ethobjs->RSL_DeferredXmit = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_DeferredXmit); ethobjs->RSL_LateCollision = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_LateCollision); ethobjs->RSL_Excessive = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_Excessive); ethobjs->RSL_CarrierErr = (USHORT)SWAPS(((PRSL)(acb->acb_logbuf_virtptr))->RSL_CarrierErr); tempptr = (PUSHORT)&(((PRSL)(acb->acb_logbuf_virtptr))->RSL_2_Collision); value = 0; for (i = 0; i < 14; i++) { value += SWAPS( *(tempptr+i) ); } ethobjs->RSL_More_Collision = value; } } // // Take the Mac request off the macreq queue and place it on // the confirm queue so that the command can be completed. // NetFlexDequeue_TwoPtrQ( (PVOID *)&(acb->acb_macreq_head), (PVOID *)&(acb->acb_macreq_tail), (PVOID)macreq ); NetFlexEnqueue_TwoPtrQ_Tail( (PVOID *)&(acb->acb_confirm_qhead), (PVOID *)&(acb->acb_confirm_qtail), (PVOID)macreq ); } // if (macreq) // // Free up the SCB request associated with this command. // scbreq->req_macreq = NULL; NetFlexEnqueue_OnePtrQ_Head( (PVOID *)&(acb->acb_scbreq_free), (PVOID)scbreq ); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexEnableInterrupt // // Description: // This routine is used to enable the adapter to // interrupt the system. // // Input: // Context - Our Driver Context for this adapter or head. // // Output: // None // // Called By: // Miniport Wrapper // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VOID NetFlexEnableInterrupt( IN NDIS_HANDLE Context ) { USHORT actl_reg; PACB acb = (PACB) Context; DebugPrint(3,("NF(%d)(E)\n",acb->anum)); // // Enable System Interrupts // actl_reg = acb->actl_reg | ACTL_SINTEN; NdisRawWritePortUshort(acb->SifActlPort, actl_reg); acb->InterruptsDisabled = FALSE; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexDisableInterrupt // // Description: // This routine is used to disable the adapter from being // able to interrupt the system. // // Input: // Context - Our Driver Context for this adapter or head. // // Output: // None // // Called By: // Miniport Wrapper // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VOID NetFlexDisableInterrupt( IN NDIS_HANDLE Context ) { USHORT actl_reg; PACB acb = (PACB) Context; // // Disable System Interrupts // actl_reg = acb->actl_reg & ~ACTL_SINTEN; NdisRawWritePortUshort(acb->SifActlPort, actl_reg); acb->InterruptsDisabled = TRUE; DebugPrint(3,("NF(%d)(D)\n",acb->anum)); }