*** if_re.c.orig Thu Nov 27 21:28:28 2003 --- if_re.c Thu Jun 17 18:37:15 2004 *************** *** 229,235 **** static void re_setmulti (struct rl_softc *); static void re_reset (struct rl_softc *); ! static int re_diag (struct rl_softc *); #ifdef RE_USEIOSPACE #define RL_RES SYS_RES_IOPORT --- 229,235 ---- static void re_setmulti (struct rl_softc *); static void re_reset (struct rl_softc *); ! static int re_diag (device_t); #ifdef RE_USEIOSPACE #define RL_RES SYS_RES_IOPORT *************** *** 695,718 **** */ static int ! re_diag(sc) ! struct rl_softc *sc; { struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf *m0; struct ether_header *eh; struct rl_desc *cur_rx; u_int16_t status; u_int32_t rxstat; ! int total_len, i, error = 0; u_int8_t dst[] = { 0x00, 'h', 'e', 'l', 'l', 'o' }; u_int8_t src[] = { 0x00, 'w', 'o', 'r', 'l', 'd' }; ! /* Allocate a single mbuf */ ! MGETHDR(m0, M_DONTWAIT, MT_DATA); ! if (m0 == NULL) ! return(ENOBUFS); /* * Initialize the NIC in test mode. This sets the chip up --- 695,737 ---- */ static int ! re_diag(dev) ! device_t dev; { + struct rl_softc *sc = device_get_softc(dev); struct ifnet *ifp = &sc->arpcom.ac_if; struct mbuf *m0; struct ether_header *eh; struct rl_desc *cur_rx; u_int16_t status; u_int32_t rxstat; ! int total_len, i, error = 0, retries = 0; u_int8_t dst[] = { 0x00, 'h', 'e', 'l', 'l', 'o' }; u_int8_t src[] = { 0x00, 'w', 'o', 'r', 'l', 'd' }; + u_int16_t phy, bmsr; ! /* Reset the PHY, put it in loopback mode. */ ! for (i = 0; i < 32; i++) { ! bmsr = re_miibus_readreg(dev, i, MII_BMSR); ! bmsr = re_miibus_readreg(dev, i, MII_BMSR); ! if (bmsr) ! break; ! } ! ! if (i != 32) { ! phy = i; ! re_miibus_writereg(dev, phy, MII_BMCR, BMCR_RESET); ! ! for (i = 0; i < 100; i++) { ! if (!(re_miibus_readreg(dev, phy, ! MII_BMCR) & BMCR_RESET)) ! break; ! DELAY(1000); ! } ! ! re_miibus_writereg(dev, phy, MII_BMCR, BMCR_LOOP); ! } /* * Initialize the NIC in test mode. This sets the chip up *************** *** 730,741 **** DELAY(100000); re_init(sc); /* Put some data in the mbuf */ eh = mtod(m0, struct ether_header *); bcopy ((char *)&dst, eh->ether_dhost, ETHER_ADDR_LEN); bcopy ((char *)&src, eh->ether_shost, ETHER_ADDR_LEN); ! eh->ether_type = htons(ETHERTYPE_IP); m0->m_pkthdr.len = m0->m_len = ETHER_MIN_LEN - ETHER_CRC_LEN; /* --- 749,786 ---- DELAY(100000); re_init(sc); + /* Wait for link change... */ + + for (i = 0; i < RL_TIMEOUT; i++) { + status = CSR_READ_2(sc, RL_ISR); + if (status & (RL_ISR_LINKCHG|RL_ISR_CABLE_LEN_CHGD)) + break; + DELAY(10); + } + + sc->rl_link = 1; + + retry: + + /* Allocate a single mbuf */ + + MGETHDR(m0, M_DONTWAIT, MT_DATA); + if (m0 == NULL) { + error = ENOBUFS; + goto done; + } + /* Put some data in the mbuf */ + bzero(m0->m_data, ETHER_MIN_LEN); eh = mtod(m0, struct ether_header *); bcopy ((char *)&dst, eh->ether_dhost, ETHER_ADDR_LEN); bcopy ((char *)&src, eh->ether_shost, ETHER_ADDR_LEN); ! eh->ether_type= htons(ETHER_MIN_LEN); ! m0->m_data[14] = 0x00; ! m0->m_data[15] = 0x00; ! m0->m_data[16] = 0xE3; ! bcopy("01234567890123456789", m0->m_data + 17, 20); m0->m_pkthdr.len = m0->m_len = ETHER_MIN_LEN - ETHER_CRC_LEN; /* *************** *** 750,764 **** /* Wait for it to propagate through the chip */ DELAY(100000); for (i = 0; i < RL_TIMEOUT; i++) { status = CSR_READ_2(sc, RL_ISR); if ((status & (RL_ISR_TIMEOUT_EXPIRED|RL_ISR_RX_OK)) == (RL_ISR_TIMEOUT_EXPIRED|RL_ISR_RX_OK)) break; ! DELAY(10); } if (i == RL_TIMEOUT) { printf("re%d: diagnostic failed, failed to receive packet " "in loopback mode\n", sc->rl_unit); error = EIO; --- 795,814 ---- /* Wait for it to propagate through the chip */ DELAY(100000); + for (i = 0; i < RL_TIMEOUT; i++) { status = CSR_READ_2(sc, RL_ISR); if ((status & (RL_ISR_TIMEOUT_EXPIRED|RL_ISR_RX_OK)) == (RL_ISR_TIMEOUT_EXPIRED|RL_ISR_RX_OK)) break; ! DELAY(1000); } if (i == RL_TIMEOUT) { + if (status & RL_ISR_TX_DESC_UNAVAIL && retries < 4) { + retries++; + goto retry; + } printf("re%d: diagnostic failed, failed to receive packet " "in loopback mode\n", sc->rl_unit); error = EIO; *************** *** 798,804 **** if (bcmp((char *)&eh->ether_dhost, (char *)&dst, ETHER_ADDR_LEN) || bcmp((char *)&eh->ether_shost, (char *)&src, ETHER_ADDR_LEN) || ! ntohs(eh->ether_type) != ETHERTYPE_IP) { printf("re%d: WARNING, DMA FAILURE!\n", sc->rl_unit); printf("re%d: expected TX data: %6D/%6D/0x%x\n", sc->rl_unit, dst, ":", src, ":", ETHERTYPE_IP); --- 848,854 ---- if (bcmp((char *)&eh->ether_dhost, (char *)&dst, ETHER_ADDR_LEN) || bcmp((char *)&eh->ether_shost, (char *)&src, ETHER_ADDR_LEN) || ! ntohs(eh->ether_type) != ETHER_MIN_LEN) { printf("re%d: WARNING, DMA FAILURE!\n", sc->rl_unit); printf("re%d: expected TX data: %6D/%6D/0x%x\n", sc->rl_unit, dst, ":", src, ":", ETHERTYPE_IP); *************** *** 1278,1284 **** ether_ifattach(ifp, eaddr); /* Perform hardware diagnostic. */ ! error = re_diag(sc); if (error) { printf("re%d: attach aborted due to hardware diag failure\n", --- 1328,1334 ---- ether_ifattach(ifp, eaddr); /* Perform hardware diagnostic. */ ! error = re_diag(dev); if (error) { printf("re%d: attach aborted due to hardware diag failure\n", *************** *** 1321,1327 **** sc = device_get_softc(dev); KASSERT(mtx_initialized(&sc->rl_mtx), ("rl mutex not initialized")); - RL_LOCK(sc); ifp = &sc->arpcom.ac_if; /* These should only be active if attach succeeded */ --- 1371,1376 ---- *************** *** 1342,1347 **** --- 1391,1397 ---- ifp->if_flags &= ~IFF_UP; ether_ifdetach(ifp); } + if (sc->rl_miibus) device_delete_child(dev, sc->rl_miibus); bus_generic_detach(dev); *************** *** 1402,1408 **** if (sc->rl_parent_tag) bus_dma_tag_destroy(sc->rl_parent_tag); - RL_UNLOCK(sc); mtx_destroy(&sc->rl_mtx); return(0); --- 1452,1457 ---- *************** *** 1751,1763 **** --- 1800,1822 ---- { struct rl_softc *sc; struct mii_data *mii; + struct ifnet *ifp; sc = xsc; + ifp = &sc->arpcom.ac_if; + RL_LOCK(sc); mii = device_get_softc(sc->rl_miibus); mii_tick(mii); + if (!sc->rl_link && mii->mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { + sc->rl_link++; + if (ifp->if_snd.ifq_head != NULL) + re_start(ifp); + } + sc->rl_stat_ch = timeout(re_tick, sc, hz); RL_UNLOCK(sc); *************** *** 1841,1846 **** --- 1900,1906 ---- for (;;) { status = CSR_READ_2(sc, RL_ISR); + /* If the card has gone away the read returns 0xffff. */ if (status == 0xffff) break; *************** *** 2005,2010 **** --- 2065,2075 ---- sc = ifp->if_softc; RL_LOCK(sc); + if (!sc->rl_link && ifp->if_snd.ifq_len < 10) { + RL_UNLOCK(sc); + return; + } + idx = sc->rl_ldata.rl_tx_prodidx; while (sc->rl_ldata.rl_tx_mbuf[idx] == NULL) { *************** *** 2033,2038 **** --- 2098,2105 ---- sc->rl_ldata.rl_tx_prodidx = idx; + RL_UNLOCK(sc); + /* * RealTek put the TX poll request register in a different * location on the 8169 gigE chip. I don't know why. *************** *** 2040,2046 **** if (sc->rl_type == RL_8169) CSR_WRITE_2(sc, RL_GTXSTART, RL_TXSTART_START); ! else CSR_WRITE_2(sc, RL_TXSTART, RL_TXSTART_START); /* --- 2107,2113 ---- if (sc->rl_type == RL_8169) CSR_WRITE_2(sc, RL_GTXSTART, RL_TXSTART_START); ! else CSR_WRITE_2(sc, RL_TXSTART, RL_TXSTART_START); /* *************** *** 2053,2060 **** */ CSR_WRITE_4(sc, RL_TIMERCNT, 1); - RL_UNLOCK(sc); - /* * Set a timeout in case the chip goes out to lunch. */ --- 2120,2125 ---- *************** *** 2110,2115 **** --- 2175,2196 ---- re_tx_list_init(sc); /* + * Load the addresses of the RX and TX lists into the chip. + */ + + CSR_WRITE_4(sc, RL_RXLIST_ADDR_HI, + RL_ADDR_HI(sc->rl_ldata.rl_rx_list_addr)); + CSR_WRITE_4(sc, RL_RXLIST_ADDR_LO, + RL_ADDR_LO(sc->rl_ldata.rl_rx_list_addr)); + + CSR_WRITE_4(sc, RL_TXLIST_ADDR_HI, + RL_ADDR_HI(sc->rl_ldata.rl_tx_list_addr)); + CSR_WRITE_4(sc, RL_TXLIST_ADDR_LO, + RL_ADDR_LO(sc->rl_ldata.rl_tx_list_addr)); + + CSR_WRITE_1(sc, RL_EARLY_TX_THRESH, 16); + + /* * Enable transmit and receive. */ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); *************** *** 2183,2204 **** CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); #endif /* - * Load the addresses of the RX and TX lists into the chip. - */ - - CSR_WRITE_4(sc, RL_RXLIST_ADDR_HI, - RL_ADDR_HI(sc->rl_ldata.rl_rx_list_addr)); - CSR_WRITE_4(sc, RL_RXLIST_ADDR_LO, - RL_ADDR_LO(sc->rl_ldata.rl_rx_list_addr)); - - CSR_WRITE_4(sc, RL_TXLIST_ADDR_HI, - RL_ADDR_HI(sc->rl_ldata.rl_tx_list_addr)); - CSR_WRITE_4(sc, RL_TXLIST_ADDR_LO, - RL_ADDR_LO(sc->rl_ldata.rl_tx_list_addr)); - - CSR_WRITE_1(sc, RL_EARLY_TX_THRESH, 16); - - /* * Initialize the timer interrupt register so that * a timer interrupt will be generated once the timer * reaches a certain number of ticks. The timer is --- 2264,2269 ---- *************** *** 2222,2227 **** --- 2287,2294 ---- RL_UNLOCK(sc); return; } + + sc->rl_link = 0; mii_mediachg(mii);