Newer
Older
cpw16(MultiIntr, 0);
cpw16_f(IntrMask, cp_intr_mask);
cpw8_f(Cfg9346, Cfg9346_Lock);
}
unsigned i;
for (i = 0; i < CP_RX_RING_SIZE; i++) {
struct sk_buff *skb;
skb = netdev_alloc_skb_ip_align(dev, cp->rx_buf_sz);
mapping = dma_map_single(&cp->pdev->dev, skb->data,
cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
if (i == (CP_RX_RING_SIZE - 1))
cp->rx_ring[i].opts1 =
cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz);
else
cp->rx_ring[i].opts1 =
cpu_to_le32(DescOwn | cp->rx_buf_sz);
}
return 0;
err_out:
cp_clean_rings(cp);
return -ENOMEM;
}
static void cp_init_rings_index (struct cp_private *cp)
{
cp->rx_tail = 0;
cp->tx_head = cp->tx_tail = 0;
}
static int cp_init_rings (struct cp_private *cp)
{
memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
cp->tx_ring[CP_TX_RING_SIZE - 1].opts1 = cpu_to_le32(RingEnd);
return cp_refill_rx (cp);
}
static int cp_alloc_rings (struct cp_private *cp)
{
void *mem;
mem = dma_alloc_coherent(&cp->pdev->dev, CP_RING_BYTES,
&cp->ring_dma, GFP_KERNEL);
if (!mem)
return -ENOMEM;
cp->rx_ring = mem;
cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
return cp_init_rings(cp);
}
static void cp_clean_rings (struct cp_private *cp)
{
unsigned i;
for (i = 0; i < CP_RX_RING_SIZE; i++) {
dma_unmap_single(&cp->pdev->dev,le64_to_cpu(desc->addr),
dev_kfree_skb(cp->rx_skb[i]);
}
}
for (i = 0; i < CP_TX_RING_SIZE; i++) {
if (cp->tx_skb[i]) {
struct sk_buff *skb = cp->tx_skb[i];
dma_unmap_single(&cp->pdev->dev,le64_to_cpu(desc->addr),
le32_to_cpu(desc->opts1) & 0xffff,
PCI_DMA_TODEVICE);
cp->dev->stats.tx_dropped++;
memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
memset(cp->rx_skb, 0, sizeof(struct sk_buff *) * CP_RX_RING_SIZE);
memset(cp->tx_skb, 0, sizeof(struct sk_buff *) * CP_TX_RING_SIZE);
}
static void cp_free_rings (struct cp_private *cp)
{
cp_clean_rings(cp);
dma_free_coherent(&cp->pdev->dev, CP_RING_BYTES, cp->rx_ring,
cp->ring_dma);
cp->rx_ring = NULL;
cp->tx_ring = NULL;
}
static int cp_open (struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
int rc;
netif_dbg(cp, ifup, dev, "enabling interface\n");
rc = cp_alloc_rings(cp);
if (rc)
return rc;
napi_enable(&cp->napi);
rc = request_irq(dev->irq, cp_interrupt, IRQF_SHARED, dev->name, dev);
if (rc)
goto err_out_hw;
netif_carrier_off(dev);
mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
netif_start_queue(dev);
return 0;
err_out_hw:
napi_disable(&cp->napi);
cp_stop_hw(cp);
cp_free_rings(cp);
return rc;
}
static int cp_close (struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
napi_disable(&cp->napi);
netif_dbg(cp, ifdown, dev, "disabling interface\n");
spin_lock_irqsave(&cp->lock, flags);
netif_stop_queue(dev);
netif_carrier_off(dev);
cp_stop_hw(cp);
spin_unlock_irqrestore(&cp->lock, flags);
free_irq(dev->irq, dev);
cp_free_rings(cp);
return 0;
}
static void cp_tx_timeout(struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
int rc;
netdev_warn(dev, "Transmit timeout, status %2x %4x %4x %4x\n",
cpr8(Cmd), cpr16(CpCmd),
cpr16(IntrStatus), cpr16(IntrMask));
spin_lock_irqsave(&cp->lock, flags);
cp_stop_hw(cp);
cp_clean_rings(cp);
rc = cp_init_rings(cp);
cp_start_hw(cp);
netif_wake_queue(dev);
spin_unlock_irqrestore(&cp->lock, flags);
}
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
#ifdef BROKEN
static int cp_change_mtu(struct net_device *dev, int new_mtu)
{
struct cp_private *cp = netdev_priv(dev);
int rc;
unsigned long flags;
/* check for invalid MTU, according to hardware limits */
if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
return -EINVAL;
/* if network interface not up, no need for complexity */
if (!netif_running(dev)) {
dev->mtu = new_mtu;
cp_set_rxbufsize(cp); /* set new rx buf size */
return 0;
}
spin_lock_irqsave(&cp->lock, flags);
cp_stop_hw(cp); /* stop h/w and free rings */
cp_clean_rings(cp);
dev->mtu = new_mtu;
cp_set_rxbufsize(cp); /* set new rx buf size */
rc = cp_init_rings(cp); /* realloc and restart h/w */
cp_start_hw(cp);
spin_unlock_irqrestore(&cp->lock, flags);
return rc;
}
#endif /* BROKEN */
static const char mii_2_8139_map[8] = {
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
BasicModeCtrl,
BasicModeStatus,
0,
0,
NWayAdvert,
NWayLPAR,
NWayExpansion,
0
};
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
struct cp_private *cp = netdev_priv(dev);
return location < 8 && mii_2_8139_map[location] ?
readw(cp->regs + mii_2_8139_map[location]) : 0;
}
static void mdio_write(struct net_device *dev, int phy_id, int location,
int value)
{
struct cp_private *cp = netdev_priv(dev);
if (location == 0) {
cpw8(Cfg9346, Cfg9346_Unlock);
cpw16(BasicModeCtrl, value);
cpw8(Cfg9346, Cfg9346_Lock);
} else if (location < 8 && mii_2_8139_map[location])
cpw16(mii_2_8139_map[location], value);
}
/* Set the ethtool Wake-on-LAN settings */
static int netdev_set_wol (struct cp_private *cp,
const struct ethtool_wolinfo *wol)
{
u8 options;
options = cpr8 (Config3) & ~(LinkUp | MagicPacket);
/* If WOL is being disabled, no need for complexity */
if (wol->wolopts) {
if (wol->wolopts & WAKE_PHY) options |= LinkUp;
if (wol->wolopts & WAKE_MAGIC) options |= MagicPacket;
}
cpw8 (Cfg9346, Cfg9346_Unlock);
cpw8 (Config3, options);
cpw8 (Cfg9346, Cfg9346_Lock);
options = 0; /* Paranoia setting */
options = cpr8 (Config5) & ~(UWF | MWF | BWF);
/* If WOL is being disabled, no need for complexity */
if (wol->wolopts) {
if (wol->wolopts & WAKE_UCAST) options |= UWF;
if (wol->wolopts & WAKE_BCAST) options |= BWF;
if (wol->wolopts & WAKE_MCAST) options |= MWF;
}
cpw8 (Config5, options);
cp->wol_enabled = (wol->wolopts) ? 1 : 0;
return 0;
}
/* Get the ethtool Wake-on-LAN settings */
static void netdev_get_wol (struct cp_private *cp,
struct ethtool_wolinfo *wol)
{
u8 options;
wol->wolopts = 0; /* Start from scratch */
wol->supported = WAKE_PHY | WAKE_BCAST | WAKE_MAGIC |
WAKE_MCAST | WAKE_UCAST;
/* We don't need to go on if WOL is disabled */
if (!cp->wol_enabled) return;
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
options = cpr8 (Config3);
if (options & LinkUp) wol->wolopts |= WAKE_PHY;
if (options & MagicPacket) wol->wolopts |= WAKE_MAGIC;
options = 0; /* Paranoia setting */
options = cpr8 (Config5);
if (options & UWF) wol->wolopts |= WAKE_UCAST;
if (options & BWF) wol->wolopts |= WAKE_BCAST;
if (options & MWF) wol->wolopts |= WAKE_MCAST;
}
static void cp_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info)
{
struct cp_private *cp = netdev_priv(dev);
strcpy (info->driver, DRV_NAME);
strcpy (info->version, DRV_VERSION);
strcpy (info->bus_info, pci_name(cp->pdev));
}
static int cp_get_regs_len(struct net_device *dev)
{
return CP_REGS_SIZE;
}
static int cp_get_sset_count (struct net_device *dev, int sset)
switch (sset) {
case ETH_SS_STATS:
return CP_NUM_STATS;
default:
return -EOPNOTSUPP;
}
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
}
static int cp_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct cp_private *cp = netdev_priv(dev);
int rc;
unsigned long flags;
spin_lock_irqsave(&cp->lock, flags);
rc = mii_ethtool_gset(&cp->mii_if, cmd);
spin_unlock_irqrestore(&cp->lock, flags);
return rc;
}
static int cp_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct cp_private *cp = netdev_priv(dev);
int rc;
unsigned long flags;
spin_lock_irqsave(&cp->lock, flags);
rc = mii_ethtool_sset(&cp->mii_if, cmd);
spin_unlock_irqrestore(&cp->lock, flags);
return rc;
}
static int cp_nway_reset(struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
return mii_nway_restart(&cp->mii_if);
}
static u32 cp_get_msglevel(struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
return cp->msg_enable;
}
static void cp_set_msglevel(struct net_device *dev, u32 value)
{
struct cp_private *cp = netdev_priv(dev);
cp->msg_enable = value;
}
static int cp_set_features(struct net_device *dev, u32 features)
if (!((dev->features ^ features) & NETIF_F_RXCSUM))
return 0;
spin_lock_irqsave(&cp->lock, flags);
if (features & NETIF_F_RXCSUM)
cp->cpcmd |= RxChkSum;
if (features & NETIF_F_HW_VLAN_RX)
cp->cpcmd |= RxVlanOn;
else
cp->cpcmd &= ~RxVlanOn;
cpw16_f(CpCmd, cp->cpcmd);
spin_unlock_irqrestore(&cp->lock, flags);
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
return 0;
}
static void cp_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
{
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
if (regs->len < CP_REGS_SIZE)
return /* -EINVAL */;
regs->version = CP_REGS_VER;
spin_lock_irqsave(&cp->lock, flags);
memcpy_fromio(p, cp->regs, CP_REGS_SIZE);
spin_unlock_irqrestore(&cp->lock, flags);
}
static void cp_get_wol (struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave (&cp->lock, flags);
netdev_get_wol (cp, wol);
spin_unlock_irqrestore (&cp->lock, flags);
}
static int cp_set_wol (struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct cp_private *cp = netdev_priv(dev);
unsigned long flags;
int rc;
spin_lock_irqsave (&cp->lock, flags);
rc = netdev_set_wol (cp, wol);
spin_unlock_irqrestore (&cp->lock, flags);
return rc;
}
static void cp_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
{
switch (stringset) {
case ETH_SS_STATS:
memcpy(buf, ðtool_stats_keys, sizeof(ethtool_stats_keys));
break;
default:
BUG();
break;
}
}
static void cp_get_ethtool_stats (struct net_device *dev,
struct ethtool_stats *estats, u64 *tmp_stats)
{
struct cp_private *cp = netdev_priv(dev);
struct cp_dma_stats *nic_stats;
dma_addr_t dma;
nic_stats = dma_alloc_coherent(&cp->pdev->dev, sizeof(*nic_stats),
&dma, GFP_KERNEL);
if (!nic_stats)
return;
cpw32(StatsAddr + 4, (u64)dma >> 32);
cpw32(StatsAddr, ((u64)dma & DMA_BIT_MASK(32)) | DumpStats);
for (i = 0; i < 1000; i++) {
cpw32(StatsAddr, 0);
cpw32(StatsAddr + 4, 0);
cpr32(StatsAddr);
tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok);
tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok);
tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err);
tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err);
tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo);
tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align);
tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col);
tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol);
tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys);
tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast);
tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast);
tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
dma_free_coherent(&cp->pdev->dev, sizeof(*nic_stats), nic_stats, dma);
static const struct ethtool_ops cp_ethtool_ops = {
.get_drvinfo = cp_get_drvinfo,
.get_regs_len = cp_get_regs_len,
.get_sset_count = cp_get_sset_count,
.get_settings = cp_get_settings,
.set_settings = cp_set_settings,
.nway_reset = cp_nway_reset,
.get_link = ethtool_op_get_link,
.get_msglevel = cp_get_msglevel,
.set_msglevel = cp_set_msglevel,
.get_regs = cp_get_regs,
.get_wol = cp_get_wol,
.set_wol = cp_set_wol,
.get_strings = cp_get_strings,
.get_ethtool_stats = cp_get_ethtool_stats,
.get_eeprom_len = cp_get_eeprom_len,
.get_eeprom = cp_get_eeprom,
.set_eeprom = cp_set_eeprom,
};
static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
{
struct cp_private *cp = netdev_priv(dev);
int rc;
unsigned long flags;
if (!netif_running(dev))
return -EINVAL;
spin_lock_irqsave(&cp->lock, flags);
rc = generic_mii_ioctl(&cp->mii_if, if_mii(rq), cmd, NULL);
spin_unlock_irqrestore(&cp->lock, flags);
return rc;
}
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
static int cp_set_mac_address(struct net_device *dev, void *p)
{
struct cp_private *cp = netdev_priv(dev);
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
spin_lock_irq(&cp->lock);
cpw8_f(Cfg9346, Cfg9346_Unlock);
cpw32_f(MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
cpw32_f(MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4)));
cpw8_f(Cfg9346, Cfg9346_Lock);
spin_unlock_irq(&cp->lock);
return 0;
}
/* Serial EEPROM section. */
/* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
#define EE_CS 0x08 /* EEPROM chip select. */
#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */
#define EE_WRITE_0 0x00
#define EE_WRITE_1 0x02
#define EE_DATA_READ 0x01 /* EEPROM chip data out. */
#define EE_ENB (0x80 | EE_CS)
/* Delay between EEPROM clock transitions.
No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
*/
#define eeprom_delay() readl(ee_addr)
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5)
#define EE_READ_CMD (6)
#define EE_ERASE_CMD (7)
#define EE_EWDS_ADDR (0)
#define EE_WRAL_ADDR (1)
#define EE_ERAL_ADDR (2)
#define EE_EWEN_ADDR (3)
#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139
static void eeprom_cmd_start(void __iomem *ee_addr)
{
writeb (EE_ENB & ~EE_CS, ee_addr);
writeb (EE_ENB, ee_addr);
eeprom_delay ();
static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len)
{
int i;
/* Shift the command bits out. */
for (i = cmd_len - 1; i >= 0; i--) {
int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
writeb (EE_ENB | dataval, ee_addr);
eeprom_delay ();
writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay ();
}
writeb (EE_ENB, ee_addr);
eeprom_delay ();
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
}
static void eeprom_cmd_end(void __iomem *ee_addr)
{
writeb (~EE_CS, ee_addr);
eeprom_delay ();
}
static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd,
int addr_len)
{
int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2));
eeprom_cmd_start(ee_addr);
eeprom_cmd(ee_addr, cmd, 3 + addr_len);
eeprom_cmd_end(ee_addr);
}
static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len)
{
int i;
u16 retval = 0;
void __iomem *ee_addr = ioaddr + Cfg9346;
int read_cmd = location | (EE_READ_CMD << addr_len);
eeprom_cmd_start(ee_addr);
eeprom_cmd(ee_addr, read_cmd, 3 + addr_len);
for (i = 16; i > 0; i--) {
writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay ();
retval =
(retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
0);
writeb (EE_ENB, ee_addr);
eeprom_delay ();
}
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
static void write_eeprom(void __iomem *ioaddr, int location, u16 val,
int addr_len)
{
int i;
void __iomem *ee_addr = ioaddr + Cfg9346;
int write_cmd = location | (EE_WRITE_CMD << addr_len);
eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len);
eeprom_cmd_start(ee_addr);
eeprom_cmd(ee_addr, write_cmd, 3 + addr_len);
eeprom_cmd(ee_addr, val, 16);
eeprom_cmd_end(ee_addr);
eeprom_cmd_start(ee_addr);
for (i = 0; i < 20000; i++)
if (readb(ee_addr) & EE_DATA_READ)
break;
eeprom_cmd_end(ee_addr);
eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len);
}
static int cp_get_eeprom_len(struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
int size;
spin_lock_irq(&cp->lock);
size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128;
spin_unlock_irq(&cp->lock);
return size;
}
static int cp_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 *data)
{
struct cp_private *cp = netdev_priv(dev);
unsigned int addr_len;
u16 val;
u32 offset = eeprom->offset >> 1;
u32 len = eeprom->len;
u32 i = 0;
eeprom->magic = CP_EEPROM_MAGIC;
spin_lock_irq(&cp->lock);
addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
if (eeprom->offset & 1) {
val = read_eeprom(cp->regs, offset, addr_len);
data[i++] = (u8)(val >> 8);
offset++;
}
while (i < len - 1) {
val = read_eeprom(cp->regs, offset, addr_len);
data[i++] = (u8)val;
data[i++] = (u8)(val >> 8);
offset++;
}
if (i < len) {
val = read_eeprom(cp->regs, offset, addr_len);
data[i] = (u8)val;
}
spin_unlock_irq(&cp->lock);
return 0;
}
static int cp_set_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 *data)
{
struct cp_private *cp = netdev_priv(dev);
unsigned int addr_len;
u16 val;
u32 offset = eeprom->offset >> 1;
u32 len = eeprom->len;
u32 i = 0;
if (eeprom->magic != CP_EEPROM_MAGIC)
return -EINVAL;
spin_lock_irq(&cp->lock);
addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
if (eeprom->offset & 1) {
val = read_eeprom(cp->regs, offset, addr_len) & 0xff;
val |= (u16)data[i++] << 8;
write_eeprom(cp->regs, offset, val, addr_len);
offset++;
}
while (i < len - 1) {
val = (u16)data[i++];
val |= (u16)data[i++] << 8;
write_eeprom(cp->regs, offset, val, addr_len);
offset++;
}
if (i < len) {
val = read_eeprom(cp->regs, offset, addr_len) & 0xff00;
val |= (u16)data[i];
write_eeprom(cp->regs, offset, val, addr_len);
}
spin_unlock_irq(&cp->lock);
return 0;
}
/* Put the board into D3cold state and wait for WakeUp signal */
static void cp_set_d3_state (struct cp_private *cp)
{
pci_enable_wake (cp->pdev, 0, 1); /* Enable PME# generation */
pci_set_power_state (cp->pdev, PCI_D3hot);
}
static const struct net_device_ops cp_netdev_ops = {
.ndo_open = cp_open,
.ndo_stop = cp_close,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = cp_set_mac_address,
.ndo_set_multicast_list = cp_set_rx_mode,
.ndo_get_stats = cp_get_stats,
.ndo_do_ioctl = cp_ioctl,
.ndo_start_xmit = cp_start_xmit,
.ndo_set_features = cp_set_features,
#ifdef BROKEN
.ndo_change_mtu = cp_change_mtu,
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cp_poll_controller,
#endif
};
static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
struct cp_private *cp;
int rc;
void __iomem *regs;
Greg Kroah-Hartman
committed
resource_size_t pciaddr;
unsigned int addr_len, i, pci_using_dac;
#ifndef MODULE
static int version_printed;
if (version_printed++ == 0)
#endif
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) {
dev_info(&pdev->dev,
"This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip, use 8139too\n",
pdev->vendor, pdev->device, pdev->revision);
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
return -ENODEV;
}
dev = alloc_etherdev(sizeof(struct cp_private));
if (!dev)
return -ENOMEM;
SET_NETDEV_DEV(dev, &pdev->dev);
cp = netdev_priv(dev);
cp->pdev = pdev;
cp->dev = dev;
cp->msg_enable = (debug < 0 ? CP_DEF_MSG_ENABLE : debug);
spin_lock_init (&cp->lock);
cp->mii_if.dev = dev;
cp->mii_if.mdio_read = mdio_read;
cp->mii_if.mdio_write = mdio_write;
cp->mii_if.phy_id = CP_INTERNAL_PHY;
cp->mii_if.phy_id_mask = 0x1f;
cp->mii_if.reg_num_mask = 0x1f;
cp_set_rxbufsize(cp);
rc = pci_enable_device(pdev);
if (rc)
goto err_out_free;
rc = pci_set_mwi(pdev);
if (rc)
goto err_out_disable;
rc = pci_request_regions(pdev, DRV_NAME);
if (rc)
goto err_out_mwi;
pciaddr = pci_resource_start(pdev, 1);
if (!pciaddr) {
rc = -EIO;
dev_err(&pdev->dev, "no MMIO resource\n");
goto err_out_res;
}
if (pci_resource_len(pdev, 1) < CP_REGS_SIZE) {
rc = -EIO;
dev_err(&pdev->dev, "MMIO resource (%llx) too small\n",
(unsigned long long)pci_resource_len(pdev, 1));
goto err_out_res;
}
/* Configure DMA attributes. */
if ((sizeof(dma_addr_t) > 4) &&
!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) &&
!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
pci_using_dac = 1;
} else {
pci_using_dac = 0;
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
dev_err(&pdev->dev,
"No usable DMA configuration, aborting\n");
rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
dev_err(&pdev->dev,
"No usable consistent DMA configuration, aborting\n");
goto err_out_res;
}
}
cp->cpcmd = (pci_using_dac ? PCIDAC : 0) |
PCIMulRW | RxChkSum | CpRxOn | CpTxOn;
dev->features |= NETIF_F_RXCSUM;
dev->hw_features |= NETIF_F_RXCSUM;
regs = ioremap(pciaddr, CP_REGS_SIZE);
if (!regs) {
rc = -EIO;
dev_err(&pdev->dev, "Cannot map PCI MMIO (%Lx@%Lx)\n",
(unsigned long long)pci_resource_len(pdev, 1),
(unsigned long long)pciaddr);
goto err_out_res;
}
dev->base_addr = (unsigned long) regs;
cp->regs = regs;
cp_stop_hw(cp);
/* read MAC address from EEPROM */
addr_len = read_eeprom (regs, 0, 8) == 0x8129 ? 8 : 6;
for (i = 0; i < 3; i++)
((__le16 *) (dev->dev_addr))[i] =
cpu_to_le16(read_eeprom (regs, i + 7, addr_len));
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
netif_napi_add(dev, &cp->napi, cp_rx_poll, 16);
dev->ethtool_ops = &cp_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
/* disabled by default until verified */
dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
NETIF_F_HIGHDMA;
dev->irq = pdev->irq;
rc = register_netdev(dev);
if (rc)
goto err_out_iomap;
netdev_info(dev, "RTL-8139C+ at 0x%lx, %pM, IRQ %d\n",
dev->base_addr, dev->dev_addr, dev->irq);
pci_set_drvdata(pdev, dev);
/* enable busmastering and memory-write-invalidate */
pci_set_master(pdev);
if (cp->wol_enabled)
cp_set_d3_state (cp);
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
return 0;
err_out_iomap:
iounmap(regs);
err_out_res:
pci_release_regions(pdev);
err_out_mwi:
pci_clear_mwi(pdev);
err_out_disable:
pci_disable_device(pdev);
err_out_free:
free_netdev(dev);
return rc;
}
static void cp_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct cp_private *cp = netdev_priv(dev);
unregister_netdev(dev);
iounmap(cp->regs);
if (cp->wol_enabled)
pci_set_power_state (pdev, PCI_D0);
pci_release_regions(pdev);
pci_clear_mwi(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_netdev(dev);
}
#ifdef CONFIG_PM
static int cp_suspend (struct pci_dev *pdev, pm_message_t state)
struct net_device *dev = pci_get_drvdata(pdev);
struct cp_private *cp = netdev_priv(dev);
if (!netif_running(dev))
return 0;
netif_device_detach (dev);
netif_stop_queue (dev);
spin_lock_irqsave (&cp->lock, flags);
/* Disable Rx and Tx */
cpw16 (IntrMask, 0);
cpw8 (Cmd, cpr8 (Cmd) & (~RxOn | ~TxOn));
spin_unlock_irqrestore (&cp->lock, flags);