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 --- |