891 lines
20 KiB
C
891 lines
20 KiB
C
/*++
|
||
|
||
Copyright (c) 1990-1992 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
request.c
|
||
|
||
Abstract:
|
||
|
||
This is the cose to handle requests for the National Semiconductor
|
||
SONIC Ethernet controller. This driver conforms to the NDIS 3.0
|
||
miniport interface.
|
||
|
||
Author:
|
||
|
||
Adam Barr (adamba) 14-Nov-1990
|
||
|
||
Environment:
|
||
|
||
Kernel Mode - Or whatever is the equivalent.
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include <ndis.h>
|
||
|
||
#include <sonichrd.h>
|
||
#include <sonicsft.h>
|
||
|
||
|
||
|
||
//
|
||
// This macro determines if the directed address
|
||
// filtering in the CAM is actually necessary given
|
||
// the current filter.
|
||
//
|
||
|
||
#define CAM_DIRECTED_SIGNIFICANT(_Filter) \
|
||
((((_Filter) & NDIS_PACKET_TYPE_DIRECTED) && \
|
||
(!((_Filter) & NDIS_PACKET_TYPE_PROMISCUOUS))) ? 1 : 0)
|
||
|
||
|
||
//
|
||
// This macro determines if the multicast filtering in
|
||
// the CAM are actually necessary given the current filter.
|
||
//
|
||
|
||
#define CAM_MULTICAST_SIGNIFICANT(_Filter) \
|
||
((((_Filter) & NDIS_PACKET_TYPE_MULTICAST) && \
|
||
(!((_Filter) & (NDIS_PACKET_TYPE_ALL_MULTICAST | \
|
||
NDIS_PACKET_TYPE_PROMISCUOUS)))) ? 1 : 0)
|
||
|
||
|
||
STATIC
|
||
NDIS_STATUS
|
||
ChangeClassDispatch(
|
||
IN PSONIC_ADAPTER Adapter,
|
||
IN UINT NewFilterClasses
|
||
);
|
||
|
||
STATIC
|
||
NDIS_STATUS
|
||
ChangeAddressDispatch(
|
||
IN PSONIC_ADAPTER Adapter,
|
||
IN UINT AddressCount,
|
||
IN CHAR Addresses[][ETH_LENGTH_OF_ADDRESS]
|
||
);
|
||
|
||
|
||
|
||
|
||
extern
|
||
NDIS_STATUS
|
||
SonicQueryInformation(
|
||
IN NDIS_HANDLE MiniportAdapterContext,
|
||
IN NDIS_OID Oid,
|
||
IN PVOID InformationBuffer,
|
||
IN ULONG InformationBufferLength,
|
||
OUT PULONG BytesWritten,
|
||
OUT PULONG BytesNeeded
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
SonicQueryInformation handles a query operation for a
|
||
single OID.
|
||
|
||
Arguments:
|
||
|
||
MiniportAdapterContext - Context registered with the wrapper, really
|
||
a pointer to the adapter.
|
||
|
||
Oid - The OID of the 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 OID, returns the amount of storage needed.
|
||
|
||
Return Value:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_PENDING
|
||
NDIS_STATUS_INVALID_LENGTH
|
||
NDIS_STATUS_INVALID_OID
|
||
|
||
--*/
|
||
|
||
{
|
||
PSONIC_ADAPTER Adapter = PSONIC_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
|
||
INT i;
|
||
INT SupportedOids;
|
||
NDIS_OID MaskOid;
|
||
PVOID SourceBuffer;
|
||
ULONG SourceBufferLength;
|
||
ULONG GenericUlong;
|
||
USHORT GenericUshort;
|
||
UCHAR VendorId[4];
|
||
#ifdef SONIC_EISA
|
||
static const UCHAR EisaDescriptor[] = "SONIC EISA Bus Master Ethernet Adapter (DP83932EB-EISA)";
|
||
#endif
|
||
#ifdef SONIC_INTERNAL
|
||
static const UCHAR InternalDescriptor[] = "MIPS R4000 on-board network controller";
|
||
#endif
|
||
|
||
static const NDIS_OID SonicSupportedOids[] = {
|
||
OID_GEN_SUPPORTED_LIST,
|
||
OID_GEN_HARDWARE_STATUS,
|
||
OID_GEN_MEDIA_SUPPORTED,
|
||
OID_GEN_MEDIA_IN_USE,
|
||
OID_GEN_MAXIMUM_LOOKAHEAD,
|
||
OID_GEN_MAXIMUM_FRAME_SIZE,
|
||
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
||
OID_GEN_MAC_OPTIONS,
|
||
OID_GEN_PROTOCOL_OPTIONS,
|
||
OID_GEN_LINK_SPEED,
|
||
OID_GEN_TRANSMIT_BUFFER_SPACE,
|
||
OID_GEN_RECEIVE_BUFFER_SPACE,
|
||
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
||
OID_GEN_RECEIVE_BLOCK_SIZE,
|
||
OID_GEN_VENDOR_ID,
|
||
OID_GEN_VENDOR_DESCRIPTION,
|
||
OID_GEN_DRIVER_VERSION,
|
||
OID_GEN_CURRENT_PACKET_FILTER,
|
||
OID_GEN_CURRENT_LOOKAHEAD,
|
||
OID_GEN_XMIT_OK,
|
||
OID_GEN_RCV_OK,
|
||
OID_GEN_XMIT_ERROR,
|
||
OID_GEN_RCV_ERROR,
|
||
OID_GEN_RCV_NO_BUFFER,
|
||
OID_GEN_DIRECTED_BYTES_XMIT,
|
||
OID_GEN_DIRECTED_FRAMES_XMIT,
|
||
OID_GEN_MULTICAST_BYTES_XMIT,
|
||
OID_GEN_MULTICAST_FRAMES_XMIT,
|
||
OID_GEN_BROADCAST_BYTES_XMIT,
|
||
OID_GEN_BROADCAST_FRAMES_XMIT,
|
||
OID_GEN_DIRECTED_BYTES_RCV,
|
||
OID_GEN_DIRECTED_FRAMES_RCV,
|
||
OID_GEN_MULTICAST_BYTES_RCV,
|
||
OID_GEN_MULTICAST_FRAMES_RCV,
|
||
OID_GEN_BROADCAST_BYTES_RCV,
|
||
OID_GEN_BROADCAST_FRAMES_RCV,
|
||
OID_GEN_RCV_CRC_ERROR,
|
||
OID_GEN_TRANSMIT_QUEUE_LENGTH,
|
||
OID_802_3_PERMANENT_ADDRESS,
|
||
OID_802_3_CURRENT_ADDRESS,
|
||
OID_802_3_MULTICAST_LIST,
|
||
OID_802_3_MAXIMUM_LIST_SIZE,
|
||
OID_802_3_RCV_ERROR_ALIGNMENT,
|
||
OID_802_3_XMIT_ONE_COLLISION,
|
||
OID_802_3_XMIT_MORE_COLLISIONS,
|
||
OID_802_3_XMIT_DEFERRED,
|
||
OID_802_3_XMIT_MAX_COLLISIONS,
|
||
OID_802_3_RCV_OVERRUN,
|
||
OID_802_3_XMIT_UNDERRUN,
|
||
OID_802_3_XMIT_HEARTBEAT_FAILURE,
|
||
OID_802_3_XMIT_TIMES_CRS_LOST,
|
||
OID_802_3_XMIT_LATE_COLLISIONS
|
||
};
|
||
|
||
//
|
||
// Check that the OID is valid.
|
||
//
|
||
|
||
SupportedOids = sizeof(SonicSupportedOids)/sizeof(ULONG);
|
||
|
||
for (i=0; i<SupportedOids; i++) {
|
||
if (Oid == SonicSupportedOids[i]) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i == SupportedOids) {
|
||
*BytesWritten = 0;
|
||
return NDIS_STATUS_INVALID_OID;
|
||
}
|
||
|
||
//
|
||
// Initialize these once, since this is the majority
|
||
// of cases.
|
||
//
|
||
|
||
SourceBuffer = &GenericUlong;
|
||
SourceBufferLength = sizeof(ULONG);
|
||
|
||
switch (Oid & OID_TYPE_MASK) {
|
||
|
||
case OID_TYPE_GENERAL_OPERATIONAL:
|
||
|
||
switch (Oid) {
|
||
|
||
case OID_GEN_MAC_OPTIONS:
|
||
|
||
GenericUlong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
|
||
NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
|
||
NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
|
||
NDIS_MAC_OPTION_NO_LOOPBACK
|
||
);
|
||
|
||
break;
|
||
|
||
case OID_GEN_SUPPORTED_LIST:
|
||
|
||
SourceBuffer = (PVOID)SonicSupportedOids;
|
||
SourceBufferLength = SupportedOids * sizeof(ULONG);
|
||
break;
|
||
|
||
case OID_GEN_HARDWARE_STATUS:
|
||
|
||
GenericUlong = NdisHardwareStatusReady;
|
||
break;
|
||
|
||
case OID_GEN_MEDIA_SUPPORTED:
|
||
|
||
GenericUlong = NdisMedium802_3;
|
||
break;
|
||
|
||
case OID_GEN_MEDIA_IN_USE:
|
||
|
||
GenericUlong = NdisMedium802_3;
|
||
break;
|
||
|
||
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
||
|
||
GenericUlong = (SONIC_INDICATE_MAXIMUM-14 < SONIC_LOOPBACK_MAXIMUM) ?
|
||
SONIC_INDICATE_MAXIMUM-14 : SONIC_LOOPBACK_MAXIMUM;
|
||
break;
|
||
|
||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||
|
||
GenericUlong = 1500;
|
||
break;
|
||
|
||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||
|
||
GenericUlong = 1514;
|
||
break;
|
||
|
||
case OID_GEN_LINK_SPEED:
|
||
|
||
GenericUlong = 100000; // 10 Mbps in 100 bps units
|
||
break;
|
||
|
||
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
||
|
||
GenericUlong = SONIC_LARGE_BUFFER_SIZE * SONIC_NUMBER_OF_TRANSMIT_DESCRIPTORS;
|
||
break;
|
||
|
||
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
||
|
||
GenericUlong = SONIC_LARGE_BUFFER_SIZE * SONIC_NUMBER_OF_RECEIVE_DESCRIPTORS;
|
||
break;
|
||
|
||
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||
|
||
GenericUlong = SONIC_LARGE_BUFFER_SIZE;
|
||
break;
|
||
|
||
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
||
|
||
GenericUlong = SONIC_LARGE_BUFFER_SIZE;
|
||
break;
|
||
|
||
case OID_GEN_VENDOR_ID:
|
||
|
||
SONIC_MOVE_MEMORY(VendorId, Adapter->PermanentNetworkAddress, 3);
|
||
VendorId[3] = 0x0;
|
||
SourceBuffer = VendorId;
|
||
SourceBufferLength = sizeof(VendorId);
|
||
break;
|
||
|
||
case OID_GEN_VENDOR_DESCRIPTION:
|
||
|
||
switch (Adapter->AdapterType) {
|
||
#ifdef SONIC_EISA
|
||
case SONIC_ADAPTER_TYPE_EISA:
|
||
SourceBuffer = (PVOID)EisaDescriptor;
|
||
SourceBufferLength = sizeof(EisaDescriptor);
|
||
break;
|
||
#endif
|
||
#ifdef SONIC_INTERNAL
|
||
case SONIC_ADAPTER_TYPE_INTERNAL:
|
||
SourceBuffer = (PVOID)InternalDescriptor;
|
||
SourceBufferLength = sizeof(InternalDescriptor);
|
||
break;
|
||
#endif
|
||
default:
|
||
ASSERT(FALSE);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case OID_GEN_DRIVER_VERSION:
|
||
|
||
GenericUshort = (SONIC_NDIS_MAJOR_VERSION << 8) + SONIC_NDIS_MINOR_VERSION;
|
||
SourceBuffer = &GenericUshort;
|
||
SourceBufferLength = sizeof(USHORT);
|
||
break;
|
||
|
||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||
|
||
GenericUlong = Adapter->CurrentPacketFilter;
|
||
break;
|
||
|
||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||
|
||
GenericUlong = (SONIC_INDICATE_MAXIMUM-14 < SONIC_LOOPBACK_MAXIMUM) ?
|
||
SONIC_INDICATE_MAXIMUM-14 : SONIC_LOOPBACK_MAXIMUM;
|
||
break;
|
||
|
||
default:
|
||
|
||
ASSERT(FALSE);
|
||
break;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case OID_TYPE_GENERAL_STATISTICS:
|
||
|
||
MaskOid = (Oid & OID_INDEX_MASK) - 1;
|
||
|
||
switch (Oid & OID_REQUIRED_MASK) {
|
||
|
||
case OID_REQUIRED_MANDATORY:
|
||
|
||
ASSERT (MaskOid < GM_ARRAY_SIZE);
|
||
|
||
if (MaskOid == GM_RECEIVE_NO_BUFFER) {
|
||
|
||
//
|
||
// This one is read off the card, update unless our
|
||
// counter is more (which indicates an imminent
|
||
// overflow interrupt, so we don't update).
|
||
//
|
||
|
||
USHORT MissedPacket;
|
||
SONIC_READ_PORT(Adapter, SONIC_FRAME_ALIGNMENT_ERROR, &MissedPacket);
|
||
|
||
if ((Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER] & 0xffff) <
|
||
MissedPacket) {
|
||
|
||
Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER] =
|
||
(Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER] & 0xffff0000) +
|
||
MissedPacket;
|
||
|
||
}
|
||
}
|
||
|
||
GenericUlong = Adapter->GeneralMandatory[MaskOid];
|
||
break;
|
||
|
||
case OID_REQUIRED_OPTIONAL:
|
||
|
||
ASSERT (MaskOid < GO_ARRAY_SIZE);
|
||
|
||
if (MaskOid == GO_RECEIVE_CRC) {
|
||
|
||
//
|
||
// This one is read off the card, update unless our
|
||
// counter is more (which indicates an imminent
|
||
// overflow interrupt, so we don't update).
|
||
//
|
||
|
||
USHORT CrcError;
|
||
SONIC_READ_PORT(Adapter, SONIC_FRAME_ALIGNMENT_ERROR, &CrcError);
|
||
|
||
if ((Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START] & 0xffff) <
|
||
CrcError) {
|
||
|
||
Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START] =
|
||
(Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START] & 0xffff0000) +
|
||
CrcError;
|
||
|
||
}
|
||
}
|
||
|
||
if ((MaskOid / 2) < GO_COUNT_ARRAY_SIZE) {
|
||
|
||
if (MaskOid & 0x01) {
|
||
// Frame count
|
||
GenericUlong = Adapter->GeneralOptionalFrameCount[MaskOid / 2];
|
||
} else {
|
||
// Byte count
|
||
SourceBuffer = &Adapter->GeneralOptionalByteCount[MaskOid / 2];
|
||
SourceBufferLength = sizeof(LARGE_INTEGER);
|
||
}
|
||
|
||
} else {
|
||
|
||
GenericUlong = Adapter->GeneralOptional[MaskOid - GO_ARRAY_START];
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
ASSERT(FALSE);
|
||
break;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case OID_TYPE_802_3_OPERATIONAL:
|
||
|
||
switch (Oid) {
|
||
|
||
case OID_802_3_PERMANENT_ADDRESS:
|
||
|
||
SourceBuffer = Adapter->PermanentNetworkAddress;
|
||
SourceBufferLength = 6;
|
||
break;
|
||
|
||
case OID_802_3_CURRENT_ADDRESS:
|
||
|
||
SourceBuffer = Adapter->CurrentNetworkAddress;
|
||
SourceBufferLength = 6;
|
||
break;
|
||
|
||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||
|
||
GenericUlong = SONIC_CAM_ENTRIES - 1;
|
||
break;
|
||
|
||
default:
|
||
|
||
ASSERT(FALSE);
|
||
break;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case OID_TYPE_802_3_STATISTICS:
|
||
|
||
MaskOid = (Oid & OID_INDEX_MASK) - 1;
|
||
|
||
switch (Oid & OID_REQUIRED_MASK) {
|
||
|
||
case OID_REQUIRED_MANDATORY:
|
||
|
||
ASSERT (MaskOid < MM_ARRAY_SIZE);
|
||
|
||
if (MaskOid == MM_RECEIVE_ERROR_ALIGNMENT) {
|
||
|
||
//
|
||
// This one is read off the card, update unless our
|
||
// counter is more (which indicates an imminent
|
||
// overflow interrupt, so we don't update).
|
||
//
|
||
|
||
USHORT FaError;
|
||
SONIC_READ_PORT(Adapter, SONIC_FRAME_ALIGNMENT_ERROR, &FaError);
|
||
|
||
if ((Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT] & 0xffff) <
|
||
FaError) {
|
||
|
||
Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT] =
|
||
(Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT] & 0xffff0000) +
|
||
FaError;
|
||
|
||
}
|
||
}
|
||
|
||
GenericUlong = Adapter->MediaMandatory[MaskOid];
|
||
break;
|
||
|
||
case OID_REQUIRED_OPTIONAL:
|
||
|
||
ASSERT (MaskOid < MO_ARRAY_SIZE);
|
||
GenericUlong = Adapter->MediaOptional[MaskOid];
|
||
break;
|
||
|
||
default:
|
||
|
||
ASSERT(FALSE);
|
||
break;
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
if (SourceBufferLength > InformationBufferLength) {
|
||
*BytesNeeded = SourceBufferLength;
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
}
|
||
|
||
SONIC_MOVE_MEMORY (InformationBuffer, SourceBuffer, SourceBufferLength);
|
||
*BytesWritten = SourceBufferLength;
|
||
|
||
return NDIS_STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
|
||
STATIC
|
||
NDIS_STATUS
|
||
SonicSetInformation(
|
||
IN NDIS_HANDLE MiniportAdapterContext,
|
||
IN NDIS_OID Oid,
|
||
IN PVOID InformationBuffer,
|
||
IN ULONG InformationBufferLength,
|
||
OUT PULONG BytesRead,
|
||
OUT PULONG BytesNeeded
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
SonicQueryInformation handles a set operation for a
|
||
single OID.
|
||
|
||
Arguments:
|
||
|
||
MiniportAdapterContext - Context registered with the wrapper, really
|
||
a pointer to the adapter.
|
||
|
||
Oid - The OID of the 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 OID, returns the amount of storage needed.
|
||
|
||
Return Value:
|
||
|
||
NDIS_STATUS_SUCCESS
|
||
NDIS_STATUS_PENDING
|
||
NDIS_STATUS_INVALID_LENGTH
|
||
NDIS_STATUS_INVALID_OID
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PSONIC_ADAPTER Adapter = PSONIC_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
|
||
NDIS_STATUS Status;
|
||
ULONG PacketFilter;
|
||
|
||
//
|
||
// Now check for the most common OIDs
|
||
//
|
||
|
||
switch (Oid) {
|
||
|
||
case OID_802_3_MULTICAST_LIST:
|
||
|
||
if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS != 0) {
|
||
|
||
//
|
||
// The data must be a multiple of the Ethernet
|
||
// address size.
|
||
//
|
||
|
||
return NDIS_STATUS_INVALID_DATA;
|
||
|
||
}
|
||
#if DBG
|
||
if (SonicDbg) {
|
||
DbgPrint("Processing Change Multicast List request\n");
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Now make the change.
|
||
//
|
||
|
||
Status = ChangeAddressDispatch(
|
||
Adapter,
|
||
InformationBufferLength / ETH_LENGTH_OF_ADDRESS,
|
||
InformationBuffer
|
||
);
|
||
|
||
*BytesRead = InformationBufferLength;
|
||
|
||
return Status;
|
||
|
||
break;
|
||
|
||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||
|
||
if (InformationBufferLength != 4) {
|
||
|
||
*BytesNeeded = 4;
|
||
return NDIS_STATUS_INVALID_LENGTH;
|
||
|
||
}
|
||
|
||
#if DBG
|
||
if (SonicDbg) {
|
||
DbgPrint("Processing Change Packet Filter request\n");
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Now call the filter package to set the packet filter.
|
||
//
|
||
|
||
SONIC_MOVE_MEMORY ((PVOID)&PacketFilter, InformationBuffer, sizeof(ULONG));
|
||
|
||
//
|
||
// Verify bits
|
||
//
|
||
|
||
if (PacketFilter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
|
||
NDIS_PACKET_TYPE_SMT |
|
||
NDIS_PACKET_TYPE_MAC_FRAME |
|
||
NDIS_PACKET_TYPE_FUNCTIONAL |
|
||
NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
|
||
NDIS_PACKET_TYPE_GROUP
|
||
)) {
|
||
|
||
*BytesRead = 4;
|
||
*BytesNeeded = 0;
|
||
|
||
return NDIS_STATUS_NOT_SUPPORTED;
|
||
|
||
}
|
||
|
||
Status = ChangeClassDispatch(
|
||
Adapter,
|
||
PacketFilter
|
||
);
|
||
|
||
*BytesRead = 4;
|
||
return Status;
|
||
|
||
break;
|
||
|
||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||
|
||
//
|
||
// No need to record requested lookahead length since we
|
||
// always indicate the whole packet.
|
||
//
|
||
|
||
*BytesRead = 4;
|
||
return NDIS_STATUS_SUCCESS;
|
||
break;
|
||
|
||
default:
|
||
|
||
return NDIS_STATUS_INVALID_OID;
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
STATIC
|
||
NDIS_STATUS
|
||
ChangeClassDispatch(
|
||
IN PSONIC_ADAPTER Adapter,
|
||
IN UINT NewFilterClasses
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Modifies the Receive Control Register and Cam Enable registers,
|
||
then re-loads the CAM if necessary.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter.
|
||
|
||
NewFilterClasses - New set of filters.
|
||
|
||
Return Value:
|
||
|
||
NDIS_STATUS_PENDING - if the CAM was reloaded.
|
||
NDIS_STATUS_SUCCESS - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// The new value for the RCR.
|
||
//
|
||
USHORT NewReceiveControl = SONIC_RCR_DEFAULT_VALUE;
|
||
|
||
//
|
||
// First take care of the Receive Control Register.
|
||
//
|
||
|
||
if (NewFilterClasses & NDIS_PACKET_TYPE_PROMISCUOUS) {
|
||
|
||
NewReceiveControl |= SONIC_RCR_PROMISCUOUS_PHYSICAL |
|
||
SONIC_RCR_ACCEPT_BROADCAST |
|
||
SONIC_RCR_ACCEPT_ALL_MULTICAST;
|
||
|
||
} else {
|
||
|
||
if (NewFilterClasses & NDIS_PACKET_TYPE_ALL_MULTICAST) {
|
||
|
||
NewReceiveControl |= SONIC_RCR_ACCEPT_ALL_MULTICAST;
|
||
|
||
}
|
||
|
||
if (NewFilterClasses & NDIS_PACKET_TYPE_BROADCAST) {
|
||
|
||
NewReceiveControl |= SONIC_RCR_ACCEPT_BROADCAST;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
Adapter->ReceiveControlRegister = NewReceiveControl;
|
||
|
||
SONIC_WRITE_PORT(Adapter, SONIC_RECEIVE_CONTROL,
|
||
Adapter->ReceiveControlRegister
|
||
);
|
||
|
||
if (CAM_DIRECTED_SIGNIFICANT(NewFilterClasses)) {
|
||
|
||
Adapter->CamDescriptorArea->CamEnable |= 1;
|
||
|
||
} else {
|
||
|
||
Adapter->CamDescriptorArea->CamEnable &= ~1;
|
||
|
||
}
|
||
|
||
if (CAM_MULTICAST_SIGNIFICANT(NewFilterClasses)) {
|
||
|
||
Adapter->CamDescriptorArea->CamEnable |=
|
||
Adapter->MulticastCamEnableBits;
|
||
|
||
} else {
|
||
|
||
Adapter->CamDescriptorArea->CamEnable &= 1;
|
||
|
||
}
|
||
|
||
//
|
||
// This will cause a LOAD_CAM interrupt when it is done.
|
||
//
|
||
|
||
SonicStartCamReload(Adapter);
|
||
|
||
Adapter->CurrentPacketFilter = NewFilterClasses;
|
||
|
||
return NDIS_STATUS_PENDING;
|
||
|
||
}
|
||
|
||
STATIC
|
||
NDIS_STATUS
|
||
ChangeAddressDispatch(
|
||
IN PSONIC_ADAPTER Adapter,
|
||
IN UINT AddressCount,
|
||
IN CHAR Addresses[][ETH_LENGTH_OF_ADDRESS]
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Modifies the Receive Control Register and Cam Enable registers,
|
||
then re-loads the CAM if necessary.
|
||
|
||
Arguments:
|
||
|
||
Adapter - The adapter.
|
||
|
||
AddressCount - The number of addresses in Addresses
|
||
|
||
Addresses - The new multicast address list.
|
||
|
||
Return Value:
|
||
|
||
NDIS_STATUS_PENDING - if the CAM was reloaded.
|
||
NDIS_STATUS_SUCCESS - otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
ULONG EnableBit;
|
||
NDIS_STATUS Status;
|
||
UINT i;
|
||
|
||
//
|
||
// The first entry in the CAM is for our address.
|
||
//
|
||
|
||
Adapter->MulticastCamEnableBits = 1;
|
||
EnableBit = 1;
|
||
|
||
//
|
||
// Loop through, copying the addresses into the CAM.
|
||
//
|
||
|
||
for (i=0; i<AddressCount; i++) {
|
||
|
||
EnableBit <<= 1;
|
||
Adapter->MulticastCamEnableBits |= EnableBit;
|
||
|
||
SONIC_LOAD_CAM_FRAGMENT(
|
||
&Adapter->CamDescriptorArea->CamFragments[i+1],
|
||
i+1,
|
||
Addresses[i]
|
||
);
|
||
|
||
}
|
||
|
||
Adapter->CamDescriptorAreaSize = AddressCount + 1;
|
||
|
||
//
|
||
// Now see if we have to worry about re-loading the
|
||
// CAM also.
|
||
//
|
||
|
||
if (CAM_MULTICAST_SIGNIFICANT(Adapter->CurrentPacketFilter)) {
|
||
|
||
Adapter->CamDescriptorArea->CamEnable = Adapter->MulticastCamEnableBits;
|
||
|
||
//
|
||
// This will cause a LOAD_CAM interrupt when it is done.
|
||
//
|
||
|
||
SonicStartCamReload(Adapter);
|
||
|
||
#if DBG
|
||
if (SonicDbg) {
|
||
DbgPrint("Processing Address request pended\n");
|
||
}
|
||
#endif
|
||
|
||
|
||
Status = NDIS_STATUS_PENDING;
|
||
|
||
} else {
|
||
|
||
#if DBG
|
||
if (SonicDbg) {
|
||
DbgPrint("Processing Address request succeeded\n");
|
||
}
|
||
#endif
|
||
|
||
Status = NDIS_STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
return Status;
|
||
|
||
}
|
||
|