Deleted Added
full compact
if_wb.c (41934) if_wb.c (42718)
1/*
2 * Copyright (c) 1997, 1998
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 *
1/*
2 * Copyright (c) 1997, 1998
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 * $Id: if_wb.c,v 1.4 1998/12/14 06:32:56 dillon Exp $
32 * $Id: if_wb.c,v 1.36 1999/01/16 05:28:52 wpaul Exp $
33 */
34
35/*
36 * Winbond fast ethernet PCI NIC driver
37 *
38 * Supports various cheap network adapters based on the Winbond W89C840F
39 * fast ethernet controller chip. This includes adapters manufactured by
40 * Winbond itself and some made by Linksys.

--- 75 unchanged lines hidden (view full) ---

116#define WB_USEIOSPACE
117
118/* #define WB_BACKGROUND_AUTONEG */
119
120#include <pci/if_wbreg.h>
121
122#ifndef lint
123static const char rcsid[] =
33 */
34
35/*
36 * Winbond fast ethernet PCI NIC driver
37 *
38 * Supports various cheap network adapters based on the Winbond W89C840F
39 * fast ethernet controller chip. This includes adapters manufactured by
40 * Winbond itself and some made by Linksys.

--- 75 unchanged lines hidden (view full) ---

116#define WB_USEIOSPACE
117
118/* #define WB_BACKGROUND_AUTONEG */
119
120#include <pci/if_wbreg.h>
121
122#ifndef lint
123static const char rcsid[] =
124 "$Id: if_wb.c,v 1.4 1998/12/14 06:32:56 dillon Exp $";
124 "$Id: if_wb.c,v 1.36 1999/01/16 05:28:52 wpaul Exp $";
125#endif
126
127/*
128 * Various supported device vendors/types and their names.
129 */
130static struct wb_type wb_devs[] = {
131 { WB_VENDORID, WB_DEVICEID_840F,
132 "Winbond W89C840F 10/100BaseTX" },

--- 36 unchanged lines hidden (view full) ---

169static int wb_ioctl __P((struct ifnet *, u_long, caddr_t));
170static void wb_init __P((void *));
171static void wb_stop __P((struct wb_softc *));
172static void wb_watchdog __P((struct ifnet *));
173static void wb_shutdown __P((int, void *));
174static int wb_ifmedia_upd __P((struct ifnet *));
175static void wb_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
176
125#endif
126
127/*
128 * Various supported device vendors/types and their names.
129 */
130static struct wb_type wb_devs[] = {
131 { WB_VENDORID, WB_DEVICEID_840F,
132 "Winbond W89C840F 10/100BaseTX" },

--- 36 unchanged lines hidden (view full) ---

169static int wb_ioctl __P((struct ifnet *, u_long, caddr_t));
170static void wb_init __P((void *));
171static void wb_stop __P((struct wb_softc *));
172static void wb_watchdog __P((struct ifnet *));
173static void wb_shutdown __P((int, void *));
174static int wb_ifmedia_upd __P((struct ifnet *));
175static void wb_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
176
177static void wb_eeprom_putbyte __P((struct wb_softc *, u_int8_t));
178static void wb_eeprom_getword __P((struct wb_softc *, u_int8_t, u_int16_t *));
177static void wb_eeprom_putbyte __P((struct wb_softc *, int));
178static void wb_eeprom_getword __P((struct wb_softc *, int, u_int16_t *));
179static void wb_read_eeprom __P((struct wb_softc *, caddr_t, int,
180 int, int));
181static void wb_mii_sync __P((struct wb_softc *));
182static void wb_mii_send __P((struct wb_softc *, u_int32_t, int));
183static int wb_mii_readreg __P((struct wb_softc *, struct wb_mii_frame *));
184static int wb_mii_writereg __P((struct wb_softc *, struct wb_mii_frame *));
185static u_int16_t wb_phy_readreg __P((struct wb_softc *, int));
179static void wb_read_eeprom __P((struct wb_softc *, caddr_t, int,
180 int, int));
181static void wb_mii_sync __P((struct wb_softc *));
182static void wb_mii_send __P((struct wb_softc *, u_int32_t, int));
183static int wb_mii_readreg __P((struct wb_softc *, struct wb_mii_frame *));
184static int wb_mii_writereg __P((struct wb_softc *, struct wb_mii_frame *));
185static u_int16_t wb_phy_readreg __P((struct wb_softc *, int));
186static void wb_phy_writereg __P((struct wb_softc *, u_int16_t, u_int16_t));
186static void wb_phy_writereg __P((struct wb_softc *, int, int));
187
188static void wb_autoneg_xmit __P((struct wb_softc *));
189static void wb_autoneg_mii __P((struct wb_softc *, int, int));
190static void wb_setmode_mii __P((struct wb_softc *, int));
191static void wb_getmode_mii __P((struct wb_softc *));
187
188static void wb_autoneg_xmit __P((struct wb_softc *));
189static void wb_autoneg_mii __P((struct wb_softc *, int, int));
190static void wb_setmode_mii __P((struct wb_softc *, int));
191static void wb_getmode_mii __P((struct wb_softc *));
192static void wb_setcfg __P((struct wb_softc *, u_int16_t));
193static u_int8_t wb_calchash __P((u_int8_t *));
192static void wb_setcfg __P((struct wb_softc *, int));
193static u_int8_t wb_calchash __P((caddr_t));
194static void wb_setmulti __P((struct wb_softc *));
195static void wb_reset __P((struct wb_softc *));
196static int wb_list_rx_init __P((struct wb_softc *));
197static int wb_list_tx_init __P((struct wb_softc *));
198
199#define WB_SETBIT(sc, reg, x) \
200 CSR_WRITE_4(sc, reg, \
201 CSR_READ_4(sc, reg) | x)

--- 10 unchanged lines hidden (view full) ---

212 CSR_WRITE_4(sc, WB_SIO, \
213 CSR_READ_4(sc, WB_SIO) & ~x)
214
215/*
216 * Send a read command and address to the EEPROM, check for ACK.
217 */
218static void wb_eeprom_putbyte(sc, addr)
219 struct wb_softc *sc;
194static void wb_setmulti __P((struct wb_softc *));
195static void wb_reset __P((struct wb_softc *));
196static int wb_list_rx_init __P((struct wb_softc *));
197static int wb_list_tx_init __P((struct wb_softc *));
198
199#define WB_SETBIT(sc, reg, x) \
200 CSR_WRITE_4(sc, reg, \
201 CSR_READ_4(sc, reg) | x)

--- 10 unchanged lines hidden (view full) ---

212 CSR_WRITE_4(sc, WB_SIO, \
213 CSR_READ_4(sc, WB_SIO) & ~x)
214
215/*
216 * Send a read command and address to the EEPROM, check for ACK.
217 */
218static void wb_eeprom_putbyte(sc, addr)
219 struct wb_softc *sc;
220 u_int8_t addr;
220 int addr;
221{
222 register int d, i;
223
224 d = addr | WB_EECMD_READ;
225
226 /*
227 * Feed in each bit and stobe the clock.
228 */

--- 13 unchanged lines hidden (view full) ---

242 return;
243}
244
245/*
246 * Read a word of data stored in the EEPROM at address 'addr.'
247 */
248static void wb_eeprom_getword(sc, addr, dest)
249 struct wb_softc *sc;
221{
222 register int d, i;
223
224 d = addr | WB_EECMD_READ;
225
226 /*
227 * Feed in each bit and stobe the clock.
228 */

--- 13 unchanged lines hidden (view full) ---

242 return;
243}
244
245/*
246 * Read a word of data stored in the EEPROM at address 'addr.'
247 */
248static void wb_eeprom_getword(sc, addr, dest)
249 struct wb_softc *sc;
250 u_int8_t addr;
250 int addr;
251 u_int16_t *dest;
252{
253 register int i;
254 u_int16_t word = 0;
255
256 /* Enter EEPROM access mode. */
257 CSR_WRITE_4(sc, WB_SIO, WB_SIO_EESEL|WB_SIO_EE_CS);
258

--- 251 unchanged lines hidden (view full) ---

510 frame.mii_regaddr = reg;
511 wb_mii_readreg(sc, &frame);
512
513 return(frame.mii_data);
514}
515
516static void wb_phy_writereg(sc, reg, data)
517 struct wb_softc *sc;
251 u_int16_t *dest;
252{
253 register int i;
254 u_int16_t word = 0;
255
256 /* Enter EEPROM access mode. */
257 CSR_WRITE_4(sc, WB_SIO, WB_SIO_EESEL|WB_SIO_EE_CS);
258

--- 251 unchanged lines hidden (view full) ---

510 frame.mii_regaddr = reg;
511 wb_mii_readreg(sc, &frame);
512
513 return(frame.mii_data);
514}
515
516static void wb_phy_writereg(sc, reg, data)
517 struct wb_softc *sc;
518 u_int16_t reg;
519 u_int16_t data;
518 int reg;
519 int data;
520{
521 struct wb_mii_frame frame;
522
523 bzero((char *)&frame, sizeof(frame));
524
525 frame.mii_phyaddr = sc->wb_phy_addr;
526 frame.mii_regaddr = reg;
527 frame.mii_data = data;
528
529 wb_mii_writereg(sc, &frame);
530
531 return;
532}
533
534static u_int8_t wb_calchash(addr)
520{
521 struct wb_mii_frame frame;
522
523 bzero((char *)&frame, sizeof(frame));
524
525 frame.mii_phyaddr = sc->wb_phy_addr;
526 frame.mii_regaddr = reg;
527 frame.mii_data = data;
528
529 wb_mii_writereg(sc, &frame);
530
531 return;
532}
533
534static u_int8_t wb_calchash(addr)
535 u_int8_t *addr;
535 caddr_t addr;
536{
537 u_int32_t crc, carry;
538 int i, j;
539 u_int8_t c;
540
541 /* Compute CRC for the address value. */
542 crc = 0xFFFFFFFF; /* initial value */
543

--- 381 unchanged lines hidden (view full) ---

925
926/*
927 * The Winbond manual states that in order to fiddle with the
928 * 'full-duplex' and '100Mbps' bits in the netconfig register, we
929 * first have to put the transmit and/or receive logic in the idle state.
930 */
931static void wb_setcfg(sc, bmcr)
932 struct wb_softc *sc;
536{
537 u_int32_t crc, carry;
538 int i, j;
539 u_int8_t c;
540
541 /* Compute CRC for the address value. */
542 crc = 0xFFFFFFFF; /* initial value */
543

--- 381 unchanged lines hidden (view full) ---

925
926/*
927 * The Winbond manual states that in order to fiddle with the
928 * 'full-duplex' and '100Mbps' bits in the netconfig register, we
929 * first have to put the transmit and/or receive logic in the idle state.
930 */
931static void wb_setcfg(sc, bmcr)
932 struct wb_softc *sc;
933 u_int16_t bmcr;
933 int bmcr;
934{
935 int i, restart = 0;
936
937 if (CSR_READ_4(sc, WB_NETCFG) & (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)) {
938 restart = 1;
939 WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON));
940
941 for (i = 0; i < WB_TIMEOUT; i++) {

--- 412 unchanged lines hidden (view full) ---

1354
1355 ifp = &sc->arpcom.ac_if;
1356
1357 while(!((rxstat = sc->wb_cdata.wb_rx_head->wb_ptr->wb_status) &
1358 WB_RXSTAT_OWN)) {
1359 cur_rx = sc->wb_cdata.wb_rx_head;
1360 sc->wb_cdata.wb_rx_head = cur_rx->wb_nextdesc;
1361
934{
935 int i, restart = 0;
936
937 if (CSR_READ_4(sc, WB_NETCFG) & (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)) {
938 restart = 1;
939 WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON));
940
941 for (i = 0; i < WB_TIMEOUT; i++) {

--- 412 unchanged lines hidden (view full) ---

1354
1355 ifp = &sc->arpcom.ac_if;
1356
1357 while(!((rxstat = sc->wb_cdata.wb_rx_head->wb_ptr->wb_status) &
1358 WB_RXSTAT_OWN)) {
1359 cur_rx = sc->wb_cdata.wb_rx_head;
1360 sc->wb_cdata.wb_rx_head = cur_rx->wb_nextdesc;
1361
1362 if ((rxstat & WB_RXSTAT_RXERR) || (rxstat & WB_RXSTAT_MIIERR)
1362 if ((rxstat & WB_RXSTAT_MIIERR)
1363 || WB_RXBYTES(cur_rx->wb_ptr->wb_status) == 0) {
1364 ifp->if_ierrors++;
1365 wb_reset(sc);
1366 printf("wb%x: receiver babbling: possible chip "
1367 "bug, forcing reset\n", sc->wb_unit);
1368 ifp->if_flags |= IFF_OACTIVE;
1369 ifp->if_timer = 2;
1370 return;
1371 }
1372
1363 || WB_RXBYTES(cur_rx->wb_ptr->wb_status) == 0) {
1364 ifp->if_ierrors++;
1365 wb_reset(sc);
1366 printf("wb%x: receiver babbling: possible chip "
1367 "bug, forcing reset\n", sc->wb_unit);
1368 ifp->if_flags |= IFF_OACTIVE;
1369 ifp->if_timer = 2;
1370 return;
1371 }
1372
1373 if (rxstat & WB_RXSTAT_RXERR) {
1374 ifp->if_ierrors++;
1375 cur_rx->wb_ptr->wb_ctl =
1376 WB_RXCTL_RLINK | (MCLBYTES - 1);
1377 cur_rx->wb_ptr->wb_status = WB_RXSTAT;
1378 continue;
1379 }
1380
1373 /* No errors; receive the packet. */
1381 /* No errors; receive the packet. */
1374 m = cur_rx->wb_mbuf;
1375 total_len = WB_RXBYTES(cur_rx->wb_ptr->wb_status);
1376
1377 /*
1378 * XXX The Winbond chip includes the CRC with every
1379 * received frame, and there's no way to turn this
1380 * behavior off (at least, I can't find anything in
1381 * the manual that explains how to do it) so we have
1382 * to trim off the CRC manually.
1383 */
1384 total_len -= ETHER_CRC_LEN;
1385
1382 total_len = WB_RXBYTES(cur_rx->wb_ptr->wb_status);
1383
1384 /*
1385 * XXX The Winbond chip includes the CRC with every
1386 * received frame, and there's no way to turn this
1387 * behavior off (at least, I can't find anything in
1388 * the manual that explains how to do it) so we have
1389 * to trim off the CRC manually.
1390 */
1391 total_len -= ETHER_CRC_LEN;
1392
1393 if (total_len < MINCLSIZE) {
1394 m = m_devget(mtod(cur_rx->wb_mbuf, char *),
1395 total_len, 0, ifp, NULL);
1396 cur_rx->wb_ptr->wb_ctl =
1397 WB_RXCTL_RLINK | (MCLBYTES - 1);
1398 cur_rx->wb_ptr->wb_status = WB_RXSTAT;
1399 if (m == NULL) {
1400 ifp->if_ierrors++;
1401 continue;
1402 }
1403 } else {
1404 m = cur_rx->wb_mbuf;
1386 /*
1387 * Try to conjure up a new mbuf cluster. If that
1388 * fails, it means we have an out of memory condition and
1389 * should leave the buffer in place and continue. This will
1390 * result in a lost packet, but there's little else we
1391 * can do in this situation.
1392 */
1405 /*
1406 * Try to conjure up a new mbuf cluster. If that
1407 * fails, it means we have an out of memory condition and
1408 * should leave the buffer in place and continue. This will
1409 * result in a lost packet, but there's little else we
1410 * can do in this situation.
1411 */
1393 if (wb_newbuf(sc, cur_rx) == ENOBUFS) {
1394 ifp->if_ierrors++;
1395 cur_rx->wb_ptr->wb_ctl =
1412 if (wb_newbuf(sc, cur_rx) == ENOBUFS) {
1413 ifp->if_ierrors++;
1414 cur_rx->wb_ptr->wb_ctl =
1396 WB_RXCTL_RLINK | (MCLBYTES - 1);
1415 WB_RXCTL_RLINK | (MCLBYTES - 1);
1397 cur_rx->wb_ptr->wb_status = WB_RXSTAT;
1398 continue;
1416 cur_rx->wb_ptr->wb_status = WB_RXSTAT;
1417 continue;
1418 }
1419 m->m_pkthdr.rcvif = ifp;
1420 m->m_pkthdr.len = m->m_len = total_len;
1399 }
1400
1401 ifp->if_ipackets++;
1402 eh = mtod(m, struct ether_header *);
1421 }
1422
1423 ifp->if_ipackets++;
1424 eh = mtod(m, struct ether_header *);
1403 m->m_pkthdr.rcvif = ifp;
1404 m->m_pkthdr.len = m->m_len = total_len;
1405
1406#if NBPFILTER > 0
1407 /*
1408 * Handle BPF listeners. Let the BPF user see the packet, but
1409 * don't pass it up to the ether_input() layer unless it's
1410 * a broadcast packet, multicast packet, matches our ethernet
1411 * address or the interface is in promiscuous mode.
1412 */

--- 143 unchanged lines hidden (view full) ---

1556 if (status & WB_ISR_RX_OK)
1557 wb_rxeof(sc);
1558
1559 if (status & WB_ISR_RX_IDLE)
1560 wb_rxeoc(sc);
1561
1562 if ((status & WB_ISR_RX_NOBUF) || (status & WB_ISR_RX_ERR)) {
1563 ifp->if_ierrors++;
1425
1426#if NBPFILTER > 0
1427 /*
1428 * Handle BPF listeners. Let the BPF user see the packet, but
1429 * don't pass it up to the ether_input() layer unless it's
1430 * a broadcast packet, multicast packet, matches our ethernet
1431 * address or the interface is in promiscuous mode.
1432 */

--- 143 unchanged lines hidden (view full) ---

1576 if (status & WB_ISR_RX_OK)
1577 wb_rxeof(sc);
1578
1579 if (status & WB_ISR_RX_IDLE)
1580 wb_rxeoc(sc);
1581
1582 if ((status & WB_ISR_RX_NOBUF) || (status & WB_ISR_RX_ERR)) {
1583 ifp->if_ierrors++;
1584#ifdef foo
1564 wb_stop(sc);
1565 wb_reset(sc);
1566 wb_init(sc);
1585 wb_stop(sc);
1586 wb_reset(sc);
1587 wb_init(sc);
1588#endif
1567 }
1568
1569 if (status & WB_ISR_TX_OK)
1570 wb_txeof(sc);
1571
1572 if (status & WB_ISR_TX_NOBUF)
1573 wb_txeoc(sc);
1574

--- 194 unchanged lines hidden (view full) ---

1769 /*
1770 * Place the request for the upload interrupt
1771 * in the last descriptor in the chain. This way, if
1772 * we're chaining several packets at once, we'll only
1773 * get an interupt once for the whole chain rather than
1774 * once for each packet.
1775 */
1776 WB_TXCTL(cur_tx) |= WB_TXCTL_FINT;
1589 }
1590
1591 if (status & WB_ISR_TX_OK)
1592 wb_txeof(sc);
1593
1594 if (status & WB_ISR_TX_NOBUF)
1595 wb_txeoc(sc);
1596

--- 194 unchanged lines hidden (view full) ---

1791 /*
1792 * Place the request for the upload interrupt
1793 * in the last descriptor in the chain. This way, if
1794 * we're chaining several packets at once, we'll only
1795 * get an interupt once for the whole chain rather than
1796 * once for each packet.
1797 */
1798 WB_TXCTL(cur_tx) |= WB_TXCTL_FINT;
1799 cur_tx->wb_ptr->wb_frag[0].wb_ctl |= WB_TXCTL_FINT;
1777 sc->wb_cdata.wb_tx_tail = cur_tx;
1778
1779 if (sc->wb_cdata.wb_tx_head == NULL) {
1780 sc->wb_cdata.wb_tx_head = start_tx;
1781 WB_TXOWN(start_tx) = WB_TXSTAT_OWN;
1782 CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
1783 } else {
1784 /*

--- 344 unchanged lines hidden ---
1800 sc->wb_cdata.wb_tx_tail = cur_tx;
1801
1802 if (sc->wb_cdata.wb_tx_head == NULL) {
1803 sc->wb_cdata.wb_tx_head = start_tx;
1804 WB_TXOWN(start_tx) = WB_TXSTAT_OWN;
1805 CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
1806 } else {
1807 /*

--- 344 unchanged lines hidden ---