* Multicast support added;

* STATISTICS switched off to prevent trashing syslog.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43152 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Siarzhuk Zharski 2011-11-03 05:30:51 +00:00
parent be8c82d459
commit f3f68b1f92
3 changed files with 91 additions and 15 deletions

View File

@ -10,6 +10,7 @@
#include <net/if_media.h>
#include <lock.h>
#include <stdio.h>
#include "Driver.h"
#include "Settings.h"
@ -90,7 +91,7 @@ Device::Open(uint32 flags)
fPCIInfo.u.h0.interrupt_line);
}
_SetRxMode(false);
_SetRxMode();
// enable al known interrupts
WritePCI32(IntMask, knownInterruptsMask);
@ -206,13 +207,13 @@ Device::Control(uint32 op, void *buffer, size_t length)
return B_OK;
case ETHER_SETPROMISC:
TRACE("ETHER_SETPROMISC\n");
return _SetRxMode(*((uint8*)buffer));
return _SetRxMode((uint8*)buffer);
case ETHER_ADDMULTI:
return _ModifyMulticastTable(true, (ether_address_t*)buffer);
case ETHER_REMMULTI:
TRACE_ALWAYS("Multicast operations are not implemented.\n");
return B_ERROR;
return _ModifyMulticastTable(false, (ether_address_t*)buffer);
case ETHER_SET_LINK_STATE_SEM:
fLinkStateChangeSem = *(sem_id *)buffer;
@ -408,19 +409,38 @@ Device::GetLinkState(ether_link_state *linkState)
status_t
Device::_SetRxMode(bool isPromiscuousModeOn)
Device::_SetRxMode(uint8* setPromiscuousOn)
{
// clean the Rx MAC Control register
WritePCI16(RxMACControl, (ReadPCI16(RxMACControl) & ~RXM_Mask));
uint16 rxMode = ReadPCI16(RxMACControl);
uint16 rxMode = RXM_Broadcast | RXM_Multicast | RXM_Physical;
if (isPromiscuousModeOn) {
rxMode |= RXM_AllPhysical;
// clean the Rx MAC Control register
WritePCI16(RxMACControl, rxMode & ~RXM_Mask);
rxMode &= RXM_Mask;
if (setPromiscuousOn != NULL) {
if (*setPromiscuousOn != 0)
rxMode |= RXM_AllPhysical;
else
rxMode &= ~RXM_AllPhysical;
}
uint32 multicastFilter[2] = { 0 };
if ((rxMode & RXM_AllPhysical) == 0 && fMulticastHashes.Count() <= 128) {
for (int32 i = 0; i < fMulticastHashes.Count(); i++) {
uint32 hash = fMulticastHashes[i];
multicastFilter[hash >> 31] |= 1 << ((hash >> 26) & 0x1f);
}
} else
multicastFilter[0] = multicastFilter[1] = 0xffffffff;
rxMode |= RXM_Broadcast | RXM_Multicast | RXM_Physical;
// set multicast filters
WritePCI32(RxHashTable, 0xffffffff);
WritePCI32(RxHashTable + 4, 0xffffffff);
WritePCI32(RxHashTable, multicastFilter[0]);
WritePCI32(RxHashTable + 4, multicastFilter[1]);
// update rx mode
WritePCI16(RxMACControl, ReadPCI16(RxMACControl) | rxMode);
@ -519,6 +539,9 @@ Device::_InitRxFilter()
WritePCI8(RxMACAddress + i, fMACAddress.ebyte[i]);
}
// clear promiscuous bit on initialization
filter &= ~RXM_AllPhysical;
// enable packet filtering
WritePCI16(RxMACControl, filter);
}
@ -623,6 +646,52 @@ Device::ReadMACAddress(ether_address_t& address)
}
uint32
Device::_EthernetCRC32(const uint8* buffer, size_t length)
{
uint32 result = 0xffffffff;
for (size_t i = 0; i < length; i++) {
uint8 data = *buffer++;
for (int bit = 0; bit < 8; bit++, data >>= 1) {
uint32 carry = ((result & 0x80000000) ? 1 : 0) ^ (data & 0x01);
result <<= 1;
if (carry != 0)
result = (result ^ 0x04c11db6) | carry;
}
}
return result;
}
status_t
Device::_ModifyMulticastTable(bool join, ether_address_t* group)
{
char groupName[6 * 3 + 1] = { 0 };
sprintf(groupName, "%02x:%02x:%02x:%02x:%02x:%02x",
group->ebyte[0], group->ebyte[1], group->ebyte[2],
group->ebyte[3], group->ebyte[4], group->ebyte[5]);
TRACE("%s multicast group %s\n", join ? "Joining" : "Leaving", groupName);
uint32 hash = _EthernetCRC32(group->ebyte, 6);
bool isInTable = fMulticastHashes.Find(hash) != fMulticastHashes.End();
if (isInTable && join)
return B_OK; // already listed - nothing to do
if (!isInTable && !join) {
TRACE_ALWAYS("Cannot leave unlisted multicast group %s!\n", groupName);
return B_ERROR;
}
if (join)
fMulticastHashes.PushBack(hash);
else
fMulticastHashes.Remove(hash);
return _SetRxMode();
}
void
Device::DumpRegisters()
{

View File

@ -8,6 +8,8 @@
#define _SiS19X_DEVICE_H_
#include <util/Vector.h>
#include "Driver.h"
#include "MIIBus.h"
#include "Registers.h"
@ -83,7 +85,10 @@ protected:
status_t ReadMACAddress(ether_address_t& address);
uint16 _ReadEEPROM(uint32 address);
void _InitRxFilter();
status_t _SetRxMode(bool isPromiscuousModeOn);
status_t _SetRxMode(uint8* setPromiscuousOn = NULL);
uint32 _EthernetCRC32(const uint8* buffer, size_t length);
status_t _ModifyMulticastTable(bool add,
ether_address_t* group);
static int32 _TimerHandler(struct timer* timer);
@ -104,6 +109,8 @@ static int32 _TimerHandler(struct timer* timer);
// connection data
ether_address_t fMACAddress;
Vector<uint32> fMulticastHashes;
public:
bool fOpen;

View File

@ -39,7 +39,7 @@ extern bool gTraceFlow;
"Returns:%#010x\n", result);
#define STATISTICS 1
#define STATISTICS 0
struct Statistics {
Statistics();