1/******************************************************************************* 2 3 4 Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. 5 6 This program is free software; you can redistribute it and/or modify it 7 under the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 2 of the License, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 more details. 15 16 You should have received a copy of the GNU General Public License along with 17 this program; if not, write to the Free Software Foundation, Inc., 59 18 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 The full GNU General Public License is included in this distribution in the 21 file called LICENSE. 22 23 Contact Information: 24 Linux NICS <linux.nics@intel.com> 25 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 26 27*******************************************************************************/ 28 29/* ethtool support for e1000 */ 30 31#include "e1000.h" 32 33#include <asm/uaccess.h> 34 35extern char e1000_driver_name[]; 36extern char e1000_driver_version[]; 37 38extern int e1000_up(struct e1000_adapter *adapter); 39extern void e1000_down(struct e1000_adapter *adapter); 40extern void e1000_reset(struct e1000_adapter *adapter); 41 42static void 43e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) 44{ 45 struct e1000_hw *hw = &adapter->hw; 46 47 if(hw->media_type == e1000_media_type_copper) { 48 49 ecmd->supported = (SUPPORTED_10baseT_Half | 50 SUPPORTED_10baseT_Full | 51 SUPPORTED_100baseT_Half | 52 SUPPORTED_100baseT_Full | 53 SUPPORTED_1000baseT_Full| 54 SUPPORTED_Autoneg | 55 SUPPORTED_TP); 56 57 ecmd->advertising = ADVERTISED_TP; 58 59 if(hw->autoneg == 1) { 60 ecmd->advertising |= ADVERTISED_Autoneg; 61 62 /* the e1000 autoneg seems to match ethtool nicely */ 63 64 ecmd->advertising |= hw->autoneg_advertised; 65 } 66 67 ecmd->port = PORT_TP; 68 ecmd->phy_address = hw->phy_addr; 69 70 if(hw->mac_type == e1000_82543) 71 ecmd->transceiver = XCVR_EXTERNAL; 72 else 73 ecmd->transceiver = XCVR_INTERNAL; 74 75 } else { 76 ecmd->supported = (SUPPORTED_1000baseT_Full | 77 SUPPORTED_FIBRE | 78 SUPPORTED_Autoneg); 79 80 ecmd->advertising = (SUPPORTED_1000baseT_Full | 81 SUPPORTED_FIBRE | 82 SUPPORTED_Autoneg); 83 84 ecmd->port = PORT_FIBRE; 85 86 if(hw->mac_type >= e1000_82545) 87 ecmd->transceiver = XCVR_INTERNAL; 88 else 89 ecmd->transceiver = XCVR_EXTERNAL; 90 } 91 92 if(netif_carrier_ok(adapter->netdev)) { 93 94 e1000_get_speed_and_duplex(hw, &adapter->link_speed, 95 &adapter->link_duplex); 96 ecmd->speed = adapter->link_speed; 97 98 /* unfortunatly FULL_DUPLEX != DUPLEX_FULL 99 * and HALF_DUPLEX != DUPLEX_HALF */ 100 101 if(adapter->link_duplex == FULL_DUPLEX) 102 ecmd->duplex = DUPLEX_FULL; 103 else 104 ecmd->duplex = DUPLEX_HALF; 105 } else { 106 ecmd->speed = -1; 107 ecmd->duplex = -1; 108 } 109 110 ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); 111} 112 113static int 114e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) 115{ 116 struct e1000_hw *hw = &adapter->hw; 117 118 if(ecmd->autoneg == AUTONEG_ENABLE) { 119 hw->autoneg = 1; 120 hw->autoneg_advertised = 0x002F; 121 ecmd->advertising = 0x002F; 122 } else { 123 hw->autoneg = 0; 124 switch(ecmd->speed + ecmd->duplex) { 125 case SPEED_10 + DUPLEX_HALF: 126 hw->forced_speed_duplex = e1000_10_half; 127 break; 128 case SPEED_10 + DUPLEX_FULL: 129 hw->forced_speed_duplex = e1000_10_full; 130 break; 131 case SPEED_100 + DUPLEX_HALF: 132 hw->forced_speed_duplex = e1000_100_half; 133 break; 134 case SPEED_100 + DUPLEX_FULL: 135 hw->forced_speed_duplex = e1000_100_full; 136 break; 137 case SPEED_1000 + DUPLEX_FULL: 138 hw->autoneg = 1; 139 hw->autoneg_advertised = ADVERTISE_1000_FULL; 140 break; 141 case SPEED_1000 + DUPLEX_HALF: /* not supported */ 142 default: 143 return -EINVAL; 144 } 145 } 146 147 /* reset the link */ 148 149 if(netif_running(adapter->netdev)) { 150 e1000_down(adapter); 151 e1000_up(adapter); 152 } else 153 e1000_reset(adapter); 154 155 return 0; 156} 157 158static inline int 159e1000_eeprom_size(struct e1000_hw *hw) 160{ 161 if((hw->mac_type > e1000_82544) && 162 (E1000_READ_REG(hw, EECD) & E1000_EECD_SIZE)) 163 return 512; 164 else 165 return 128; 166} 167 168static void 169e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, 170 struct ethtool_drvinfo *drvinfo) 171{ 172 strncpy(drvinfo->driver, e1000_driver_name, 32); 173 strncpy(drvinfo->version, e1000_driver_version, 32); 174 strncpy(drvinfo->fw_version, "N/A", 32); 175 strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32); 176#define E1000_REGS_LEN 32 177 drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); 178 drvinfo->eedump_len = e1000_eeprom_size(&adapter->hw); 179} 180 181static void 182e1000_ethtool_gregs(struct e1000_adapter *adapter, 183 struct ethtool_regs *regs, uint32_t *regs_buff) 184{ 185 struct e1000_hw *hw = &adapter->hw; 186 187 regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; 188 189 regs_buff[0] = E1000_READ_REG(hw, CTRL); 190 regs_buff[1] = E1000_READ_REG(hw, STATUS); 191 192 regs_buff[2] = E1000_READ_REG(hw, RCTL); 193 regs_buff[3] = E1000_READ_REG(hw, RDLEN); 194 regs_buff[4] = E1000_READ_REG(hw, RDH); 195 regs_buff[5] = E1000_READ_REG(hw, RDT); 196 regs_buff[6] = E1000_READ_REG(hw, RDTR); 197 198 regs_buff[7] = E1000_READ_REG(hw, TCTL); 199 regs_buff[8] = E1000_READ_REG(hw, TDLEN); 200 regs_buff[9] = E1000_READ_REG(hw, TDH); 201 regs_buff[10] = E1000_READ_REG(hw, TDT); 202 regs_buff[11] = E1000_READ_REG(hw, TIDV); 203 204 return; 205} 206 207static int 208e1000_ethtool_geeprom(struct e1000_adapter *adapter, 209 struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) 210{ 211 struct e1000_hw *hw = &adapter->hw; 212 int i, max_len, first_word, last_word; 213 214 if(eeprom->len == 0) 215 return -EINVAL; 216 217 eeprom->magic = hw->vendor_id | (hw->device_id << 16); 218 219 max_len = e1000_eeprom_size(hw); 220 221 if(eeprom->offset > eeprom->offset + eeprom->len) 222 return -EINVAL; 223 224 if((eeprom->offset + eeprom->len) > max_len) 225 eeprom->len = (max_len - eeprom->offset); 226 227 first_word = eeprom->offset >> 1; 228 last_word = (eeprom->offset + eeprom->len - 1) >> 1; 229 230 for(i = 0; i <= (last_word - first_word); i++) 231 e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]); 232 233 return 0; 234} 235 236static int 237e1000_ethtool_seeprom(struct e1000_adapter *adapter, 238 struct ethtool_eeprom *eeprom, void *user_data) 239{ 240 struct e1000_hw *hw = &adapter->hw; 241 uint16_t eeprom_buff[256]; 242 int i, max_len, first_word, last_word; 243 void *ptr; 244 245 if(eeprom->len == 0) 246 return -EOPNOTSUPP; 247 248 if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) 249 return -EFAULT; 250 251 max_len = e1000_eeprom_size(hw); 252 253 if((eeprom->offset + eeprom->len) > max_len) 254 eeprom->len = (max_len - eeprom->offset); 255 256 first_word = eeprom->offset >> 1; 257 last_word = (eeprom->offset + eeprom->len - 1) >> 1; 258 ptr = (void *)eeprom_buff; 259 260 if(eeprom->offset & 1) { 261 /* need read/modify/write of first changed EEPROM word */ 262 /* only the second byte of the word is being modified */ 263 e1000_read_eeprom(hw, first_word, &eeprom_buff[0]); 264 ptr++; 265 } 266 if((eeprom->offset + eeprom->len) & 1) { 267 /* need read/modify/write of last changed EEPROM word */ 268 /* only the first byte of the word is being modified */ 269 e1000_read_eeprom(hw, last_word, 270 &eeprom_buff[last_word - first_word]); 271 } 272 if(copy_from_user(ptr, user_data, eeprom->len)) 273 return -EFAULT; 274 275 for(i = 0; i <= (last_word - first_word); i++) 276 e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]); 277 278 /* Update the checksum over the first part of the EEPROM if needed */ 279 if(first_word <= EEPROM_CHECKSUM_REG) 280 e1000_update_eeprom_checksum(hw); 281 282 return 0; 283} 284 285static void 286e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) 287{ 288 struct e1000_hw *hw = &adapter->hw; 289 290 switch(adapter->hw.device_id) { 291 case E1000_DEV_ID_82542: 292 case E1000_DEV_ID_82543GC_FIBER: 293 case E1000_DEV_ID_82543GC_COPPER: 294 case E1000_DEV_ID_82544EI_FIBER: 295 wol->supported = 0; 296 wol->wolopts = 0; 297 return; 298 299 case E1000_DEV_ID_82546EB_FIBER: 300 /* Wake events only supported on port A for dual fiber */ 301 if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { 302 wol->supported = 0; 303 wol->wolopts = 0; 304 return; 305 } 306 /* Fall Through */ 307 308 default: 309 wol->supported = WAKE_PHY | WAKE_UCAST | 310 WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; 311 312 wol->wolopts = 0; 313 if(adapter->wol & E1000_WUFC_LNKC) 314 wol->wolopts |= WAKE_PHY; 315 if(adapter->wol & E1000_WUFC_EX) 316 wol->wolopts |= WAKE_UCAST; 317 if(adapter->wol & E1000_WUFC_MC) 318 wol->wolopts |= WAKE_MCAST; 319 if(adapter->wol & E1000_WUFC_BC) 320 wol->wolopts |= WAKE_BCAST; 321 if(adapter->wol & E1000_WUFC_MAG) 322 wol->wolopts |= WAKE_MAGIC; 323 return; 324 } 325} 326 327static int 328e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) 329{ 330 struct e1000_hw *hw = &adapter->hw; 331 332 switch(adapter->hw.device_id) { 333 case E1000_DEV_ID_82542: 334 case E1000_DEV_ID_82543GC_FIBER: 335 case E1000_DEV_ID_82543GC_COPPER: 336 case E1000_DEV_ID_82544EI_FIBER: 337 return wol->wolopts ? -EOPNOTSUPP : 0; 338 339 case E1000_DEV_ID_82546EB_FIBER: 340 /* Wake events only supported on port A for dual fiber */ 341 if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) 342 return wol->wolopts ? -EOPNOTSUPP : 0; 343 /* Fall Through */ 344 345 default: 346 if(wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) 347 return -EOPNOTSUPP; 348 349 adapter->wol = 0; 350 351 if(wol->wolopts & WAKE_PHY) 352 adapter->wol |= E1000_WUFC_LNKC; 353 if(wol->wolopts & WAKE_UCAST) 354 adapter->wol |= E1000_WUFC_EX; 355 if(wol->wolopts & WAKE_MCAST) 356 adapter->wol |= E1000_WUFC_MC; 357 if(wol->wolopts & WAKE_BCAST) 358 adapter->wol |= E1000_WUFC_BC; 359 if(wol->wolopts & WAKE_MAGIC) 360 adapter->wol |= E1000_WUFC_MAG; 361 } 362 363 return 0; 364} 365 366 367/* toggle LED 4 times per second = 2 "blinks" per second */ 368#define E1000_ID_INTERVAL (HZ/4) 369 370/* bit defines for adapter->led_status */ 371#define E1000_LED_ON 0 372 373static void 374e1000_led_blink_callback(unsigned long data) 375{ 376 struct e1000_adapter *adapter = (struct e1000_adapter *) data; 377 378 if(test_and_change_bit(E1000_LED_ON, &adapter->led_status)) 379 e1000_led_off(&adapter->hw); 380 else 381 e1000_led_on(&adapter->hw); 382 383 mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL); 384} 385 386static int 387e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id) 388{ 389 if(!adapter->blink_timer.function) { 390 init_timer(&adapter->blink_timer); 391 adapter->blink_timer.function = e1000_led_blink_callback; 392 adapter->blink_timer.data = (unsigned long) adapter; 393 } 394 395 e1000_setup_led(&adapter->hw); 396 mod_timer(&adapter->blink_timer, jiffies); 397 398 set_current_state(TASK_INTERRUPTIBLE); 399 if(id->data) 400 schedule_timeout(id->data * HZ); 401 else 402 schedule_timeout(MAX_SCHEDULE_TIMEOUT); 403 404 del_timer_sync(&adapter->blink_timer); 405 e1000_led_off(&adapter->hw); 406 clear_bit(E1000_LED_ON, &adapter->led_status); 407 e1000_cleanup_led(&adapter->hw); 408 409 return 0; 410} 411 412int 413e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) 414{ 415 struct e1000_adapter *adapter = netdev->priv; 416 void *addr = ifr->ifr_data; 417 uint32_t cmd; 418 419 if(get_user(cmd, (uint32_t *) addr)) 420 return -EFAULT; 421 422 switch(cmd) { 423 case ETHTOOL_GSET: { 424 struct ethtool_cmd ecmd = {ETHTOOL_GSET}; 425 e1000_ethtool_gset(adapter, &ecmd); 426 if(copy_to_user(addr, &ecmd, sizeof(ecmd))) 427 return -EFAULT; 428 return 0; 429 } 430 case ETHTOOL_SSET: { 431 struct ethtool_cmd ecmd; 432 if(!capable(CAP_NET_ADMIN)) 433 return -EPERM; 434 if(copy_from_user(&ecmd, addr, sizeof(ecmd))) 435 return -EFAULT; 436 return e1000_ethtool_sset(adapter, &ecmd); 437 } 438 case ETHTOOL_GDRVINFO: { 439 struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO}; 440 e1000_ethtool_gdrvinfo(adapter, &drvinfo); 441 if(copy_to_user(addr, &drvinfo, sizeof(drvinfo))) 442 return -EFAULT; 443 return 0; 444 } 445 case ETHTOOL_GREGS: { 446 struct ethtool_regs regs = {ETHTOOL_GREGS}; 447 uint32_t regs_buff[E1000_REGS_LEN]; 448 449 if(copy_from_user(®s, addr, sizeof(regs))) 450 return -EFAULT; 451 e1000_ethtool_gregs(adapter, ®s, regs_buff); 452 if(copy_to_user(addr, ®s, sizeof(regs))) 453 return -EFAULT; 454 455 addr += offsetof(struct ethtool_regs, data); 456 if(copy_to_user(addr, regs_buff, regs.len)) 457 return -EFAULT; 458 459 return 0; 460 } 461 case ETHTOOL_NWAY_RST: { 462 if(!capable(CAP_NET_ADMIN)) 463 return -EPERM; 464 if(netif_running(netdev)) { 465 e1000_down(adapter); 466 e1000_up(adapter); 467 } 468 return 0; 469 } 470 case ETHTOOL_PHYS_ID: { 471 struct ethtool_value id; 472 if(copy_from_user(&id, addr, sizeof(id))) 473 return -EFAULT; 474 return e1000_ethtool_led_blink(adapter, &id); 475 } 476 case ETHTOOL_GLINK: { 477 struct ethtool_value link = {ETHTOOL_GLINK}; 478 link.data = netif_carrier_ok(netdev); 479 if(copy_to_user(addr, &link, sizeof(link))) 480 return -EFAULT; 481 return 0; 482 } 483 case ETHTOOL_GWOL: { 484 struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; 485 e1000_ethtool_gwol(adapter, &wol); 486 if(copy_to_user(addr, &wol, sizeof(wol)) != 0) 487 return -EFAULT; 488 return 0; 489 } 490 case ETHTOOL_SWOL: { 491 struct ethtool_wolinfo wol; 492 if(!capable(CAP_NET_ADMIN)) 493 return -EPERM; 494 if(copy_from_user(&wol, addr, sizeof(wol)) != 0) 495 return -EFAULT; 496 return e1000_ethtool_swol(adapter, &wol); 497 } 498 case ETHTOOL_GEEPROM: { 499 struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM}; 500 uint16_t eeprom_buff[256]; 501 void *ptr; 502 int err; 503 504 if(copy_from_user(&eeprom, addr, sizeof(eeprom))) 505 return -EFAULT; 506 507 if((err = e1000_ethtool_geeprom(adapter, 508 &eeprom, eeprom_buff))) 509 return err; 510 511 if(copy_to_user(addr, &eeprom, sizeof(eeprom))) 512 return -EFAULT; 513 514 addr += offsetof(struct ethtool_eeprom, data); 515 ptr = ((void *)eeprom_buff) + (eeprom.offset & 1); 516 517 if(copy_to_user(addr, ptr, eeprom.len)) 518 return -EFAULT; 519 return 0; 520 } 521 case ETHTOOL_SEEPROM: { 522 struct ethtool_eeprom eeprom; 523 524 if(!capable(CAP_NET_ADMIN)) 525 return -EPERM; 526 527 if(copy_from_user(&eeprom, addr, sizeof(eeprom))) 528 return -EFAULT; 529 530 addr += offsetof(struct ethtool_eeprom, data); 531 return e1000_ethtool_seeprom(adapter, &eeprom, addr); 532 } 533 default: 534 return -EOPNOTSUPP; 535 } 536} 537 538 539