From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/ieepro/request.c | 989 +++++++++++++++++++++++++++++++++++++ 1 file changed, 989 insertions(+) create mode 100644 private/ntos/ndis/ieepro/request.c (limited to 'private/ntos/ndis/ieepro/request.c') diff --git a/private/ntos/ndis/ieepro/request.c b/private/ntos/ndis/ieepro/request.c new file mode 100644 index 000000000..995b8c0f2 --- /dev/null +++ b/private/ntos/ndis/ieepro/request.c @@ -0,0 +1,989 @@ +#include +#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); +} + + -- cgit v1.2.3