1/* 2 * Copyright (c) 1997, 1998, 1999 3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 15 unchanged lines hidden (view full) --- 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 * |
32 * $FreeBSD: head/sys/pci/if_xl.c 102336 2002-08-24 00:02:03Z alfred $ |
33 */ 34 35/* 36 * 3Com 3c90x Etherlink XL PCI NIC driver 37 * 38 * Supports the 3Com "boomerang", "cyclone" and "hurricane" PCI 39 * bus-master chips (3c90x cards and embedded controllers) including 40 * the following: --- 106 unchanged lines hidden (view full) --- 147 * might not work on some devices. 148 */ 149#define XL_USEIOSPACE 150 151#include <pci/if_xlreg.h> 152 153#if !defined(lint) 154static const char rcsid[] = |
155 "$FreeBSD: head/sys/pci/if_xl.c 102336 2002-08-24 00:02:03Z alfred $"; |
156#endif 157 158#define XL905B_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 159 160/* 161 * Various supported device vendors/types and their names. 162 */ 163static struct xl_type xl_devs[] = { --- 153 unchanged lines hidden (view full) --- 317/* 318 * Murphy's law says that it's possible the chip can wedge and 319 * the 'command in progress' bit may never clear. Hence, we wait 320 * only a finite amount of time to avoid getting caught in an 321 * infinite loop. Normally this delay routine would be a macro, 322 * but it isn't called during normal operation so we can afford 323 * to make it a function. 324 */ |
325static void 326xl_wait(sc) |
327 struct xl_softc *sc; 328{ 329 register int i; 330 331 for (i = 0; i < XL_TIMEOUT; i++) { 332 if (!(CSR_READ_2(sc, XL_STATUS) & XL_STAT_CMDBUSY)) 333 break; 334 } --- 19 unchanged lines hidden (view full) --- 354 355#define MII_CLR(x) \ 356 CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \ 357 CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~x) 358 359/* 360 * Sync the PHYs by setting data bit and strobing the clock 32 times. 361 */ |
362static void 363xl_mii_sync(sc) |
364 struct xl_softc *sc; 365{ 366 register int i; 367 368 XL_SEL_WIN(4); 369 MII_SET(XL_MII_DIR|XL_MII_DATA); 370 371 for (i = 0; i < 32; i++) { --- 4 unchanged lines hidden (view full) --- 376 } 377 378 return; 379} 380 381/* 382 * Clock a series of bits through the MII. 383 */ |
384static void 385xl_mii_send(sc, bits, cnt) |
386 struct xl_softc *sc; 387 u_int32_t bits; 388 int cnt; 389{ 390 int i; 391 392 XL_SEL_WIN(4); 393 MII_CLR(XL_MII_CLK); --- 9 unchanged lines hidden (view full) --- 403 DELAY(1); 404 MII_SET(XL_MII_CLK); 405 } 406} 407 408/* 409 * Read an PHY register through the MII. 410 */ |
411static int 412xl_mii_readreg(sc, frame) |
413 struct xl_softc *sc; 414 struct xl_mii_frame *frame; 415 416{ 417 int i, ack; 418 419 XL_LOCK(sc); 420 --- 81 unchanged lines hidden (view full) --- 502 if (ack) 503 return(1); 504 return(0); 505} 506 507/* 508 * Write to a PHY register through the MII. 509 */ |
510static int 511xl_mii_writereg(sc, frame) |
512 struct xl_softc *sc; 513 struct xl_mii_frame *frame; 514 515{ 516 XL_LOCK(sc); 517 518 /* 519 * Set up frame for TX. --- 33 unchanged lines hidden (view full) --- 553 */ 554 MII_CLR(XL_MII_DIR); 555 556 XL_UNLOCK(sc); 557 558 return(0); 559} 560 |
561static int 562xl_miibus_readreg(dev, phy, reg) |
563 device_t dev; 564 int phy, reg; 565{ 566 struct xl_softc *sc; 567 struct xl_mii_frame frame; 568 569 sc = device_get_softc(dev); 570 --- 11 unchanged lines hidden (view full) --- 582 583 frame.mii_phyaddr = phy; 584 frame.mii_regaddr = reg; 585 xl_mii_readreg(sc, &frame); 586 587 return(frame.mii_data); 588} 589 |
590static int 591xl_miibus_writereg(dev, phy, reg, data) |
592 device_t dev; 593 int phy, reg, data; 594{ 595 struct xl_softc *sc; 596 struct xl_mii_frame frame; 597 598 sc = device_get_softc(dev); 599 --- 6 unchanged lines hidden (view full) --- 606 frame.mii_regaddr = reg; 607 frame.mii_data = data; 608 609 xl_mii_writereg(sc, &frame); 610 611 return(0); 612} 613 |
614static void 615xl_miibus_statchg(dev) |
616 device_t dev; 617{ 618 struct xl_softc *sc; 619 struct mii_data *mii; 620 621 622 sc = device_get_softc(dev); 623 mii = device_get_softc(sc->xl_miibus); --- 20 unchanged lines hidden (view full) --- 644 * plus BNC and AUI ports. This means we will have both an miibus attached 645 * plus some non-MII media settings. In order to allow this, we have to 646 * add the extra media to the miibus's ifmedia struct, but we can't do 647 * that during xl_attach() because the miibus hasn't been attached yet. 648 * So instead, we wait until the miibus probe/attach is done, at which 649 * point we will get a callback telling is that it's safe to add our 650 * extra media. 651 */ |
652static void 653xl_miibus_mediainit(dev) |
654 device_t dev; 655{ 656 struct xl_softc *sc; 657 struct mii_data *mii; 658 struct ifmedia *ifm; 659 660 sc = device_get_softc(dev); 661 mii = device_get_softc(sc->xl_miibus); --- 31 unchanged lines hidden (view full) --- 693 694 return; 695} 696 697/* 698 * The EEPROM is slow: give it time to come ready after issuing 699 * it a command. 700 */ |
701static int 702xl_eeprom_wait(sc) |
703 struct xl_softc *sc; 704{ 705 int i; 706 707 for (i = 0; i < 100; i++) { 708 if (CSR_READ_2(sc, XL_W0_EE_CMD) & XL_EE_BUSY) 709 DELAY(162); 710 else --- 7 unchanged lines hidden (view full) --- 718 719 return(0); 720} 721 722/* 723 * Read a sequence of words from the EEPROM. Note that ethernet address 724 * data is stored in the EEPROM in network byte order. 725 */ |
726static int 727xl_read_eeprom(sc, dest, off, cnt, swap) |
728 struct xl_softc *sc; 729 caddr_t dest; 730 int off; 731 int cnt; 732 int swap; 733{ 734 int err = 0, i; 735 u_int16_t word = 0, *ptr; --- 70 unchanged lines hidden (view full) --- 806 /* return the filter bit position */ 807 return(crc & 0x000000FF); 808} 809 810/* 811 * NICs older than the 3c905B have only one multicast option, which 812 * is to enable reception of all multicast frames. 813 */ |
814static void 815xl_setmulti(sc) |
816 struct xl_softc *sc; 817{ 818 struct ifnet *ifp; 819 struct ifmultiaddr *ifma; 820 u_int8_t rxfilt; 821 int mcnt = 0; 822 823 ifp = &sc->arpcom.ac_if; --- 18 unchanged lines hidden (view full) --- 842 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); 843 844 return; 845} 846 847/* 848 * 3c905B adapters have a hash filter that we can program. 849 */ |
850static void 851xl_setmulti_hash(sc) |
852 struct xl_softc *sc; 853{ 854 struct ifnet *ifp; 855 int h = 0, i; 856 struct ifmultiaddr *ifma; 857 u_int8_t rxfilt; 858 int mcnt = 0; 859 --- 29 unchanged lines hidden (view full) --- 889 rxfilt &= ~XL_RXFILTER_MULTIHASH; 890 891 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt); 892 893 return; 894} 895 896#ifdef notdef |
897static void 898xl_testpacket(sc) |
899 struct xl_softc *sc; 900{ 901 struct mbuf *m; 902 struct ifnet *ifp; 903 904 ifp = &sc->arpcom.ac_if; 905 906 MGETHDR(m, M_DONTWAIT, MT_DATA); --- 12 unchanged lines hidden (view full) --- 919 m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3; 920 IF_ENQUEUE(&ifp->if_snd, m); 921 xl_start(ifp); 922 923 return; 924} 925#endif 926 |
927static void 928xl_setcfg(sc) |
929 struct xl_softc *sc; 930{ 931 u_int32_t icfg; 932 933 XL_SEL_WIN(3); 934 icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG); 935 icfg &= ~XL_ICFG_CONNECTOR_MASK; 936 if (sc->xl_media & XL_MEDIAOPT_MII || 937 sc->xl_media & XL_MEDIAOPT_BT4) 938 icfg |= (XL_XCVR_MII << XL_ICFG_CONNECTOR_BITS); 939 if (sc->xl_media & XL_MEDIAOPT_BTX) 940 icfg |= (XL_XCVR_AUTO << XL_ICFG_CONNECTOR_BITS); 941 942 CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg); 943 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP); 944 945 return; 946} 947 |
948static void 949xl_setmode(sc, media) |
950 struct xl_softc *sc; 951 int media; 952{ 953 u_int32_t icfg; 954 u_int16_t mediastat; 955 956 printf("xl%d: selecting ", sc->xl_unit); 957 --- 78 unchanged lines hidden (view full) --- 1036 XL_SEL_WIN(4); 1037 CSR_WRITE_2(sc, XL_W4_MEDIA_STATUS, mediastat); 1038 DELAY(800); 1039 XL_SEL_WIN(7); 1040 1041 return; 1042} 1043 |
1044static void 1045xl_reset(sc) |
1046 struct xl_softc *sc; 1047{ 1048 register int i; 1049 1050 XL_SEL_WIN(0); 1051 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RESET | 1052 ((sc->xl_flags & XL_FLAG_WEIRDRESET) ? 1053 XL_RESETOPT_DISADVFD:0)); --- 34 unchanged lines hidden (view full) --- 1088 DELAY(100000); 1089 return; 1090} 1091 1092/* 1093 * Probe for a 3Com Etherlink XL chip. Check the PCI vendor and device 1094 * IDs against our list and return a device name if we find a match. 1095 */ |
1096static int 1097xl_probe(dev) |
1098 device_t dev; 1099{ 1100 struct xl_type *t; 1101 1102 t = xl_devs; 1103 1104 while(t->xl_name != NULL) { 1105 if ((pci_get_vendor(dev) == t->xl_vid) && --- 14 unchanged lines hidden (view full) --- 1120 * 3c90x adapters) to return an incorrect result. I have encountered 1121 * one Dell Latitude laptop docking station with an integrated 3c905-TX 1122 * which doesn't have any of the 'mediaopt' bits set. This screws up 1123 * the attach routine pretty badly because it doesn't know what media 1124 * to look for. If we find ourselves in this predicament, this routine 1125 * will try to guess the media options values and warn the user of a 1126 * possible manufacturing defect with his adapter/system/whatever. 1127 */ |
1128static void 1129xl_mediacheck(sc) |
1130 struct xl_softc *sc; 1131{ 1132 1133 /* 1134 * If some of the media options bits are set, assume they are 1135 * correct. If not, try to figure it out down below. 1136 * XXX I should check for 10baseFL, but I don't have an adapter 1137 * to test with. --- 23 unchanged lines hidden (view full) --- 1161 "should probably consult your vendor\n", sc->xl_unit); 1162 } 1163 1164 xl_choose_xcvr(sc, 1); 1165 1166 return; 1167} 1168 |
1169static void 1170xl_choose_xcvr(sc, verbose) |
1171 struct xl_softc *sc; 1172 int verbose; 1173{ 1174 u_int16_t devid; 1175 1176 /* 1177 * Read the device ID from the EEPROM. 1178 * This is what's loaded into the PCI device ID register, so it has --- 78 unchanged lines hidden (view full) --- 1257 1258 return; 1259} 1260 1261/* 1262 * Attach the interface. Allocate softc structures, do ifmedia 1263 * setup and ethernet/BPF attach. 1264 */ |
1265static int 1266xl_attach(dev) |
1267 device_t dev; 1268{ 1269 u_char eaddr[ETHER_ADDR_LEN]; 1270 u_int32_t command; 1271 struct xl_softc *sc; 1272 struct ifnet *ifp; 1273 int media = IFM_ETHER|IFM_100_TX|IFM_FDX; 1274 int unit, error = 0, rid; --- 374 unchanged lines hidden (view full) --- 1649 1650fail: 1651 XL_UNLOCK(sc); 1652 mtx_destroy(&sc->xl_mtx); 1653 1654 return(error); 1655} 1656 |
1657static int 1658xl_detach(dev) |
1659 device_t dev; 1660{ 1661 struct xl_softc *sc; 1662 struct ifnet *ifp; 1663 1664 sc = device_get_softc(dev); 1665 XL_LOCK(sc); 1666 ifp = &sc->arpcom.ac_if; --- 22 unchanged lines hidden (view full) --- 1689 mtx_destroy(&sc->xl_mtx); 1690 1691 return(0); 1692} 1693 1694/* 1695 * Initialize the transmit descriptors. 1696 */ |
1697static int 1698xl_list_tx_init(sc) |
1699 struct xl_softc *sc; 1700{ 1701 struct xl_chain_data *cd; 1702 struct xl_list_data *ld; 1703 int i; 1704 1705 cd = &sc->xl_cdata; 1706 ld = sc->xl_ldata; --- 49 unchanged lines hidden (view full) --- 1756 return(0); 1757} 1758 1759/* 1760 * Initialize the RX descriptors and allocate mbufs for them. Note that 1761 * we arrange the descriptors in a closed ring, so that the last descriptor 1762 * points back to the first. 1763 */ |
1764static int 1765xl_list_rx_init(sc) |
1766 struct xl_softc *sc; 1767{ 1768 struct xl_chain_data *cd; 1769 struct xl_list_data *ld; 1770 int i; 1771 1772 cd = &sc->xl_cdata; 1773 ld = sc->xl_ldata; --- 17 unchanged lines hidden (view full) --- 1791 cd->xl_rx_head = &cd->xl_rx_chain[0]; 1792 1793 return(0); 1794} 1795 1796/* 1797 * Initialize an RX descriptor and attach an MBUF cluster. 1798 */ |
1799static int 1800xl_newbuf(sc, c) |
1801 struct xl_softc *sc; 1802 struct xl_chain_onefrag *c; 1803{ 1804 struct mbuf *m_new = NULL; 1805 1806 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 1807 if (m_new == NULL) 1808 return(ENOBUFS); --- 12 unchanged lines hidden (view full) --- 1821 c->xl_mbuf = m_new; 1822 c->xl_ptr->xl_frag.xl_addr = vtophys(mtod(m_new, caddr_t)); 1823 c->xl_ptr->xl_frag.xl_len = MCLBYTES | XL_LAST_FRAG; 1824 c->xl_ptr->xl_status = 0; 1825 1826 return(0); 1827} 1828 |
1829static int 1830xl_rx_resync(sc) |
1831 struct xl_softc *sc; 1832{ 1833 struct xl_chain_onefrag *pos; 1834 int i; 1835 1836 pos = sc->xl_cdata.xl_rx_head; 1837 1838 for (i = 0; i < XL_RX_LIST_CNT; i++) { --- 9 unchanged lines hidden (view full) --- 1848 1849 return(EAGAIN); 1850} 1851 1852/* 1853 * A frame has been uploaded: pass the resulting mbuf chain up to 1854 * the higher level protocols. 1855 */ |
1856static void 1857xl_rxeof(sc) |
1858 struct xl_softc *sc; 1859{ 1860 struct ether_header *eh; 1861 struct mbuf *m; 1862 struct ifnet *ifp; 1863 struct xl_chain_onefrag *cur_rx; 1864 int total_len = 0; 1865 u_int32_t rxstat; --- 99 unchanged lines hidden (view full) --- 1965 1966 return; 1967} 1968 1969/* 1970 * A frame was downloaded to the chip. It's safe for us to clean up 1971 * the list buffers. 1972 */ |
1973static void 1974xl_txeof(sc) |
1975 struct xl_softc *sc; 1976{ 1977 struct xl_chain *cur_tx; 1978 struct ifnet *ifp; 1979 1980 ifp = &sc->arpcom.ac_if; 1981 1982 /* Clear the timeout timer. */ --- 75 unchanged lines hidden (view full) --- 2058 return; 2059} 2060 2061/* 2062 * TX 'end of channel' interrupt handler. Actually, we should 2063 * only get a 'TX complete' interrupt if there's a transmit error, 2064 * so this is really TX error handler. 2065 */ |
2066static void 2067xl_txeoc(sc) |
2068 struct xl_softc *sc; 2069{ 2070 u_int8_t txstat; 2071 2072 while((txstat = CSR_READ_1(sc, XL_TX_STATUS))) { 2073 if (txstat & XL_TXSTATUS_UNDERRUN || 2074 txstat & XL_TXSTATUS_JABBER || 2075 txstat & XL_TXSTATUS_RECLAIM) { --- 45 unchanged lines hidden (view full) --- 2121 * to clear this interrupt/error and advance to the next. 2122 */ 2123 CSR_WRITE_1(sc, XL_TX_STATUS, 0x01); 2124 } 2125 2126 return; 2127} 2128 |
2129static void 2130xl_intr(arg) |
2131 void *arg; 2132{ 2133 struct xl_softc *sc; 2134 struct ifnet *ifp; 2135 u_int16_t status; 2136 2137 sc = arg; 2138 XL_LOCK(sc); --- 42 unchanged lines hidden (view full) --- 2181 if (ifp->if_snd.ifq_head != NULL) 2182 (*ifp->if_start)(ifp); 2183 2184 XL_UNLOCK(sc); 2185 2186 return; 2187} 2188 |
2189static void 2190xl_stats_update(xsc) |
2191 void *xsc; 2192{ 2193 struct xl_softc *sc; 2194 struct ifnet *ifp; 2195 struct xl_stats xl_stats; 2196 u_int8_t *p; 2197 int i; 2198 struct mii_data *mii = NULL; --- 38 unchanged lines hidden (view full) --- 2237 2238 return; 2239} 2240 2241/* 2242 * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data 2243 * pointers to the fragment pointers. 2244 */ |
2245static int 2246xl_encap(sc, c, m_head) |
2247 struct xl_softc *sc; 2248 struct xl_chain *c; 2249 struct mbuf *m_head; 2250{ 2251 int frag = 0; 2252 struct xl_frag *f = NULL; 2253 int total_len; 2254 struct mbuf *m; --- 63 unchanged lines hidden (view full) --- 2318} 2319 2320/* 2321 * Main transmit routine. To avoid having to do mbuf copies, we put pointers 2322 * to the mbuf data regions directly in the transmit lists. We also save a 2323 * copy of the pointers since the transmit list fragment pointers are 2324 * physical addresses. 2325 */ |
2326static void 2327xl_start(ifp) |
2328 struct ifnet *ifp; 2329{ 2330 struct xl_softc *sc; 2331 struct mbuf *m_head = NULL; 2332 struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx; 2333 2334 sc = ifp->if_softc; 2335 XL_LOCK(sc); --- 233 unchanged lines hidden (view full) --- 2569 */ 2570 ifp->if_timer = 5; 2571 2572 XL_UNLOCK(sc); 2573 2574 return; 2575} 2576 |
2577static void 2578xl_init(xsc) |
2579 void *xsc; 2580{ 2581 struct xl_softc *sc = xsc; 2582 struct ifnet *ifp = &sc->arpcom.ac_if; 2583 int i; 2584 u_int16_t rxfilt = 0; 2585 struct mii_data *mii = NULL; 2586 --- 192 unchanged lines hidden (view full) --- 2779 XL_UNLOCK(sc); 2780 2781 return; 2782} 2783 2784/* 2785 * Set media options. 2786 */ |
2787static int 2788xl_ifmedia_upd(ifp) |
2789 struct ifnet *ifp; 2790{ 2791 struct xl_softc *sc; 2792 struct ifmedia *ifm = NULL; 2793 struct mii_data *mii = NULL; 2794 2795 sc = ifp->if_softc; 2796 if (sc->xl_miibus != NULL) --- 23 unchanged lines hidden (view full) --- 2820 } 2821 2822 return(0); 2823} 2824 2825/* 2826 * Report current media status. 2827 */ |
2828static void 2829xl_ifmedia_sts(ifp, ifmr) |
2830 struct ifnet *ifp; 2831 struct ifmediareq *ifmr; 2832{ 2833 struct xl_softc *sc; 2834 u_int32_t icfg; 2835 struct mii_data *mii = NULL; 2836 2837 sc = ifp->if_softc; --- 47 unchanged lines hidden (view full) --- 2885 default: 2886 printf("xl%d: unknown XCVR type: %d\n", sc->xl_unit, icfg); 2887 break; 2888 } 2889 2890 return; 2891} 2892 |
2893static int 2894xl_ioctl(ifp, command, data) |
2895 struct ifnet *ifp; 2896 u_long command; 2897 caddr_t data; 2898{ 2899 struct xl_softc *sc = ifp->if_softc; 2900 struct ifreq *ifr = (struct ifreq *) data; 2901 int error = 0; 2902 struct mii_data *mii = NULL; --- 58 unchanged lines hidden (view full) --- 2961 break; 2962 } 2963 2964 XL_UNLOCK(sc); 2965 2966 return(error); 2967} 2968 |
2969static void 2970xl_watchdog(ifp) |
2971 struct ifnet *ifp; 2972{ 2973 struct xl_softc *sc; 2974 u_int16_t status = 0; 2975 2976 sc = ifp->if_softc; 2977 2978 XL_LOCK(sc); --- 19 unchanged lines hidden (view full) --- 2998 2999 return; 3000} 3001 3002/* 3003 * Stop the adapter and free any mbufs allocated to the 3004 * RX and TX lists. 3005 */ |
3006static void 3007xl_stop(sc) |
3008 struct xl_softc *sc; 3009{ 3010 register int i; 3011 struct ifnet *ifp; 3012 3013 XL_LOCK(sc); 3014 3015 ifp = &sc->arpcom.ac_if; --- 52 unchanged lines hidden (view full) --- 3068 3069 return; 3070} 3071 3072/* 3073 * Stop all chip I/O so that the kernel's probe routines don't 3074 * get confused by errant DMAs when rebooting. 3075 */ |
3076static void 3077xl_shutdown(dev) |
3078 device_t dev; 3079{ 3080 struct xl_softc *sc; 3081 3082 sc = device_get_softc(dev); 3083 3084 XL_LOCK(sc); 3085 xl_reset(sc); 3086 xl_stop(sc); 3087 XL_UNLOCK(sc); 3088 3089 return; 3090} 3091 |
3092static int 3093xl_suspend(dev) |
3094 device_t dev; 3095{ 3096 struct xl_softc *sc; 3097 3098 sc = device_get_softc(dev); 3099 3100 XL_LOCK(sc); 3101 xl_stop(sc); 3102 XL_UNLOCK(sc); 3103 3104 return(0); 3105} 3106 |
3107static int 3108xl_resume(dev) |
3109 device_t dev; 3110{ 3111 struct xl_softc *sc; 3112 struct ifnet *ifp; 3113 3114 sc = device_get_softc(dev); 3115 XL_LOCK(sc); 3116 ifp = &sc->arpcom.ac_if; 3117 3118 xl_reset(sc); 3119 if (ifp->if_flags & IFF_UP) 3120 xl_init(sc); 3121 3122 XL_UNLOCK(sc); 3123 return(0); 3124} |