1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
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
99
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 = (ecmd->advertising & 0x002F);
121 } else {
122 hw->autoneg = 0;
123 switch(ecmd->speed + ecmd->duplex) {
124 case SPEED_10 + DUPLEX_HALF:
125 hw->forced_speed_duplex = e1000_10_half;
126 break;
127 case SPEED_10 + DUPLEX_FULL:
128 hw->forced_speed_duplex = e1000_10_full;
129 break;
130 case SPEED_100 + DUPLEX_HALF:
131 hw->forced_speed_duplex = e1000_100_half;
132 break;
133 case SPEED_100 + DUPLEX_FULL:
134 hw->forced_speed_duplex = e1000_100_full;
135 break;
136 case SPEED_1000 + DUPLEX_FULL:
137 hw->autoneg = 1;
138 hw->autoneg_advertised = ADVERTISE_1000_FULL;
139 break;
140 case SPEED_1000 + DUPLEX_HALF:
141 default:
142 return -EINVAL;
143 }
144 }
145
146
147
148 if(netif_running(adapter->netdev)) {
149 e1000_down(adapter);
150 e1000_up(adapter);
151 } else
152 e1000_reset(adapter);
153
154 return 0;
155}
156
157static inline int
158e1000_eeprom_size(struct e1000_hw *hw)
159{
160 if((hw->mac_type > e1000_82544) &&
161 (E1000_READ_REG(hw, EECD) & E1000_EECD_SIZE))
162 return 512;
163 else
164 return 128;
165}
166
167static void
168e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
169 struct ethtool_drvinfo *drvinfo)
170{
171 strncpy(drvinfo->driver, e1000_driver_name, 32);
172 strncpy(drvinfo->version, e1000_driver_version, 32);
173 strncpy(drvinfo->fw_version, "N/A", 32);
174 strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
175#define E1000_REGS_LEN 32
176 drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t);
177 drvinfo->eedump_len = e1000_eeprom_size(&adapter->hw);
178}
179
180static void
181e1000_ethtool_gregs(struct e1000_adapter *adapter,
182 struct ethtool_regs *regs, uint32_t *regs_buff)
183{
184 struct e1000_hw *hw = &adapter->hw;
185
186 regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
187
188 regs_buff[0] = E1000_READ_REG(hw, CTRL);
189 regs_buff[1] = E1000_READ_REG(hw, STATUS);
190
191 regs_buff[2] = E1000_READ_REG(hw, RCTL);
192 regs_buff[3] = E1000_READ_REG(hw, RDLEN);
193 regs_buff[4] = E1000_READ_REG(hw, RDH);
194 regs_buff[5] = E1000_READ_REG(hw, RDT);
195 regs_buff[6] = E1000_READ_REG(hw, RDTR);
196
197 regs_buff[7] = E1000_READ_REG(hw, TCTL);
198 regs_buff[8] = E1000_READ_REG(hw, TDLEN);
199 regs_buff[9] = E1000_READ_REG(hw, TDH);
200 regs_buff[10] = E1000_READ_REG(hw, TDT);
201 regs_buff[11] = E1000_READ_REG(hw, TIDV);
202
203 return;
204}
205
206static int
207e1000_ethtool_geeprom(struct e1000_adapter *adapter,
208 struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
209{
210 struct e1000_hw *hw = &adapter->hw;
211 int i, max_len, first_word, last_word;
212
213 if(eeprom->len == 0)
214 return -EINVAL;
215
216 eeprom->magic = hw->vendor_id | (hw->device_id << 16);
217
218 max_len = e1000_eeprom_size(hw);
219
220 if(eeprom->offset > eeprom->offset + eeprom->len)
221 return -EINVAL;
222
223 if((eeprom->offset + eeprom->len) > max_len)
224 eeprom->len = (max_len - eeprom->offset);
225
226 first_word = eeprom->offset >> 1;
227 last_word = (eeprom->offset + eeprom->len - 1) >> 1;
228
229 for(i = 0; i <= (last_word - first_word); i++)
230 e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]);
231 return 0;
232}
233
234static int
235e1000_ethtool_seeprom(struct e1000_adapter *adapter,
236 struct ethtool_eeprom *eeprom, void *user_data)
237{
238 struct e1000_hw *hw = &adapter->hw;
239 uint16_t eeprom_buff[256];
240 int i, max_len, first_word, last_word;
241 void *ptr;
242
243 if(eeprom->len == 0)
244 return -EOPNOTSUPP;
245
246 if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
247 return -EFAULT;
248
249 max_len = e1000_eeprom_size(hw);
250
251 if((eeprom->offset + eeprom->len) > max_len)
252 eeprom->len = (max_len - eeprom->offset);
253
254 first_word = eeprom->offset >> 1;
255 last_word = (eeprom->offset + eeprom->len - 1) >> 1;
256 ptr = (void *)eeprom_buff;
257
258 if(eeprom->offset & 1) {
259
260
261 e1000_read_eeprom(hw, first_word, &eeprom_buff[0]);
262 ptr++;
263 }
264 if((eeprom->offset + eeprom->len) & 1) {
265
266
267 e1000_read_eeprom(hw, last_word,
268 &eeprom_buff[last_word - first_word]);
269 }
270 if(copy_from_user(ptr, user_data, eeprom->len))
271 return -EFAULT;
272
273 for(i = 0; i <= (last_word - first_word); i++)
274 e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]);
275
276
277 if(first_word <= EEPROM_CHECKSUM_REG)
278 e1000_update_eeprom_checksum(hw);
279
280 return 0;
281}
282
283static void
284e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
285{
286 struct e1000_hw *hw = &adapter->hw;
287
288 switch(adapter->hw.device_id) {
289 case E1000_DEV_ID_82542:
290 case E1000_DEV_ID_82543GC_FIBER:
291 case E1000_DEV_ID_82543GC_COPPER:
292 case E1000_DEV_ID_82544EI_FIBER:
293 default:
294 wol->supported = 0;
295 wol->wolopts = 0;
296 return;
297
298 case E1000_DEV_ID_82546EB_FIBER:
299
300 if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
301 wol->supported = 0;
302 wol->wolopts = 0;
303 return;
304 }
305
306
307 case E1000_DEV_ID_82544EI_COPPER:
308 case E1000_DEV_ID_82544GC_COPPER:
309 case E1000_DEV_ID_82544GC_LOM:
310 case E1000_DEV_ID_82540EM:
311 case E1000_DEV_ID_82540EM_LOM:
312 case E1000_DEV_ID_82545EM_COPPER:
313 case E1000_DEV_ID_82545EM_FIBER:
314 case E1000_DEV_ID_82546EB_COPPER:
315 wol->supported = WAKE_PHY | WAKE_UCAST |
316 WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
317
318 wol->wolopts = 0;
319 if(adapter->wol & E1000_WUFC_LNKC)
320 wol->wolopts |= WAKE_PHY;
321 if(adapter->wol & E1000_WUFC_EX)
322 wol->wolopts |= WAKE_UCAST;
323 if(adapter->wol & E1000_WUFC_MC)
324 wol->wolopts |= WAKE_MCAST;
325 if(adapter->wol & E1000_WUFC_BC)
326 wol->wolopts |= WAKE_BCAST;
327 if(adapter->wol & E1000_WUFC_MAG)
328 wol->wolopts |= WAKE_MAGIC;
329 return;
330 }
331}
332
333static int
334e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
335{
336 struct e1000_hw *hw = &adapter->hw;
337
338 switch(adapter->hw.device_id) {
339 case E1000_DEV_ID_82542:
340 case E1000_DEV_ID_82543GC_FIBER:
341 case E1000_DEV_ID_82543GC_COPPER:
342 case E1000_DEV_ID_82544EI_FIBER:
343 default:
344 return wol->wolopts ? -EOPNOTSUPP : 0;
345
346 case E1000_DEV_ID_82546EB_FIBER:
347
348 if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
349 return wol->wolopts ? -EOPNOTSUPP : 0;
350
351
352 case E1000_DEV_ID_82544EI_COPPER:
353 case E1000_DEV_ID_82544GC_COPPER:
354 case E1000_DEV_ID_82544GC_LOM:
355 case E1000_DEV_ID_82540EM:
356 case E1000_DEV_ID_82540EM_LOM:
357 case E1000_DEV_ID_82545EM_COPPER:
358 case E1000_DEV_ID_82545EM_FIBER:
359 case E1000_DEV_ID_82546EB_COPPER:
360 if(wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
361 return -EOPNOTSUPP;
362
363 adapter->wol = 0;
364
365 if(wol->wolopts & WAKE_PHY)
366 adapter->wol |= E1000_WUFC_LNKC;
367 if(wol->wolopts & WAKE_UCAST)
368 adapter->wol |= E1000_WUFC_EX;
369 if(wol->wolopts & WAKE_MCAST)
370 adapter->wol |= E1000_WUFC_MC;
371 if(wol->wolopts & WAKE_BCAST)
372 adapter->wol |= E1000_WUFC_BC;
373 if(wol->wolopts & WAKE_MAGIC)
374 adapter->wol |= E1000_WUFC_MAG;
375 }
376
377 return 0;
378}
379
380
381
382#define E1000_ID_INTERVAL (HZ/4)
383
384
385#define E1000_LED_ON 0
386
387static void
388e1000_led_blink_callback(unsigned long data)
389{
390 struct e1000_adapter *adapter = (struct e1000_adapter *) data;
391
392 if(test_and_change_bit(E1000_LED_ON, &adapter->led_status))
393 e1000_led_off(&adapter->hw);
394 else
395 e1000_led_on(&adapter->hw);
396
397 mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);
398}
399
400static int
401e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id)
402{
403 if(!adapter->blink_timer.function) {
404 init_timer(&adapter->blink_timer);
405 adapter->blink_timer.function = e1000_led_blink_callback;
406 adapter->blink_timer.data = (unsigned long) adapter;
407 }
408
409 e1000_setup_led(&adapter->hw);
410 mod_timer(&adapter->blink_timer, jiffies);
411
412 set_current_state(TASK_INTERRUPTIBLE);
413 if(id->data)
414 schedule_timeout(id->data * HZ);
415 else
416 schedule_timeout(MAX_SCHEDULE_TIMEOUT);
417
418 del_timer_sync(&adapter->blink_timer);
419 e1000_led_off(&adapter->hw);
420 clear_bit(E1000_LED_ON, &adapter->led_status);
421 e1000_cleanup_led(&adapter->hw);
422
423 return 0;
424}
425
426int
427e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
428{
429 struct e1000_adapter *adapter = netdev->priv;
430 void *addr = ifr->ifr_data;
431 uint32_t cmd;
432
433 if(get_user(cmd, (uint32_t *) addr))
434 return -EFAULT;
435
436 switch(cmd) {
437 case ETHTOOL_GSET: {
438 struct ethtool_cmd ecmd = {ETHTOOL_GSET};
439 e1000_ethtool_gset(adapter, &ecmd);
440 if(copy_to_user(addr, &ecmd, sizeof(ecmd)))
441 return -EFAULT;
442 return 0;
443 }
444 case ETHTOOL_SSET: {
445 struct ethtool_cmd ecmd;
446 if(!capable(CAP_NET_ADMIN))
447 return -EPERM;
448 if(copy_from_user(&ecmd, addr, sizeof(ecmd)))
449 return -EFAULT;
450 return e1000_ethtool_sset(adapter, &ecmd);
451 }
452 case ETHTOOL_GDRVINFO: {
453 struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO};
454 e1000_ethtool_gdrvinfo(adapter, &drvinfo);
455 if(copy_to_user(addr, &drvinfo, sizeof(drvinfo)))
456 return -EFAULT;
457 return 0;
458 }
459 case ETHTOOL_GREGS: {
460 struct ethtool_regs regs = {ETHTOOL_GREGS};
461 uint32_t regs_buff[E1000_REGS_LEN];
462
463 if(copy_from_user(®s, addr, sizeof(regs)))
464 return -EFAULT;
465 e1000_ethtool_gregs(adapter, ®s, regs_buff);
466 if(copy_to_user(addr, ®s, sizeof(regs)))
467 return -EFAULT;
468
469 addr += offsetof(struct ethtool_regs, data);
470 if(copy_to_user(addr, regs_buff, regs.len))
471 return -EFAULT;
472
473 return 0;
474 }
475 case ETHTOOL_NWAY_RST: {
476 if(!capable(CAP_NET_ADMIN))
477 return -EPERM;
478 if(netif_running(netdev)) {
479 e1000_down(adapter);
480 e1000_up(adapter);
481 }
482 return 0;
483 }
484 case ETHTOOL_PHYS_ID: {
485 struct ethtool_value id;
486 if(copy_from_user(&id, addr, sizeof(id)))
487 return -EFAULT;
488 return e1000_ethtool_led_blink(adapter, &id);
489 }
490 case ETHTOOL_GLINK: {
491 struct ethtool_value link = {ETHTOOL_GLINK};
492 link.data = netif_carrier_ok(netdev);
493 if(copy_to_user(addr, &link, sizeof(link)))
494 return -EFAULT;
495 return 0;
496 }
497 case ETHTOOL_GWOL: {
498 struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
499 e1000_ethtool_gwol(adapter, &wol);
500 if(copy_to_user(addr, &wol, sizeof(wol)) != 0)
501 return -EFAULT;
502 return 0;
503 }
504 case ETHTOOL_SWOL: {
505 struct ethtool_wolinfo wol;
506 if(!capable(CAP_NET_ADMIN))
507 return -EPERM;
508 if(copy_from_user(&wol, addr, sizeof(wol)) != 0)
509 return -EFAULT;
510 return e1000_ethtool_swol(adapter, &wol);
511 }
512 case ETHTOOL_GEEPROM: {
513 struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM};
514 uint16_t eeprom_buff[256];
515 void *ptr;
516 int err;
517
518 if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
519 return -EFAULT;
520
521 if((err = e1000_ethtool_geeprom(adapter, &eeprom, eeprom_buff))<0)
522 return err;
523
524 if(copy_to_user(addr, &eeprom, sizeof(eeprom)))
525 return -EFAULT;
526
527 addr += offsetof(struct ethtool_eeprom, data);
528 ptr = ((void *)eeprom_buff) + (eeprom.offset & 1);
529
530 if(copy_to_user(addr, ptr, eeprom.len))
531 return -EFAULT;
532 return 0;
533 }
534 case ETHTOOL_SEEPROM: {
535 struct ethtool_eeprom eeprom;
536
537 if(!capable(CAP_NET_ADMIN))
538 return -EPERM;
539
540 if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
541 return -EFAULT;
542
543 addr += offsetof(struct ethtool_eeprom, data);
544 return e1000_ethtool_seeprom(adapter, &eeprom, addr);
545 }
546 default:
547 return -EOPNOTSUPP;
548 }
549}
550
551
552