mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
890 lines
20 KiB
890 lines
20 KiB
/*++
|
|
|
|
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;
|
|
|
|
}
|
|
|