Annotation of sys/dev/ic/rtl81x9.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rtl81x9.c,v 1.56 2007/05/08 18:49:32 deraadt Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1997, 1998
! 5: * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Bill Paul.
! 18: * 4. Neither the name of the author nor the names of any co-contributors
! 19: * may be used to endorse or promote products derived from this software
! 20: * without specific prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
! 23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 25: * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
! 26: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 27: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 28: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 29: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 30: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 31: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 32: * THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: /*
! 36: * RealTek 8129/8139 PCI NIC driver
! 37: *
! 38: * Supports several extremely cheap PCI 10/100 adapters based on
! 39: * the RealTek chipset. Datasheets can be obtained from
! 40: * www.realtek.com.tw.
! 41: *
! 42: * Written by Bill Paul <wpaul@ctr.columbia.edu>
! 43: * Electrical Engineering Department
! 44: * Columbia University, New York City
! 45: */
! 46:
! 47: /*
! 48: * The RealTek 8139 PCI NIC redefines the meaning of 'low end.' This is
! 49: * probably the worst PCI ethernet controller ever made, with the possible
! 50: * exception of the FEAST chip made by SMC. The 8139 supports bus-master
! 51: * DMA, but it has a terrible interface that nullifies any performance
! 52: * gains that bus-master DMA usually offers.
! 53: *
! 54: * For transmission, the chip offers a series of four TX descriptor
! 55: * registers. Each transmit frame must be in a contiguous buffer, aligned
! 56: * on a longword (32-bit) boundary. This means we almost always have to
! 57: * do mbuf copies in order to transmit a frame, except in the unlikely
! 58: * case where a) the packet fits into a single mbuf, and b) the packet
! 59: * is 32-bit aligned within the mbuf's data area. The presence of only
! 60: * four descriptor registers means that we can never have more than four
! 61: * packets queued for transmission at any one time.
! 62: *
! 63: * Reception is not much better. The driver has to allocate a single large
! 64: * buffer area (up to 64K in size) into which the chip will DMA received
! 65: * frames. Because we don't know where within this region received packets
! 66: * will begin or end, we have no choice but to copy data from the buffer
! 67: * area into mbufs in order to pass the packets up to the higher protocol
! 68: * levels.
! 69: *
! 70: * It's impossible given this rotten design to really achieve decent
! 71: * performance at 100Mbps, unless you happen to have a 400MHz PII or
! 72: * some equally overmuscled CPU to drive it.
! 73: *
! 74: * On the bright side, the 8139 does have a built-in PHY, although
! 75: * rather than using an MDIO serial interface like most other NICs, the
! 76: * PHY registers are directly accessible through the 8139's register
! 77: * space. The 8139 supports autonegotiation, as well as a 64-bit multicast
! 78: * filter.
! 79: *
! 80: * The 8129 chip is an older version of the 8139 that uses an external PHY
! 81: * chip. The 8129 has a serial MDIO interface for accessing the MII where
! 82: * the 8139 lets you directly access the on-board PHY registers. We need
! 83: * to select which interface to use depending on the chip type.
! 84: */
! 85:
! 86: #include "bpfilter.h"
! 87:
! 88: #include <sys/param.h>
! 89: #include <sys/systm.h>
! 90: #include <sys/sockio.h>
! 91: #include <sys/mbuf.h>
! 92: #include <sys/malloc.h>
! 93: #include <sys/kernel.h>
! 94: #include <sys/socket.h>
! 95: #include <sys/device.h>
! 96: #include <sys/timeout.h>
! 97:
! 98: #include <net/if.h>
! 99: #include <net/if_dl.h>
! 100: #include <net/if_types.h>
! 101:
! 102: #ifdef INET
! 103: #include <netinet/in.h>
! 104: #include <netinet/in_systm.h>
! 105: #include <netinet/in_var.h>
! 106: #include <netinet/ip.h>
! 107: #include <netinet/if_ether.h>
! 108: #endif
! 109:
! 110: #include <net/if_media.h>
! 111:
! 112: #if NBPFILTER > 0
! 113: #include <net/bpf.h>
! 114: #endif
! 115:
! 116: #include <machine/bus.h>
! 117:
! 118: #include <dev/mii/mii.h>
! 119: #include <dev/mii/miivar.h>
! 120: #include <dev/pci/pcireg.h>
! 121: #include <dev/pci/pcivar.h>
! 122: #include <dev/pci/pcidevs.h>
! 123:
! 124: #include <dev/ic/rtl81x9reg.h>
! 125:
! 126: /*
! 127: * Various supported PHY vendors/types and their names. Note that
! 128: * this driver will work with pretty much any MII-compliant PHY,
! 129: * so failure to positively identify the chip is not a fatal error.
! 130: */
! 131:
! 132: void rl_tick(void *);
! 133: void rl_shutdown(void *);
! 134: void rl_powerhook(int, void *);
! 135:
! 136: int rl_encap(struct rl_softc *, struct mbuf * );
! 137:
! 138: void rl_rxeof(struct rl_softc *);
! 139: void rl_txeof(struct rl_softc *);
! 140: void rl_start(struct ifnet *);
! 141: int rl_ioctl(struct ifnet *, u_long, caddr_t);
! 142: void rl_init(void *);
! 143: void rl_stop(struct rl_softc *);
! 144: void rl_watchdog(struct ifnet *);
! 145: int rl_ifmedia_upd(struct ifnet *);
! 146: void rl_ifmedia_sts(struct ifnet *, struct ifmediareq *);
! 147:
! 148: void rl_eeprom_getword(struct rl_softc *, int, int, u_int16_t *);
! 149: void rl_eeprom_putbyte(struct rl_softc *, int, int);
! 150: void rl_read_eeprom(struct rl_softc *, caddr_t, int, int, int, int);
! 151:
! 152: void rl_mii_sync(struct rl_softc *);
! 153: void rl_mii_send(struct rl_softc *, u_int32_t, int);
! 154: int rl_mii_readreg(struct rl_softc *, struct rl_mii_frame *);
! 155: int rl_mii_writereg(struct rl_softc *, struct rl_mii_frame *);
! 156:
! 157: int rl_miibus_readreg(struct device *, int, int);
! 158: void rl_miibus_writereg(struct device *, int, int, int);
! 159: void rl_miibus_statchg(struct device *);
! 160:
! 161: void rl_setmulti(struct rl_softc *);
! 162: void rl_reset(struct rl_softc *);
! 163: int rl_list_tx_init(struct rl_softc *);
! 164:
! 165: #define EE_SET(x) \
! 166: CSR_WRITE_1(sc, RL_EECMD, \
! 167: CSR_READ_1(sc, RL_EECMD) | x)
! 168:
! 169: #define EE_CLR(x) \
! 170: CSR_WRITE_1(sc, RL_EECMD, \
! 171: CSR_READ_1(sc, RL_EECMD) & ~x)
! 172:
! 173: /*
! 174: * Send a read command and address to the EEPROM, check for ACK.
! 175: */
! 176: void rl_eeprom_putbyte(sc, addr, addr_len)
! 177: struct rl_softc *sc;
! 178: int addr, addr_len;
! 179: {
! 180: register int d, i;
! 181:
! 182: d = (RL_EECMD_READ << addr_len) | addr;
! 183:
! 184: /*
! 185: * Feed in each bit and strobe the clock.
! 186: */
! 187: for (i = RL_EECMD_LEN + addr_len; i; i--) {
! 188: if (d & (1 << (i - 1)))
! 189: EE_SET(RL_EE_DATAIN);
! 190: else
! 191: EE_CLR(RL_EE_DATAIN);
! 192:
! 193: DELAY(100);
! 194: EE_SET(RL_EE_CLK);
! 195: DELAY(150);
! 196: EE_CLR(RL_EE_CLK);
! 197: DELAY(100);
! 198: }
! 199: }
! 200:
! 201: /*
! 202: * Read a word of data stored in the EEPROM at address 'addr.'
! 203: */
! 204: void rl_eeprom_getword(sc, addr, addr_len, dest)
! 205: struct rl_softc *sc;
! 206: int addr, addr_len;
! 207: u_int16_t *dest;
! 208: {
! 209: register int i;
! 210: u_int16_t word = 0;
! 211:
! 212: /* Enter EEPROM access mode. */
! 213: CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM|RL_EE_SEL);
! 214:
! 215: /*
! 216: * Send address of word we want to read.
! 217: */
! 218: rl_eeprom_putbyte(sc, addr, addr_len);
! 219:
! 220: CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM|RL_EE_SEL);
! 221:
! 222: /*
! 223: * Start reading bits from EEPROM.
! 224: */
! 225: for (i = 16; i > 0; i--) {
! 226: EE_SET(RL_EE_CLK);
! 227: DELAY(100);
! 228: if (CSR_READ_1(sc, RL_EECMD) & RL_EE_DATAOUT)
! 229: word |= 1 << (i - 1);
! 230: EE_CLR(RL_EE_CLK);
! 231: DELAY(100);
! 232: }
! 233:
! 234: /* Turn off EEPROM access mode. */
! 235: CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
! 236:
! 237: *dest = word;
! 238: }
! 239:
! 240: /*
! 241: * Read a sequence of words from the EEPROM.
! 242: */
! 243: void rl_read_eeprom(sc, dest, off, addr_len, cnt, swap)
! 244: struct rl_softc *sc;
! 245: caddr_t dest;
! 246: int off;
! 247: int addr_len;
! 248: int cnt;
! 249: int swap;
! 250: {
! 251: int i;
! 252: u_int16_t word = 0, *ptr;
! 253:
! 254: for (i = 0; i < cnt; i++) {
! 255: rl_eeprom_getword(sc, off + i, addr_len, &word);
! 256: ptr = (u_int16_t *)(dest + (i * 2));
! 257: if (swap)
! 258: *ptr = letoh16(word);
! 259: else
! 260: *ptr = word;
! 261: }
! 262: }
! 263:
! 264: /*
! 265: * MII access routines are provided for the 8129, which
! 266: * doesn't have a built-in PHY. For the 8139, we fake things
! 267: * up by diverting rl_phy_readreg()/rl_phy_writereg() to the
! 268: * direct access PHY registers.
! 269: */
! 270: #define MII_SET(x) \
! 271: CSR_WRITE_1(sc, RL_MII, \
! 272: CSR_READ_1(sc, RL_MII) | x)
! 273:
! 274: #define MII_CLR(x) \
! 275: CSR_WRITE_1(sc, RL_MII, \
! 276: CSR_READ_1(sc, RL_MII) & ~x)
! 277:
! 278: /*
! 279: * Sync the PHYs by setting data bit and strobing the clock 32 times.
! 280: */
! 281: void rl_mii_sync(sc)
! 282: struct rl_softc *sc;
! 283: {
! 284: register int i;
! 285:
! 286: MII_SET(RL_MII_DIR|RL_MII_DATAOUT);
! 287:
! 288: for (i = 0; i < 32; i++) {
! 289: MII_SET(RL_MII_CLK);
! 290: DELAY(1);
! 291: MII_CLR(RL_MII_CLK);
! 292: DELAY(1);
! 293: }
! 294: }
! 295:
! 296: /*
! 297: * Clock a series of bits through the MII.
! 298: */
! 299: void rl_mii_send(sc, bits, cnt)
! 300: struct rl_softc *sc;
! 301: u_int32_t bits;
! 302: int cnt;
! 303: {
! 304: int i;
! 305:
! 306: MII_CLR(RL_MII_CLK);
! 307:
! 308: for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
! 309: if (bits & i)
! 310: MII_SET(RL_MII_DATAOUT);
! 311: else
! 312: MII_CLR(RL_MII_DATAOUT);
! 313: DELAY(1);
! 314: MII_CLR(RL_MII_CLK);
! 315: DELAY(1);
! 316: MII_SET(RL_MII_CLK);
! 317: }
! 318: }
! 319:
! 320: /*
! 321: * Read an PHY register through the MII.
! 322: */
! 323: int rl_mii_readreg(sc, frame)
! 324: struct rl_softc *sc;
! 325: struct rl_mii_frame *frame;
! 326: {
! 327: int i, ack, s;
! 328:
! 329: s = splnet();
! 330:
! 331: /*
! 332: * Set up frame for RX.
! 333: */
! 334: frame->mii_stdelim = RL_MII_STARTDELIM;
! 335: frame->mii_opcode = RL_MII_READOP;
! 336: frame->mii_turnaround = 0;
! 337: frame->mii_data = 0;
! 338:
! 339: CSR_WRITE_2(sc, RL_MII, 0);
! 340:
! 341: /*
! 342: * Turn on data xmit.
! 343: */
! 344: MII_SET(RL_MII_DIR);
! 345:
! 346: rl_mii_sync(sc);
! 347:
! 348: /*
! 349: * Send command/address info.
! 350: */
! 351: rl_mii_send(sc, frame->mii_stdelim, 2);
! 352: rl_mii_send(sc, frame->mii_opcode, 2);
! 353: rl_mii_send(sc, frame->mii_phyaddr, 5);
! 354: rl_mii_send(sc, frame->mii_regaddr, 5);
! 355:
! 356: /* Idle bit */
! 357: MII_CLR((RL_MII_CLK|RL_MII_DATAOUT));
! 358: DELAY(1);
! 359: MII_SET(RL_MII_CLK);
! 360: DELAY(1);
! 361:
! 362: /* Turn off xmit. */
! 363: MII_CLR(RL_MII_DIR);
! 364:
! 365: /* Check for ack */
! 366: MII_CLR(RL_MII_CLK);
! 367: DELAY(1);
! 368: ack = CSR_READ_2(sc, RL_MII) & RL_MII_DATAIN;
! 369: MII_SET(RL_MII_CLK);
! 370: DELAY(1);
! 371:
! 372: /*
! 373: * Now try reading data bits. If the ack failed, we still
! 374: * need to clock through 16 cycles to keep the PHY(s) in sync.
! 375: */
! 376: if (ack) {
! 377: for(i = 0; i < 16; i++) {
! 378: MII_CLR(RL_MII_CLK);
! 379: DELAY(1);
! 380: MII_SET(RL_MII_CLK);
! 381: DELAY(1);
! 382: }
! 383: goto fail;
! 384: }
! 385:
! 386: for (i = 0x8000; i; i >>= 1) {
! 387: MII_CLR(RL_MII_CLK);
! 388: DELAY(1);
! 389: if (!ack) {
! 390: if (CSR_READ_2(sc, RL_MII) & RL_MII_DATAIN)
! 391: frame->mii_data |= i;
! 392: DELAY(1);
! 393: }
! 394: MII_SET(RL_MII_CLK);
! 395: DELAY(1);
! 396: }
! 397:
! 398: fail:
! 399:
! 400: MII_CLR(RL_MII_CLK);
! 401: DELAY(1);
! 402: MII_SET(RL_MII_CLK);
! 403: DELAY(1);
! 404:
! 405: splx(s);
! 406:
! 407: if (ack)
! 408: return(1);
! 409: return(0);
! 410: }
! 411:
! 412: /*
! 413: * Write to a PHY register through the MII.
! 414: */
! 415: int rl_mii_writereg(sc, frame)
! 416: struct rl_softc *sc;
! 417: struct rl_mii_frame *frame;
! 418: {
! 419: int s;
! 420:
! 421: s = splnet();
! 422: /*
! 423: * Set up frame for TX.
! 424: */
! 425:
! 426: frame->mii_stdelim = RL_MII_STARTDELIM;
! 427: frame->mii_opcode = RL_MII_WRITEOP;
! 428: frame->mii_turnaround = RL_MII_TURNAROUND;
! 429:
! 430: /*
! 431: * Turn on data output.
! 432: */
! 433: MII_SET(RL_MII_DIR);
! 434:
! 435: rl_mii_sync(sc);
! 436:
! 437: rl_mii_send(sc, frame->mii_stdelim, 2);
! 438: rl_mii_send(sc, frame->mii_opcode, 2);
! 439: rl_mii_send(sc, frame->mii_phyaddr, 5);
! 440: rl_mii_send(sc, frame->mii_regaddr, 5);
! 441: rl_mii_send(sc, frame->mii_turnaround, 2);
! 442: rl_mii_send(sc, frame->mii_data, 16);
! 443:
! 444: /* Idle bit. */
! 445: MII_SET(RL_MII_CLK);
! 446: DELAY(1);
! 447: MII_CLR(RL_MII_CLK);
! 448: DELAY(1);
! 449:
! 450: /*
! 451: * Turn off xmit.
! 452: */
! 453: MII_CLR(RL_MII_DIR);
! 454:
! 455: splx(s);
! 456:
! 457: return(0);
! 458: }
! 459:
! 460: /*
! 461: * Program the 64-bit multicast hash filter.
! 462: */
! 463: void rl_setmulti(sc)
! 464: struct rl_softc *sc;
! 465: {
! 466: struct ifnet *ifp;
! 467: int h = 0;
! 468: u_int32_t hashes[2] = { 0, 0 };
! 469: struct arpcom *ac = &sc->sc_arpcom;
! 470: struct ether_multi *enm;
! 471: struct ether_multistep step;
! 472: u_int32_t rxfilt;
! 473: int mcnt = 0;
! 474:
! 475: ifp = &sc->sc_arpcom.ac_if;
! 476:
! 477: rxfilt = CSR_READ_4(sc, RL_RXCFG);
! 478:
! 479: allmulti:
! 480: if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
! 481: rxfilt |= RL_RXCFG_RX_MULTI;
! 482: CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
! 483: CSR_WRITE_4(sc, RL_MAR0, 0xFFFFFFFF);
! 484: CSR_WRITE_4(sc, RL_MAR4, 0xFFFFFFFF);
! 485: return;
! 486: }
! 487:
! 488: /* first, zot all the existing hash bits */
! 489: CSR_WRITE_4(sc, RL_MAR0, 0);
! 490: CSR_WRITE_4(sc, RL_MAR4, 0);
! 491:
! 492: /* now program new ones */
! 493: ETHER_FIRST_MULTI(step, ac, enm);
! 494: while (enm != NULL) {
! 495: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
! 496: ifp->if_flags |= IFF_ALLMULTI;
! 497: goto allmulti;
! 498: }
! 499: mcnt++;
! 500: h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
! 501: if (h < 32)
! 502: hashes[0] |= (1 << h);
! 503: else
! 504: hashes[1] |= (1 << (h - 32));
! 505: mcnt++;
! 506: ETHER_NEXT_MULTI(step, enm);
! 507: }
! 508:
! 509: if (mcnt)
! 510: rxfilt |= RL_RXCFG_RX_MULTI;
! 511: else
! 512: rxfilt &= ~RL_RXCFG_RX_MULTI;
! 513:
! 514: CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
! 515: CSR_WRITE_4(sc, RL_MAR0, hashes[0]);
! 516: CSR_WRITE_4(sc, RL_MAR4, hashes[1]);
! 517: }
! 518:
! 519: void
! 520: rl_reset(sc)
! 521: struct rl_softc *sc;
! 522: {
! 523: register int i;
! 524:
! 525: CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RESET);
! 526:
! 527: for (i = 0; i < RL_TIMEOUT; i++) {
! 528: DELAY(10);
! 529: if (!(CSR_READ_1(sc, RL_COMMAND) & RL_CMD_RESET))
! 530: break;
! 531: }
! 532: if (i == RL_TIMEOUT)
! 533: printf("%s: reset never completed!\n", sc->sc_dev.dv_xname);
! 534:
! 535: }
! 536:
! 537: /*
! 538: * Initialize the transmit descriptors.
! 539: */
! 540: int
! 541: rl_list_tx_init(sc)
! 542: struct rl_softc *sc;
! 543: {
! 544: struct rl_chain_data *cd;
! 545: int i;
! 546:
! 547: cd = &sc->rl_cdata;
! 548: for (i = 0; i < RL_TX_LIST_CNT; i++) {
! 549: cd->rl_tx_chain[i] = NULL;
! 550: CSR_WRITE_4(sc,
! 551: RL_TXADDR0 + (i * sizeof(u_int32_t)), 0x0000000);
! 552: }
! 553:
! 554: sc->rl_cdata.cur_tx = 0;
! 555: sc->rl_cdata.last_tx = 0;
! 556:
! 557: return(0);
! 558: }
! 559:
! 560: /*
! 561: * A frame has been uploaded: pass the resulting mbuf chain up to
! 562: * the higher level protocols.
! 563: *
! 564: * You know there's something wrong with a PCI bus-master chip design
! 565: * when you have to use m_devget().
! 566: *
! 567: * The receive operation is badly documented in the datasheet, so I'll
! 568: * attempt to document it here. The driver provides a buffer area and
! 569: * places its base address in the RX buffer start address register.
! 570: * The chip then begins copying frames into the RX buffer. Each frame
! 571: * is preceded by a 32-bit RX status word which specifies the length
! 572: * of the frame and certain other status bits. Each frame (starting with
! 573: * the status word) is also 32-bit aligned. The frame length is in the
! 574: * first 16 bits of the status word; the lower 15 bits correspond with
! 575: * the 'rx status register' mentioned in the datasheet.
! 576: *
! 577: * Note: to make the Alpha happy, the frame payload needs to be aligned
! 578: * on a 32-bit boundary. To achieve this, we cheat a bit by copying from
! 579: * the ring buffer starting at an address two bytes before the actual
! 580: * data location. We can then shave off the first two bytes using m_adj().
! 581: * The reason we do this is because m_devget() doesn't let us specify an
! 582: * offset into the mbuf storage space, so we have to artificially create
! 583: * one. The ring is allocated in such a way that there are a few unused
! 584: * bytes of space preceding it so that it will be safe for us to do the
! 585: * 2-byte backstep even if reading from the ring at offset 0.
! 586: */
! 587: void
! 588: rl_rxeof(sc)
! 589: struct rl_softc *sc;
! 590: {
! 591: struct mbuf *m;
! 592: struct ifnet *ifp;
! 593: int total_len;
! 594: u_int32_t rxstat;
! 595: caddr_t rxbufpos;
! 596: int wrap = 0;
! 597: u_int16_t cur_rx;
! 598: u_int16_t limit;
! 599: u_int16_t rx_bytes = 0, max_bytes;
! 600:
! 601: ifp = &sc->sc_arpcom.ac_if;
! 602:
! 603: cur_rx = (CSR_READ_2(sc, RL_CURRXADDR) + 16) % RL_RXBUFLEN;
! 604:
! 605: /* Do not try to read past this point. */
! 606: limit = CSR_READ_2(sc, RL_CURRXBUF) % RL_RXBUFLEN;
! 607:
! 608: if (limit < cur_rx)
! 609: max_bytes = (RL_RXBUFLEN - cur_rx) + limit;
! 610: else
! 611: max_bytes = limit - cur_rx;
! 612:
! 613: while((CSR_READ_1(sc, RL_COMMAND) & RL_CMD_EMPTY_RXBUF) == 0) {
! 614: bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
! 615: 0, sc->sc_rx_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
! 616: rxbufpos = sc->rl_cdata.rl_rx_buf + cur_rx;
! 617: rxstat = *(u_int32_t *)rxbufpos;
! 618:
! 619: /*
! 620: * Here's a totally undocumented fact for you. When the
! 621: * RealTek chip is in the process of copying a packet into
! 622: * RAM for you, the length will be 0xfff0. If you spot a
! 623: * packet header with this value, you need to stop. The
! 624: * datasheet makes absolutely no mention of this and
! 625: * RealTek should be shot for this.
! 626: */
! 627: rxstat = htole32(rxstat);
! 628: total_len = rxstat >> 16;
! 629: if (total_len == RL_RXSTAT_UNFINISHED) {
! 630: bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
! 631: 0, sc->sc_rx_dmamap->dm_mapsize,
! 632: BUS_DMASYNC_PREREAD);
! 633: break;
! 634: }
! 635:
! 636: if (!(rxstat & RL_RXSTAT_RXOK) ||
! 637: total_len < ETHER_MIN_LEN ||
! 638: total_len > ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) {
! 639: ifp->if_ierrors++;
! 640: rl_init(sc);
! 641: bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
! 642: 0, sc->sc_rx_dmamap->dm_mapsize,
! 643: BUS_DMASYNC_PREREAD);
! 644: return;
! 645: }
! 646:
! 647: /* No errors; receive the packet. */
! 648: rx_bytes += total_len + 4;
! 649:
! 650: /*
! 651: * XXX The RealTek chip includes the CRC with every
! 652: * received frame, and there's no way to turn this
! 653: * behavior off (at least, I can't find anything in
! 654: * the manual that explains how to do it) so we have
! 655: * to trim off the CRC manually.
! 656: */
! 657: total_len -= ETHER_CRC_LEN;
! 658:
! 659: /*
! 660: * Avoid trying to read more bytes than we know
! 661: * the chip has prepared for us.
! 662: */
! 663: if (rx_bytes > max_bytes) {
! 664: bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
! 665: 0, sc->sc_rx_dmamap->dm_mapsize,
! 666: BUS_DMASYNC_PREREAD);
! 667: break;
! 668: }
! 669:
! 670: rxbufpos = sc->rl_cdata.rl_rx_buf +
! 671: ((cur_rx + sizeof(u_int32_t)) % RL_RXBUFLEN);
! 672:
! 673: if (rxbufpos == (sc->rl_cdata.rl_rx_buf + RL_RXBUFLEN))
! 674: rxbufpos = sc->rl_cdata.rl_rx_buf;
! 675:
! 676: wrap = (sc->rl_cdata.rl_rx_buf + RL_RXBUFLEN) - rxbufpos;
! 677:
! 678: if (total_len > wrap) {
! 679: m = m_devget(rxbufpos - ETHER_ALIGN,
! 680: wrap + ETHER_ALIGN, 0, ifp, NULL);
! 681: if (m == NULL)
! 682: ifp->if_ierrors++;
! 683: else {
! 684: m_copyback(m, wrap + ETHER_ALIGN,
! 685: total_len - wrap, sc->rl_cdata.rl_rx_buf);
! 686: m = m_pullup(m, sizeof(struct ip) +ETHER_ALIGN);
! 687: if (m == NULL)
! 688: ifp->if_ierrors++;
! 689: else
! 690: m_adj(m, ETHER_ALIGN);
! 691: }
! 692: cur_rx = (total_len - wrap + ETHER_CRC_LEN);
! 693: } else {
! 694: m = m_devget(rxbufpos - ETHER_ALIGN,
! 695: total_len + ETHER_ALIGN, 0, ifp, NULL);
! 696: if (m == NULL)
! 697: ifp->if_ierrors++;
! 698: else
! 699: m_adj(m, ETHER_ALIGN);
! 700: cur_rx += total_len + 4 + ETHER_CRC_LEN;
! 701: }
! 702:
! 703: /*
! 704: * Round up to 32-bit boundary.
! 705: */
! 706: cur_rx = (cur_rx + 3) & ~3;
! 707: CSR_WRITE_2(sc, RL_CURRXADDR, cur_rx - 16);
! 708:
! 709: if (m == NULL) {
! 710: bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
! 711: 0, sc->sc_rx_dmamap->dm_mapsize,
! 712: BUS_DMASYNC_PREREAD);
! 713: continue;
! 714: }
! 715:
! 716: ifp->if_ipackets++;
! 717:
! 718: #if NBPFILTER > 0
! 719: /*
! 720: * Handle BPF listeners. Let the BPF user see the packet.
! 721: */
! 722: if (ifp->if_bpf)
! 723: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
! 724: #endif
! 725: ether_input_mbuf(ifp, m);
! 726:
! 727: bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
! 728: 0, sc->sc_rx_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
! 729: }
! 730: }
! 731:
! 732: /*
! 733: * A frame was downloaded to the chip. It's safe for us to clean up
! 734: * the list buffers.
! 735: */
! 736: void rl_txeof(sc)
! 737: struct rl_softc *sc;
! 738: {
! 739: struct ifnet *ifp;
! 740: u_int32_t txstat;
! 741:
! 742: ifp = &sc->sc_arpcom.ac_if;
! 743:
! 744: /*
! 745: * Go through our tx list and free mbufs for those
! 746: * frames that have been uploaded.
! 747: */
! 748: do {
! 749: if (RL_LAST_TXMBUF(sc) == NULL)
! 750: break;
! 751: txstat = CSR_READ_4(sc, RL_LAST_TXSTAT(sc));
! 752: if (!(txstat & (RL_TXSTAT_TX_OK|
! 753: RL_TXSTAT_TX_UNDERRUN|RL_TXSTAT_TXABRT)))
! 754: break;
! 755:
! 756: ifp->if_collisions += (txstat & RL_TXSTAT_COLLCNT) >> 24;
! 757:
! 758: bus_dmamap_sync(sc->sc_dmat, RL_LAST_TXMAP(sc),
! 759: 0, RL_LAST_TXMAP(sc)->dm_mapsize,
! 760: BUS_DMASYNC_POSTWRITE);
! 761: bus_dmamap_unload(sc->sc_dmat, RL_LAST_TXMAP(sc));
! 762: m_freem(RL_LAST_TXMBUF(sc));
! 763: RL_LAST_TXMBUF(sc) = NULL;
! 764: /*
! 765: * If there was a transmit underrun, bump the TX threshold.
! 766: * Make sure not to overflow the 63 * 32byte we can address
! 767: * with the 6 available bit.
! 768: */
! 769: if ((txstat & RL_TXSTAT_TX_UNDERRUN) &&
! 770: (sc->rl_txthresh < 2016))
! 771: sc->rl_txthresh += 32;
! 772: if (txstat & RL_TXSTAT_TX_OK)
! 773: ifp->if_opackets++;
! 774: else {
! 775: int oldthresh;
! 776:
! 777: ifp->if_oerrors++;
! 778: if ((txstat & RL_TXSTAT_TXABRT) ||
! 779: (txstat & RL_TXSTAT_OUTOFWIN))
! 780: CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
! 781: oldthresh = sc->rl_txthresh;
! 782: /* error recovery */
! 783: rl_reset(sc);
! 784: rl_init(sc);
! 785: /* restore original threshold */
! 786: sc->rl_txthresh = oldthresh;
! 787: return;
! 788: }
! 789: RL_INC(sc->rl_cdata.last_tx);
! 790: ifp->if_flags &= ~IFF_OACTIVE;
! 791: } while (sc->rl_cdata.last_tx != sc->rl_cdata.cur_tx);
! 792:
! 793: if (RL_LAST_TXMBUF(sc) == NULL)
! 794: ifp->if_timer = 0;
! 795: else if (ifp->if_timer == 0)
! 796: ifp->if_timer = 5;
! 797: }
! 798:
! 799: int rl_intr(arg)
! 800: void *arg;
! 801: {
! 802: struct rl_softc *sc;
! 803: struct ifnet *ifp;
! 804: int claimed = 0;
! 805: u_int16_t status;
! 806:
! 807: sc = arg;
! 808: ifp = &sc->sc_arpcom.ac_if;
! 809:
! 810: /* Disable interrupts. */
! 811: CSR_WRITE_2(sc, RL_IMR, 0x0000);
! 812:
! 813: for (;;) {
! 814: status = CSR_READ_2(sc, RL_ISR);
! 815: /* If the card has gone away, the read returns 0xffff. */
! 816: if (status == 0xffff)
! 817: break;
! 818: if (status != 0)
! 819: CSR_WRITE_2(sc, RL_ISR, status);
! 820: if ((status & RL_INTRS) == 0)
! 821: break;
! 822: if (status & RL_ISR_RX_OK)
! 823: rl_rxeof(sc);
! 824: if (status & RL_ISR_RX_ERR)
! 825: rl_rxeof(sc);
! 826: if ((status & RL_ISR_TX_OK) || (status & RL_ISR_TX_ERR))
! 827: rl_txeof(sc);
! 828: if (status & RL_ISR_SYSTEM_ERR) {
! 829: rl_reset(sc);
! 830: rl_init(sc);
! 831: }
! 832: claimed = 1;
! 833: }
! 834:
! 835: /* Re-enable interrupts. */
! 836: CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
! 837:
! 838: if (!IFQ_IS_EMPTY(&ifp->if_snd))
! 839: rl_start(ifp);
! 840:
! 841: return (claimed);
! 842: }
! 843:
! 844: /*
! 845: * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
! 846: * pointers to the fragment pointers.
! 847: */
! 848: int rl_encap(sc, m_head)
! 849: struct rl_softc *sc;
! 850: struct mbuf *m_head;
! 851: {
! 852: struct mbuf *m_new;
! 853:
! 854: /*
! 855: * The RealTek is brain damaged and wants longword-aligned
! 856: * TX buffers, plus we can only have one fragment buffer
! 857: * per packet. We have to copy pretty much all the time.
! 858: */
! 859: MGETHDR(m_new, M_DONTWAIT, MT_DATA);
! 860: if (m_new == NULL) {
! 861: m_freem(m_head);
! 862: return(1);
! 863: }
! 864: if (m_head->m_pkthdr.len > MHLEN) {
! 865: MCLGET(m_new, M_DONTWAIT);
! 866: if (!(m_new->m_flags & M_EXT)) {
! 867: m_freem(m_new);
! 868: m_freem(m_head);
! 869: return(1);
! 870: }
! 871: }
! 872: m_copydata(m_head, 0, m_head->m_pkthdr.len, mtod(m_new, caddr_t));
! 873: m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
! 874:
! 875: /* Pad frames to at least 60 bytes. */
! 876: if (m_new->m_pkthdr.len < RL_MIN_FRAMELEN) {
! 877: /*
! 878: * Make security-conscious people happy: zero out the
! 879: * bytes in the pad area, since we don't know what
! 880: * this mbuf cluster buffer's previous user might
! 881: * have left in it.
! 882: */
! 883: bzero(mtod(m_new, char *) + m_new->m_pkthdr.len,
! 884: RL_MIN_FRAMELEN - m_new->m_pkthdr.len);
! 885: m_new->m_pkthdr.len +=
! 886: (RL_MIN_FRAMELEN - m_new->m_pkthdr.len);
! 887: m_new->m_len = m_new->m_pkthdr.len;
! 888: }
! 889:
! 890: if (bus_dmamap_load_mbuf(sc->sc_dmat, RL_CUR_TXMAP(sc),
! 891: m_new, BUS_DMA_NOWAIT) != 0) {
! 892: m_freem(m_new);
! 893: m_freem(m_head);
! 894: return (1);
! 895: }
! 896: m_freem(m_head);
! 897:
! 898: RL_CUR_TXMBUF(sc) = m_new;
! 899: bus_dmamap_sync(sc->sc_dmat, RL_CUR_TXMAP(sc), 0,
! 900: RL_CUR_TXMAP(sc)->dm_mapsize, BUS_DMASYNC_PREWRITE);
! 901: return(0);
! 902: }
! 903:
! 904: /*
! 905: * Main transmit routine.
! 906: */
! 907:
! 908: void rl_start(ifp)
! 909: struct ifnet *ifp;
! 910: {
! 911: struct rl_softc *sc;
! 912: struct mbuf *m_head = NULL;
! 913: int pkts = 0;
! 914:
! 915: sc = ifp->if_softc;
! 916:
! 917: while(RL_CUR_TXMBUF(sc) == NULL) {
! 918: IFQ_DEQUEUE(&ifp->if_snd, m_head);
! 919: if (m_head == NULL)
! 920: break;
! 921:
! 922: /* Pack the data into the descriptor. */
! 923: if (rl_encap(sc, m_head))
! 924: break;
! 925: pkts++;
! 926:
! 927: #if NBPFILTER > 0
! 928: /*
! 929: * If there's a BPF listener, bounce a copy of this frame
! 930: * to him.
! 931: */
! 932: if (ifp->if_bpf)
! 933: bpf_mtap(ifp->if_bpf, RL_CUR_TXMBUF(sc),
! 934: BPF_DIRECTION_OUT);
! 935: #endif
! 936: /*
! 937: * Transmit the frame.
! 938: */
! 939: CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),
! 940: RL_CUR_TXMAP(sc)->dm_segs[0].ds_addr);
! 941: CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
! 942: RL_TXTHRESH(sc->rl_txthresh) |
! 943: RL_CUR_TXMAP(sc)->dm_segs[0].ds_len);
! 944:
! 945: RL_INC(sc->rl_cdata.cur_tx);
! 946:
! 947: /*
! 948: * Set a timeout in case the chip goes out to lunch.
! 949: */
! 950: ifp->if_timer = 5;
! 951: }
! 952: if (pkts == 0)
! 953: return;
! 954:
! 955: /*
! 956: * We broke out of the loop because all our TX slots are
! 957: * full. Mark the NIC as busy until it drains some of the
! 958: * packets from the queue.
! 959: */
! 960: if (RL_CUR_TXMBUF(sc) != NULL)
! 961: ifp->if_flags |= IFF_OACTIVE;
! 962: }
! 963:
! 964: void rl_init(xsc)
! 965: void *xsc;
! 966: {
! 967: struct rl_softc *sc = xsc;
! 968: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 969: int s;
! 970: u_int32_t rxcfg = 0;
! 971:
! 972: s = splnet();
! 973:
! 974: /*
! 975: * Cancel pending I/O and free all RX/TX buffers.
! 976: */
! 977: rl_stop(sc);
! 978:
! 979: /*
! 980: * Init our MAC address. Even though the chipset
! 981: * documentation doesn't mention it, we need to enter "Config
! 982: * register write enable" mode to modify the ID registers.
! 983: */
! 984: CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG);
! 985: CSR_WRITE_RAW_4(sc, RL_IDR0,
! 986: (u_int8_t *)(&sc->sc_arpcom.ac_enaddr[0]));
! 987: CSR_WRITE_RAW_4(sc, RL_IDR4,
! 988: (u_int8_t *)(&sc->sc_arpcom.ac_enaddr[4]));
! 989: CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
! 990:
! 991: /* Init the RX buffer pointer register. */
! 992: CSR_WRITE_4(sc, RL_RXADDR, sc->rl_cdata.rl_rx_buf_pa);
! 993:
! 994: /* Init TX descriptors. */
! 995: rl_list_tx_init(sc);
! 996:
! 997: /*
! 998: * Enable transmit and receive.
! 999: */
! 1000: CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB);
! 1001:
! 1002: /*
! 1003: * Set the initial TX and RX configuration.
! 1004: */
! 1005: CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG);
! 1006: CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG);
! 1007:
! 1008: /* Set the individual bit to receive frames for this host only. */
! 1009: rxcfg = CSR_READ_4(sc, RL_RXCFG);
! 1010: rxcfg |= RL_RXCFG_RX_INDIV;
! 1011:
! 1012: /* If we want promiscuous mode, set the allframes bit. */
! 1013: if (ifp->if_flags & IFF_PROMISC)
! 1014: rxcfg |= RL_RXCFG_RX_ALLPHYS;
! 1015: else
! 1016: rxcfg &= ~RL_RXCFG_RX_ALLPHYS;
! 1017: CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
! 1018:
! 1019: /*
! 1020: * Set capture broadcast bit to capture broadcast frames.
! 1021: */
! 1022: if (ifp->if_flags & IFF_BROADCAST)
! 1023: rxcfg |= RL_RXCFG_RX_BROAD;
! 1024: else
! 1025: rxcfg &= ~RL_RXCFG_RX_BROAD;
! 1026: CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
! 1027:
! 1028: /*
! 1029: * Program the multicast filter, if necessary.
! 1030: */
! 1031: rl_setmulti(sc);
! 1032:
! 1033: /*
! 1034: * Enable interrupts.
! 1035: */
! 1036: CSR_WRITE_2(sc, RL_IMR, RL_INTRS);
! 1037:
! 1038: /* Set initial TX threshold */
! 1039: sc->rl_txthresh = RL_TX_THRESH_INIT;
! 1040:
! 1041: /* Start RX/TX process. */
! 1042: CSR_WRITE_4(sc, RL_MISSEDPKT, 0);
! 1043:
! 1044: /* Enable receiver and transmitter. */
! 1045: CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB);
! 1046:
! 1047: mii_mediachg(&sc->sc_mii);
! 1048:
! 1049: CSR_WRITE_1(sc, RL_CFG1, RL_CFG1_DRVLOAD|RL_CFG1_FULLDUPLEX);
! 1050:
! 1051: ifp->if_flags |= IFF_RUNNING;
! 1052: ifp->if_flags &= ~IFF_OACTIVE;
! 1053:
! 1054: splx(s);
! 1055:
! 1056: timeout_set(&sc->sc_tick_tmo, rl_tick, sc);
! 1057: timeout_add(&sc->sc_tick_tmo, hz);
! 1058: }
! 1059:
! 1060: /*
! 1061: * Set media options.
! 1062: */
! 1063: int rl_ifmedia_upd(ifp)
! 1064: struct ifnet *ifp;
! 1065: {
! 1066: struct rl_softc *sc = (struct rl_softc *)ifp->if_softc;
! 1067:
! 1068: mii_mediachg(&sc->sc_mii);
! 1069: return (0);
! 1070: }
! 1071:
! 1072: /*
! 1073: * Report current media status.
! 1074: */
! 1075: void rl_ifmedia_sts(ifp, ifmr)
! 1076: struct ifnet *ifp;
! 1077: struct ifmediareq *ifmr;
! 1078: {
! 1079: struct rl_softc *sc = ifp->if_softc;
! 1080:
! 1081: mii_pollstat(&sc->sc_mii);
! 1082: ifmr->ifm_status = sc->sc_mii.mii_media_status;
! 1083: ifmr->ifm_active = sc->sc_mii.mii_media_active;
! 1084: }
! 1085:
! 1086: int rl_ioctl(ifp, command, data)
! 1087: struct ifnet *ifp;
! 1088: u_long command;
! 1089: caddr_t data;
! 1090: {
! 1091: struct rl_softc *sc = ifp->if_softc;
! 1092: struct ifreq *ifr = (struct ifreq *) data;
! 1093: struct ifaddr *ifa = (struct ifaddr *)data;
! 1094: int s, error = 0;
! 1095:
! 1096: s = splnet();
! 1097:
! 1098: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
! 1099: splx(s);
! 1100: return error;
! 1101: }
! 1102:
! 1103: switch(command) {
! 1104: case SIOCSIFADDR:
! 1105: ifp->if_flags |= IFF_UP;
! 1106: switch (ifa->ifa_addr->sa_family) {
! 1107: #ifdef INET
! 1108: case AF_INET:
! 1109: rl_init(sc);
! 1110: arp_ifinit(&sc->sc_arpcom, ifa);
! 1111: break;
! 1112: #endif /* INET */
! 1113: default:
! 1114: rl_init(sc);
! 1115: break;
! 1116: }
! 1117: break;
! 1118: case SIOCSIFMTU:
! 1119: if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
! 1120: error = EINVAL;
! 1121: } else if (ifp->if_mtu != ifr->ifr_mtu) {
! 1122: ifp->if_mtu = ifr->ifr_mtu;
! 1123: }
! 1124: break;
! 1125: case SIOCSIFFLAGS:
! 1126: if (ifp->if_flags & IFF_UP) {
! 1127: rl_init(sc);
! 1128: } else {
! 1129: if (ifp->if_flags & IFF_RUNNING)
! 1130: rl_stop(sc);
! 1131: }
! 1132: error = 0;
! 1133: break;
! 1134: case SIOCADDMULTI:
! 1135: case SIOCDELMULTI:
! 1136: error = (command == SIOCADDMULTI) ?
! 1137: ether_addmulti(ifr, &sc->sc_arpcom) :
! 1138: ether_delmulti(ifr, &sc->sc_arpcom);
! 1139:
! 1140: if (error == ENETRESET) {
! 1141: /*
! 1142: * Multicast list has changed; set the hardware
! 1143: * filter accordingly.
! 1144: */
! 1145: if (ifp->if_flags & IFF_RUNNING)
! 1146: rl_setmulti(sc);
! 1147: error = 0;
! 1148: }
! 1149: break;
! 1150: case SIOCGIFMEDIA:
! 1151: case SIOCSIFMEDIA:
! 1152: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
! 1153: break;
! 1154: default:
! 1155: error = EINVAL;
! 1156: break;
! 1157: }
! 1158:
! 1159: splx(s);
! 1160:
! 1161: return(error);
! 1162: }
! 1163:
! 1164: void rl_watchdog(ifp)
! 1165: struct ifnet *ifp;
! 1166: {
! 1167: struct rl_softc *sc;
! 1168:
! 1169: sc = ifp->if_softc;
! 1170:
! 1171: printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
! 1172: ifp->if_oerrors++;
! 1173: rl_txeof(sc);
! 1174: rl_rxeof(sc);
! 1175: rl_init(sc);
! 1176: }
! 1177:
! 1178: /*
! 1179: * Stop the adapter and free any mbufs allocated to the
! 1180: * RX and TX lists.
! 1181: */
! 1182: void rl_stop(sc)
! 1183: struct rl_softc *sc;
! 1184: {
! 1185: register int i;
! 1186: struct ifnet *ifp;
! 1187:
! 1188: ifp = &sc->sc_arpcom.ac_if;
! 1189: ifp->if_timer = 0;
! 1190:
! 1191: timeout_del(&sc->sc_tick_tmo);
! 1192:
! 1193: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 1194:
! 1195: CSR_WRITE_1(sc, RL_COMMAND, 0x00);
! 1196: CSR_WRITE_2(sc, RL_IMR, 0x0000);
! 1197:
! 1198: /*
! 1199: * Free the TX list buffers.
! 1200: */
! 1201: for (i = 0; i < RL_TX_LIST_CNT; i++) {
! 1202: if (sc->rl_cdata.rl_tx_chain[i] != NULL) {
! 1203: bus_dmamap_sync(sc->sc_dmat,
! 1204: sc->rl_cdata.rl_tx_dmamap[i], 0,
! 1205: sc->rl_cdata.rl_tx_dmamap[i]->dm_mapsize,
! 1206: BUS_DMASYNC_POSTWRITE);
! 1207: bus_dmamap_unload(sc->sc_dmat,
! 1208: sc->rl_cdata.rl_tx_dmamap[i]);
! 1209: m_freem(sc->rl_cdata.rl_tx_chain[i]);
! 1210: sc->rl_cdata.rl_tx_chain[i] = NULL;
! 1211: CSR_WRITE_4(sc, RL_TXADDR0 + (i * sizeof(u_int32_t)),
! 1212: 0x00000000);
! 1213: }
! 1214: }
! 1215: }
! 1216:
! 1217: int
! 1218: rl_attach(sc)
! 1219: struct rl_softc *sc;
! 1220: {
! 1221: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
! 1222: int rseg, i;
! 1223: u_int16_t rl_id, rl_did;
! 1224: caddr_t kva;
! 1225: int addr_len;
! 1226:
! 1227: rl_reset(sc);
! 1228:
! 1229: /*
! 1230: * Check EEPROM type 9346 or 9356.
! 1231: */
! 1232: rl_read_eeprom(sc, (caddr_t)&rl_id, RL_EE_ID, RL_EEADDR_LEN1, 1, 0);
! 1233: if (rl_id == 0x8129)
! 1234: addr_len = RL_EEADDR_LEN1;
! 1235: else
! 1236: addr_len = RL_EEADDR_LEN0;
! 1237:
! 1238: /*
! 1239: * Get station address.
! 1240: */
! 1241: rl_read_eeprom(sc, (caddr_t)sc->sc_arpcom.ac_enaddr, RL_EE_EADDR,
! 1242: addr_len, 3, 1);
! 1243:
! 1244: printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
! 1245:
! 1246: rl_read_eeprom(sc, (caddr_t)&rl_did, RL_EE_PCI_DID, addr_len, 1, 0);
! 1247:
! 1248: if (rl_did == RT_DEVICEID_8139 || rl_did == ACCTON_DEVICEID_5030 ||
! 1249: rl_did == DELTA_DEVICEID_8139 || rl_did == ADDTRON_DEVICEID_8139 ||
! 1250: rl_did == DLINK_DEVICEID_8139 || rl_did == DLINK_DEVICEID_8139_2 ||
! 1251: rl_did == ABOCOM_DEVICEID_8139)
! 1252: sc->rl_type = RL_8139;
! 1253: else if (rl_did == RT_DEVICEID_8129)
! 1254: sc->rl_type = RL_8129;
! 1255: else
! 1256: sc->rl_type = RL_UNKNOWN; /* could be 8138 or other */
! 1257:
! 1258: if (bus_dmamem_alloc(sc->sc_dmat, RL_RXBUFLEN + 32, PAGE_SIZE, 0,
! 1259: &sc->sc_rx_seg, 1, &rseg, BUS_DMA_NOWAIT)) {
! 1260: printf("\n%s: can't alloc rx buffers\n", sc->sc_dev.dv_xname);
! 1261: return (1);
! 1262: }
! 1263: if (bus_dmamem_map(sc->sc_dmat, &sc->sc_rx_seg, rseg,
! 1264: RL_RXBUFLEN + 32, &kva, BUS_DMA_NOWAIT)) {
! 1265: printf("%s: can't map dma buffers (%d bytes)\n",
! 1266: sc->sc_dev.dv_xname, RL_RXBUFLEN + 32);
! 1267: bus_dmamem_free(sc->sc_dmat, &sc->sc_rx_seg, rseg);
! 1268: return (1);
! 1269: }
! 1270: if (bus_dmamap_create(sc->sc_dmat, RL_RXBUFLEN + 32, 1,
! 1271: RL_RXBUFLEN + 32, 0, BUS_DMA_NOWAIT, &sc->sc_rx_dmamap)) {
! 1272: printf("%s: can't create dma map\n", sc->sc_dev.dv_xname);
! 1273: bus_dmamem_unmap(sc->sc_dmat, kva, RL_RXBUFLEN + 32);
! 1274: bus_dmamem_free(sc->sc_dmat, &sc->sc_rx_seg, rseg);
! 1275: return (1);
! 1276: }
! 1277: if (bus_dmamap_load(sc->sc_dmat, sc->sc_rx_dmamap, kva,
! 1278: RL_RXBUFLEN + 32, NULL, BUS_DMA_NOWAIT)) {
! 1279: printf("%s: can't load dma map\n", sc->sc_dev.dv_xname);
! 1280: bus_dmamap_destroy(sc->sc_dmat, sc->sc_rx_dmamap);
! 1281: bus_dmamem_unmap(sc->sc_dmat, kva, RL_RXBUFLEN + 32);
! 1282: bus_dmamem_free(sc->sc_dmat, &sc->sc_rx_seg, rseg);
! 1283: return (1);
! 1284: }
! 1285: sc->rl_cdata.rl_rx_buf = kva;
! 1286: sc->rl_cdata.rl_rx_buf_pa = sc->sc_rx_dmamap->dm_segs[0].ds_addr;
! 1287:
! 1288: bzero(sc->rl_cdata.rl_rx_buf, RL_RXBUFLEN + 32);
! 1289:
! 1290: bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
! 1291: 0, sc->sc_rx_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
! 1292:
! 1293: for (i = 0; i < RL_TX_LIST_CNT; i++) {
! 1294: if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
! 1295: BUS_DMA_NOWAIT, &sc->rl_cdata.rl_tx_dmamap[i]) != 0) {
! 1296: printf("%s: can't create tx maps\n",
! 1297: sc->sc_dev.dv_xname);
! 1298: /* XXX free any allocated... */
! 1299: return (1);
! 1300: }
! 1301: }
! 1302:
! 1303: /* Leave a few bytes before the start of the RX ring buffer. */
! 1304: sc->rl_cdata.rl_rx_buf_ptr = sc->rl_cdata.rl_rx_buf;
! 1305: sc->rl_cdata.rl_rx_buf += sizeof(u_int64_t);
! 1306: sc->rl_cdata.rl_rx_buf_pa += sizeof(u_int64_t);
! 1307:
! 1308: ifp->if_softc = sc;
! 1309: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
! 1310: ifp->if_ioctl = rl_ioctl;
! 1311: ifp->if_start = rl_start;
! 1312: ifp->if_watchdog = rl_watchdog;
! 1313: ifp->if_baudrate = 10000000;
! 1314: IFQ_SET_READY(&ifp->if_snd);
! 1315:
! 1316: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
! 1317:
! 1318: ifp->if_capabilities = IFCAP_VLAN_MTU;
! 1319:
! 1320: /*
! 1321: * Initialize our media structures and probe the MII.
! 1322: */
! 1323: sc->sc_mii.mii_ifp = ifp;
! 1324: sc->sc_mii.mii_readreg = rl_miibus_readreg;
! 1325: sc->sc_mii.mii_writereg = rl_miibus_writereg;
! 1326: sc->sc_mii.mii_statchg = rl_miibus_statchg;
! 1327: ifmedia_init(&sc->sc_mii.mii_media, 0, rl_ifmedia_upd, rl_ifmedia_sts);
! 1328: mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
! 1329: MII_OFFSET_ANY, 0);
! 1330: if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
! 1331: ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
! 1332: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
! 1333: } else
! 1334: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
! 1335:
! 1336: /*
! 1337: * Attach us everywhere
! 1338: */
! 1339: if_attach(ifp);
! 1340: ether_ifattach(ifp);
! 1341:
! 1342: sc->sc_sdhook = shutdownhook_establish(rl_shutdown, sc);
! 1343: sc->sc_pwrhook = powerhook_establish(rl_powerhook, sc);
! 1344:
! 1345: return (0);
! 1346: }
! 1347:
! 1348: void
! 1349: rl_shutdown(arg)
! 1350: void *arg;
! 1351: {
! 1352: struct rl_softc *sc = (struct rl_softc *)arg;
! 1353:
! 1354: rl_stop(sc);
! 1355: }
! 1356:
! 1357: void
! 1358: rl_powerhook(why, arg)
! 1359: int why;
! 1360: void *arg;
! 1361: {
! 1362: if (why == PWR_RESUME)
! 1363: rl_init(arg);
! 1364: }
! 1365:
! 1366: int
! 1367: rl_miibus_readreg(self, phy, reg)
! 1368: struct device *self;
! 1369: int phy, reg;
! 1370: {
! 1371: struct rl_softc *sc = (struct rl_softc *)self;
! 1372: struct rl_mii_frame frame;
! 1373: u_int16_t rl8139_reg;
! 1374:
! 1375: if (sc->rl_type == RL_8139) {
! 1376: /*
! 1377: * The RTL8139 PHY is mapped into PCI registers, unfortunately
! 1378: * it has no phyid, or phyaddr, so assume it is phyaddr 0.
! 1379: */
! 1380: if (phy != 0)
! 1381: return(0);
! 1382:
! 1383: switch (reg) {
! 1384: case MII_BMCR:
! 1385: rl8139_reg = RL_BMCR;
! 1386: break;
! 1387: case MII_BMSR:
! 1388: rl8139_reg = RL_BMSR;
! 1389: break;
! 1390: case MII_ANAR:
! 1391: rl8139_reg = RL_ANAR;
! 1392: break;
! 1393: case MII_ANER:
! 1394: rl8139_reg = RL_ANER;
! 1395: break;
! 1396: case MII_ANLPAR:
! 1397: rl8139_reg = RL_LPAR;
! 1398: break;
! 1399: case RL_MEDIASTAT:
! 1400: return (CSR_READ_1(sc, RL_MEDIASTAT));
! 1401: case MII_PHYIDR1:
! 1402: case MII_PHYIDR2:
! 1403: default:
! 1404: return (0);
! 1405: }
! 1406: return (CSR_READ_2(sc, rl8139_reg));
! 1407: }
! 1408:
! 1409: bzero((char *)&frame, sizeof(frame));
! 1410:
! 1411: frame.mii_phyaddr = phy;
! 1412: frame.mii_regaddr = reg;
! 1413: rl_mii_readreg(sc, &frame);
! 1414:
! 1415: return(frame.mii_data);
! 1416: }
! 1417:
! 1418: void
! 1419: rl_miibus_writereg(self, phy, reg, val)
! 1420: struct device *self;
! 1421: int phy, reg, val;
! 1422: {
! 1423: struct rl_softc *sc = (struct rl_softc *)self;
! 1424: struct rl_mii_frame frame;
! 1425: u_int16_t rl8139_reg = 0;
! 1426:
! 1427: if (sc->rl_type == RL_8139) {
! 1428: if (phy)
! 1429: return;
! 1430:
! 1431: switch (reg) {
! 1432: case MII_BMCR:
! 1433: rl8139_reg = RL_BMCR;
! 1434: break;
! 1435: case MII_BMSR:
! 1436: rl8139_reg = RL_BMSR;
! 1437: break;
! 1438: case MII_ANAR:
! 1439: rl8139_reg = RL_ANAR;
! 1440: break;
! 1441: case MII_ANER:
! 1442: rl8139_reg = RL_ANER;
! 1443: break;
! 1444: case MII_ANLPAR:
! 1445: rl8139_reg = RL_LPAR;
! 1446: break;
! 1447: case MII_PHYIDR1:
! 1448: case MII_PHYIDR2:
! 1449: return;
! 1450: }
! 1451: CSR_WRITE_2(sc, rl8139_reg, val);
! 1452: return;
! 1453: }
! 1454:
! 1455: bzero((char *)&frame, sizeof(frame));
! 1456: frame.mii_phyaddr = phy;
! 1457: frame.mii_regaddr = reg;
! 1458: frame.mii_data = val;
! 1459: rl_mii_writereg(sc, &frame);
! 1460: }
! 1461:
! 1462: void
! 1463: rl_miibus_statchg(self)
! 1464: struct device *self;
! 1465: {
! 1466: }
! 1467:
! 1468: void
! 1469: rl_tick(v)
! 1470: void *v;
! 1471: {
! 1472: struct rl_softc *sc = v;
! 1473:
! 1474: mii_tick(&sc->sc_mii);
! 1475: timeout_add(&sc->sc_tick_tmo, hz);
! 1476: }
! 1477:
! 1478: struct cfdriver rl_cd = {
! 1479: 0, "rl", DV_IFNET
! 1480: };
CVSweb