/*++ Copyright (c) 1992 Microsoft Corporation Module Name: ltreset.c Abstract: This module contains Author: Nikhil Kamkolkar (nikhilk@microsoft.com) Stephen Hou (stephh@microsoft.com) Revision History: 19 Jun 1992 Initial Version (dch@pacvax.pacersoft.com) Notes: Tab stop: 4 --*/ #define LTRESET_H_LOCALS #include "ltmain.h" #include "ltreset.h" #include "ltfirm.h" #include "lttimer.h" // Define file id for errorlogging #define FILENUM LTRESET NDIS_STATUS LtReset( IN NDIS_HANDLE MacBindingHandle ) /*++ Routine Description: called by NDIS to reset the adapter Arguments: MacBindingHandle : context passed back in OpenAdapter Return Value: NDIS_STATUS_PENDING : if the reset successfully pended and waiting to be completed NDIS_STATUS_RESET_IN_PROGRESS : if the adapter is current being reset NDIS_STATUS_ADAPTER_REMOVED : if the adapter has been closed NDIS_STATUS_CLOSING : if the binding request the reset is closing --*/ { NDIS_STATUS Status; BOOLEAN TimerCancelled = FALSE; PLT_ADAPTER Adapter = ((PLT_OPEN)MacBindingHandle)->LtAdapter; PLT_OPEN Open = (PLT_OPEN)MacBindingHandle; LtReferenceBinding(Open,&Status); if (Status == NDIS_STATUS_SUCCESS) { if (Adapter->Flags & ADAPTER_RESET_IN_PROGRESS) { Status = NDIS_STATUS_RESET_IN_PROGRESS; } if (Adapter->Flags & ADAPTER_CLOSING) { Status = NDIS_STATUS_ADAPTER_REMOVED; } if (Open->Flags & BINDING_CLOSING) { Status = NDIS_STATUS_CLOSING; } } if (Status != NDIS_STATUS_SUCCESS) { LtDeReferenceBinding(Open); return(Status); } // kill the timer so we don't get any conflicts when trying to reset the card NdisCancelTimer(&Adapter->PollingTimer, &TimerCancelled); if (TimerCancelled) { LtDeReferenceAdapter(Adapter); } // indicate the start of the reset to all bindings LtResetSignalBindings( Adapter, NDIS_STATUS_RESET_START); NdisAcquireSpinLock(&Adapter->Lock); // set the reset in progress flag Adapter->Flags ^= ADAPTER_RESET_IN_PROGRESS; Adapter->ResetOwner = Open; NdisReleaseSpinLock(&Adapter->Lock); LtResetSetupForReset(Adapter); // intstantiate the reference for the timer // too late to do anything other than return // success since the reset's done. no problem // as long as the adapter can't close while the // reset is in progress. LtReferenceAdapter(Adapter,&Status); // card's essentially reset, restart the timer NdisSetTimer(&Adapter->PollingTimer, LT_POLLING_TIME); return(NDIS_STATUS_PENDING); } VOID LtResetComplete( PLT_ADAPTER Adapter ) /*++ Routine Description: completes the pending reset Arguments: Adapter : pointer to the logical adapter Return Value: none --*/ { NdisAcquireSpinLock(&Adapter->Lock); // flip the reset in progress flags Adapter->Flags ^= ADAPTER_RESET_IN_PROGRESS; NdisReleaseSpinLock(&Adapter->Lock); LtResetSignalBindings( Adapter, NDIS_STATUS_RESET_END); NdisCompleteReset( (Adapter->ResetOwner)->NdisBindingContext, NDIS_STATUS_SUCCESS); LtDeReferenceBinding(Adapter->ResetOwner); } STATIC VOID LtResetSetupForReset( IN PLT_ADAPTER Adapter ) /*++ Routine Description: Kills off anything in the transmit, receive and loopback queues and returns the appropriate status. It then resets the card and acquires a new NodeId Arguments: Adapter : pointer to the logical adapter Return Value: none --*/ { PLIST_ENTRY CurrentPacketLink; PLT_PACKET_RESERVED PacketReserved; PRECV_DESC RecvDesc; UINT PacketLength; PNDIS_PACKET Packet; PLT_OPEN Open; NdisAcquireSpinLock(&Adapter->Lock); // remove everything from the receive list and return it to the free list while(!IsListEmpty(&Adapter->Receive)){ CurrentPacketLink = RemoveHeadList(&Adapter->Receive); RecvDesc = CONTAINING_RECORD( CurrentPacketLink, RECV_DESC, Linkage); PacketLength = RecvDesc->BufferLength; NdisFreeMemory( RecvDesc, sizeof(RecvDesc)+PacketLength, 0); } // complete any pending transmits while(!IsListEmpty(&Adapter->Transmit)) { CurrentPacketLink = RemoveHeadList(&Adapter->Transmit); PacketReserved = CONTAINING_RECORD( CurrentPacketLink, LT_PACKET_RESERVED, Linkage); Packet = CONTAINING_RECORD( PacketReserved, NDIS_PACKET, MacReserved); Open = PacketReserved->MacBindingHandle; NdisReleaseSpinLock(&Adapter->Lock); NdisCompleteSend( Open->NdisBindingContext, Packet, NDIS_STATUS_REQUEST_ABORTED); // decrement the count instantiated by the send LtDeReferenceBinding(Open); LtDeReferenceAdapter(Adapter); NdisAcquireSpinLock(&Adapter->Lock); } // complete anything on the loopback queue while(!IsListEmpty(&Adapter->LoopBack)) { CurrentPacketLink = RemoveHeadList(&Adapter->LoopBack); PacketReserved = CONTAINING_RECORD( CurrentPacketLink, LT_PACKET_RESERVED, Linkage); Packet = CONTAINING_RECORD( PacketReserved, NDIS_PACKET, MacReserved); Open = PacketReserved->MacBindingHandle; NdisReleaseSpinLock(&Adapter->Lock); NdisCompleteSend( Open->NdisBindingContext, Packet, NDIS_STATUS_REQUEST_ABORTED); // decrement the count instantiated by the send LtDeReferenceBinding(Open); LtDeReferenceAdapter(Adapter); NdisAcquireSpinLock(&Adapter->Lock); } NdisReleaseSpinLock(&Adapter->Lock); LtFirmInitialize(Adapter, Adapter->NodeId); } STATIC VOID LtResetSignalBindings( PLT_ADAPTER Adapter, NDIS_STATUS StatusToSignal ) /*++ Routine Description: Loops through all bindings and indicates the status passed Arguments: Adapter : pointer to the logical adapter StatusToSignal : status to indicate to all bindings associated with the adapter Return Value: none --*/ { PLT_OPEN Open; PLIST_ENTRY CurrentLink; NDIS_STATUS Status; CurrentLink = Adapter->OpenBindings.Flink; while (CurrentLink != &Adapter->OpenBindings) { Open = CONTAINING_RECORD( CurrentLink, LT_OPEN, Linkage ); // skip the binding if it's closing if (Open->Flags & BINDING_CLOSING) { CurrentLink = CurrentLink->Flink; continue; } // increment the reference count while in the binding // only return we can get back is that the binding is // closing down, but this isn't a problem since we won't // reach this statement if that's true because of the prior // statements LtReferenceBinding(Open,&Status); NdisIndicateStatus( Open->NdisBindingContext, StatusToSignal, 0, 0); // decrement refcount now that we've finished with that binding LtDeReferenceBinding(Open); CurrentLink = CurrentLink->Flink; } }