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