|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
ltreq.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 LTREQ_H_LOCALS
#include "ltmain.h"
#include "ltreq.h"
// Define file id for errorlogging
#define FILENUM LTREQ
NDIS_STATUS LtRequest( IN NDIS_HANDLE MacBindingHandle, IN PNDIS_REQUEST NdisRequest ) /*++
Routine Description:
called by NDIS to query or set card/driver information on a binding
Arguments:
MacBindingHandle : the binding submitting the request NdisRequest : the request we've been asked to satisfy
Return Values:
NDIS_STATUS_SUCCESS : if completed successfully NDIS_STATUS_RESET_IN_PROGRESS : if the adapter's in the middle of a reset NDIS_STATUS_ADAPTER_REMOVED : if the adapter's been closed NDIS_STATUS_CLOSING : if the binding is closing down NDIS_STATUS_NOT_SUPPORTED : if we do not support the requested action
--*/ { NDIS_STATUS Status; PLT_ADAPTER Adapter = ((PLT_OPEN)MacBindingHandle)->LtAdapter; PLT_OPEN Open = (PLT_OPEN)MacBindingHandle;
if (Adapter->Flags & ADAPTER_RESET_IN_PROGRESS) { return(NDIS_STATUS_RESET_IN_PROGRESS); }
switch (NdisRequest->RequestType) { case NdisRequestSetInformation: case NdisRequestQueryInformation:
// increment count since we'll be in the binding with the request
LtReferenceBinding(Open,&Status); if (Status == NDIS_STATUS_SUCCESS) { if (NdisRequest->RequestType == NdisRequestSetInformation) { Status = LtReqSetInformation( Adapter, Open, NdisRequest->DATA.SET_INFORMATION.Oid, NdisRequest->DATA.SET_INFORMATION.InformationBuffer, NdisRequest->DATA.SET_INFORMATION.InformationBufferLength, &(NdisRequest->DATA.SET_INFORMATION.BytesRead), &(NdisRequest->DATA.SET_INFORMATION.BytesNeeded)); } else { Status = LtReqQueryInformation( Adapter, Open, NdisRequest->DATA.QUERY_INFORMATION.Oid, NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength, &(NdisRequest->DATA.QUERY_INFORMATION.BytesWritten), &(NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded), FALSE); }
// completed the request for the binding; outa there
LtDeReferenceBinding(Open); }
break;
default: // Unkown request
Status = NDIS_STATUS_NOT_SUPPORTED; break;
}
return(Status); }
NDIS_STATUS LtReqQueryGlobalStatistics( IN NDIS_HANDLE MacAdapterContext, IN PNDIS_REQUEST NdisRequest ) /*++
Routine Description:
called by NDIS to query or set global card/driver information
Arguments:
MacAdapterContext : the adapter the request is submitted on NdisRequest : the request we've been asked to satisfy
Return Values:
NDIS_STATUS_SUCCESS : if completed successfully NDIS_STATUS_RESET_IN_PROGRESS : if the adapter's in the middle of a reset NDIS_STATUS_ADAPTER_REMOVED : if the adapter's been closed NDIS_STATUS_CLOSING : if the binding is closing down NDIS_STATUS_NOT_SUPPORTED : if we do not support the requested action
--*/ { NDIS_STATUS Status; PLT_ADAPTER Adapter = MacAdapterContext;
if (Adapter->Flags & ADAPTER_RESET_IN_PROGRESS) { return(NDIS_STATUS_RESET_IN_PROGRESS); }
switch (NdisRequest->RequestType) { case NdisRequestQueryStatistics:
LtReferenceAdapter(Adapter,&Status); if (Status != NDIS_STATUS_SUCCESS) break;
Status = LtReqQueryInformation( Adapter, NULL, NdisRequest->DATA.QUERY_INFORMATION.Oid, NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength, &(NdisRequest->DATA.QUERY_INFORMATION.BytesWritten), &(NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded), TRUE);
LtDeReferenceAdapter(Adapter); break;
default:
Status = NDIS_STATUS_NOT_SUPPORTED; break; }
return(Status); }
STATIC NDIS_STATUS LtReqSetInformation( IN PLT_ADAPTER Adapter, IN PLT_OPEN Open, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN INT InformationBufferLength, IN PUINT BytesRead, IN PUINT BytesNeeded ) /*++
Routine Description:
performs a set operation for a single OID.
Arguments:
Adapter : The adapter that the set is for Open : The binding that the set is for Oid : The OID to set InformationBuffer : Holds the data to be set InformationBufferLength : The length of InformationBuffer BytesRead : If the call is successful, returns the number of bytes read from InformationBuffer BytesNeeded : If there is not enough data in InformationBuffer to satisfy the request, returns the amount of storage needed.
Return Value:
NDIS_STATUS_SUCCESS : if successful NDIS_STATUS_INVALID_OID : if the oid is not supported NDIS_STATUS_INVALID_DATA : if InformationBuffer contains bad data NDIS_STATUS_INVALID_LENGTH : if the InformationBufferLength is incorrect
--*/ {
ULONG PacketFilter, NewLookAhead; NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
//
// Now check for the most common OIDs
//
DBGPRINT(DBG_COMP_REQ,DBG_LEVEL_INFO, ("LtReqSetInformation: setting OID - 0x%.8lx\n", Oid));
switch (Oid) { case OID_GEN_CURRENT_PACKET_FILTER:
// Localtalk only supports Directed and broadcast packets.
// And the Lt firmware does not support PROMISCUSOUS mode.
// so return NDIS_STATUS_NOT_SUPPORTED for these packet filters.
if (InformationBufferLength != 4) { StatusToReturn = NDIS_STATUS_INVALID_LENGTH; break;
}
NdisMoveMemory( (PVOID)&PacketFilter, InformationBuffer, sizeof(ULONG));
DBGPRINT(DBG_COMP_REQ,DBG_LEVEL_INFO, ("LtReqSetInformation: Requested packet filter is %x\n", PacketFilter));
if (PacketFilter == NDIS_PACKET_TYPE_BROADCAST || PacketFilter == NDIS_PACKET_TYPE_DIRECTED || PacketFilter == (NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED)) { NdisAcquireSpinLock(&Adapter->Lock); Adapter->GlobalPacketFilter |= PacketFilter; Open->CurrentPacketFilter = PacketFilter; NdisReleaseSpinLock(&Adapter->Lock); *BytesRead = InformationBufferLength;
} else { StatusToReturn = NDIS_STATUS_INVALID_DATA; }
break;
case OID_GEN_CURRENT_LOOKAHEAD:
if (InformationBufferLength != 4) { StatusToReturn = NDIS_STATUS_INVALID_LENGTH; break;
}
NdisMoveMemory( (PVOID)&NewLookAhead, InformationBuffer, sizeof(ULONG));
DBGPRINT(DBG_COMP_REQ,DBG_LEVEL_INFO, ("LtReqSetInformation: Requested Lookahead size is %d\n", NewLookAhead));
if ((NewLookAhead > LT_MAX_INDICATE_SIZE) || (NewLookAhead < LT_MIN_INDICATE_SIZE)) { StatusToReturn = NDIS_STATUS_INVALID_DATA; break;
}
NdisAcquireSpinLock(&Adapter->Lock); // valid lookahead size, so set it
Open->CurrentLookAheadSize = NewLookAhead;
// adjust the global lookaheadsize
if (Adapter->GlobalLookAheadSize < NewLookAhead) { Adapter->GlobalLookAheadSize = NewLookAhead; } else { LtReqAdjustLookAhead( &Adapter->GlobalLookAheadSize, &Adapter->OpenBindings); } NdisReleaseSpinLock(&Adapter->Lock); *BytesRead = 4; break;
default:
StatusToReturn = NDIS_STATUS_INVALID_OID; break; }
return(StatusToReturn); }
LtReqQueryInformation( IN PLT_ADAPTER Adapter, IN PLT_OPEN Open, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN INT InformationBufferLength, IN PUINT BytesWritten, IN PUINT BytesNeeded, IN BOOLEAN Global ) /*++
Routine Description:
performs a query operation for a single OID.
Arguments:
Adapter : The adapter that the query is for Open : The binding that the query is for Oid : The OID to query InformationBuffer : Holds the result of the query. InformationBufferLength : The length of InformationBuffer. BytesWritten : If the call is successful, returns the number of bytes written to InformationBuffer BytesNeeded : If there is not enough room in InformationBuffer to satisfy the request, returns the amount of storage needed Global : TRUE if the request originated from the adapter. FALSE if the request came from a binding
Return Value:
NDIS_STATUS_SUCCESS : if successful NDIS_STATUS_INVALID_OID : if the query is on an OID we do not support NDIS_STATUS_BUFFER_TOO_SHORT: if InformationBufferLength is too small to hold the information returned
--*/ {
UINT OidIndex; ULONG GenericUlong; USHORT GenericUshort; PVOID SourceBuffer = &GenericUlong; UINT SourceBufferLength = sizeof(ULONG); PNDIS_OID SupportedOidArray = LtProtocolSupportedOids; UINT SupportedOids = (sizeof(LtProtocolSupportedOids)/sizeof(ULONG)); static UCHAR VendorDescription[] = LT_VENDOR_DESCR; static UCHAR VendorId[3] = LT_VENDOR_ID;
if (Global) { SupportedOidArray = LtGlobalSupportedOids; SupportedOids = sizeof(LtGlobalSupportedOids)/sizeof(ULONG); }
//
// Check that the OID is valid.
//
for (OidIndex=0; OidIndex < SupportedOids; OidIndex++) { if (Oid == SupportedOidArray[OidIndex]) { break; } }
if (OidIndex == SupportedOids) { *BytesWritten = 0; return(NDIS_STATUS_INVALID_OID); }
switch (Oid) { case OID_GEN_SUPPORTED_LIST:
SourceBuffer = SupportedOidArray; SourceBufferLength = SupportedOids * sizeof(ULONG); break;
case OID_GEN_HARDWARE_STATUS:
GenericUlong = NdisHardwareStatusReady; if (Adapter->Flags & ADAPTER_RESET_IN_PROGRESS) { GenericUlong = NdisHardwareStatusReset; } break;
case OID_GEN_MEDIA_SUPPORTED:
GenericUlong = NdisMediumLocalTalk; break;
case OID_GEN_MEDIA_IN_USE:
GenericUlong = NdisMediumLocalTalk; // if no binding exists then media is not in use
if (Global && Adapter->OpenCount == 0) { SourceBufferLength = 0; } break;
case OID_GEN_MAXIMUM_LOOKAHEAD:
GenericUlong = LT_MAX_INDICATE_SIZE; break;
case OID_GEN_MAXIMUM_FRAME_SIZE:
GenericUlong = LT_MAXIMUM_PACKET_SIZE; break;
case OID_GEN_LINK_SPEED:
GenericUlong = LT_LINK_SPEED; break;
case OID_GEN_TRANSMIT_BUFFER_SPACE:
GenericUlong = LT_MAXIMUM_PACKET_SIZE; break;
case OID_GEN_RECEIVE_BUFFER_SPACE:
// BUGBUG: need to determine number of recv buffers or in this case the
// amount of space for receives
GenericUlong = LT_MAXIMUM_PACKET_SIZE * 5; break;
case OID_GEN_TRANSMIT_BLOCK_SIZE:
GenericUlong = 1; break;
case OID_GEN_RECEIVE_BLOCK_SIZE:
// BUGBUG: need to determine number of recv buffers
GenericUlong = 5; break;
case OID_GEN_VENDOR_ID:
SourceBuffer = VendorId; SourceBufferLength = sizeof(VendorId); break;
case OID_GEN_VENDOR_DESCRIPTION:
SourceBuffer = VendorDescription; SourceBufferLength = sizeof(VendorDescription); break;
case OID_GEN_CURRENT_PACKET_FILTER:
GenericUlong = Open->CurrentPacketFilter; if (Global) { GenericUlong = Adapter->GlobalPacketFilter; } break;
case OID_GEN_CURRENT_LOOKAHEAD:
GenericUlong = Open->CurrentLookAheadSize; if (Global) { GenericUlong = Adapter->GlobalLookAheadSize; } break;
case OID_GEN_DRIVER_VERSION:
GenericUshort = (LT_MAJOR_VERSION << 8) + LT_MINOR_VERSION; SourceBuffer = &GenericUshort; SourceBufferLength = sizeof(USHORT); break;
case OID_GEN_MAXIMUM_TOTAL_SIZE:
GenericUlong = LT_MAXIMUM_PACKET_SIZE; break;
case OID_GEN_XMIT_OK: case OID_GEN_RCV_OK: case OID_GEN_XMIT_ERROR: case OID_GEN_RCV_ERROR: case OID_GEN_RCV_NO_BUFFER:
OidIndex = (Oid & LT_OID_INDEX_MASK) - 1; ASSERT(OidIndex < GM_ARRAY_SIZE); GenericUlong = Adapter->GeneralMandatory[OidIndex]; break;
case OID_GEN_DIRECTED_BYTES_XMIT: case OID_GEN_BROADCAST_BYTES_XMIT: case OID_GEN_DIRECTED_BYTES_RCV: case OID_GEN_BROADCAST_BYTES_RCV:
OidIndex = (Oid & LT_OID_INDEX_MASK) - 1; ASSERT(OidIndex < GM_ARRAY_SIZE); SourceBuffer = &Adapter->GeneralOptionalByteCount[OidIndex / 2]; SourceBufferLength = sizeof(LARGE_INTEGER); break;
case OID_GEN_DIRECTED_FRAMES_XMIT: case OID_GEN_BROADCAST_FRAMES_XMIT: case OID_GEN_DIRECTED_FRAMES_RCV: case OID_GEN_BROADCAST_FRAMES_RCV:
OidIndex = (Oid & LT_OID_INDEX_MASK) - 1; ASSERT(OidIndex < GO_COUNT_ARRAY_SIZE); GenericUlong = Adapter->GeneralOptionalFrameCount[OidIndex / 2]; break;
case OID_GEN_RCV_CRC_ERROR: case OID_GEN_TRANSMIT_QUEUE_LENGTH:
OidIndex = (Oid & LT_OID_INDEX_MASK) - 1; ASSERT(OidIndex < GO_ARRAY_SIZE); GenericUlong = Adapter->GeneralOptional[OidIndex - GO_ARRAY_START]; break;
case OID_GEN_MAC_OPTIONS:
GenericUlong = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA; break;
case OID_LTALK_CURRENT_NODE_ID:
SourceBuffer = &GenericUshort; GenericUshort = Adapter->NodeId; SourceBufferLength = 2; break;
case OID_LTALK_IN_BROADCASTS: case OID_LTALK_IN_LENGTH_ERRORS:
OidIndex = (Oid & LT_OID_INDEX_MASK) - 1; ASSERT (OidIndex < MM_ARRAY_SIZE); GenericUlong = Adapter->MediaMandatory[OidIndex]; break;
case OID_LTALK_OUT_NO_HANDLERS: case OID_LTALK_DEFERS:
OidIndex = (Oid & LT_OID_INDEX_MASK) - 1; ASSERT (OidIndex < MO_ARRAY_SIZE); GenericUlong = Adapter->MediaOptional[OidIndex]; break;
default:
// should never get here
ASSERT(FALSE); break; }
if ((INT)SourceBufferLength > InformationBufferLength) { *BytesNeeded = SourceBufferLength; return(NDIS_STATUS_BUFFER_TOO_SHORT); }
NdisMoveMemory( InformationBuffer, SourceBuffer, SourceBufferLength);
*BytesWritten = SourceBufferLength;
return(NDIS_STATUS_SUCCESS); }
STATIC VOID LtReqAdjustLookAhead( OUT PUINT GlobalLookAheadSize, IN PLIST_ENTRY OpenBindings ) /*++
Routine Description:
called by LtReqSetInformation to adjust the global lookahead size when the previously largest lookahead size (on a binding) is adjusted
THIS ROUTINE IS CALLED WITH THE SPINLOCK HELD
Arguments:
GlobalLookAheadSize : the global lookahead param we're adjusting OpenBindings : the list of bindings we need to traverse
Return Value:
none
--*/ { PLT_OPEN Binding; PLIST_ENTRY p = OpenBindings->Flink; UINT MaxLookAheadSize = 0;
while(p != OpenBindings) { Binding = CONTAINING_RECORD( p, LT_OPEN, Linkage);
if (Binding->CurrentLookAheadSize > MaxLookAheadSize) { MaxLookAheadSize = Binding->CurrentLookAheadSize; } p = p->Flink; } *GlobalLookAheadSize = MaxLookAheadSize; }
|