aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sis190.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sis190.c')
-rw-r--r--drivers/net/sis190.c154
1 files changed, 138 insertions, 16 deletions
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index d915507e90eb..1e8e7111c261 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -232,6 +232,14 @@ enum sis190_eeprom_access_register_bits {
232 EEWOP = 0x00000100 // unused 232 EEWOP = 0x00000100 // unused
233}; 233};
234 234
235/* EEPROM Addresses */
236enum sis190_eeprom_address {
237 EEPROMSignature = 0x00,
238 EEPROMCLK = 0x01, // unused
239 EEPROMInfo = 0x02,
240 EEPROMMACAddr = 0x03
241};
242
235struct sis190_private { 243struct sis190_private {
236 void __iomem *mmio_addr; 244 void __iomem *mmio_addr;
237 struct pci_dev *pci_dev; 245 struct pci_dev *pci_dev;
@@ -1240,6 +1248,125 @@ static void sis190_tx_timeout(struct net_device *dev)
1240 netif_wake_queue(dev); 1248 netif_wake_queue(dev);
1241} 1249}
1242 1250
1251static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
1252 struct net_device *dev)
1253{
1254 struct sis190_private *tp = netdev_priv(dev);
1255 void __iomem *ioaddr = tp->mmio_addr;
1256 u16 sig;
1257 int i;
1258
1259 net_probe(tp, KERN_INFO "%s: Read MAC address from EEPROM\n",
1260 pci_name(pdev));
1261
1262 /* Check to see if there is a sane EEPROM */
1263 sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);
1264
1265 if ((sig == 0xffff) || (sig == 0x0000)) {
1266 net_probe(tp, KERN_INFO "%s: Error EEPROM read %x.\n",
1267 pci_name(pdev), sig);
1268 return -EIO;
1269 }
1270
1271 /* Get MAC address from EEPROM */
1272 for (i = 0; i < MAC_ADDR_LEN / 2; i++) {
1273 u16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
1274
1275 ((u16 *)dev->dev_addr)[0] = le16_to_cpu(w);
1276 }
1277
1278 return 0;
1279}
1280
1281/**
1282 * sis190_get_mac_addr_from_apc - Get MAC address for SiS965 model
1283 * @pdev: PCI device
1284 * @dev: network device to get address for
1285 *
1286 * SiS965 model, use APC CMOS RAM to store MAC address.
1287 * APC CMOS RAM is accessed through ISA bridge.
1288 * MAC address is read into @net_dev->dev_addr.
1289 */
1290static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
1291 struct net_device *dev)
1292{
1293 struct sis190_private *tp = netdev_priv(dev);
1294 struct pci_dev *isa_bridge;
1295 u8 reg, tmp8;
1296 int i;
1297
1298 net_probe(tp, KERN_INFO "%s: Read MAC address from APC.\n",
1299 pci_name(pdev));
1300
1301 isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0965, NULL);
1302 if (!isa_bridge) {
1303 net_probe(tp, KERN_INFO "%s: Can not find ISA bridge.\n",
1304 pci_name(pdev));
1305 return -EIO;
1306 }
1307
1308 /* Enable port 78h & 79h to access APC Registers. */
1309 pci_read_config_byte(isa_bridge, 0x48, &tmp8);
1310 reg = (tmp8 & ~0x02);
1311 pci_write_config_byte(isa_bridge, 0x48, reg);
1312 udelay(50);
1313 pci_read_config_byte(isa_bridge, 0x48, &reg);
1314
1315 for (i = 0; i < MAC_ADDR_LEN; i++) {
1316 outb(0x9 + i, 0x78);
1317 dev->dev_addr[i] = inb(0x79);
1318 }
1319
1320 outb(0x12, 0x78);
1321 reg = inb(0x79);
1322
1323 /* Restore the value to ISA Bridge */
1324 pci_write_config_byte(isa_bridge, 0x48, tmp8);
1325 pci_dev_put(isa_bridge);
1326
1327 return 0;
1328}
1329
1330/**
1331 * sis190_init_rxfilter - Initialize the Rx filter
1332 * @dev: network device to initialize
1333 *
1334 * Set receive filter address to our MAC address
1335 * and enable packet filtering.
1336 */
1337static inline void sis190_init_rxfilter(struct net_device *dev)
1338{
1339 struct sis190_private *tp = netdev_priv(dev);
1340 void __iomem *ioaddr = tp->mmio_addr;
1341 u16 ctl;
1342 int i;
1343
1344 ctl = SIS_R16(RxMacControl);
1345 /*
1346 * Disable packet filtering before setting filter.
1347 * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
1348 * only and followed by RxMacAddr (6 bytes). Strange. -- FR
1349 */
1350 SIS_W16(RxMacControl, ctl & ~0x0f00);
1351
1352 for (i = 0; i < MAC_ADDR_LEN; i++)
1353 SIS_W8(RxMacAddr + i, dev->dev_addr[i]);
1354
1355 SIS_W16(RxMacControl, ctl);
1356 SIS_PCI_COMMIT();
1357}
1358
1359static int sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev)
1360{
1361 u8 from;
1362
1363 pci_read_config_byte(pdev, 0x73, &from);
1364
1365 return (from & 0x00000001) ?
1366 sis190_get_mac_addr_from_apc(pdev, dev) :
1367 sis190_get_mac_addr_from_eeprom(pdev, dev);
1368}
1369
1243static void sis190_set_speed_auto(struct net_device *dev) 1370static void sis190_set_speed_auto(struct net_device *dev)
1244{ 1371{
1245 struct sis190_private *tp = netdev_priv(dev); 1372 struct sis190_private *tp = netdev_priv(dev);
@@ -1355,7 +1482,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
1355 struct sis190_private *tp; 1482 struct sis190_private *tp;
1356 struct net_device *dev; 1483 struct net_device *dev;
1357 void __iomem *ioaddr; 1484 void __iomem *ioaddr;
1358 int i, rc; 1485 int rc;
1359 1486
1360 if (!printed_version) { 1487 if (!printed_version) {
1361 net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n"); 1488 net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n");
@@ -1371,18 +1498,11 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
1371 tp = netdev_priv(dev); 1498 tp = netdev_priv(dev);
1372 ioaddr = tp->mmio_addr; 1499 ioaddr = tp->mmio_addr;
1373 1500
1374 /* Get MAC address */ 1501 rc = sis190_get_mac_addr(pdev, dev);
1375 /* Read node address from the EEPROM */ 1502 if (rc < 0)
1376 1503 goto err_release_board;
1377 if (SIS_R32(ROMControl) & 0x4) {
1378 for (i = 0; i < 3; i++) {
1379 SIS_W16(RxMacAddr + 2*i,
1380 sis190_read_eeprom(ioaddr, 3 + i));
1381 }
1382 }
1383 1504
1384 for (i = 0; i < MAC_ADDR_LEN; i++) 1505 sis190_init_rxfilter(dev);
1385 dev->dev_addr[i] = SIS_R8(RxMacAddr + i);
1386 1506
1387 INIT_WORK(&tp->phy_task, sis190_phy_task, dev); 1507 INIT_WORK(&tp->phy_task, sis190_phy_task, dev);
1388 1508
@@ -1403,10 +1523,8 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
1403 1523
1404 spin_lock_init(&tp->lock); 1524 spin_lock_init(&tp->lock);
1405 rc = register_netdev(dev); 1525 rc = register_netdev(dev);
1406 if (rc < 0) { 1526 if (rc < 0)
1407 sis190_release_board(pdev); 1527 goto err_release_board;
1408 goto out;
1409 }
1410 1528
1411 pci_set_drvdata(pdev, dev); 1529 pci_set_drvdata(pdev, dev);
1412 1530
@@ -1423,6 +1541,10 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
1423 sis190_set_speed_auto(dev); 1541 sis190_set_speed_auto(dev);
1424out: 1542out:
1425 return rc; 1543 return rc;
1544
1545err_release_board:
1546 sis190_release_board(pdev);
1547 goto out;
1426} 1548}
1427 1549
1428static void __devexit sis190_remove_one(struct pci_dev *pdev) 1550static void __devexit sis190_remove_one(struct pci_dev *pdev)