diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/netflex/reset.c | 1924 |
1 files changed, 1924 insertions, 0 deletions
diff --git a/private/ntos/ndis/netflex/reset.c b/private/ntos/ndis/netflex/reset.c new file mode 100644 index 000000000..f907de47e --- /dev/null +++ b/private/ntos/ndis/netflex/reset.c @@ -0,0 +1,1924 @@ +//********************************************************************** +//********************************************************************** +// +// File Name: RESET.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 <ndis.h> +#include "tmsstrct.h" +#include "macstrct.h" +#include "adapter.h" +#include "protos.h" + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexResetDispatch +// +// Description: +// Kick off a reset! +// +// Input: +// MiniportAdapterContext - really our acb. +// +// Output: +// Returns NDIS_STATUS_PENDING unless we are already handling a reset, +// in which case we return NDIS_STATUS_RESET_IN_PROGRESS. +// +// Called By: +// Miniport Wrapper +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +NDIS_STATUS +NetFlexResetDispatch( + OUT PBOOLEAN AddressingReset, + IN NDIS_HANDLE MiniportAdapterContext + ) +{ + PACB acb = (PACB) MiniportAdapterContext; + BOOLEAN ReceiveResult = FALSE; + + DebugPrint(1,("NF(%d): Reset Called!\n",acb->anum)); + + if ( acb->ResetState && (acb->ResetState != RESET_HALTED)) + { + return NDIS_STATUS_RESET_IN_PROGRESS; + } + + acb->acb_lastringstate = NdisRingStateClosed; + acb->acb_state = AS_RESETTING; + acb->ResetState = RESET_STAGE_1; + + // + // Cancel the DPC Timer! + // + + NdisMCancelTimer(&acb->DpcTimer,&ReceiveResult); + + // + // Set the timer for the NetFlexResetHandler DPC. + // + NdisMSetTimer(&acb->ResetTimer,500 ); + + return NDIS_STATUS_PENDING; +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexResetHandler +// +// Description: +// Performs that operations to put the adatper +// through a reset and back into operation. +// +// +// Input: +// +// SystemSpecific1 - Not used. +// acb - The Adapter whose hardware is being reset. +// SystemSpecific2 - Not used. +// SystemSpecific3 - Not used. +// +// Output: +// None. +// +// Called By: +// via acb->ResetTimer +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +VOID +NetFlexResetHandler( + IN PVOID SystemSpecific1, + IN PACB acb, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3 + ) +{ + NDIS_STATUS Status; + BOOLEAN ReceiveResult; + BOOLEAN DoneWReset; + + // + // Cancel the reset timer + // + NdisMCancelTimer(&acb->ResetTimer,&ReceiveResult); + + do + { + DoneWReset = TRUE; // default to true... + + // + // Based on the current acb->ResetState, proceed with the reset. + // + switch(acb->ResetState) + { + + case RESET_STAGE_1: + + acb->ResetRetries = 0; + acb->InitRetries = 0; + + // + // Issue Close + // + NetFlexCloseAdapter(acb); + + // + // Remove all xmit mappings, and clean up queues + // + NetFlexRemoveRequests(acb); + acb->ResetState = RESET_STAGE_2; + + case RESET_STAGE_2: + + // + // Try soft resetting adapter + // + Status = NetFlexAdapterReset(acb,SOFT_RESET); + // + // Was the reset successful? + // + if (Status != NDIS_STATUS_SUCCESS) + { + // No! + // Increment the retry count + // + acb->ResetRetries++; + // + // have we tried 3 times? + // + if (acb->ResetRetries < 3 ) + { + // no, try it again in 10 sec + // + NdisMSetTimer(&acb->ResetTimer,10000 ); + } + else + { + // yes, try a hard reset + // + acb->ResetState = RESET_STAGE_3; + acb->ResetRetries = 0; + DoneWReset = FALSE; + } + break; + } + + // + // Yes, soft reset was successful, send open request... + // Note: When the Open request completes/fails + // we wind up in Reset_Stage_4. + // + acb->ResetState = RESET_STAGE_4; + acb->InitRetries++; + + NetFlexOpenAdapter(acb); + + // + // Give the Open 20 seconds to Complete + // + NdisMSetTimer(&acb->ResetTimer,20000); + break; + + case RESET_STAGE_3: + // + // Perform Hard Reset! + // + Status = NetFlexAdapterReset(acb,HARD_RESET); + // + // Was the reset successful? + // + if (Status != NDIS_STATUS_SUCCESS) + { + // No! + // Increment the retry count + // + acb->ResetRetries++; + // + // have we tried Hard Reset 3 times? + // + if (acb->ResetRetries < 3 ) + { + // no, try it again in 10 sec + // + acb->ResetState = RESET_STAGE_3; + NdisMSetTimer(&acb->ResetTimer,10000 ); + } + else + { + // Hard Reset timed out, do the reset indications. + // + DebugPrint(0,("NF(%d): Reset - Exceeded Hard Reset Retries\n",acb->anum)); + NetFlexDoResetIndications(acb,NDIS_STATUS_FAILURE); + } + break; + } + + // + // Yes, hard reset was successful, go do init stuff... + // + acb->ResetState = RESET_STAGE_4; + // + // Send Open Comand, when complete, we end up in Reset_Stage_4 + // + NetFlexOpenAdapter(acb); + // + // Give the Open 20 seconds to Complete + // + NdisMSetTimer(&acb->ResetTimer,20000); + break; + + case RESET_STAGE_4: + + // + // Increment the retry count + // + acb->InitRetries++; + + if (acb->acb_state != AS_OPENED) + { + // Have we expired the retry count, do the indications + // + if (acb->InitRetries > 4) + { + DebugPrint(0,("NF(%d): Reset - Exceeded Open Retries\n",acb->anum)); + + NetFlexDoResetIndications(acb,NDIS_STATUS_FAILURE); + } + else + { + // Perform a Soft Reset again! + // + acb->ResetState = RESET_STAGE_2; + DoneWReset = FALSE; + } + } + else + { + // We were successful! + // + NetFlexDoResetIndications(acb,NDIS_STATUS_SUCCESS); + } + break; + } + } while (!DoneWReset); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexDoResetIndications +// +// Description: +// This routine is called by NetFlexResetHandler to perform any +// indications which need to be done after a reset. Note that +// this routine will be called after either a successful reset +// or a failed reset. +// +// Input: +// acb - Our Driver Context. +// +// Output: +// Status - The status of the reset to send to the protocol(s). +// +// Called By: +// NetFlexResetHandler +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +VOID +NetFlexDoResetIndications( + IN PACB acb, + IN NDIS_STATUS Status + ) +{ + USHORT actl_reg; + // + // If we have a bad result, we stop the chip and do the indication + // back to the protocol(s). + // + if (Status != NDIS_STATUS_SUCCESS) + { + DebugPrint(0,("NF(%d): Reset failed!\n",acb->anum)); + + // + // Stop the chip + // + NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg)); + actl_reg |= ACTL_ARESET; + NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg); + + // + // Reset has failed, errorlog an entry if + // did not already send out a message. + // + if (!acb->ResetErrorLogged) + { + NdisWriteErrorLogEntry( acb->acb_handle, + EVENT_NDIS_RESET_FAILURE_ERROR, + 1, + NETFLEX_RESET_FAILURE_ERROR_CODE + ); + acb->ResetErrorLogged = TRUE; + } + + acb->ResetState = RESET_HALTED; + acb->acb_state = AS_CARDERROR; + Status = NDIS_STATUS_HARD_ERRORS; + + } + + // + // Verify that the dpc timer is set. + // + NdisMSetTimer(&acb->DpcTimer,10); + + NdisMResetComplete( acb->acb_handle, + Status, + TRUE ); + + // + // We are no longer resetting the Adapter. + // + + if (Status == NDIS_STATUS_SUCCESS) + { + acb->ResetState = 0; + + // + // Did we send out a message that a reset failed before? + // + if (acb->ResetErrorLogged) + { + // + // Log the fact that everything is ok now... + // + NdisWriteErrorLogEntry( acb->acb_handle, + EVENT_NDIS_RESET_FAILURE_CORRECTION, + 0); + + acb->ResetErrorLogged = FALSE; + } + else + { + if (acb->acb_lastringstatus & + ( NDIS_RING_SIGNAL_LOSS | + NDIS_RING_LOBE_WIRE_FAULT | + NDIS_RING_AUTO_REMOVAL_ERROR | + NDIS_RING_REMOVE_RECEIVED + )) + { + // + // Log the fact that we have reinserted in a TR MAU... + // + acb->SentRingStatusLog = FALSE; + acb->acb_lastringstatus = 0; + NdisWriteErrorLogEntry( acb->acb_handle, + EVENT_NDIS_TOKEN_RING_CORRECTION, + 0); + + } + } + } + + DebugPrint(1,("NF(%d): Reset Complete.\n",acb->anum)); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexCheckForHang +// +// Description: +// This function simply gets call once every two seconds to +// check on the head of the command block queue. +// It will fire off the queue if the head has been sleeping on +// the job. +// +// It also detects when the NetFlex adapter has failed, where the +// symptoms are that the adapter will transmit packets, but will +// not receive them. +// +// Input: acb - Our Driver Context. +// +// Output: True if we think the adapter is hung.. +// +// Called By: Miniport Wrapper +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +BOOLEAN +NetFlexCheckForHang( + IN NDIS_HANDLE MiniportAdapterContext + ) +{ + PXMIT xmitptr; + PMACREQ macreq; + PSCBREQ scbreq; + + PACB acb = (PACB) MiniportAdapterContext; + + // + // If we're run into a hard error, return true + // + + if (acb->acb_state == AS_HARDERROR) + { + return TRUE; + } + + // + // If we're not open return false + // + else if (acb->acb_state != AS_OPENED) + { + return FALSE; + } + + // + // Is there a command outstanding? + // + if (acb->acb_scbreq_head != NULL) + { + scbreq = acb->acb_scbreq_head; + macreq = scbreq->req_macreq; + + if (macreq != NULL) + { + // See if the command block has timed-out. + // + if (macreq->req_timeout) + { + // See if we have given it enough time + // + if ( macreq->req_timeoutcount >= 40) + { + DebugPrint(1,("NF(%d): CheckHang - Command Timed Out!\n",acb->anum)); + return TRUE; + } + else + { + macreq->req_timeoutcount++; + } + } + else + { + // Start testing this command to check timeout + // + macreq->req_timeout = TRUE; + macreq->req_timeoutcount = 0; + } + } + } + + if (acb->FullDuplexEnabled) + { + NdisAcquireSpinLock(&acb->XmitLock); + } + + // + // See if there is any xmits which have not been processed + // + if (acb->acb_xmit_ahead != NULL) + { + xmitptr = acb->acb_xmit_ahead; + + if (xmitptr->XMIT_Timeout) + { +#if DBG + if (xmitptr->XMIT_CSTAT & XCSTAT_COMPLETE) + { + DebugPrint(0,("NF(%d): CheckHang - Xmit Complete but Xmit Timed Out!\n",acb->anum)); + } + else + { + DebugPrint(0,("NF(%d): CheckHang - Xmit Timed Out!\n",acb->anum)); + } +#endif + + if (acb->FullDuplexEnabled) + { + NdisReleaseSpinLock(&acb->XmitLock); + } + + return TRUE; + } + xmitptr->XMIT_Timeout++; + } + + // + // If we are in full-duplex mode then that is the extent of our + // checking to see if we are hung. If we are in half-duplex mode + // then we might want to send a dummy packet to see if our receiver + // is working correctly.... + // + if (acb->FullDuplexEnabled) + { + NdisReleaseSpinLock(&acb->XmitLock); + } + + // + // Should we do extreme checking? + // + if (!acb->acb_parms->utd_extremecheckforhang) + { + return(FALSE); + } + + // + // Have we been getting interrupts? + // + if (acb->acb_int_count != 0) + { + // + // We got some, initialize the counts. + // + acb->acb_int_count = 0; + acb->acb_int_timeout = 0; + } + else + { + // + // Increment the timeout count. + // + acb->acb_int_timeout++; + + // + // We will do this 5 times before we reset. + // + if (5 == acb->acb_int_timeout) + { + // + // Clear our counts and request a reset. + // + acb->acb_int_timeout = 0; + acb->acb_int_count = 0; + + return(TRUE); + } + } + + // + // Not certain we're hung yet... + // + return FALSE; +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexOpenAdapter +// +// Description: +// This routine is called to queue up and issue +// an open command to the adapter. +// +// If the system is still in initialization, then +// the routine polls for the open command to complete, +// otherwise, the interrupt hander processes the complete +// and then returns to the reset handler for completion. +// +// Input: +// acb - Our Driver Context. +// +// Output: +// Success or Failure. +// +// Called By: +// NetFlexResetHandler, NetFlexBoardInitandReg +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +NDIS_STATUS +NetFlexOpenAdapter( + PACB acb + ) +{ + NDIS_STATUS Status; + PMACREQ macreq; + PSCBREQ scbreq; + ULONG Counter=0; + + // + // Open Adapter + // + acb->acb_state = AS_OPENING; + acb->acb_lastringstate = NdisRingStateOpening; + + // + // Are we doing an open for reset or during initialization? + // + if (!acb->AdapterInitializing) + { + // + // Get a free block. + // + Status = NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_scbreq_free), + (PVOID *)&scbreq); + + if (Status != NDIS_STATUS_SUCCESS) + { + DebugPrint(0,("NF(%d): Could not get an SCBREQ for the Open Command\n",acb->anum)); + return Status; + } + + acb->acb_opnblk_virtptr->OPEN_Options = acb->acb_openoptions; + scbreq->req_scb.SCB_Cmd = TMS_OPEN; + scbreq->req_scb.SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_opnblk_physptr))); + + Status = NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_macreq_free), + (PVOID *)¯eq); + if (Status != NDIS_STATUS_SUCCESS) + { + // We have no more room for another request currently + // + DebugPrint(0,("NF(%d): No macreq for the Open Command\n",acb->anum)); + // + // Put the SCBREQ back... + // + NetFlexEnqueue_OnePtrQ_Head((PVOID *)&acb->acb_scbreq_free,(PVOID)scbreq); + return Status; + } + + macreq->req_info = 0; + macreq->req_type = OPENADAPTER_CMP; + macreq->req_status = NDIS_STATUS_SUCCESS; + scbreq->req_macreq = macreq; + + NetFlexEnqueue_TwoPtrQ_Tail((PVOID *)&(acb->acb_macreq_head), + (PVOID *)&(acb->acb_macreq_tail), + (PVOID)macreq); + // + // Verify that interrupts are enabled! + // + NetFlexEnableInterrupt(acb); + + // + // Send the command out... + // + NetFlexQueueSCB(acb, scbreq); + + // + // Note: acb->ErrorCode will be set while processing the + // open command complete if there is an error. + // + } + else + { + // + // Open for Initialization + // + ULONG Counter = 0; + ULONG CounterTimeOut = 2000; // 2 seconds in miliseconds + USHORT sifint_reg; + + Status = NDIS_STATUS_FAILURE; + + // + // Make sure the command is clear, try for 2 seconds + // + while ((acb->acb_scb_virtptr->SCB_Cmd != 0) && (Counter++ < CounterTimeOut)) + NdisStallExecution((UINT)1000); + + if (Counter < CounterTimeOut) + { + // Get the command together... + // + acb->acb_opnblk_virtptr->OPEN_Options = acb->acb_openoptions; + acb->acb_scb_virtptr->SCB_Cmd = TMS_OPEN; + acb->acb_scb_virtptr->SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_opnblk_physptr))); + + // + // Make sure interrupts are disabled! + // + NetFlexDisableInterrupt(acb); + + // + // Send the SCB to the adapter. + // + NdisRawWritePortUshort(acb->SifIntPort, SIFINT_CMD); + + Counter = 0; + CounterTimeOut = 20000; // 20 seconds in miliseconds + + do + { + Counter++; + NdisStallExecution((UINT)1000); // 1 milisecond in microseconds + // + // Read the Sifint register. + // + NdisRawReadPortUshort( acb->SifIntPort, &sifint_reg); + + // + // Is there an interrupt pending? + // + if ((sifint_reg & SIFINT_SYSINT) && ((sifint_reg & INT_CODES) == INT_COMMAND)) + { + + // Ack the interrupt + // + sifint_reg &= ~SIFINT_SYSINT; + NdisRawWritePortUshort( acb->SifIntPort, sifint_reg); + + if (acb->acb_ssb_virtptr->SSB_Status == SSB_GOOD) + { + Status = NDIS_STATUS_SUCCESS; + } + else + { + DebugPrint(0,("NF(%d): Bad status %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Status)); + + if (acb->acb_ssb_virtptr->SSB_Status & SSB_OPENERR) // only Token Ring + { + Status = NDIS_STATUS_TOKEN_RING_OPEN_ERROR; + acb->acb_lastopenstat = NDIS_STATUS_TOKEN_RING_OPEN_ERROR; + } + else + { + acb->acb_lastopenstat = 0; + } + acb->acb_lastringstate = NdisRingStateOpenFailure; + } + // + // Issue a ssb clear. + // + NdisRawWritePortUshort( acb->SifIntPort, SIFINT_SSBCLEAR); + + break; + } + } while (Counter < CounterTimeOut); + } + + // + // Did it work? + // + if (Status == NDIS_STATUS_SUCCESS) + { + // Set State to Opened + // + acb->acb_state = AS_OPENED; + // + // Now lets finish the open by sending a receive command to the adapter. + // + acb->acb_rcv_whead = acb->acb_rcv_head; + + // + // Now lets finish the open by sending a + // transmit command to the adapter. + // + + acb->acb_xmit_whead = acb->acb_xmit_wtail = acb->acb_xmit_head; + + // + // Verify that interrupts are enabled! + // + NetFlexEnableInterrupt(acb); + + // + // If the adapter is ready for a command, call a + // routine that will kick off the transmit command. + // + if (acb->acb_scb_virtptr->SCB_Cmd == 0) + { + NetFlexSendNextSCB(acb); + } + else if (!acb->acb_scbclearout) + { + // Make sure we are interrupted when the SCB is + // available so that we can send the transmit command. + // + acb->acb_scbclearout = TRUE; + NdisRawWritePortUshort( acb->SifIntPort, (USHORT) SIFINT_SCBREQST); + } + } + else + { + // Set State back to Initialized since the open failed. + // + acb->acb_state = AS_INITIALIZED; + } + } + + return Status; +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexCloseAdapter +// +// Description: +// This routine is called to queue up and issue an close +// command to the adapter. +// +// Input: +// acb - Our Driver Context. +// +// Output: +// Success or Failure. +// +// Called By: +// NetFlexResetHandler +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +BOOLEAN +NetFlexCloseAdapter( + PACB acb) + +{ + USHORT Counter = 0; + USHORT CounterTimeOut = 500; + + if ((acb->acb_state == AS_OPENED) || + (acb->acb_state == AS_RESETTING)) + { + // + // Make sure the command is clear, try for 5 seconds + // + while ((acb->acb_scb_virtptr->SCB_Cmd != 0) && (Counter++ < CounterTimeOut)) { + + NdisStallExecution((UINT)1000); + } + + if (acb->acb_scb_virtptr->SCB_Cmd == 0) + { + // + // Send Close, + // + + acb->acb_scb_virtptr->SCB_Cmd = TMS_CLOSE; + NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_CMD); + + acb->acb_state = AS_CLOSING; + // + // Give it a little time... + // + NdisStallExecution((UINT)10000); + } + + return (Counter >= CounterTimeOut); + } + return TRUE; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexHalt +// +// Description: +// Removes an adapter previously initialized. +// +// Input: +// MacAdapterContext - Actually as pointer to an PACB. +// +// Output: +// None. +// +// Called By: +// Miniport Wrapper. +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +VOID +NetFlexHalt( + IN NDIS_HANDLE MiniportAdapterContext + ) +{ + USHORT actl_reg; + BOOLEAN ReceiveResult1; + BOOLEAN ReceiveResult2; + + // + // The adapter to halt + // + PACB acb = (PACB) MiniportAdapterContext; + + DebugPrint(1,("NF(%d): Halt Called!\n", acb->anum)); + + // + // Cancel all of our timers. + // + NdisMCancelTimer(&acb->DpcTimer, &ReceiveResult1); + NdisMCancelTimer(&acb->ResetTimer, &ReceiveResult2); + + // + // Is one of the timer dpc's going to fire? + // + if (!ReceiveResult1 || !ReceiveResult2) + { + NdisStallExecution(500000); + } + + // + // Send Close + // + NetFlexCloseAdapter(acb); + + // + // Stop Adapter + // + NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg)); + actl_reg |= ACTL_ARESET; + NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg); + + // + // Complete mappings + // + NetFlexRemoveRequests(acb); + + // + // Free adapter resources + // + NetFlexDeregisterAdapter(acb); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexShutdown +// +// Description: +// Removes an adapter previously initialized. +// +// Input: +// MacAdapterContext - Actually as pointer to an PACB. +// +// Output: +// None. +// +// Called By: +// Miniport Wrapper. +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +VOID +NetFlexShutdown( + IN NDIS_HANDLE MiniportAdapterContext + ) +{ + PACB acb = (PACB) MiniportAdapterContext; + USHORT actl_reg; + + // + // Send Close. + // + + NetFlexCloseAdapter(acb); + + // + // Stop Adapter + // + + NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg)); + actl_reg |= ACTL_ARESET; + NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg); +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexRemoveRequests +// +// Description: +// Clean up queues during a Reset and Halt +// +// Input: +// acb - Pointer to acb +// +// Output: +// None +// +// Called By: +// NetFlexResetHandler, +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +VOID +NetFlexRemoveRequests( + PACB acb + ) +{ + PXMIT xmitptr; + PRCV rcvptr; + UINT curmap; + PNDIS_PACKET packet; + PNDIS_BUFFER curbuf; + PMULTI_TABLE mt; + PETH_OBJS ethobjs; + USHORT i; + PSCBREQ scbreq; + PMACREQ macreq; + + // + // Terminate all the transmits on the active queue. + // + xmitptr = acb->acb_xmit_ahead; + + while (xmitptr != NULL) + { + // Did we use an internal buffer? + // + if (xmitptr->XMIT_OurBufferPtr != NULL) + { + // We've used one of our adapter buffers, so put the adapter + // buffer back on the free list. + // + if (xmitptr->XMIT_OurBufferPtr->BufferSize != acb->acb_smallbufsz) { + xmitptr->XMIT_OurBufferPtr->Next = acb->OurBuffersListHead; + acb->OurBuffersListHead = xmitptr->XMIT_OurBufferPtr; + } + else { // small buffer + xmitptr->XMIT_OurBufferPtr->Next = acb->SmallBuffersListHead; + acb->SmallBuffersListHead = xmitptr->XMIT_OurBufferPtr; + } + xmitptr->XMIT_OurBufferPtr = NULL; + } + else + { + packet = xmitptr->XMIT_Packet; + + if ( packet != NULL ) { + + curmap = xmitptr->XMIT_MapReg; + + // Complete mappings, but don't complete the sends... + // + + NdisQueryPacket( + packet, + NULL, + NULL, + (PNDIS_BUFFER *) &curbuf, + NULL + ); + + while (curbuf) + { + NdisMCompleteBufferPhysicalMapping( + acb->acb_handle, + (PNDIS_BUFFER) curbuf, + curmap + ); + + curmap++; + if (curmap == acb->acb_maxmaps) + { + curmap = 0; + } + + NdisGetNextBuffer(curbuf, &curbuf); + } + } + } + + xmitptr->XMIT_CSTAT = 0; + xmitptr->XMIT_Packet = NULL; + + // + // If we've reached the active queue tail, we are done. + // + if (xmitptr == acb->acb_xmit_atail) + xmitptr = NULL; + else + xmitptr = xmitptr->XMIT_Next; + } + + acb->acb_xmit_ahead = acb->acb_xmit_atail = NULL; + acb->acb_avail_xmit = acb->acb_parms->utd_maxtrans; + + // + // Clean up the Receive Lists + // + + rcvptr = acb->acb_rcv_head; + + do { + + // + // Mark receive list available + // + rcvptr->RCV_CSTAT = + ((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO; + + // + // Get next receive list + // + rcvptr = rcvptr->RCV_Next; + + } while (rcvptr != acb->acb_rcv_head); + + // + // Clean up multicast if ethernet. + // + if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3) + { + ethobjs = (PETH_OBJS)acb->acb_spec_objs; + + NdisZeroMemory( + ethobjs->MulticastEntries, + ethobjs->MaxMulticast * NET_ADDR_SIZE + ); + + ethobjs->NumberOfEntries = 0; + } + + // + // Clean up SCB Requests + // + while (acb->acb_scbreq_head) + { + NetFlexDequeue_TwoPtrQ_Head((PVOID *)&acb->acb_scbreq_head, + (PVOID *)&acb->acb_scbreq_tail, + (PVOID *)&scbreq); + + NdisZeroMemory(scbreq, sizeof(SCBREQ)); + + NetFlexEnqueue_OnePtrQ_Head((PVOID *)&acb->acb_scbreq_free,(PVOID)scbreq); + + } + + // + // Clean up MacReq Requests + // + while (acb->acb_macreq_head) + { + NetFlexDequeue_TwoPtrQ_Head((PVOID *)&acb->acb_macreq_head, + (PVOID *)&acb->acb_macreq_tail, + (PVOID *)¯eq); + + NdisZeroMemory(macreq, sizeof(MACREQ)); + + NetFlexEnqueue_OnePtrQ_Head( (PVOID *)&acb->acb_macreq_free, + (PVOID)macreq); + + } + + // + // Clean Up some more State stuff... + // + acb->RequestInProgress = FALSE; + acb->acb_scbclearout = FALSE; + acb->acb_scbreq_next = NULL; + acb->acb_gen_objs.cur_filter = 0; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexAdapterReset +// +// Description: +// This routine resets the Super Eagle or Eagle +// +// Input: +// mode - 0 = Hard Reset, ~0 = Soft Reset +// +// Output: +// status - NDIS_STATUS_SUCCESS if Success +// +// Called By: +// NetFlexResetHandler +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +NDIS_STATUS +NetFlexAdapterReset( + PACB acb, + INT mode) +{ + NDIS_STATUS status; + + // + // Which Reset? + // + if (mode == HARD_RESET) + { + + // Do the reset + // + NdisRawWritePortUshort(acb->SifActlPort, ACTL_HARD_RESET); + + // + // Wait 15 milliseconds to let the reset take place. + // + NdisStallExecution((UINT)15000); // Wait 15 milliseconds + + // + // Call NetFlexSetupNetType to verify everything gets set correctly. + // + NetFlexSetupNetType(acb); + + // + // Make sure that promiscuous mode is turned off + // + acb->acb_opnblk_virtptr->OPEN_Options &= SWAPS((USHORT) ~(OOPTS_CNMAC | OOPTS_CMAC)); + + // + // Download and initialize the adapter + // + if ((status = NetFlexDownload(acb)) == NDIS_STATUS_SUCCESS) + { + // Verify Bring Up Diagnostics + // + if ((status = NetFlexBudWait(acb))== NDIS_STATUS_SUCCESS) + { + // Initialize the adapter + // + if ((status = NetFlexInitializeAdapter(acb)) == NDIS_STATUS_SUCCESS) + { + // Yes, do we need to save the address that will give up our upstream address? + // + if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5) + { + // Yes, get it... + // + NetFlexGetUpstreamAddrPtr(acb); + } + } + } + } + + if (status != NDIS_STATUS_SUCCESS) + { + DebugPrint(0,("NF(%d): Hard Reset Failed!\n",acb->anum)); + } + } + else + { + // A Soft Reset was requested. Write the reset code into the + // SIF interrupt register. + // + NdisRawWritePortUshort(acb->SifIntPort, SIF_SOFT_RESET); + + // + // Write the saved ACTL Settings. + // + NdisRawWritePortUshort( acb->SifActlPort, acb->actl_reg); + + // + // Go check to see if the bring up diagnostics worked... + // + if ((status = NetFlexBudWait(acb)) == NDIS_STATUS_SUCCESS) + { + status = NetFlexInitializeAdapter(acb); + } + + if (status != NDIS_STATUS_SUCCESS) + { + DebugPrint(0,("NF(%d): Soft Reset Failed!\n",acb->anum)); + } + } + + return status; +} + + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexBudWait +// +// Description: +// This routine waits for the Bring Up Diags +// (BUD) code to finish on the Super Eagle or Eagle +// +// Input: +// acb - Our Driver Context. +// +// Output: +// status - 0 = SUCCESS, ~0 = failure +// +// Called By: +// NetFlexAdapterReset, NetFlexDownload +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +NDIS_STATUS +NetFlexBudWait( + PACB acb + ) +{ + int i; + USHORT value; + + // + // Wait for Bring Up Diagnotics to start. + // + for (i = 0; i < 3000; i++) + { + NdisStallExecution((UINT)1000); /* Wait 1 millisecond */ + NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) &value); + if ((value & 0x00f0) >= 0x0020) + break; + } + + if (i >= 3000) + { + // Diags never got started!! + // + DebugPrint(0,("NF(%d): Diags never got started\n",acb->anum)); + DebugPrint(0,("NF(%d): Sif int is 0x%x\n",acb->anum,value)); + return(NDIS_STATUS_FAILURE); + } + + // + // Wait for either success or failure. + // + for (i = 0; i < 3000; i++) + { + NdisStallExecution((UINT)1000); /* Wait 1 millisecond */ + NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) (&value)); + if ((value & 0x00f0) >= 0x0030) + break; + } + + if (i >= 3000) + { + // Diags never finished!! + // + DebugPrint(0,("NetFlex: Diags never finished\n")); + return(NDIS_STATUS_FAILURE); + } + + if ((value & 0x00f0) != 0x0040) + { + // Diags failed!! + // + DebugPrint(0,("NF(%d): Diags Failed!\n",acb->anum)); + return(NDIS_STATUS_FAILURE); + } + else + { + // The Diags passed OK! + // + DebugPrint(0,("NF(%d): Diags Passed OK\n",acb->anum)); + return(NDIS_STATUS_SUCCESS); + } +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexInitializeAdapter +// +// Description: +// This routine initializes the adapter for open. +// +// Input: +// acb - Our Driver Context +// +// Output: +// Returns a NDIS_STATUS_SUCCESS if the adapter +// initialized properly. Otherwise, an error code is returned, +// showing that an initialization error has occurred. +// +// Called By: +// NetFlexProcess_Open_Request +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +NDIS_STATUS +NetFlexInitializeAdapter( + PACB acb + ) +{ + ULONG temp; + INT i; + SHORT *ps; + + // + // Set the SIF address register to point to the INIT block location + // and copy the INIT block info into the data inc register. + // make sure we are at chapter 1. + // + NdisRawWritePortUshort(acb->SifAddrxPort, (USHORT) 1); + NdisRawWritePortUshort(acb->SifAddrPort, (USHORT) ADDR_INIT); + + for (i = 0, ps = (SHORT *) &acb->acb_initblk; + i < (SIZE_INIT / 2); i++, ps++) + { + NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) *ps); + } + + // + // Now write the SCB and SSB addresses into the + // data inc register. + // + temp = CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_scb_physptr) + sizeof(USHORT)); + NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) (temp >> 16)); + NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) temp); + + temp = CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_ssb_physptr)); + NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) (temp >> 16)); + NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) temp); + + // + // Now write the execute command out to the SIF. + // + NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_CMD); + + // + // Wait for the intialization to complete. + // + for (i = 0; i < 3000; i++) + { + NdisStallExecution((UINT)1000); /* Wait 1 millisecond */ + NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) (&temp)); + if ((temp & 0x00ff) != 0x0040) + break; + } + + if ( (i >= 3000) || ((temp & 0x00ff) != 0x0000) ) + { + // + // Initialization never finished!! OR Initialization failed!! + // + return(NDIS_STATUS_FAILURE); + + } + return(NDIS_STATUS_SUCCESS); +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexDownload +// +// Description: +// This routine downloads the TMS380 MAC code to the +// Super Eagle or Eagle. +// +// Input: +// acb - Our Driver Context. +// +// Output: +// status - 0 = SUCCESS, ~0 = failure +// +// Called By: +// NetFlexAdapterReset +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +NDIS_STATUS +NetFlexDownload( + PACB acb + ) +{ + LONG j; + USHORT temp_value; + LONG totalbytes; + PUSHORT MappedBuffer; + PDL_STRUCT ds; + PUCHAR dataptr; + + if (macgbls.DownloadCode == NULL) + { + DebugPrint(0,("NF(%d) - No Download code!\n",acb->anum)); + return NDIS_STATUS_FAILURE; + } + + // + // Get our pointers ready. Currently the MappedBuffer is pointing + // to the length of the header. The data begins after the header. + // Also the section headers are contained within the header just + // past the length field which is 2 bytes long. + // + + MappedBuffer = macgbls.DownloadCode; + + dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) ); + + ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2); + + // + // If we're using FPA skip to the second set of mac code. The + // order of the mac code is TOK, ETH, TOKFPA and ETHFPA. + // + if (acb->acb_usefpa) + { + for (j=0; j<2; j++) + { + totalbytes = 0; + while (ds->dl_chap != 0x7ffe) + { + totalbytes += ds->dl_bytes; + ds++; + } + + MappedBuffer = (PUSHORT)(dataptr + totalbytes); + + dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) ); + ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2); + } + } + + // + // No need to perform a hard reset of the Super Eagle or Eagle + // since we have already done. + // + if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3) + { + // + // We need to skip around the download code for Token Ring. + // Therefore, find the end of the token ring download code. + // + totalbytes = 0; + while (ds->dl_chap != 0x7ffe) + { + totalbytes += ds->dl_bytes; + ds++; + } + + MappedBuffer = (PUSHORT)(dataptr + totalbytes); + + dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) ); + ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2); + } + + // + // Download each section of data + // + while (ds->dl_chap != 0x7ffe) + { + NdisRawWritePortUshort( acb->SifAddrxPort, (USHORT) ds->dl_chap); + NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) ds->dl_addr); + + for (j = 0; j < (ds->dl_bytes / 2); j++) + { + NdisRawWritePortUshort( acb->SifDIncPort, + (USHORT)(SWAPS(*( (PUSHORT)(dataptr)))) ); + dataptr += 2; + } + ds++; + } + + // + // Now turn off the CP halt bit in the ACTL register to let the + // TMS380 chipset startup. Wait for the BUD to finish and report + // the appropriate status code. + // + NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&temp_value)); + + temp_value &= ~ACTL_CPHALT; + + NdisRawWritePortUshort( acb->SifActlPort, (USHORT) temp_value); + + // + // Save the Current Actl value + // + acb->actl_reg = temp_value; + + return NDIS_STATUS_SUCCESS; +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexSetupNetType +// +// Description: +// This routine sets up the Super Eagle to run the type of +// network and network speed requested by config. It assumes +// that the adapter is in a halted state after reset. +// +// Input: +// acb - Our Driver Context. +// +// Output: +// Returns NDIS_STATUS_SUCCESS for a successful +// completion. Otherwise, an error code is returned. +// +// Called By: +// NetFlexResetHandler, NetFlexBoardInitandReg +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +VOID +NetFlexSetupNetType( + PACB acb + ) +{ + USHORT cfg_reg, actl_reg; + USHORT cfg_reg2, tmp_reg; + UCHAR cfg_regl, cfg_regh; + NDIS_MEDIUM nettype; + ULONG netspeed; + USHORT board_id = acb->acb_boardid; + + // + // Get the network type and speed the user set up in EISA config. + // The port address for the cfg port is odd which will cause an + // alignment fault on RISC. + // + // NdisRawReadPortUshort(acb->AdapterConfigPort, &cfg_reg); + NdisRawReadPortUchar(acb->AdapterConfigPort, &cfg_regl); + NdisRawReadPortUchar(acb->AdapterConfigPort+1, &cfg_regh); + cfg_reg = (cfg_regh << 8) + cfg_regl; + + // + // Read the actl register and turn off the reset bit. + // + NdisRawReadPortUshort( acb->SifActlPort, &actl_reg); + + actl_reg &= ~ACTL_ARESET; + + // + // If we're using FPA turn on ROM reserved bit 11 + // + if (acb->acb_usefpa) + { + actl_reg |= ACTL_ROM; + } + + // + // If the board is a Cpqtok board, just fill in the parameters, + // reset the board, and get out. If the board is a Netflx board, + // fill in the parameters, reset the board specifying the type and + // speed of the network, make sure we get what we asked for, and + // then get out. + + if ( (board_id & NETFLEX_REVMASK) == CPQTOK_ID && + (board_id != DURANGO_ID)) + { + // This is a JUPITER board + // + DebugPrint(1,("NF(%d): Setting up Jupiter\n",acb->anum)); + + if (acb->AdapterInitializing) + { + nettype = NdisMedium802_5; + if (cfg_reg & CFG_16MBS) + netspeed = 4; + else + netspeed = 16; + // + // Setup the ProcessReceiveHandler + // + acb->ProcessReceiveHandler = &NetFlexProcessTrRcv; + } + } + else if ( ((board_id & NETFLEX_REVMASK) == NETFLEX_ID) || + ((board_id & NETFLEX_REVMASK) == RODAN_ID) || + (board_id == DURANGO_ID) ) + { + // + // This is a NETFLEX, MAPLE, DURANGO or RODAN board + // + // The Nselout1 bit has been redefined as the media bit. If this + // bit is set to a 1, AUI/DB-9 has been selected. Otherwise, + // unshielded has been selected. + // If the CFG_MEDIA bit is set, Unshielded has been selected. + + DebugPrint(1,("NF(%d): Setting up Netflx, Durango, or Rodan\n",acb->anum)); + + if (cfg_reg & CFG_MEDIA) + { + actl_reg &= (~ACTL_NSELOUT1); + } + else + { + actl_reg |= ACTL_NSELOUT1; + } + + if (cfg_reg & CFG_16MBS) + { + actl_reg |= ACTL_NSELOUT0; + } + else + { + actl_reg &= (~ACTL_NSELOUT0); + } + } + else + { + // This is a BONSAI board + // + // Bits 3 and 2 represent net type for head 1 and 2, respectively. + DebugPrint(1,("NF(%d): Setting up Bonsai head %d\n",acb->anum,acb->acb_portnumber)); + + if (acb->acb_portnumber == PORT1) + { + if (cfg_reg & CFG_DUALPT_ADP1) + { + actl_reg &= (~ACTL_NSELOUT1); + } + else + { + actl_reg |= ACTL_NSELOUT1; + } + } + else + { + if (cfg_reg & CFG_DUALPT_ADP2) + { + actl_reg &= (~ACTL_NSELOUT1); + } + else + { + actl_reg |= ACTL_NSELOUT1; + } + } + } + + NdisRawWritePortUshort(acb->SifActlPort, actl_reg); + + // + // If this is during an initial initialization + // + if (acb->AdapterInitializing) + { + // + // If this is a NETFLEX type board, make sure we got what + // we were asking for + // + if ( ( (board_id & NETFLEX_REVMASK) == NETFLEX_ID ) || + ( (board_id & NETFLEX_REVMASK) == BONSAI_ID ) || + ( (board_id & NETFLEX_REVMASK) == RODAN_ID ) || + (board_id == DURANGO_ID) ) + { + NdisRawReadPortUshort( acb->SifActlPort, &actl_reg); + // + // Now, find out our network type and speed. + // + if (actl_reg & ACTL_TEST1) + { + // + // We are token ring. Are we 16 mbps or 4 mbps. + // + nettype = NdisMedium802_5; + if (actl_reg & ACTL_TEST0) + netspeed = 4; + else + netspeed = 16; + + // + // Setup the ProcessReceiveHandler + // + acb->ProcessReceiveHandler = &NetFlexProcessTrRcv; + + } + else + { + // Ethernet is selected + nettype = NdisMedium802_3; + netspeed = 10; + // + // Setup the ProcessReceiveHandler + // + acb->ProcessReceiveHandler = &NetFlexProcessEthRcv; + } + } + // + // Initialize some of acb fields as well as adapter information. + // + acb->acb_gen_objs.media_type_in_use = nettype; + acb->acb_gen_objs.link_speed = netspeed; + } + else + { + nettype = acb->acb_gen_objs.media_type_in_use; + netspeed = acb->acb_gen_objs.link_speed; + } + + // + // Check Full Duplex Support... Ethernet Only! + // + if (nettype == NdisMedium802_3) + { + // Do we want Full Duplex? + // + + if (acb->acb_portnumber != PORT2) + { + NdisRawReadPortUchar( acb->BasePorts + CFG_REG2_OFF , &cfg_reg2); + if (cfg_reg2 & CFG_FULL_DUPLEX) + { + acb->FullDuplexEnabled = TRUE; + } + } + else + { + NdisRawReadPortUchar( acb->BasePorts + CFG_REG2_OFF - DUALHEAD_CFG_PORT_OFFSET, &cfg_reg2); + if (cfg_reg2 & CFG_FULL_DUPLEX_HEAD2) + { + acb->FullDuplexEnabled = TRUE; + } + } + + if (acb->FullDuplexEnabled) + { + DebugPrint(1,("NF(%d): Enabling FullDuplex Support!\n",acb->anum)); + if ( (board_id & NETFLEX_REVMASK) == BONSAI_ID ) + { + // On Bansai, disable colision detect by writing to 0xZc67 for H2 0xZc66 for H1 + // + if (acb->acb_portnumber == PORT2) + { + NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_HEAD2_OFF , 0xff); + } + else + { + NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_HEAD1_OFF , 0xff); + } + } + else + { + // On NetFlex/NetFlex-2, disable colision detect by writing to 0xZc65 + // until status indicates that it is ok, per Ray... + // + do + { + NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_OFF , 0xff); + NdisStallExecution((UINT)1000); // Wait 1 milliseconds + NdisRawReadPortUchar( acb->ExtConfigPorts + LOOP_BACK_STATUS_OFF , &tmp_reg); + } while (tmp_reg & COLL_DETECT_ENABLED); + } + } + } +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexFinishUnloading +// +// Description: This routine finishes the unloading process +// +// Input: None. +// +// Output: None. +// +// Calls: NdisDeregisterMac,NdisTerminateWrapper, +// +// Called By: NetFlexUnload, NetFlexDeregisterAdapter +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +VOID NetFlexFinishUnloading(VOID) +{ + // + // + // Free the memory with the download software in it. + // + if (macgbls.DownloadCode != NULL) { + + NdisFreeMemory( macgbls.DownloadCode, + macgbls.DownloadLength, + 0); + + } + + NdisTerminateWrapper(macgbls.mac_wrapper,(PVOID)NULL); + macgbls.mac_wrapper = NULL; + macgbls.DownloadCode= NULL; + macgbls.DownloadLength = 0; +} + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Routine Name: NetFlexDeregisterAdapter +// +// Description: +// This routine finishes the removal of an adapter. +// +// Input: +// acb - Our Driver Context. +// +// Output: +// None. +// +// Called By: +// NetFlexHalt, NetFlexInitialize +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +VOID NetFlexDeregisterAdapter(PACB acb) +{ + // + // Remove the acb from the mac's acb list + // + NetFlexDequeue_OnePtrQ((PVOID *) &macgbls.mac_adapters,(PVOID)acb); + + if (acb->acb_interrupt.InterruptObject != NULL) + NdisMDeregisterInterrupt(&acb->acb_interrupt); + + // + // Deallocate the memory for the acb. + // + NetFlexDeallocateAcb(acb); + + if ((macgbls.mac_adapters == NULL) && !macgbls.Initializing) + { + NetFlexFinishUnloading(); + } +} + |