* 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:
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <net/if_media.h>
|
#include <net/if_media.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "Driver.h"
|
#include "Driver.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
@@ -90,7 +91,7 @@ Device::Open(uint32 flags)
|
|||||||
fPCIInfo.u.h0.interrupt_line);
|
fPCIInfo.u.h0.interrupt_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
_SetRxMode(false);
|
_SetRxMode();
|
||||||
|
|
||||||
// enable al known interrupts
|
// enable al known interrupts
|
||||||
WritePCI32(IntMask, knownInterruptsMask);
|
WritePCI32(IntMask, knownInterruptsMask);
|
||||||
@@ -206,13 +207,13 @@ Device::Control(uint32 op, void *buffer, size_t length)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
case ETHER_SETPROMISC:
|
case ETHER_SETPROMISC:
|
||||||
TRACE("ETHER_SETPROMISC\n");
|
return _SetRxMode((uint8*)buffer);
|
||||||
return _SetRxMode(*((uint8*)buffer));
|
|
||||||
|
|
||||||
case ETHER_ADDMULTI:
|
case ETHER_ADDMULTI:
|
||||||
|
return _ModifyMulticastTable(true, (ether_address_t*)buffer);
|
||||||
|
|
||||||
case ETHER_REMMULTI:
|
case ETHER_REMMULTI:
|
||||||
TRACE_ALWAYS("Multicast operations are not implemented.\n");
|
return _ModifyMulticastTable(false, (ether_address_t*)buffer);
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
case ETHER_SET_LINK_STATE_SEM:
|
case ETHER_SET_LINK_STATE_SEM:
|
||||||
fLinkStateChangeSem = *(sem_id *)buffer;
|
fLinkStateChangeSem = *(sem_id *)buffer;
|
||||||
@@ -408,19 +409,38 @@ Device::GetLinkState(ether_link_state *linkState)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Device::_SetRxMode(bool isPromiscuousModeOn)
|
Device::_SetRxMode(uint8* setPromiscuousOn)
|
||||||
{
|
{
|
||||||
// clean the Rx MAC Control register
|
uint16 rxMode = ReadPCI16(RxMACControl);
|
||||||
WritePCI16(RxMACControl, (ReadPCI16(RxMACControl) & ~RXM_Mask));
|
|
||||||
|
|
||||||
uint16 rxMode = RXM_Broadcast | RXM_Multicast | RXM_Physical;
|
// clean the Rx MAC Control register
|
||||||
if (isPromiscuousModeOn) {
|
WritePCI16(RxMACControl, rxMode & ~RXM_Mask);
|
||||||
rxMode |= RXM_AllPhysical;
|
|
||||||
|
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
|
// set multicast filters
|
||||||
WritePCI32(RxHashTable, 0xffffffff);
|
WritePCI32(RxHashTable, multicastFilter[0]);
|
||||||
WritePCI32(RxHashTable + 4, 0xffffffff);
|
WritePCI32(RxHashTable + 4, multicastFilter[1]);
|
||||||
|
|
||||||
// update rx mode
|
// update rx mode
|
||||||
WritePCI16(RxMACControl, ReadPCI16(RxMACControl) | rxMode);
|
WritePCI16(RxMACControl, ReadPCI16(RxMACControl) | rxMode);
|
||||||
@@ -519,6 +539,9 @@ Device::_InitRxFilter()
|
|||||||
WritePCI8(RxMACAddress + i, fMACAddress.ebyte[i]);
|
WritePCI8(RxMACAddress + i, fMACAddress.ebyte[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear promiscuous bit on initialization
|
||||||
|
filter &= ~RXM_AllPhysical;
|
||||||
|
|
||||||
// enable packet filtering
|
// enable packet filtering
|
||||||
WritePCI16(RxMACControl, filter);
|
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
|
void
|
||||||
Device::DumpRegisters()
|
Device::DumpRegisters()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#define _SiS19X_DEVICE_H_
|
#define _SiS19X_DEVICE_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <util/Vector.h>
|
||||||
|
|
||||||
#include "Driver.h"
|
#include "Driver.h"
|
||||||
#include "MIIBus.h"
|
#include "MIIBus.h"
|
||||||
#include "Registers.h"
|
#include "Registers.h"
|
||||||
@@ -83,7 +85,10 @@ protected:
|
|||||||
status_t ReadMACAddress(ether_address_t& address);
|
status_t ReadMACAddress(ether_address_t& address);
|
||||||
uint16 _ReadEEPROM(uint32 address);
|
uint16 _ReadEEPROM(uint32 address);
|
||||||
void _InitRxFilter();
|
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);
|
static int32 _TimerHandler(struct timer* timer);
|
||||||
|
|
||||||
@@ -104,6 +109,8 @@ static int32 _TimerHandler(struct timer* timer);
|
|||||||
// connection data
|
// connection data
|
||||||
ether_address_t fMACAddress;
|
ether_address_t fMACAddress;
|
||||||
|
|
||||||
|
Vector<uint32> fMulticastHashes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool fOpen;
|
bool fOpen;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ extern bool gTraceFlow;
|
|||||||
"Returns:%#010x\n", result);
|
"Returns:%#010x\n", result);
|
||||||
|
|
||||||
|
|
||||||
#define STATISTICS 1
|
#define STATISTICS 0
|
||||||
|
|
||||||
struct Statistics {
|
struct Statistics {
|
||||||
Statistics();
|
Statistics();
|
||||||
|
|||||||
Reference in New Issue
Block a user