aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sis190.c
diff options
context:
space:
mode:
authorFrancois Romieu <romieu@fr.zoreil.com>2005-07-30 07:12:37 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-07-30 18:21:00 -0400
commit830fb7d23217ae748df0b16d4d419110810036b7 (patch)
tree86596d111407994a02e14525ae87081882467734 /drivers/net/sis190.c
parent40292fb0f041362bca2f6ad975acedce4f6e3f3e (diff)
[PATCH] sis190: initialisation of MAC address.
Extract some mac addr code from SiS's driver. Some magic may hide beyond the isa bridge. The Rx mac control register is now set without condition. Note: good or bad, this part of the code is quite close to sis900.c. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
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)