aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-07-09 18:33:39 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-10 12:22:29 -0400
commitf4331a6d24f2e5524678caf4621d35f33fb934da (patch)
treef0e6d97478b4e1e25eed0eff767c732834780ef1 /drivers
parent8a3e3bfdf47b82bfbd78aabf7f72df4dff12abcc (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.c140
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
82static const u32 default_msg = 85static 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
3435static 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
3444static 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
3453static 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
3462static 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
3487static 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
3432static const struct ethtool_ops sky2_ethtool_ops = { 3519static 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,