diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-07-09 18:33:39 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-10 12:22:29 -0400 |
commit | f4331a6d24f2e5524678caf4621d35f33fb934da (patch) | |
tree | f0e6d97478b4e1e25eed0eff767c732834780ef1 /drivers | |
parent | 8a3e3bfdf47b82bfbd78aabf7f72df4dff12abcc (diff) |
sky2: add support for read/write of EEPROM
Add get/set eeprom support for sky2.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/sky2.c | 140 |
1 files changed, 115 insertions, 25 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index b0950e1c4b68..99a999383e9b 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -77,6 +77,9 @@ | |||
77 | #define NAPI_WEIGHT 64 | 77 | #define NAPI_WEIGHT 64 |
78 | #define PHY_RETRIES 1000 | 78 | #define PHY_RETRIES 1000 |
79 | 79 | ||
80 | #define SKY2_EEPROM_MAGIC 0x9955aabb | ||
81 | |||
82 | |||
80 | #define RING_NEXT(x,s) (((x)+1) & ((s)-1)) | 83 | #define RING_NEXT(x,s) (((x)+1) & ((s)-1)) |
81 | 84 | ||
82 | static const u32 default_msg = | 85 | static const u32 default_msg = |
@@ -3429,34 +3432,121 @@ static int sky2_set_tso(struct net_device *dev, u32 data) | |||
3429 | return ethtool_op_set_tso(dev, data); | 3432 | return ethtool_op_set_tso(dev, data); |
3430 | } | 3433 | } |
3431 | 3434 | ||
3435 | static int sky2_get_eeprom_len(struct net_device *dev) | ||
3436 | { | ||
3437 | struct sky2_port *sky2 = netdev_priv(dev); | ||
3438 | u16 reg2; | ||
3439 | |||
3440 | reg2 = sky2_pci_read32(sky2->hw, PCI_DEV_REG2); | ||
3441 | return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); | ||
3442 | } | ||
3443 | |||
3444 | static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset) | ||
3445 | { | ||
3446 | sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset); | ||
3447 | |||
3448 | while (!(sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F)) | ||
3449 | cpu_relax(); | ||
3450 | return sky2_pci_read32(hw, cap + PCI_VPD_DATA); | ||
3451 | } | ||
3452 | |||
3453 | static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val) | ||
3454 | { | ||
3455 | sky2_pci_write32(hw, cap + PCI_VPD_DATA, val); | ||
3456 | sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); | ||
3457 | do { | ||
3458 | cpu_relax(); | ||
3459 | } while (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F); | ||
3460 | } | ||
3461 | |||
3462 | static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | ||
3463 | u8 *data) | ||
3464 | { | ||
3465 | struct sky2_port *sky2 = netdev_priv(dev); | ||
3466 | int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); | ||
3467 | int length = eeprom->len; | ||
3468 | u16 offset = eeprom->offset; | ||
3469 | |||
3470 | if (!cap) | ||
3471 | return -EINVAL; | ||
3472 | |||
3473 | eeprom->magic = SKY2_EEPROM_MAGIC; | ||
3474 | |||
3475 | while (length > 0) { | ||
3476 | u32 val = sky2_vpd_read(sky2->hw, cap, offset); | ||
3477 | int n = min_t(int, length, sizeof(val)); | ||
3478 | |||
3479 | memcpy(data, &val, n); | ||
3480 | length -= n; | ||
3481 | data += n; | ||
3482 | offset += n; | ||
3483 | } | ||
3484 | return 0; | ||
3485 | } | ||
3486 | |||
3487 | static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | ||
3488 | u8 *data) | ||
3489 | { | ||
3490 | struct sky2_port *sky2 = netdev_priv(dev); | ||
3491 | int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); | ||
3492 | int length = eeprom->len; | ||
3493 | u16 offset = eeprom->offset; | ||
3494 | |||
3495 | if (!cap) | ||
3496 | return -EINVAL; | ||
3497 | |||
3498 | if (eeprom->magic != SKY2_EEPROM_MAGIC) | ||
3499 | return -EINVAL; | ||
3500 | |||
3501 | while (length > 0) { | ||
3502 | u32 val; | ||
3503 | int n = min_t(int, length, sizeof(val)); | ||
3504 | |||
3505 | if (n < sizeof(val)) | ||
3506 | val = sky2_vpd_read(sky2->hw, cap, offset); | ||
3507 | memcpy(&val, data, n); | ||
3508 | |||
3509 | sky2_vpd_write(sky2->hw, cap, offset, val); | ||
3510 | |||
3511 | length -= n; | ||
3512 | data += n; | ||
3513 | offset += n; | ||
3514 | } | ||
3515 | return 0; | ||
3516 | } | ||
3517 | |||
3518 | |||
3432 | static const struct ethtool_ops sky2_ethtool_ops = { | 3519 | static const struct ethtool_ops sky2_ethtool_ops = { |
3433 | .get_settings = sky2_get_settings, | 3520 | .get_settings = sky2_get_settings, |
3434 | .set_settings = sky2_set_settings, | 3521 | .set_settings = sky2_set_settings, |
3435 | .get_drvinfo = sky2_get_drvinfo, | 3522 | .get_drvinfo = sky2_get_drvinfo, |
3436 | .get_wol = sky2_get_wol, | 3523 | .get_wol = sky2_get_wol, |
3437 | .set_wol = sky2_set_wol, | 3524 | .set_wol = sky2_set_wol, |
3438 | .get_msglevel = sky2_get_msglevel, | 3525 | .get_msglevel = sky2_get_msglevel, |
3439 | .set_msglevel = sky2_set_msglevel, | 3526 | .set_msglevel = sky2_set_msglevel, |
3440 | .nway_reset = sky2_nway_reset, | 3527 | .nway_reset = sky2_nway_reset, |
3441 | .get_regs_len = sky2_get_regs_len, | 3528 | .get_regs_len = sky2_get_regs_len, |
3442 | .get_regs = sky2_get_regs, | 3529 | .get_regs = sky2_get_regs, |
3443 | .get_link = ethtool_op_get_link, | 3530 | .get_link = ethtool_op_get_link, |
3444 | .get_sg = ethtool_op_get_sg, | 3531 | .get_eeprom_len = sky2_get_eeprom_len, |
3445 | .set_sg = ethtool_op_set_sg, | 3532 | .get_eeprom = sky2_get_eeprom, |
3446 | .get_tx_csum = ethtool_op_get_tx_csum, | 3533 | .set_eeprom = sky2_set_eeprom, |
3447 | .set_tx_csum = sky2_set_tx_csum, | 3534 | .get_sg = ethtool_op_get_sg, |
3448 | .get_tso = ethtool_op_get_tso, | 3535 | .set_sg = ethtool_op_set_sg, |
3449 | .set_tso = sky2_set_tso, | 3536 | .get_tx_csum = ethtool_op_get_tx_csum, |
3450 | .get_rx_csum = sky2_get_rx_csum, | 3537 | .set_tx_csum = sky2_set_tx_csum, |
3451 | .set_rx_csum = sky2_set_rx_csum, | 3538 | .get_tso = ethtool_op_get_tso, |
3452 | .get_strings = sky2_get_strings, | 3539 | .set_tso = sky2_set_tso, |
3453 | .get_coalesce = sky2_get_coalesce, | 3540 | .get_rx_csum = sky2_get_rx_csum, |
3454 | .set_coalesce = sky2_set_coalesce, | 3541 | .set_rx_csum = sky2_set_rx_csum, |
3455 | .get_ringparam = sky2_get_ringparam, | 3542 | .get_strings = sky2_get_strings, |
3456 | .set_ringparam = sky2_set_ringparam, | 3543 | .get_coalesce = sky2_get_coalesce, |
3544 | .set_coalesce = sky2_set_coalesce, | ||
3545 | .get_ringparam = sky2_get_ringparam, | ||
3546 | .set_ringparam = sky2_set_ringparam, | ||
3457 | .get_pauseparam = sky2_get_pauseparam, | 3547 | .get_pauseparam = sky2_get_pauseparam, |
3458 | .set_pauseparam = sky2_set_pauseparam, | 3548 | .set_pauseparam = sky2_set_pauseparam, |
3459 | .phys_id = sky2_phys_id, | 3549 | .phys_id = sky2_phys_id, |
3460 | .get_stats_count = sky2_get_stats_count, | 3550 | .get_stats_count = sky2_get_stats_count, |
3461 | .get_ethtool_stats = sky2_get_ethtool_stats, | 3551 | .get_ethtool_stats = sky2_get_ethtool_stats, |
3462 | .get_perm_addr = ethtool_op_get_perm_addr, | 3552 | .get_perm_addr = ethtool_op_get_perm_addr, |