652 lines
14 KiB
C
652 lines
14 KiB
C
/*++
|
|
|
|
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;
|
|
}
|
|
|