990 lines
27 KiB
C
990 lines
27 KiB
C
#include <ndis.h>
|
|
#include "82595.h"
|
|
#include "eprohw.h"
|
|
#include "eprosw.h"
|
|
#include "epro.h"
|
|
#include "eprodbg.h"
|
|
|
|
static UINT EProSupportedOids[] = {
|
|
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_802_3_PERMANENT_ADDRESS,
|
|
OID_802_3_CURRENT_ADDRESS,
|
|
OID_802_3_MAXIMUM_LIST_SIZE,
|
|
OID_802_3_MULTICAST_LIST,
|
|
OID_802_3_RCV_ERROR_ALIGNMENT,
|
|
OID_802_3_XMIT_ONE_COLLISION,
|
|
OID_802_3_XMIT_MORE_COLLISIONS
|
|
};
|
|
|
|
NDIS_STATUS EProQueryInformation(IN NDIS_HANDLE miniportAdapterContext,
|
|
IN NDIS_OID oid,
|
|
IN PVOID informationBuffer,
|
|
IN ULONG informationBufferLength,
|
|
OUT PULONG bytesWritten,
|
|
OUT PULONG bytesNeeded)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the query configuration handler for the EPro
|
|
|
|
Arguments:
|
|
|
|
miniportAdapterContext - really a pointer to our adapter structure
|
|
|
|
oid - the oid we are querying
|
|
|
|
informationBuffer - The buffer to copy the queried info into
|
|
|
|
informationLength - how much room is there in the buffer
|
|
|
|
bytesWritten - the number of bytes we actually wrote into
|
|
informationBuffer
|
|
|
|
bytesNeeded - only valid if we return not enough space error --
|
|
how much more space do we need to be able to give
|
|
you that data?
|
|
|
|
Return Values:
|
|
|
|
NDIS_STATUS_SUCCESS - operation successful
|
|
NDIS_STATUS_INALID_OID - invalid oid, or we don't support it
|
|
NDIS_STATUS_INVALID_LENGTH - not enough room in informationbuffer
|
|
see bytesNeeded for more info
|
|
|
|
--*/
|
|
{
|
|
PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
|
|
UINT bytesToMove = 0;
|
|
PVOID moveSource = NULL;
|
|
// since we can't transfer #define'd constants the way they want us to...
|
|
ULONG GenericUL;
|
|
USHORT GenericUS;
|
|
NDIS_STATUS statusToReturn = NDIS_STATUS_SUCCESS;
|
|
|
|
EPRO_DPRINTF_REQ(("EProQueryInformation. Oid = %lx\n", oid));
|
|
|
|
// the oid's are documented in the DDK. See that for info on all of them
|
|
switch(oid) {
|
|
case OID_GEN_SUPPORTED_LIST:
|
|
EPRO_DPRINTF_REQ((" querying oid: OID_GEN_SUPPORTED_LIST\n"));
|
|
moveSource = &EProSupportedOids;
|
|
bytesToMove = sizeof(EProSupportedOids);
|
|
break;
|
|
case OID_GEN_HARDWARE_STATUS:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_HARDWARE_STATUS\n"));
|
|
moveSource = &adapter->CurrentHardwareStatus;
|
|
bytesToMove = sizeof(adapter->CurrentHardwareStatus);
|
|
break;
|
|
case OID_GEN_MEDIA_SUPPORTED:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MEDIA_SUPPORTED\n"));
|
|
GenericUL = EPRO_GEN_MEDIA_SUPPORTED;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_MEDIA_IN_USE:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MEDIA_IN_USE\n"));
|
|
GenericUL = EPRO_GEN_MEDIA_IN_USE;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_MAXIMUM_LOOKAHEAD:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MAXIMUM_LOOKAHEAD\n"));
|
|
GenericUL = EPRO_GEN_MAXIMUM_LOKAHEAD;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MAXIMUM_FRAME_SIZE\n"));
|
|
GenericUL = EPRO_GEN_MAXIMUM_FRAME_SIZE;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
|
|
GenericUL = EPRO_GEN_MAXIMUM_TOTAL_SIZE;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_MAC_OPTIONS:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MAC_OPTIONS\n"));
|
|
GenericUL = EPRO_GEN_MAC_OPTIONS;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_PROTOCOL_OPTIONS:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_PROTOCOL_OPTIONS\n"));
|
|
moveSource = NULL;
|
|
bytesToMove = 0;
|
|
break;
|
|
case OID_GEN_LINK_SPEED:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_LINK_SPEED\n"));
|
|
GenericUL = EPRO_GEN_LINK_SPEED;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_TRANSMIT_BUFFER_SPACE:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
|
|
GenericUL = EPRO_GEN_TRANSMIT_BUFFER_SPACE;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_RECEIVE_BUFFER_SPACE:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RECEIVE_BUFFER_SPACE\n"));
|
|
GenericUL = EPRO_GEN_RECEIVE_BUFFER_SPACE;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
|
|
GenericUL = EPRO_TX_BUF_SIZE;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(ULONG);
|
|
break;
|
|
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RECEIVE_BOCK_SIZE\n"));
|
|
GenericUL = EPRO_RX_BUF_SIZE;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(ULONG);
|
|
break;
|
|
case OID_GEN_VENDOR_ID:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_VENDOR_ID\n"));
|
|
moveSource = &adapter->vendorID;
|
|
bytesToMove = sizeof(adapter->vendorID);
|
|
break;
|
|
case OID_GEN_VENDOR_DESCRIPTION:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_VENDOR_DESCRIPTION\n"));
|
|
moveSource = EPRO_VENDOR_DESC;
|
|
bytesToMove = sizeof(EPRO_VENDOR_DESC);
|
|
break;
|
|
case OID_GEN_DRIVER_VERSION:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_DRIVER_VERSION\n"));
|
|
GenericUS = ((USHORT)EPRO_DRIVER_VER_MAJOR << 8) |
|
|
EPRO_DRIVER_VER_MINOR;
|
|
moveSource = &GenericUS;
|
|
bytesToMove = sizeof(GenericUS);
|
|
break;
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_CURRENT_PACKET_FILTER\n"));
|
|
moveSource = &adapter->CurrentPacketFilter;
|
|
bytesToMove = sizeof(adapter->CurrentPacketFilter);
|
|
break;
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_CURRENT_LOOKAHEAD\n"));
|
|
GenericUL = adapter->RXLookAheadSize;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_GEN_XMIT_OK:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_XMIT_OK\n"));
|
|
moveSource = &adapter->FramesXmitOK;
|
|
bytesToMove = sizeof(adapter->FramesXmitOK);
|
|
break;
|
|
case OID_GEN_RCV_OK:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RCV_OK\n"));
|
|
moveSource = &adapter->FramesRcvOK;
|
|
bytesToMove = sizeof(adapter->FramesRcvOK);
|
|
break;
|
|
case OID_GEN_XMIT_ERROR:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_XMIT_ERROR\n"));
|
|
moveSource = &adapter->FramesXmitErr;
|
|
bytesToMove = sizeof(adapter->FramesXmitErr);
|
|
break;
|
|
case OID_GEN_RCV_ERROR:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RCV_ERROR\n"));
|
|
moveSource = &adapter->FramesRcvErr;
|
|
bytesToMove = sizeof(adapter->FramesRcvErr);
|
|
break;
|
|
case OID_GEN_RCV_NO_BUFFER:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RCV_NO_BUFFER\n"));
|
|
moveSource = &adapter->FramesMissed;
|
|
bytesToMove = sizeof(adapter->FramesMissed);
|
|
break;
|
|
case OID_802_3_PERMANENT_ADDRESS:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_PERMANENT_ADDRESS\n"));
|
|
moveSource = &adapter->PermanentIndividualAddress;
|
|
bytesToMove = sizeof(adapter->PermanentIndividualAddress);
|
|
break;
|
|
case OID_802_3_CURRENT_ADDRESS:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_CURRENT_ADDRESS\n"));
|
|
moveSource = &adapter->CurrentIndividualAddress;
|
|
bytesToMove = sizeof(adapter->CurrentIndividualAddress);
|
|
break;
|
|
case OID_802_3_MAXIMUM_LIST_SIZE:
|
|
EPRO_DPRINTF_REQ(("Querying Maximum Multicast List Size....\n"));
|
|
GenericUL = EPRO_MAX_MULTICAST;
|
|
moveSource = &GenericUL;
|
|
bytesToMove = sizeof(GenericUL);
|
|
break;
|
|
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_RCV_ERROR_ALIGNMENT\n"));
|
|
moveSource = &adapter->FrameAlignmentErrors;
|
|
bytesToMove = sizeof(adapter->FrameAlignmentErrors);
|
|
break;
|
|
case OID_802_3_XMIT_ONE_COLLISION:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_XMIT_ONE_COLLISION\n"));
|
|
moveSource = &adapter->FramesXmitOneCollision;
|
|
bytesToMove = sizeof(adapter->FramesXmitOneCollision);
|
|
break;
|
|
case OID_802_3_XMIT_MORE_COLLISIONS:
|
|
EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_XMIT_MORE_COLLISION\n"));
|
|
moveSource = &adapter->FramesXmitManyCollisions;
|
|
bytesToMove = sizeof(adapter->FramesXmitManyCollisions);
|
|
break;
|
|
default:
|
|
EPRO_DPRINTF_REQ(("Invalid Oid in Query.\n"));
|
|
EPRO_DPRINTF_REQ(("iq"));
|
|
statusToReturn = NDIS_STATUS_INVALID_OID;
|
|
}
|
|
|
|
if (statusToReturn == NDIS_STATUS_SUCCESS) {
|
|
if (bytesToMove > informationBufferLength) {
|
|
*bytesNeeded = bytesToMove;
|
|
statusToReturn = NDIS_STATUS_INVALID_LENGTH;
|
|
EPRO_DPRINTF_REQ(("Invalid Length in Query\n"));
|
|
} else {
|
|
NdisMoveMemory(informationBuffer, moveSource, bytesToMove);
|
|
(*bytesWritten)+=bytesToMove;
|
|
}
|
|
}
|
|
|
|
EPRO_DPRINTF_REQ(("EProQueryInfo - Done\n"));
|
|
|
|
EPRO_DPRINTF_REQ(("returning: 0x%lx\n", statusToReturn));
|
|
return(statusToReturn);
|
|
}
|
|
|
|
NDIS_STATUS EProSetInformation(IN NDIS_HANDLE miniportAdapterContext,
|
|
IN NDIS_OID oid,
|
|
IN PVOID informationBuffer,
|
|
IN ULONG informationLength,
|
|
OUT PULONG bytesRead,
|
|
OUT PULONG bytesNeeded)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the MiniportSetInformation Handler for the EPro driver
|
|
|
|
Arguments:
|
|
|
|
miniportAdapterContext - really a pointer to our adapter structure
|
|
|
|
oid - the oid to set
|
|
|
|
informationBuffer - the buffer which contains the information we need
|
|
to carry out the set
|
|
|
|
informationLength - the length of the informationBuffer's data
|
|
|
|
bytesRead - how many bytes did we actually read out of informationBuffer
|
|
|
|
bytesNeeded - if we failed -- how many bytes do we need to complete
|
|
the call?
|
|
|
|
Return Values:
|
|
|
|
NDIS_STATUS_SUCCESS - set completed OK
|
|
NDIS_STATUS_NOT_ACCEPTED - too many MC addresses set
|
|
NDIS_STATUS_INVALID_DATA - tried to set MC list, buf inf. buffer not
|
|
an integral multiple of 6 (len of 802_3 address)
|
|
NDIS_STATUS_PENDING - set PENDED (completed in EProHandleInterrupt)
|
|
NDIS_STATUS_INVALID_OID - the oid was bad, or we don't support it.
|
|
|
|
--*/
|
|
{
|
|
PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
|
|
NDIS_STATUS statusToReturn = NDIS_STATUS_SUCCESS;
|
|
ULONG genericUL;
|
|
BOOLEAN fReturn;
|
|
|
|
EPRO_DPRINTF_REQ(("EProSetInformation. Oid = %lx\n", oid));
|
|
|
|
switch(oid)
|
|
{
|
|
case OID_802_3_MULTICAST_LIST:
|
|
EPRO_DPRINTF_REQ(("setting: OID_802_3_MULTICAST_LIST\n"));
|
|
|
|
if (informationLength % EPRO_LENGTH_OF_ADDRESS != 0)
|
|
{
|
|
*bytesNeeded = EPRO_LENGTH_OF_ADDRESS;
|
|
EPRO_DPRINTF_REQ(("INVALID data length...\n"));
|
|
return(NDIS_STATUS_INVALID_DATA);
|
|
}
|
|
|
|
if ((informationLength / EPRO_LENGTH_OF_ADDRESS) > EPRO_MAX_MULTICAST)
|
|
{
|
|
EPRO_DPRINTF_REQ(("Attempted to set too many multicasts....\n"));
|
|
return(NDIS_STATUS_NOT_ACCEPTED);
|
|
}
|
|
|
|
*bytesRead = informationLength;
|
|
*bytesNeeded = 0;
|
|
|
|
//
|
|
// If they are trying to clear the multicast list and none
|
|
// have been set then we are done!
|
|
//
|
|
if ((0 == (informationLength / EPRO_LENGTH_OF_ADDRESS)) &&
|
|
(0 == adapter->NumMCAddresses))
|
|
{
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
fReturn = EProChangeMulticastList(
|
|
adapter,
|
|
informationLength / EPRO_LENGTH_OF_ADDRESS,
|
|
informationBuffer);
|
|
if (adapter->fMulticastEnable)
|
|
{
|
|
BOOLEAN fReturnStatus;
|
|
|
|
fReturnStatus = EProSetCardMulticastList(
|
|
adapter,
|
|
(fReturn) ? EPRO_CLEAR_CARD_MC : EPRO_SET_CARD_MC);
|
|
if (!fReturnStatus)
|
|
{
|
|
statusToReturn = NDIS_STATUS_NOT_ACCEPTED;
|
|
}
|
|
else
|
|
{
|
|
statusToReturn = NDIS_STATUS_PENDING;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
|
EPRO_DPRINTF_REQ(("setting: OID_GEN_CURRENT_PACKET_FILTER\n"));
|
|
if (informationLength < 4)
|
|
{
|
|
EPRO_DPRINTF_REQ(("INVALID data length...\n"));
|
|
return(NDIS_STATUS_INVALID_LENGTH);
|
|
}
|
|
|
|
NdisMoveMemory(&genericUL, informationBuffer, sizeof(ULONG));
|
|
|
|
*bytesRead = sizeof(ULONG);
|
|
*bytesNeeded = 0;
|
|
statusToReturn = EProSetPacketFilter(adapter, genericUL);
|
|
|
|
break;
|
|
|
|
case OID_GEN_CURRENT_LOOKAHEAD:
|
|
if (informationLength < 4)
|
|
{
|
|
return(NDIS_STATUS_INVALID_LENGTH);
|
|
}
|
|
|
|
EPRO_DPRINTF_REQ(("EPRO: Attempting to set lookahead size\n"));
|
|
|
|
NdisMoveMemory(&genericUL, informationBuffer, sizeof(ULONG));
|
|
|
|
*bytesRead = sizeof(ULONG);
|
|
*bytesNeeded = 0;
|
|
|
|
if (genericUL <= EPRO_GEN_MAXIMUM_LOKAHEAD)
|
|
{
|
|
EPRO_DPRINTF_REQ(("EPRO: Current lookahead is now %d bytes\n", adapter->RXLookAheadSize));
|
|
adapter->RXLookAheadSize = (USHORT)genericUL;
|
|
statusToReturn = NDIS_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
statusToReturn = NDIS_STATUS_FAILURE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
EPRO_DPRINTF_REQ(("Invalid oid in setinformation\n"));
|
|
EPRO_DPRINTF_REQ(("inv"));
|
|
statusToReturn = NDIS_STATUS_INVALID_OID;
|
|
}
|
|
|
|
return(statusToReturn);
|
|
}
|
|
|
|
NDIS_STATUS EProSetPacketFilter(PEPRO_ADAPTER adapter, ULONG newFilter)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine, invoked from EProSetInformation, is called to do the
|
|
real work of setting a packet filter.
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
// reg2flags are the flags currently set in the configuration register in
|
|
// bank2 (bank 2, reg 2). This is used when we twiddle with the bank
|
|
//
|
|
UCHAR reg2Flags = 0, result;
|
|
|
|
// Do we need to update the CONFIG registers in bank2? (iff broadcast or
|
|
// promiscuous setting are changed only) If so, then we will need to do
|
|
// a synchronized call, and also a reset...
|
|
//
|
|
BOOLEAN fUpdateConfig = FALSE;
|
|
ULONG oldFilter;
|
|
|
|
NDIS_STATUS Status;
|
|
|
|
EPRO_DPRINTF_REQ(("SetPacketFilter: %lx", newFilter));
|
|
|
|
//
|
|
// Validate the new packet filter that was passed in to be set.
|
|
//
|
|
if (newFilter & ~(NDIS_PACKET_TYPE_DIRECTED |
|
|
NDIS_PACKET_TYPE_PROMISCUOUS |
|
|
NDIS_PACKET_TYPE_BROADCAST |
|
|
//NDIS_PACKET_TYPE_ALL_MULTICAST |
|
|
NDIS_PACKET_TYPE_MULTICAST))
|
|
{
|
|
EPRO_DPRINTF_REQ(("PacketFilter NOT SUPPORTED!\n"));
|
|
EPRO_DPRINTF_REQ(("Not Supported\n"));
|
|
|
|
return(NDIS_STATUS_NOT_SUPPORTED);
|
|
}
|
|
|
|
//
|
|
// Save the new packet filter.
|
|
//
|
|
oldFilter = adapter->CurrentPacketFilter;
|
|
adapter->CurrentPacketFilter = newFilter;
|
|
|
|
|
|
//
|
|
// Ooh, here's a good hardware weirdness. If you issue the rcv enable
|
|
// command to the 82595tx when it is already in receive-enable mode,
|
|
// it munges the next received packet. no joke. So we always
|
|
// temporarily disable receives here.
|
|
//
|
|
EProReceiveDisable(adapter);
|
|
|
|
EPRO_DPRINTF_REQ(("Setting filter...\n"));
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Now, if we've modified the PROMISCUOUS or BROADCAST
|
|
// settings, we have to re-configure the card....
|
|
//
|
|
if (((oldFilter & NDIS_PACKET_TYPE_PROMISCUOUS) ^ (newFilter & NDIS_PACKET_TYPE_PROMISCUOUS)) ||
|
|
((oldFilter & NDIS_PACKET_TYPE_BROADCAST) ^ (newFilter & NDIS_PACKET_TYPE_BROADCAST)))
|
|
{
|
|
//
|
|
// Are we supposed to set or clear the promiscuous bit?
|
|
//
|
|
if (newFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
|
|
{
|
|
EPRO_DPRINTF_REQ(("Promiscuous mode set...\n"));
|
|
|
|
adapter->fPromiscuousEnable = TRUE;
|
|
reg2Flags |= I82595_PROMISCUOUS_FLAG;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Promiscuous mode bit NOT set - do we need to turn it off?
|
|
//
|
|
adapter->fPromiscuousEnable = FALSE;
|
|
}
|
|
|
|
//
|
|
// Are we supposed to set or clear the broadcast bit?
|
|
//
|
|
if (newFilter & NDIS_PACKET_TYPE_BROADCAST)
|
|
{
|
|
adapter->fBroadcastEnable = TRUE;
|
|
}
|
|
else
|
|
{
|
|
adapter->fBroadcastEnable = FALSE;
|
|
reg2Flags |= I82595_NO_BROADCAST_FLAG;
|
|
}
|
|
|
|
//
|
|
// okay, we're going to have to modify the config, so we better stop
|
|
// receives to get ready for the reset...
|
|
|
|
// Okay, we're going to have to modify the configuration...
|
|
// So wait for any receives or sends to finish so the card is
|
|
// idle...
|
|
//
|
|
if (!EProWaitForExeDma(adapter))
|
|
{
|
|
EPRO_DPRINTF_RX(("FAILURE waiting for exedma....\n"));
|
|
Status = NDIS_STATUS_NOT_ACCEPTED;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// This gets expanded to a Sync (synchronizedwithinterrupt) call --
|
|
// since it changes banks, it can NOT happen at the same time as the
|
|
// ISR (which requires bank0)
|
|
//
|
|
EProBroadcastPromiscuousChange(adapter, reg2Flags);
|
|
|
|
//
|
|
// Okay, make sure the card is idle again before we enable receives...
|
|
//
|
|
if (!EProWaitForExeDma(adapter))
|
|
{
|
|
adapter->fHung = TRUE;
|
|
return(NDIS_STATUS_HARD_ERRORS);
|
|
// EPRO_ASSERT(FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enable receives.
|
|
//
|
|
EProReceiveEnable(adapter);
|
|
|
|
//
|
|
// Has the multicast bit changed?
|
|
//
|
|
if ((oldFilter & NDIS_PACKET_TYPE_MULTICAST) ^
|
|
(newFilter & NDIS_PACKET_TYPE_MULTICAST))
|
|
{
|
|
//
|
|
// Was the bit set or turned off?
|
|
//
|
|
if (newFilter & NDIS_PACKET_TYPE_MULTICAST)
|
|
{
|
|
adapter->fMulticastEnable = TRUE;
|
|
|
|
//
|
|
// If there are no multicast addresses to set then we are done.
|
|
//
|
|
if (0 == adapter->NumMCAddresses)
|
|
{
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set the multicast addresses to the card.
|
|
//
|
|
if (!EProSetCardMulticastList(adapter, EPRO_SET_CARD_MC))
|
|
{
|
|
EPRO_DPRINTF_REQ(("ERROR setting multicastlist on card\n"));
|
|
return(NDIS_STATUS_NOT_ACCEPTED);
|
|
}
|
|
else
|
|
{
|
|
Status = NDIS_STATUS_PENDING;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If they haven't set the MC bit, we check to see if we think
|
|
// it is on and turn it off if need be...
|
|
//
|
|
adapter->fMulticastEnable = FALSE;
|
|
|
|
//
|
|
// If there are no multicast addresses set on the card
|
|
// the we are done.
|
|
//
|
|
if (0 == adapter->NumMCAddresses)
|
|
{
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Clear any multicast addresses that are currently on the
|
|
// adapter.
|
|
//
|
|
if (!EProSetCardMulticastList(adapter, EPRO_CLEAR_CARD_MC))
|
|
{
|
|
EPRO_DPRINTF_REQ(("ERROR setting Multicast List on card...\n"));
|
|
|
|
Status = NDIS_STATUS_NOT_ACCEPTED;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
Status = NDIS_STATUS_PENDING;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
|
|
//
|
|
// if the filter = 0, then we are leaving with receives disabled
|
|
//
|
|
if (0 == newFilter)
|
|
{
|
|
//
|
|
// Make sure that
|
|
//
|
|
EProReceiveDisable(adapter);
|
|
adapter->CurrentPacketFilter = newFilter;
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
// This is probably a NOTREACHED...
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
BOOLEAN EProSyncBroadcastPromiscuousChange(PVOID context)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by a macro expansion of the function
|
|
EProBroadcastPromiscuousChange -- the macro expands that call to
|
|
a NdisMSynchronizeWithInterrupt call to this function. This function
|
|
CANNOT BE CALLED DIRECTLY WHERE THERE IS A CHANCE IT CAN RUN CONCURRENTLY
|
|
WITH EProDisableInterrupts. Very Bad Things will happen if the two run
|
|
concurrently (only on an MP machine - on a UP machine, the syncwithint
|
|
call can be avoided - but alas we don't have the luxury of having
|
|
seperate binaries for each...
|
|
|
|
Arguments:
|
|
|
|
context - a EPRO_BRDPROM_CONTEXT which is basically just a strucutre
|
|
holding all the parameters to the EProBroadcastPromiscuousChange
|
|
macro (adapter structure pointer and reg2flags settings)
|
|
|
|
Return Values:
|
|
|
|
always TRUE...
|
|
|
|
--*/
|
|
{
|
|
PEPRO_ADAPTER adapter = ((PEPRO_BRDPROM_CONTEXT)context)->Adapter;
|
|
UCHAR reg2flags = ((PEPRO_BRDPROM_CONTEXT)context)->Reg2Flags;
|
|
UCHAR result;
|
|
|
|
EPRO_SWITCH_BANK_2(adapter);
|
|
|
|
EPRO_RD_PORT_UCHAR(adapter, I82595_CONFIG2_REG, &result);
|
|
result &= ~(I82595_PROMISCUOUS_FLAG | I82595_NO_BROADCAST_FLAG);
|
|
result |= reg2flags;
|
|
EPRO_WR_PORT_UCHAR(adapter, I82595_CONFIG2_REG, result);
|
|
|
|
// according to the docs, the configure is triggered by a write to reg 3, so we just
|
|
// read and write to it...
|
|
//
|
|
EPRO_RD_PORT_UCHAR(adapter, I82595_CONFIG3_REG, &result);
|
|
EPRO_WR_PORT_UCHAR(adapter, I82595_CONFIG3_REG, result);
|
|
|
|
// Probably don't need this (82595 is supposed to default to bank0 after
|
|
// a reset or sel-reset
|
|
//
|
|
EPRO_SWITCH_BANK_0(adapter);
|
|
|
|
// need to do a selreset after a config register modification
|
|
// per 82595 docs...
|
|
//
|
|
EProSelReset(adapter);
|
|
|
|
EPRO_ASSERT_BANK_0(adapter);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
EProChangeMulticastList(
|
|
IN PEPRO_ADAPTER adapter,
|
|
IN UINT addressCount,
|
|
IN UCHAR addresses[][EPRO_LENGTH_OF_ADDRESS])
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine changed the multicast list as stored by the driver.
|
|
IT DOES NOT ACTUALLY MODIFY THE MULTICAST LIST IN THE HARDWARE ---
|
|
EProSetCardMulticastList does that.
|
|
|
|
Arguments:
|
|
|
|
adapter - pointer to our adapter structure
|
|
|
|
addressCount - how many addresses to set
|
|
|
|
addresses[] - the data...
|
|
|
|
Return Values:
|
|
|
|
NDIS_STATUS_NOT_ACCEPTED - tried to set too many (notreached b/c
|
|
setpacketfilter checks this too)
|
|
NDIS_STATUS_SUCCESS - operation completed ok.
|
|
|
|
--*/
|
|
{
|
|
UINT i;
|
|
BOOLEAN fReturn = FALSE;
|
|
|
|
EPRO_DPRINTF_REQ(("EProChangeMulticastList. Setting %d addresses...\n",
|
|
addressCount));
|
|
|
|
// now, put the multicast list into the adapter structure...
|
|
//
|
|
for (i = 0; i < addressCount; i++)
|
|
{
|
|
NdisMoveMemory(
|
|
&adapter->MCAddress[i],
|
|
&addresses[i],
|
|
EPRO_LENGTH_OF_ADDRESS);
|
|
}
|
|
|
|
//
|
|
// If we just cleared the multicast address list then we need to
|
|
// return the fact.
|
|
//
|
|
if ((adapter->NumMCAddresses != 0) && (0 == addressCount))
|
|
{
|
|
fReturn = TRUE;
|
|
}
|
|
|
|
//
|
|
// Save the new number of multicast addresses.
|
|
//
|
|
adapter->NumMCAddresses = addressCount;
|
|
|
|
return(fReturn);
|
|
}
|
|
|
|
|
|
BOOLEAN EProSetCardMulticastList(PEPRO_ADAPTER adapter, int operation)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the routine which takes the driver's MC list and copies it down
|
|
to the card. The MC list must already be set in the driver with
|
|
EProChangeMulticastList.
|
|
|
|
Arguments:
|
|
|
|
adapter - pointer to our adapter structure
|
|
|
|
operation - see epro.h for the definitions. Basically SET or CLEAR
|
|
either we are turning off MC or re-entering the list.
|
|
|
|
Return Values:
|
|
|
|
TRUE - MC list set okay and has been PENDED (completed in EProHandleInterrupt)
|
|
FALSE - MC list didn't set okay and was not pended
|
|
|
|
--*/
|
|
{
|
|
// The header for the MC_SETUP structure
|
|
EPRO_MC_HEADER mcHead;
|
|
|
|
// Setting the MC list uses a transmit buffer.
|
|
PEPRO_TRANSMIT_BUFFER curTBuf = adapter->CurrentTXBuf;
|
|
|
|
// look variable...
|
|
BOOLEAN fGotBuffer = FALSE;
|
|
|
|
USHORT lengthNeeded = I82595_TX_FRM_HDR_SIZE +
|
|
(adapter->NumMCAddresses * EPRO_LENGTH_OF_ADDRESS) + 2;
|
|
USHORT timeout = 0;
|
|
|
|
EPRO_ASSERT_BANK_0(adapter);
|
|
EPRO_DPRINTF_REQ(("Setting the MC list on the card...%d\n", operation));
|
|
|
|
// Make sure we have a free buffer pointer structure.
|
|
//
|
|
if (!curTBuf->fEmpty)
|
|
{
|
|
while (!EProCheckTransmitCompletion(adapter, curTBuf))
|
|
{
|
|
timeout++;
|
|
|
|
if (timeout > EPRO_TX_TIMEOUT)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
NdisStallExecution(1);
|
|
}
|
|
}
|
|
|
|
// Is there a transmit in progress? If not, then we can just
|
|
// set the buffer to address zero and go
|
|
//
|
|
if (adapter->TXChainStart == NULL)
|
|
{
|
|
curTBuf->TXBaseAddr = EPRO_TX_LOWER_LIMIT_SHORT;
|
|
}
|
|
else
|
|
{
|
|
// Okay, there is a transmit in progress. Let's see if there is enough
|
|
// transmit buffer space.
|
|
//
|
|
USHORT freeSpace = 0;
|
|
|
|
// are we above the free space?
|
|
//
|
|
if (adapter->TXChainStart->TXBaseAddr < curTBuf->TXBaseAddr)
|
|
{
|
|
freeSpace = EPRO_TX_UPPER_LIMIT_SHORT - curTBuf->TXBaseAddr;
|
|
freeSpace += adapter->TXChainStart->TXBaseAddr -
|
|
EPRO_TX_LOWER_LIMIT_SHORT;
|
|
}
|
|
else
|
|
{
|
|
freeSpace = adapter->TXChainStart->TXBaseAddr -
|
|
curTBuf->TXBaseAddr;
|
|
}
|
|
|
|
|
|
while (freeSpace < lengthNeeded)
|
|
{
|
|
UINT timeout1;
|
|
|
|
while (!EProCheckTransmitCompletion(adapter, adapter->TXChainStart))
|
|
{
|
|
if (timeout1++ > EPRO_TX_TIMEOUT)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
NdisStallExecution(1);
|
|
}
|
|
|
|
if (adapter->TXChainStart->TXBaseAddr < curTBuf->TXBaseAddr)
|
|
{
|
|
freeSpace = EPRO_TX_UPPER_LIMIT_SHORT - curTBuf->TXBaseAddr;
|
|
freeSpace += adapter->TXChainStart->TXBaseAddr -
|
|
EPRO_TX_LOWER_LIMIT_SHORT;
|
|
}
|
|
else
|
|
{
|
|
freeSpace = adapter->TXChainStart->TXBaseAddr -
|
|
curTBuf->TXBaseAddr;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Okay, now we have to make sure we've got enough space to actually
|
|
// put the data in the transmit area...
|
|
//
|
|
|
|
// Now we've got a buffer....
|
|
//
|
|
EPRO_ASSERT(curTBuf->fEmpty);
|
|
|
|
mcHead.CommandField = I82595_CMD_MC_SETUP;
|
|
|
|
// Clear the header
|
|
//
|
|
NdisZeroMemory(mcHead.NullBytes, 5);
|
|
|
|
// Okay, are we setting or clearing? If we're clearing then the byte count
|
|
// is 0, if we're setting, then its a function of the number of addresses...
|
|
//
|
|
if (operation != EPRO_CLEAR_CARD_MC)
|
|
{
|
|
mcHead.ByteCountLo = (adapter->NumMCAddresses * EPRO_LENGTH_OF_ADDRESS) & 0xff;
|
|
mcHead.ByteCountHi = (adapter->NumMCAddresses * EPRO_LENGTH_OF_ADDRESS) >> 8;
|
|
}
|
|
else
|
|
{
|
|
mcHead.ByteCountLo = 0;
|
|
mcHead.ByteCountHi = 0;
|
|
}
|
|
|
|
EPRO_DPRINTF_REQ(("There are %d MC addresses.\n", adapter->NumMCAddresses));
|
|
EPRO_DPRINTF_REQ(("There are %x%x bytes of MC addresses at %lx\n", mcHead.ByteCountHi,
|
|
mcHead.ByteCountLo, &adapter->MCAddress));
|
|
EPRO_DPRINTF_REQ(("Sizeof MCHEAD is %x\n", sizeof(mcHead)));
|
|
|
|
// bank0
|
|
//
|
|
EPRO_ASSERT_BANK_0(adapter);
|
|
|
|
EPRO_DPRINTF_REQ(("Address on card is %lx\n", curTBuf->TXBaseAddr));
|
|
EPRO_SET_HOST_ADDR(adapter, curTBuf->TXBaseAddr);
|
|
EPRO_COPY_BUFFER_TO_NIC_USHORT(adapter, ((USHORT *)(&mcHead)), sizeof(mcHead) >> 1);
|
|
|
|
if (operation != EPRO_CLEAR_CARD_MC)
|
|
{
|
|
// since we know the len_of_address is an even #, we make the
|
|
// assumption here that the amount of memory to copy is divisible
|
|
// by two (so the shift is safe)
|
|
//
|
|
EPRO_COPY_BUFFER_TO_NIC_USHORT(
|
|
adapter,
|
|
(USHORT *)(&adapter->MCAddress),
|
|
(adapter->NumMCAddresses * 3)); // 3 shorts...
|
|
}
|
|
|
|
|
|
// okay, set up to and pend this thing....
|
|
|
|
if (!EProWaitForExeDma(adapter))
|
|
{
|
|
// we're in trouble if this happens...
|
|
//
|
|
adapter->fHung = TRUE;
|
|
return(FALSE);
|
|
// EPRO_ASSERT(FALSE);
|
|
}
|
|
|
|
adapter->IntPending = EPRO_INT_MC_SET_PENDING;
|
|
adapter->IntContext = (PVOID)curTBuf;
|
|
|
|
// enable EXE interrupts so we can do this asynchronously...
|
|
//
|
|
EProSetInterruptMask(adapter, EPRO_RX_TX_EXE_INTERRUPTS);
|
|
|
|
// set the BAR and go....
|
|
//
|
|
EPRO_WR_PORT_USHORT(adapter, I82595_TX_BAR_REG, curTBuf->TXBaseAddr);
|
|
EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_CMD_MC_SETUP);
|
|
|
|
// Move the currenttxbuf pointer forward...
|
|
//
|
|
adapter->CurrentTXBuf = curTBuf->NextBuf;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|