From bcd9a7e1d40c6b9b9476f67ef82b4839708c40b7 Mon Sep 17 00:00:00 2001 From: Philippe Houdoin Date: Sun, 22 Feb 2009 01:35:15 +0000 Subject: [PATCH] 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 --- .../kernel/drivers/network/rtl8169/device.c | 94 ++++++++++++++++++- .../kernel/drivers/network/rtl8169/device.h | 9 ++ 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/src/add-ons/kernel/drivers/network/rtl8169/device.c b/src/add-ons/kernel/drivers/network/rtl8169/device.c index 83e6e42371..375bec7e00 100644 --- a/src/add-ons/kernel/drivers/network/rtl8169/device.c +++ b/src/add-ons/kernel/drivers/network/rtl8169/device.c @@ -24,6 +24,10 @@ #include #include #include +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + #include +#endif + #include "debug.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 rtl8169_int(void *data) { @@ -406,8 +459,7 @@ rtl8169_int(void *data) } if (stat & INT_PUN) { - dump_phy_stat(device); - print_link_status(device); + rtl8169_get_link_state(device); } if (stat & (INT_TOK | INT_TER)) { @@ -571,8 +623,11 @@ rtl8169_open(const char *name, uint32 flags, void** cookie) // configure PHY phy_config(device); - dump_phy_stat(device); - print_link_status(device); +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + device->linkChangeSem = -1; +#endif + + rtl8169_get_link_state(device); // initialize MAC address 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; 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: TRACE("rtl8169_control() Invalid command\n"); break; diff --git a/src/add-ons/kernel/drivers/network/rtl8169/device.h b/src/add-ons/kernel/drivers/network/rtl8169/device.h index 11cc989cc0..4a4ec73803 100644 --- a/src/add-ons/kernel/drivers/network/rtl8169/device.h +++ b/src/add-ons/kernel/drivers/network/rtl8169/device.h @@ -92,6 +92,15 @@ typedef struct { int maxframesize; int mac_version; int phy_version; + + bool link_ok; + uint32 speed; + bool full_duplex; + +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + sem_id linkChangeSem; +#endif + } rtl8169_device; #define read8(offset) (*(volatile uint8 *) ((char *)(device->regAddr) + (offset)))