Implemented ETHER_GET_LINK_STATE and ETHER_SET_LINK_STATE_SEM for rtl8169.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29278 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin 2009-02-22 01:35:15 +00:00
parent 3291c58044
commit bcd9a7e1d4
2 changed files with 99 additions and 4 deletions

View File

@ -24,6 +24,10 @@
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <driver_settings.h> #include <driver_settings.h>
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
#include <net/if_media.h>
#endif
#include "debug.h" #include "debug.h"
#include "device.h" #include "device.h"
@ -379,6 +383,55 @@ rtl8169_rx_int(rtl8169_device *device)
} }
static status_t
rtl8169_get_link_state(rtl8169_device *device)
{
bool link_ok = false;
bool full_duplex = false;
uint32 speed = 0;
bool linkStateChange = false;
uint32 phy;
dump_phy_stat(device);
print_link_status(device);
phy = read8(REG_PHY_STAT);
if (phy & PHY_STAT_EnTBI) {
link_ok = (read32(REG_TBICSR) & TBICSR_TBILinkOk);
if (link_ok) {
speed = 1000000;
full_duplex = true;
}
} else {
if (phy & PHY_STAT_LinkSts) {
link_ok = true;
if (phy & PHY_STAT_1000MF) {
speed = 1000000;
full_duplex = true;
} else {
speed = (phy & PHY_STAT_100M) ? 100000 : 10000;
full_duplex = (phy & PHY_STAT_FullDup);
}
}
}
linkStateChange = (link_ok != device->link_ok
|| full_duplex != device->full_duplex
|| speed != device->speed);
device->link_ok = link_ok;
device->full_duplex = full_duplex;
device->speed = speed;
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
if (linkStateChange && device->linkChangeSem >= B_OK)
release_sem_etc(device->linkChangeSem, 1, B_DO_NOT_RESCHEDULE);
#endif
return B_OK;
}
static int32 static int32
rtl8169_int(void *data) rtl8169_int(void *data)
{ {
@ -406,8 +459,7 @@ rtl8169_int(void *data)
} }
if (stat & INT_PUN) { if (stat & INT_PUN) {
dump_phy_stat(device); rtl8169_get_link_state(device);
print_link_status(device);
} }
if (stat & (INT_TOK | INT_TER)) { if (stat & (INT_TOK | INT_TER)) {
@ -571,8 +623,11 @@ rtl8169_open(const char *name, uint32 flags, void** cookie)
// configure PHY // configure PHY
phy_config(device); phy_config(device);
dump_phy_stat(device); #ifdef HAIKU_TARGET_PLATFORM_HAIKU
print_link_status(device); device->linkChangeSem = -1;
#endif
rtl8169_get_link_state(device);
// initialize MAC address // initialize MAC address
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
@ -914,6 +969,37 @@ rtl8169_control(void *cookie, uint32 op, void *arg, size_t len)
*(uint32*)arg = device->maxframesize; *(uint32*)arg = device->maxframesize;
return B_OK; return B_OK;
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
case ETHER_GET_LINK_STATE:
{
ether_link_state_t state;
state.media = IFM_ETHER;
state.media |= (device->link_ok ? IFM_ACTIVE : 0);
state.media |= (device->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX);
if (device->speed == 1000000)
state.media |= IFM_1000_T;
else if (device->speed == 100000)
state.media |= IFM_100_TX;
else if (device->speed == 10000)
state.media |= IFM_10_T;
state.speed = device->speed;
state.quality = 1000;
return user_memcpy(arg, &state, sizeof(ether_link_state_t));
}
case ETHER_SET_LINK_STATE_SEM:
{
if (user_memcpy(&device->linkChangeSem, arg, sizeof(sem_id)) < B_OK) {
device->linkChangeSem = -1;
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif
default: default:
TRACE("rtl8169_control() Invalid command\n"); TRACE("rtl8169_control() Invalid command\n");
break; break;

View File

@ -92,6 +92,15 @@ typedef struct {
int maxframesize; int maxframesize;
int mac_version; int mac_version;
int phy_version; int phy_version;
bool link_ok;
uint32 speed;
bool full_duplex;
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
sem_id linkChangeSem;
#endif
} rtl8169_device; } rtl8169_device;
#define read8(offset) (*(volatile uint8 *) ((char *)(device->regAddr) + (offset))) #define read8(offset) (*(volatile uint8 *) ((char *)(device->regAddr) + (offset)))