1/*- 2 * Copyright (c) 1999 The NetBSD Foundation, Inc. 3 * Copyright (c) 2001-2003 Thomas Moestl <tmm@FreeBSD.org>. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Paul Kranenburg. 8 * --- 24 unchanged lines hidden (view full) --- 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 * 37 * from: NetBSD: hme.c,v 1.29 2002/05/05 03:02:38 thorpej Exp 38 */ 39 40#include <sys/cdefs.h> |
41__FBSDID("$FreeBSD: head/sys/dev/hme/if_hme.c 137982 2004-11-22 06:46:30Z yongari $"); |
42 43/* 44 * HME Ethernet module driver. 45 * 46 * The HME is e.g. part of the PCIO PCI multi function device. 47 * It supports TX gathering and TX and RX checksum offloading. 48 * RX buffers must be aligned at a programmable offset modulo 16. We choose 2 49 * for this offset: mbuf clusters are usually on about 2^11 boundaries, 2 bytes --- 44 unchanged lines hidden (view full) --- 94#include <dev/mii/miivar.h> 95 96#include <machine/bus.h> 97 98#include <dev/hme/if_hmereg.h> 99#include <dev/hme/if_hmevar.h> 100 101static void hme_start(struct ifnet *); |
102static void hme_start_locked(struct ifnet *); |
103static void hme_stop(struct hme_softc *); 104static int hme_ioctl(struct ifnet *, u_long, caddr_t); 105static void hme_tick(void *); 106static void hme_watchdog(struct ifnet *); 107static void hme_init(void *); |
108static void hme_init_locked(void *); |
109static int hme_add_rxbuf(struct hme_softc *, unsigned int, int); 110static int hme_meminit(struct hme_softc *); 111static int hme_mac_bitflip(struct hme_softc *, u_int32_t, u_int32_t, 112 u_int32_t, u_int32_t); 113static void hme_mifinit(struct hme_softc *); 114static void hme_reset(struct hme_softc *); 115static void hme_setladrf(struct hme_softc *, int); 116 --- 75 unchanged lines hidden (view full) --- 192 * sc_mac{t,h,o} (MAC registers) 193 * sc_mif{t,h,o} (Management Interface registers) 194 * 195 * the maximum bus burst size: 196 * sc_burst 197 * 198 */ 199 |
200 HME_LOCK_ASSERT(sc, MA_NOTOWNED); |
201 /* Make sure the chip is stopped. */ |
202 HME_LOCK(sc); |
203 hme_stop(sc); |
204 HME_UNLOCK(sc); |
205 206 /* 207 * Allocate DMA capable memory 208 * Buffer descriptors must be aligned on a 2048 byte boundary; 209 * take this into account when calculating the size. Note that 210 * the maximum number of descriptors (256) occupies 2048 bytes, 211 * so we allocate that much regardless of HME_N*DESC. 212 */ --- 71 unchanged lines hidden (view full) --- 284 } 285 286 sc->sc_csum_features = HME_CSUM_FEATURES; 287 /* Initialize ifnet structure. */ 288 ifp->if_softc = sc; 289 if_initname(ifp, device_get_name(sc->sc_dev), 290 device_get_unit(sc->sc_dev)); 291 ifp->if_mtu = ETHERMTU; |
292 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; |
293 ifp->if_start = hme_start; 294 ifp->if_ioctl = hme_ioctl; 295 ifp->if_init = hme_init; 296 ifp->if_watchdog = hme_watchdog; 297 IFQ_SET_MAXLEN(&ifp->if_snd, HME_NTXQ); 298 ifp->if_snd.ifq_drv_maxlen = HME_NTXQ; 299 IFQ_SET_READY(&ifp->if_snd); 300 |
301 HME_LOCK(sc); |
302 hme_mifinit(sc); |
303 HME_UNLOCK(sc); |
304 305 if ((error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, hme_mediachange, 306 hme_mediastatus)) != 0) { 307 device_printf(sc->sc_dev, "phy probe failed: %d\n", error); 308 goto fail_rxdesc; 309 } 310 sc->sc_mii = device_get_softc(sc->sc_miibus); 311 --- 28 unchanged lines hidden (view full) --- 340 /* 341 * Tell the upper layer(s) we support long frames/checksum offloads. 342 */ 343 ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 344 ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 345 ifp->if_hwassist |= sc->sc_csum_features; 346 ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 347 |
348 callout_init(&sc->sc_tick_ch, CALLOUT_MPSAFE); |
349 return (0); 350 351fail_txdesc: 352 for (i = 0; i < tdesc; i++) { 353 bus_dmamap_destroy(sc->sc_tdmatag, 354 sc->sc_rb.rb_txdesc[i].htx_dmamap); 355 } 356 bus_dmamap_destroy(sc->sc_rdmatag, sc->sc_rb.rb_spare_dmamap); --- 17 unchanged lines hidden (view full) --- 374} 375 376void 377hme_detach(struct hme_softc *sc) 378{ 379 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 380 int i; 381 |
382 HME_LOCK_ASSERT(sc, MA_NOTOWNED); 383 |
384 ether_ifdetach(ifp); |
385 HME_LOCK(sc); |
386 hme_stop(sc); |
387 HME_UNLOCK(sc); |
388 device_delete_child(sc->sc_dev, sc->sc_miibus); 389 390 for (i = 0; i < HME_NTXQ; i++) { 391 bus_dmamap_destroy(sc->sc_tdmatag, 392 sc->sc_rb.rb_txdesc[i].htx_dmamap); 393 } 394 bus_dmamap_destroy(sc->sc_rdmatag, sc->sc_rb.rb_spare_dmamap); 395 for (i = 0; i < HME_NRXDESC; i++) { --- 9 unchanged lines hidden (view full) --- 405 bus_dma_tag_destroy(sc->sc_cdmatag); 406 bus_dma_tag_destroy(sc->sc_pdmatag); 407} 408 409void 410hme_suspend(struct hme_softc *sc) 411{ 412 |
413 HME_LOCK(sc); |
414 hme_stop(sc); |
415 HME_UNLOCK(sc); |
416} 417 418void 419hme_resume(struct hme_softc *sc) 420{ 421 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 422 |
423 HME_LOCK(sc); |
424 if ((ifp->if_flags & IFF_UP) != 0) |
425 hme_init_locked(ifp); 426 HME_UNLOCK(sc); |
427} 428 429static void 430hme_cdma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 431{ 432 struct hme_softc *sc = (struct hme_softc *)xsc; 433 434 if (error != 0) --- 15 unchanged lines hidden (view full) --- 450 callout_reset(&sc->sc_tick_ch, hz, hme_tick, sc); 451} 452 453static void 454hme_reset(struct hme_softc *sc) 455{ 456 int s; 457 |
458 HME_LOCK(sc); |
459 s = splnet(); |
460 hme_init_locked(sc); |
461 splx(s); |
462 HME_UNLOCK(sc); |
463} 464 465static void 466hme_stop(struct hme_softc *sc) 467{ 468 u_int32_t v; 469 int n; 470 --- 211 unchanged lines hidden (view full) --- 682/* 683 * Initialization of interface; set up initialization block 684 * and transmit/receive descriptor rings. 685 */ 686static void 687hme_init(void *xsc) 688{ 689 struct hme_softc *sc = (struct hme_softc *)xsc; |
690 691 HME_LOCK(sc); 692 hme_init_locked(sc); 693 HME_UNLOCK(sc); 694} 695 696static void 697hme_init_locked(void *xsc) 698{ 699 struct hme_softc *sc = (struct hme_softc *)xsc; |
700 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 701 u_int8_t *ea; 702 u_int32_t n, v; 703 |
704 HME_LOCK_ASSERT(sc, MA_OWNED); |
705 /* 706 * Initialization sequence. The numbered steps below correspond 707 * to the sequence outlined in section 6.3.5.1 in the Ethernet 708 * Channel Engine manual (part of the PCIO manual). 709 * See also the STP2002-STQ document from Sun Microsystems. 710 */ 711 712 /* step 1 & 2. Reset the Ethernet Channel */ --- 158 unchanged lines hidden (view full) --- 871 HME_ERX_READ_4(sc, HME_ERXI_CFG), 872 HME_ETX_READ_4(sc, HME_ETXI_CFG)); 873 CTR2(KTR_HME, "hme_init: mac rxcfg %#x, maci txcfg %#x", 874 HME_MAC_READ_4(sc, HME_MACI_RXCFG), 875 HME_MAC_READ_4(sc, HME_MACI_TXCFG)); 876#endif 877 878 /* Set the current media. */ |
879 /* 880 * HME_UNLOCK(sc); 881 * mii_mediachg(sc->sc_mii); 882 * HME_LOCK(sc); 883 */ |
884 885 /* Start the one second timer. */ 886 callout_reset(&sc->sc_tick_ch, hz, hme_tick, sc); 887 888 ifp->if_flags |= IFF_RUNNING; 889 ifp->if_flags &= ~IFF_OACTIVE; 890 ifp->if_timer = 0; |
891 hme_start_locked(ifp); |
892} 893 894struct hme_txdma_arg { 895 struct hme_softc *hta_sc; 896 struct hme_txdesc *hta_htx; 897 int hta_ndescs; 898}; 899 --- 185 unchanged lines hidden (view full) --- 1085 1086 m->m_pkthdr.rcvif = ifp; 1087 m->m_pkthdr.len = m->m_len = len + HME_RXOFFS; 1088 m_adj(m, HME_RXOFFS); 1089 /* RX TCP/UDP checksum */ 1090 if (ifp->if_capenable & IFCAP_RXCSUM) 1091 hme_rxcksum(m, flags); 1092 /* Pass the packet up. */ |
1093 HME_UNLOCK(sc); |
1094 (*ifp->if_input)(ifp, m); |
1095 HME_LOCK(sc); |
1096} 1097 1098static void 1099hme_start(struct ifnet *ifp) 1100{ |
1101 struct hme_softc *sc = ifp->if_softc; 1102 1103 HME_LOCK(sc); 1104 hme_start_locked(ifp); 1105 HME_UNLOCK(sc); 1106} 1107 1108static void 1109hme_start_locked(struct ifnet *ifp) 1110{ |
1111 struct hme_softc *sc = (struct hme_softc *)ifp->if_softc; 1112 struct mbuf *m; 1113 int error, enq = 0; 1114 1115 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 1116 return; 1117 1118 error = 0; --- 92 unchanged lines hidden (view full) --- 1211 } 1212 /* Turn off watchdog */ 1213 if (sc->sc_rb.rb_td_nbusy == 0) 1214 ifp->if_timer = 0; 1215 1216 /* Update ring */ 1217 sc->sc_rb.rb_tdtail = ri; 1218 |
1219 hme_start_locked(ifp); |
1220 1221 if (sc->sc_rb.rb_td_nbusy == 0) 1222 ifp->if_timer = 0; 1223} 1224 1225/* 1226 * RX TCP/UDP checksum 1227 */ --- 112 unchanged lines hidden (view full) --- 1340} 1341 1342void 1343hme_intr(void *v) 1344{ 1345 struct hme_softc *sc = (struct hme_softc *)v; 1346 u_int32_t status; 1347 |
1348 HME_LOCK(sc); |
1349 status = HME_SEB_READ_4(sc, HME_SEBI_STAT); 1350 CTR1(KTR_HME, "hme_intr: status %#x", (u_int)status); 1351 1352 if ((status & HME_SEB_STAT_ALL_ERRORS) != 0) 1353 hme_eint(sc, status); 1354 1355 if ((status & (HME_SEB_STAT_TXALL | HME_SEB_STAT_HOSTTOTX)) != 0) 1356 hme_tint(sc); 1357 1358 if ((status & HME_SEB_STAT_RXTOHOST) != 0) 1359 hme_rint(sc); |
1360 HME_UNLOCK(sc); |
1361} 1362 1363 1364static void 1365hme_watchdog(struct ifnet *ifp) 1366{ 1367 struct hme_softc *sc = ifp->if_softc; 1368#ifdef HMEDEBUG 1369 u_int32_t status; |
1370#endif |
1371 |
1372 HME_LOCK(sc); 1373#ifdef HMEDEBUG |
1374 status = HME_SEB_READ_4(sc, HME_SEBI_STAT); 1375 CTR1(KTR_HME, "hme_watchdog: status %x", (u_int)status); 1376#endif 1377 device_printf(sc->sc_dev, "device timeout\n"); 1378 ++ifp->if_oerrors; |
1379 HME_UNLOCK(sc); |
1380 1381 hme_reset(sc); 1382} 1383 1384/* 1385 * Initialize the MII Management Interface 1386 */ 1387static void 1388hme_mifinit(struct hme_softc *sc) 1389{ 1390 u_int32_t v; 1391 |
1392 HME_LOCK_ASSERT(sc, MA_OWNED); 1393 |
1394 /* Configure the MIF in frame mode */ 1395 v = HME_MIF_READ_4(sc, HME_MIFI_CFG); 1396 v &= ~HME_MIF_CFG_BBMODE; 1397 HME_MIF_WRITE_4(sc, HME_MIFI_CFG, v); 1398} 1399 1400/* 1401 * MII interface 1402 */ 1403int 1404hme_mii_readreg(device_t dev, int phy, int reg) 1405{ 1406 struct hme_softc *sc = device_get_softc(dev); 1407 int n; 1408 u_int32_t v; 1409 |
1410 HME_LOCK(sc); |
1411 /* Select the desired PHY in the MIF configuration register */ 1412 v = HME_MIF_READ_4(sc, HME_MIFI_CFG); 1413 /* Clear PHY select bit */ 1414 v &= ~HME_MIF_CFG_PHY; 1415 if (phy == HME_PHYAD_EXTERNAL) 1416 /* Set PHY select bit to get at external device */ 1417 v |= HME_MIF_CFG_PHY; 1418 HME_MIF_WRITE_4(sc, HME_MIFI_CFG, v); --- 4 unchanged lines hidden (view full) --- 1423 (MII_COMMAND_READ << HME_MIF_FO_OPC_SHIFT) | 1424 (phy << HME_MIF_FO_PHYAD_SHIFT) | 1425 (reg << HME_MIF_FO_REGAD_SHIFT); 1426 1427 HME_MIF_WRITE_4(sc, HME_MIFI_FO, v); 1428 for (n = 0; n < 100; n++) { 1429 DELAY(1); 1430 v = HME_MIF_READ_4(sc, HME_MIFI_FO); |
1431 if (v & HME_MIF_FO_TALSB) { 1432 HME_UNLOCK(sc); |
1433 return (v & HME_MIF_FO_DATA); |
1434 } |
1435 } 1436 1437 device_printf(sc->sc_dev, "mii_read timeout\n"); |
1438 HME_UNLOCK(sc); |
1439 return (0); 1440} 1441 1442int 1443hme_mii_writereg(device_t dev, int phy, int reg, int val) 1444{ 1445 struct hme_softc *sc = device_get_softc(dev); 1446 int n; 1447 u_int32_t v; 1448 |
1449 HME_LOCK(sc); |
1450 /* Select the desired PHY in the MIF configuration register */ 1451 v = HME_MIF_READ_4(sc, HME_MIFI_CFG); 1452 /* Clear PHY select bit */ 1453 v &= ~HME_MIF_CFG_PHY; 1454 if (phy == HME_PHYAD_EXTERNAL) 1455 /* Set PHY select bit to get at external device */ 1456 v |= HME_MIF_CFG_PHY; 1457 HME_MIF_WRITE_4(sc, HME_MIFI_CFG, v); --- 5 unchanged lines hidden (view full) --- 1463 (phy << HME_MIF_FO_PHYAD_SHIFT) | 1464 (reg << HME_MIF_FO_REGAD_SHIFT) | 1465 (val & HME_MIF_FO_DATA); 1466 1467 HME_MIF_WRITE_4(sc, HME_MIFI_FO, v); 1468 for (n = 0; n < 100; n++) { 1469 DELAY(1); 1470 v = HME_MIF_READ_4(sc, HME_MIFI_FO); |
1471 if (v & HME_MIF_FO_TALSB) { 1472 HME_UNLOCK(sc); |
1473 return (1); |
1474 } |
1475 } 1476 1477 device_printf(sc->sc_dev, "mii_write timeout\n"); |
1478 HME_UNLOCK(sc); |
1479 return (0); 1480} 1481 1482void 1483hme_mii_statchg(device_t dev) 1484{ 1485 struct hme_softc *sc = device_get_softc(dev); |
1486 int instance; 1487 int phy; |
1488 u_int32_t v; 1489 |
1490 HME_LOCK(sc); 1491 instance = IFM_INST(sc->sc_mii->mii_media.ifm_cur->ifm_media); 1492 phy = sc->sc_phys[instance]; |
1493#ifdef HMEDEBUG 1494 if (sc->sc_debug) 1495 printf("hme_mii_statchg: status change: phy = %d\n", phy); 1496#endif 1497 1498 /* Select the current PHY in the MIF configuration register */ 1499 v = HME_MIF_READ_4(sc, HME_MIFI_CFG); 1500 v &= ~HME_MIF_CFG_PHY; 1501 if (phy == HME_PHYAD_EXTERNAL) 1502 v |= HME_MIF_CFG_PHY; 1503 HME_MIF_WRITE_4(sc, HME_MIFI_CFG, v); 1504 1505 /* Set the MAC Full Duplex bit appropriately */ 1506 v = HME_MAC_READ_4(sc, HME_MACI_TXCFG); |
1507 if (!hme_mac_bitflip(sc, HME_MACI_TXCFG, v, HME_MAC_TXCFG_ENABLE, 0)) { 1508 HME_UNLOCK(sc); |
1509 return; |
1510 } |
1511 if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 1512 v |= HME_MAC_TXCFG_FULLDPLX; 1513 else 1514 v &= ~HME_MAC_TXCFG_FULLDPLX; 1515 HME_MAC_WRITE_4(sc, HME_MACI_TXCFG, v); |
1516 if (!hme_mac_bitflip(sc, HME_MACI_TXCFG, v, 0, HME_MAC_TXCFG_ENABLE)) { 1517 HME_UNLOCK(sc); |
1518 return; |
1519 } 1520 HME_UNLOCK(sc); |
1521} 1522 1523static int 1524hme_mediachange(struct ifnet *ifp) 1525{ 1526 struct hme_softc *sc = ifp->if_softc; 1527 1528 return (mii_mediachg(sc->sc_mii)); 1529} 1530 1531static void 1532hme_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1533{ 1534 struct hme_softc *sc = ifp->if_softc; 1535 |
1536 HME_LOCK(sc); 1537 if ((ifp->if_flags & IFF_UP) == 0) { 1538 HME_UNLOCK(sc); |
1539 return; |
1540 } |
1541 |
1542 HME_UNLOCK(sc); |
1543 mii_pollstat(sc->sc_mii); |
1544 HME_LOCK(sc); |
1545 ifmr->ifm_active = sc->sc_mii->mii_media_active; 1546 ifmr->ifm_status = sc->sc_mii->mii_media_status; |
1547 HME_UNLOCK(sc); |
1548} 1549 1550/* 1551 * Process an ioctl request. 1552 */ 1553static int 1554hme_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1555{ 1556 struct hme_softc *sc = ifp->if_softc; 1557 struct ifreq *ifr = (struct ifreq *)data; 1558 int s, error = 0; 1559 |
1560 HME_LOCK(sc); |
1561 s = splnet(); 1562 1563 switch (cmd) { 1564 case SIOCSIFFLAGS: 1565 if ((ifp->if_flags & IFF_UP) == 0 && 1566 (ifp->if_flags & IFF_RUNNING) != 0) { 1567 /* 1568 * If interface is marked down and it is running, then 1569 * stop it. 1570 */ 1571 hme_stop(sc); 1572 ifp->if_flags &= ~IFF_RUNNING; 1573 } else if ((ifp->if_flags & IFF_UP) != 0 && 1574 (ifp->if_flags & IFF_RUNNING) == 0) { 1575 /* 1576 * If interface is marked up and it is stopped, then 1577 * start it. 1578 */ |
1579 hme_init_locked(sc); |
1580 } else if ((ifp->if_flags & IFF_UP) != 0) { 1581 /* 1582 * Reset the interface to pick up changes in any other 1583 * flags that affect hardware registers. 1584 */ |
1585 hme_init_locked(sc); |
1586 } 1587 if ((ifp->if_flags & IFF_LINK0) != 0) 1588 sc->sc_csum_features |= CSUM_UDP; 1589 else 1590 sc->sc_csum_features &= ~CSUM_UDP; 1591 if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 1592 ifp->if_hwassist = sc->sc_csum_features; 1593#ifdef HMEDEBUG 1594 sc->sc_debug = (ifp->if_flags & IFF_DEBUG) != 0 ? 1 : 0; 1595#endif 1596 break; 1597 1598 case SIOCADDMULTI: 1599 case SIOCDELMULTI: 1600 hme_setladrf(sc, 1); 1601 error = 0; 1602 break; 1603 case SIOCGIFMEDIA: 1604 case SIOCSIFMEDIA: |
1605 HME_UNLOCK(sc); |
1606 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); |
1607 HME_LOCK(sc); |
1608 break; 1609 case SIOCSIFCAP: 1610 ifp->if_capenable = ifr->ifr_reqcap; 1611 if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 1612 ifp->if_hwassist = sc->sc_csum_features; 1613 else 1614 ifp->if_hwassist = 0; 1615 break; 1616 default: |
1617 HME_UNLOCK(sc); |
1618 error = ether_ioctl(ifp, cmd, data); |
1619 HME_LOCK(sc); |
1620 break; 1621 } 1622 1623 splx(s); |
1624 HME_UNLOCK(sc); |
1625 return (error); 1626} 1627 1628/* 1629 * Set up the logical address filter. 1630 */ 1631static void 1632hme_setladrf(struct hme_softc *sc, int reenable) 1633{ 1634 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 1635 struct ifmultiaddr *inm; 1636 u_int32_t crc; 1637 u_int32_t hash[4]; 1638 u_int32_t macc; 1639 |
1640 HME_LOCK_ASSERT(sc, MA_OWNED); |
1641 /* Clear hash table */ 1642 hash[3] = hash[2] = hash[1] = hash[0] = 0; 1643 1644 /* Get current RX configuration */ 1645 macc = HME_MAC_READ_4(sc, HME_MACI_RXCFG); 1646 1647 /* 1648 * Disable the receiver while changing it's state as the documentation --- 60 unchanged lines hidden --- |