if_vx.c revision 78508
1/* 2 * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> 3 * 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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Herb Peyerl. 16 * 4. The name of Herb Peyerl may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $FreeBSD: head/sys/dev/vx/if_vx.c 78508 2001-06-20 19:48:35Z bmilekic $ 31 * 32 */ 33 34/* 35 * Created from if_ep.c driver by Fred Gray (fgray@rice.edu) to support 36 * the 3c590 family. 37 */ 38 39/* 40 * Modified from the FreeBSD 1.1.5.1 version by: 41 * Andres Vega Garcia 42 * INRIA - Sophia Antipolis, France 43 * avega@sophia.inria.fr 44 */ 45 46/* 47 * Promiscuous mode added and interrupt logic slightly changed 48 * to reduce the number of adapter failures. Transceiver select 49 * logic changed to use value from EEPROM. Autoconfiguration 50 * features added. 51 * Done by: 52 * Serge Babkin 53 * Chelindbank (Chelyabinsk, Russia) 54 * babkin@hq.icb.chel.su 55 */ 56 57 58#include <sys/param.h> 59#include <sys/systm.h> 60#include <sys/sockio.h> 61#include <sys/malloc.h> 62#include <sys/mbuf.h> 63#include <sys/socket.h> 64 65#include <net/if.h> 66 67#include <net/ethernet.h> 68#include <net/if_arp.h> 69 70#include <machine/bus_pio.h> 71#include <machine/bus.h> 72 73#include <net/bpf.h> 74 75 76#include <dev/vx/if_vxreg.h> 77 78#define ETHER_MAX_LEN 1518 79#define ETHER_ADDR_LEN 6 80#define ETHER_ALIGN 2 81 82static struct connector_entry { 83 int bit; 84 char *name; 85} conn_tab[VX_CONNECTORS] = { 86#define CONNECTOR_UTP 0 87 { 0x08, "utp"}, 88#define CONNECTOR_AUI 1 89 { 0x20, "aui"}, 90/* dummy */ 91 { 0, "???"}, 92#define CONNECTOR_BNC 3 93 { 0x10, "bnc"}, 94#define CONNECTOR_TX 4 95 { 0x02, "tx"}, 96#define CONNECTOR_FX 5 97 { 0x04, "fx"}, 98#define CONNECTOR_MII 6 99 { 0x40, "mii"}, 100 { 0, "???"} 101}; 102 103/* int vxattach __P((struct vx_softc *)); */ 104static void vxtxstat __P((struct vx_softc *)); 105static int vxstatus __P((struct vx_softc *)); 106static void vxinit __P((void *)); 107static int vxioctl __P((struct ifnet *, u_long, caddr_t)); 108static void vxstart __P((struct ifnet *ifp)); 109static void vxwatchdog __P((struct ifnet *)); 110static void vxreset __P((struct vx_softc *)); 111/* void vxstop __P((struct vx_softc *)); */ 112static void vxread __P((struct vx_softc *)); 113static struct mbuf *vxget __P((struct vx_softc *, u_int)); 114static void vxmbuffill __P((void *)); 115static void vxmbufempty __P((struct vx_softc *)); 116static void vxsetfilter __P((struct vx_softc *)); 117static void vxgetlink __P((struct vx_softc *)); 118static void vxsetlink __P((struct vx_softc *)); 119/* int vxbusyeeprom __P((struct vx_softc *)); */ 120 121 122int 123vxattach(sc) 124 struct vx_softc *sc; 125{ 126 struct ifnet *ifp = &sc->arpcom.ac_if; 127 int i; 128 129 callout_handle_init(&sc->ch); 130 GO_WINDOW(0); 131 CSR_WRITE_2(sc, VX_COMMAND, GLOBAL_RESET); 132 VX_BUSY_WAIT; 133 134 vxgetlink(sc); 135 136 /* 137 * Read the station address from the eeprom 138 */ 139 GO_WINDOW(0); 140 for (i = 0; i < 3; i++) { 141 int x; 142 if (vxbusyeeprom(sc)) 143 return 0; 144 CSR_WRITE_2(sc, VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD 145 | (EEPROM_OEM_ADDR_0 + i)); 146 if (vxbusyeeprom(sc)) 147 return 0; 148 x = CSR_READ_2(sc, VX_W0_EEPROM_DATA); 149 sc->arpcom.ac_enaddr[(i << 1)] = x >> 8; 150 sc->arpcom.ac_enaddr[(i << 1) + 1] = x; 151 } 152 153 printf(" address %6D\n", sc->arpcom.ac_enaddr, ":"); 154 155 ifp->if_unit = sc->unit; 156 ifp->if_name = "vx"; 157 ifp->if_mtu = ETHERMTU; 158 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 159 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 160 ifp->if_output = ether_output; 161 ifp->if_start = vxstart; 162 ifp->if_ioctl = vxioctl; 163 ifp->if_init = vxinit; 164 ifp->if_watchdog = vxwatchdog; 165 ifp->if_softc = sc; 166 167 ether_ifattach(ifp, ETHER_BPF_SUPPORTED); 168 169 sc->tx_start_thresh = 20; /* probably a good starting point. */ 170 171 vxstop(sc); 172 173 return 1; 174} 175 176 177 178/* 179 * The order in here seems important. Otherwise we may not receive 180 * interrupts. ?! 181 */ 182static void 183vxinit(xsc) 184 void *xsc; 185{ 186 struct vx_softc *sc = (struct vx_softc *) xsc; 187 struct ifnet *ifp = &sc->arpcom.ac_if; 188 int i; 189 190 VX_BUSY_WAIT; 191 192 GO_WINDOW(2); 193 194 for (i = 0; i < 6; i++) /* Reload the ether_addr. */ 195 CSR_WRITE_1(sc, VX_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]); 196 197 CSR_WRITE_2(sc, VX_COMMAND, RX_RESET); 198 VX_BUSY_WAIT; 199 CSR_WRITE_2(sc, VX_COMMAND, TX_RESET); 200 VX_BUSY_WAIT; 201 202 GO_WINDOW(1); /* Window 1 is operating window */ 203 for (i = 0; i < 31; i++) 204 CSR_READ_1(sc, VX_W1_TX_STATUS); 205 206 CSR_WRITE_2(sc, VX_COMMAND,SET_RD_0_MASK | S_CARD_FAILURE | 207 S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL); 208 CSR_WRITE_2(sc, VX_COMMAND,SET_INTR_MASK | S_CARD_FAILURE | 209 S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL); 210 211 /* 212 * Attempt to get rid of any stray interrupts that occured during 213 * configuration. On the i386 this isn't possible because one may 214 * already be queued. However, a single stray interrupt is 215 * unimportant. 216 */ 217 CSR_WRITE_2(sc, VX_COMMAND, ACK_INTR | 0xff); 218 219 vxsetfilter(sc); 220 vxsetlink(sc); 221 222 CSR_WRITE_2(sc, VX_COMMAND, RX_ENABLE); 223 CSR_WRITE_2(sc, VX_COMMAND, TX_ENABLE); 224 225 vxmbuffill((caddr_t) sc); 226 227 /* Interface is now `running', with no output active. */ 228 ifp->if_flags |= IFF_RUNNING; 229 ifp->if_flags &= ~IFF_OACTIVE; 230 231 /* Attempt to start output, if any. */ 232 vxstart(ifp); 233} 234 235static void 236vxsetfilter(sc) 237 struct vx_softc *sc; 238{ 239 register struct ifnet *ifp = &sc->arpcom.ac_if; 240 241 GO_WINDOW(1); /* Window 1 is operating window */ 242 CSR_WRITE_2(sc, VX_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST | 243 FIL_MULTICAST | 244 ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 )); 245} 246 247static void 248vxgetlink(sc) 249 struct vx_softc *sc; 250{ 251 int n, k; 252 253 GO_WINDOW(3); 254 sc->vx_connectors = CSR_READ_2(sc, VX_W3_RESET_OPT) & 0x7f; 255 for (n = 0, k = 0; k < VX_CONNECTORS; k++) { 256 if (sc->vx_connectors & conn_tab[k].bit) { 257 if (n > 0) { 258 printf("/"); 259 } 260 printf(conn_tab[k].name); 261 n++; 262 } 263 } 264 if (sc->vx_connectors == 0) { 265 printf("no connectors!"); 266 return; 267 } 268 GO_WINDOW(3); 269 sc->vx_connector = (CSR_READ_4(sc, VX_W3_INTERNAL_CFG) 270 & INTERNAL_CONNECTOR_MASK) 271 >> INTERNAL_CONNECTOR_BITS; 272 if (sc->vx_connector & 0x10) { 273 sc->vx_connector &= 0x0f; 274 printf("[*%s*]", conn_tab[(int)sc->vx_connector].name); 275 printf(": disable 'auto select' with DOS util!"); 276 } else { 277 printf("[*%s*]", conn_tab[(int)sc->vx_connector].name); 278 } 279} 280 281static void 282vxsetlink(sc) 283 struct vx_softc *sc; 284{ 285 register struct ifnet *ifp = &sc->arpcom.ac_if; 286 int i, j, k; 287 char *reason, *warning; 288 static short prev_flags; 289 static char prev_conn = -1; 290 291 if (prev_conn == -1) { 292 prev_conn = sc->vx_connector; 293 } 294 295 /* 296 * S.B. 297 * 298 * Now behavior was slightly changed: 299 * 300 * if any of flags link[0-2] is used and its connector is 301 * physically present the following connectors are used: 302 * 303 * link0 - AUI * highest precedence 304 * link1 - BNC 305 * link2 - UTP * lowest precedence 306 * 307 * If none of them is specified then 308 * connector specified in the EEPROM is used 309 * (if present on card or UTP if not). 310 */ 311 312 i = sc->vx_connector; /* default in EEPROM */ 313 reason = "default"; 314 warning = 0; 315 316 if (ifp->if_flags & IFF_LINK0) { 317 if (sc->vx_connectors & conn_tab[CONNECTOR_AUI].bit) { 318 i = CONNECTOR_AUI; 319 reason = "link0"; 320 } else { 321 warning = "aui not present! (link0)"; 322 } 323 } else if (ifp->if_flags & IFF_LINK1) { 324 if (sc->vx_connectors & conn_tab[CONNECTOR_BNC].bit) { 325 i = CONNECTOR_BNC; 326 reason = "link1"; 327 } else { 328 warning = "bnc not present! (link1)"; 329 } 330 } else if (ifp->if_flags & IFF_LINK2) { 331 if (sc->vx_connectors & conn_tab[CONNECTOR_UTP].bit) { 332 i = CONNECTOR_UTP; 333 reason = "link2"; 334 } else { 335 warning = "utp not present! (link2)"; 336 } 337 } else if ((sc->vx_connectors & conn_tab[(int)sc->vx_connector].bit) == 0) { 338 warning = "strange connector type in EEPROM."; 339 reason = "forced"; 340 i = CONNECTOR_UTP; 341 } 342 343 /* Avoid unnecessary message. */ 344 k = (prev_flags ^ ifp->if_flags) & (IFF_LINK0 | IFF_LINK1 | IFF_LINK2); 345 if ((k != 0) || (prev_conn != i)) { 346 if (warning != 0) { 347 printf("vx%d: warning: %s\n", sc->unit, warning); 348 } 349 printf("vx%d: selected %s. (%s)\n", 350 sc->unit, conn_tab[i].name, reason); 351 } 352 353 /* Set the selected connector. */ 354 GO_WINDOW(3); 355 j = CSR_READ_4(sc, VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK; 356 CSR_WRITE_4(sc, VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS)); 357 358 /* First, disable all. */ 359 CSR_WRITE_2(sc, VX_COMMAND, STOP_TRANSCEIVER); 360 DELAY(800); 361 GO_WINDOW(4); 362 CSR_WRITE_2(sc, VX_W4_MEDIA_TYPE, 0); 363 364 /* Second, enable the selected one. */ 365 switch(i) { 366 case CONNECTOR_UTP: 367 GO_WINDOW(4); 368 CSR_WRITE_2(sc, VX_W4_MEDIA_TYPE, ENABLE_UTP); 369 break; 370 case CONNECTOR_BNC: 371 CSR_WRITE_2(sc, VX_COMMAND, START_TRANSCEIVER); 372 DELAY(800); 373 break; 374 case CONNECTOR_TX: 375 case CONNECTOR_FX: 376 GO_WINDOW(4); 377 CSR_WRITE_2(sc, VX_W4_MEDIA_TYPE, LINKBEAT_ENABLE); 378 break; 379 default: /* AUI and MII fall here */ 380 break; 381 } 382 GO_WINDOW(1); 383 384 prev_flags = ifp->if_flags; 385 prev_conn = i; 386} 387 388static void 389vxstart(ifp) 390 struct ifnet *ifp; 391{ 392 register struct vx_softc *sc = ifp->if_softc; 393 register struct mbuf *m, *m0; 394 int sh, len, pad; 395 396 /* Don't transmit if interface is busy or not running */ 397 if ((sc->arpcom.ac_if.if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) 398 return; 399 400startagain: 401 /* Sneak a peek at the next packet */ 402 m0 = ifp->if_snd.ifq_head; 403 if (m0 == 0) { 404 return; 405 } 406 /* We need to use m->m_pkthdr.len, so require the header */ 407 if ((m0->m_flags & M_PKTHDR) == 0) 408 panic("vxstart: no header mbuf"); 409 len = m0->m_pkthdr.len; 410 411 pad = (4 - len) & 3; 412 413 /* 414 * The 3c509 automatically pads short packets to minimum ethernet length, 415 * but we drop packets that are too large. Perhaps we should truncate 416 * them instead? 417 */ 418 if (len + pad > ETHER_MAX_LEN) { 419 /* packet is obviously too large: toss it */ 420 ++ifp->if_oerrors; 421 IF_DEQUEUE(&ifp->if_snd, m0); 422 m_freem(m0); 423 goto readcheck; 424 } 425 VX_BUSY_WAIT; 426 if (CSR_READ_2(sc, VX_W1_FREE_TX) < len + pad + 4) { 427 CSR_WRITE_2(sc, VX_COMMAND, SET_TX_AVAIL_THRESH | ((len + pad + 4) >> 2)); 428 /* not enough room in FIFO */ 429 if (CSR_READ_2(sc, VX_W1_FREE_TX) < len + pad + 4) { /* make sure */ 430 ifp->if_flags |= IFF_OACTIVE; 431 ifp->if_timer = 1; 432 return; 433 } 434 } 435 CSR_WRITE_2(sc, VX_COMMAND, SET_TX_AVAIL_THRESH | (8188 >> 2)); 436 IF_DEQUEUE(&ifp->if_snd, m0); 437 if (m0 == 0) { /* not really needed */ 438 return; 439 } 440 441 VX_BUSY_WAIT; 442 CSR_WRITE_2(sc, VX_COMMAND, SET_TX_START_THRESH | 443 ((len / 4 + sc->tx_start_thresh) >> 2)); 444 445 if (sc->arpcom.ac_if.if_bpf) { 446 bpf_mtap(&sc->arpcom.ac_if, m0); 447 } 448 449 /* 450 * Do the output at splhigh() so that an interrupt from another device 451 * won't cause a FIFO underrun. 452 */ 453 sh = splhigh(); 454 455 CSR_WRITE_4(sc, VX_W1_TX_PIO_WR_1, len | TX_INDICATE); 456 457 for (m = m0; m != 0;) { 458 if (m->m_len > 3) 459 bus_space_write_multi_4(sc->vx_btag, sc->vx_bhandle, 460 VX_W1_TX_PIO_WR_1, (u_int32_t *)mtod(m, caddr_t), m->m_len / 4); 461 if (m->m_len & 3) 462 bus_space_write_multi_1(sc->vx_btag, sc->vx_bhandle, 463 VX_W1_TX_PIO_WR_1, 464 mtod(m, caddr_t) + (m->m_len & ~3) , m->m_len & 3); 465 MFREE(m, m0); 466 m = m0; 467 } 468 while (pad--) 469 CSR_WRITE_1(sc, VX_W1_TX_PIO_WR_1, 0); /* Padding */ 470 471 splx(sh); 472 473 ++ifp->if_opackets; 474 ifp->if_timer = 1; 475 476readcheck: 477 if ((CSR_READ_2(sc, VX_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) { 478 /* We received a complete packet. */ 479 480 if ((CSR_READ_2(sc, VX_STATUS) & S_INTR_LATCH) == 0) { 481 /* 482 * No interrupt, read the packet and continue 483 * Is this supposed to happen? Is my motherboard 484 * completely busted? 485 */ 486 vxread(sc); 487 } else 488 /* Got an interrupt, return so that it gets serviced. */ 489 return; 490 } else { 491 /* Check if we are stuck and reset [see XXX comment] */ 492 if (vxstatus(sc)) { 493 if (ifp->if_flags & IFF_DEBUG) 494 printf("vx%d: adapter reset\n", ifp->if_unit); 495 vxreset(sc); 496 } 497 } 498 499 goto startagain; 500} 501 502/* 503 * XXX: The 3c509 card can get in a mode where both the fifo status bit 504 * FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set 505 * We detect this situation and we reset the adapter. 506 * It happens at times when there is a lot of broadcast traffic 507 * on the cable (once in a blue moon). 508 */ 509static int 510vxstatus(sc) 511 struct vx_softc *sc; 512{ 513 int fifost; 514 515 /* 516 * Check the FIFO status and act accordingly 517 */ 518 GO_WINDOW(4); 519 fifost = CSR_READ_2(sc, VX_W4_FIFO_DIAG); 520 GO_WINDOW(1); 521 522 if (fifost & FIFOS_RX_UNDERRUN) { 523 if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) 524 printf("vx%d: RX underrun\n", sc->unit); 525 vxreset(sc); 526 return 0; 527 } 528 529 if (fifost & FIFOS_RX_STATUS_OVERRUN) { 530 if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) 531 printf("vx%d: RX Status overrun\n", sc->unit); 532 return 1; 533 } 534 535 if (fifost & FIFOS_RX_OVERRUN) { 536 if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) 537 printf("vx%d: RX overrun\n", sc->unit); 538 return 1; 539 } 540 541 if (fifost & FIFOS_TX_OVERRUN) { 542 if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) 543 printf("vx%d: TX overrun\n", sc->unit); 544 vxreset(sc); 545 return 0; 546 } 547 548 return 0; 549} 550 551static void 552vxtxstat(sc) 553 struct vx_softc *sc; 554{ 555 int i; 556 557 /* 558 * We need to read+write TX_STATUS until we get a 0 status 559 * in order to turn off the interrupt flag. 560 */ 561 while ((i = CSR_READ_1(sc, VX_W1_TX_STATUS)) & TXS_COMPLETE) { 562 CSR_WRITE_1(sc, VX_W1_TX_STATUS, 0x0); 563 564 if (i & TXS_JABBER) { 565 ++sc->arpcom.ac_if.if_oerrors; 566 if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) 567 printf("vx%d: jabber (%x)\n", sc->unit, i); 568 vxreset(sc); 569 } else if (i & TXS_UNDERRUN) { 570 ++sc->arpcom.ac_if.if_oerrors; 571 if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) 572 printf("vx%d: fifo underrun (%x) @%d\n", 573 sc->unit, i, sc->tx_start_thresh); 574 if (sc->tx_succ_ok < 100) 575 sc->tx_start_thresh = min(ETHER_MAX_LEN, sc->tx_start_thresh + 20); 576 sc->tx_succ_ok = 0; 577 vxreset(sc); 578 } else if (i & TXS_MAX_COLLISION) { 579 ++sc->arpcom.ac_if.if_collisions; 580 CSR_WRITE_2(sc, VX_COMMAND, TX_ENABLE); 581 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; 582 } else 583 sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127; 584 } 585} 586 587void 588vxintr(voidsc) 589 void *voidsc; 590{ 591 register short status; 592 struct vx_softc *sc = voidsc; 593 struct ifnet *ifp = &sc->arpcom.ac_if; 594 595 for (;;) { 596 CSR_WRITE_2(sc, VX_COMMAND, C_INTR_LATCH); 597 598 status = CSR_READ_2(sc, VX_STATUS); 599 600 if ((status & (S_TX_COMPLETE | S_TX_AVAIL | 601 S_RX_COMPLETE | S_CARD_FAILURE)) == 0) 602 break; 603 604 /* 605 * Acknowledge any interrupts. It's important that we do this 606 * first, since there would otherwise be a race condition. 607 * Due to the i386 interrupt queueing, we may get spurious 608 * interrupts occasionally. 609 */ 610 CSR_WRITE_2(sc, VX_COMMAND, ACK_INTR | status); 611 612 if (status & S_RX_COMPLETE) 613 vxread(sc); 614 if (status & S_TX_AVAIL) { 615 ifp->if_timer = 0; 616 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; 617 vxstart(&sc->arpcom.ac_if); 618 } 619 if (status & S_CARD_FAILURE) { 620 printf("vx%d: adapter failure (%x)\n", sc->unit, status); 621 ifp->if_timer = 0; 622 vxreset(sc); 623 return; 624 } 625 if (status & S_TX_COMPLETE) { 626 ifp->if_timer = 0; 627 vxtxstat(sc); 628 vxstart(ifp); 629 } 630 } 631 632 /* no more interrupts */ 633 return; 634} 635 636static void 637vxread(sc) 638 struct vx_softc *sc; 639{ 640 struct ifnet *ifp = &sc->arpcom.ac_if; 641 struct mbuf *m; 642 struct ether_header *eh; 643 u_int len; 644 645 len = CSR_READ_2(sc, VX_W1_RX_STATUS); 646 647again: 648 649 if (ifp->if_flags & IFF_DEBUG) { 650 int err = len & ERR_MASK; 651 char *s = NULL; 652 653 if (len & ERR_INCOMPLETE) 654 s = "incomplete packet"; 655 else if (err == ERR_OVERRUN) 656 s = "packet overrun"; 657 else if (err == ERR_RUNT) 658 s = "runt packet"; 659 else if (err == ERR_ALIGNMENT) 660 s = "bad alignment"; 661 else if (err == ERR_CRC) 662 s = "bad crc"; 663 else if (err == ERR_OVERSIZE) 664 s = "oversized packet"; 665 else if (err == ERR_DRIBBLE) 666 s = "dribble bits"; 667 668 if (s) 669 printf("vx%d: %s\n", sc->unit, s); 670 } 671 672 if (len & ERR_INCOMPLETE) 673 return; 674 675 if (len & ERR_RX) { 676 ++ifp->if_ierrors; 677 goto abort; 678 } 679 680 len &= RX_BYTES_MASK; /* Lower 11 bits = RX bytes. */ 681 682 /* Pull packet off interface. */ 683 m = vxget(sc, len); 684 if (m == 0) { 685 ifp->if_ierrors++; 686 goto abort; 687 } 688 689 ++ifp->if_ipackets; 690 691 { 692 struct mbuf *m0; 693 694 m0 = m_devget(mtod(m, char *), m->m_pkthdr.len, ETHER_ALIGN, ifp, NULL); 695 if (m0 == NULL) { 696 ifp->if_ierrors++; 697 goto abort; 698 } 699 700 m_freem(m); 701 m = m0; 702 } 703 704 /* We assume the header fit entirely in one mbuf. */ 705 eh = mtod(m, struct ether_header *); 706 707 /* 708 * XXX: Some cards seem to be in promiscous mode all the time. 709 * we need to make sure we only get our own stuff always. 710 * bleah! 711 */ 712 713 if ((eh->ether_dhost[0] & 1) == 0 /* !mcast and !bcast */ 714 && bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN) != 0) { 715 m_freem(m); 716 return; 717 } 718 719 m_adj(m, sizeof(struct ether_header)); 720 ether_input(ifp, eh, m); 721 722 /* 723 * In periods of high traffic we can actually receive enough 724 * packets so that the fifo overrun bit will be set at this point, 725 * even though we just read a packet. In this case we 726 * are not going to receive any more interrupts. We check for 727 * this condition and read again until the fifo is not full. 728 * We could simplify this test by not using vxstatus(), but 729 * rechecking the RX_STATUS register directly. This test could 730 * result in unnecessary looping in cases where there is a new 731 * packet but the fifo is not full, but it will not fix the 732 * stuck behavior. 733 * 734 * Even with this improvement, we still get packet overrun errors 735 * which are hurting performance. Maybe when I get some more time 736 * I'll modify vxread() so that it can handle RX_EARLY interrupts. 737 */ 738 if (vxstatus(sc)) { 739 len = CSR_READ_2(sc, VX_W1_RX_STATUS); 740 /* Check if we are stuck and reset [see XXX comment] */ 741 if (len & ERR_INCOMPLETE) { 742 if (ifp->if_flags & IFF_DEBUG) 743 printf("vx%d: adapter reset\n", sc->unit); 744 vxreset(sc); 745 return; 746 } 747 goto again; 748 } 749 750 return; 751 752abort: 753 CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK); 754} 755 756static struct mbuf * 757vxget(sc, totlen) 758 struct vx_softc *sc; 759 u_int totlen; 760{ 761 struct ifnet *ifp = &sc->arpcom.ac_if; 762 struct mbuf *top, **mp, *m; 763 int len; 764 int sh; 765 766 m = sc->mb[sc->next_mb]; 767 sc->mb[sc->next_mb] = 0; 768 if (m == 0) { 769 MGETHDR(m, M_DONTWAIT, MT_DATA); 770 if (m == 0) 771 return 0; 772 } else { 773 /* If the queue is no longer full, refill. */ 774 if (sc->last_mb == sc->next_mb && sc->buffill_pending == 0) { 775 sc->ch = timeout(vxmbuffill, sc, 1); 776 sc->buffill_pending = 1; 777 } 778 /* Convert one of our saved mbuf's. */ 779 sc->next_mb = (sc->next_mb + 1) % MAX_MBS; 780 m->m_data = m->m_pktdat; 781 m->m_flags = M_PKTHDR; 782 bzero(&m->m_pkthdr, sizeof(m->m_pkthdr)); 783 } 784 m->m_pkthdr.rcvif = ifp; 785 m->m_pkthdr.len = totlen; 786 len = MHLEN; 787 top = 0; 788 mp = ⊤ 789 790 /* 791 * We read the packet at splhigh() so that an interrupt from another 792 * device doesn't cause the card's buffer to overflow while we're 793 * reading it. We may still lose packets at other times. 794 */ 795 sh = splhigh(); 796 797 /* 798 * Since we don't set allowLargePackets bit in MacControl register, 799 * we can assume that totlen <= 1500bytes. 800 * The while loop will be performed iff we have a packet with 801 * MLEN < m_len < MINCLSIZE. 802 */ 803 while (totlen > 0) { 804 if (top) { 805 m = sc->mb[sc->next_mb]; 806 sc->mb[sc->next_mb] = 0; 807 if (m == 0) { 808 MGET(m, M_DONTWAIT, MT_DATA); 809 if (m == 0) { 810 splx(sh); 811 m_freem(top); 812 return 0; 813 } 814 } else { 815 sc->next_mb = (sc->next_mb + 1) % MAX_MBS; 816 } 817 len = MLEN; 818 } 819 if (totlen >= MINCLSIZE) { 820 MCLGET(m, M_DONTWAIT); 821 if (m->m_flags & M_EXT) 822 len = MCLBYTES; 823 } 824 len = min(totlen, len); 825 if (len > 3) 826 bus_space_read_multi_4(sc->vx_btag, sc->vx_bhandle, 827 VX_W1_RX_PIO_RD_1, mtod(m, u_int32_t *), len / 4); 828 if (len & 3) { 829 bus_space_read_multi_1(sc->vx_btag, sc->vx_bhandle, 830 VX_W1_RX_PIO_RD_1, mtod(m, u_int8_t *) + (len & ~3), 831 len & 3); 832 } 833 m->m_len = len; 834 totlen -= len; 835 *mp = m; 836 mp = &m->m_next; 837 } 838 839 CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK); 840 841 splx(sh); 842 843 return top; 844} 845 846 847static int 848vxioctl(ifp, cmd, data) 849 register struct ifnet *ifp; 850 u_long cmd; 851 caddr_t data; 852{ 853 struct vx_softc *sc = ifp->if_softc; 854 struct ifreq *ifr = (struct ifreq *) data; 855 int s, error = 0; 856 857 s = splimp(); 858 859 switch (cmd) { 860 case SIOCSIFADDR: 861 case SIOCGIFADDR: 862 ether_ioctl(ifp, cmd, data); 863 break; 864 865 case SIOCSIFFLAGS: 866 if ((ifp->if_flags & IFF_UP) == 0 && 867 (ifp->if_flags & IFF_RUNNING) != 0) { 868 /* 869 * If interface is marked up and it is stopped, then 870 * start it. 871 */ 872 vxstop(sc); 873 ifp->if_flags &= ~IFF_RUNNING; 874 } else if ((ifp->if_flags & IFF_UP) != 0 && 875 (ifp->if_flags & IFF_RUNNING) == 0) { 876 /* 877 * If interface is marked up and it is stopped, then 878 * start it. 879 */ 880 vxinit(sc); 881 } else { 882 /* 883 * deal with flags changes: 884 * IFF_MULTICAST, IFF_PROMISC, 885 * IFF_LINK0, IFF_LINK1, 886 */ 887 vxsetfilter(sc); 888 vxsetlink(sc); 889 } 890 break; 891 892 case SIOCSIFMTU: 893 /* 894 * Set the interface MTU. 895 */ 896 if (ifr->ifr_mtu > ETHERMTU) { 897 error = EINVAL; 898 } else { 899 ifp->if_mtu = ifr->ifr_mtu; 900 } 901 break; 902 903 case SIOCADDMULTI: 904 case SIOCDELMULTI: 905 /* 906 * Multicast list has changed; set the hardware filter 907 * accordingly. 908 */ 909 vxreset(sc); 910 error = 0; 911 break; 912 913 914 default: 915 error = EINVAL; 916 } 917 918 splx(s); 919 920 return (error); 921} 922 923static void 924vxreset(sc) 925 struct vx_softc *sc; 926{ 927 int s; 928 s = splimp(); 929 930 vxstop(sc); 931 vxinit(sc); 932 splx(s); 933} 934 935static void 936vxwatchdog(ifp) 937 struct ifnet *ifp; 938{ 939 struct vx_softc *sc = ifp->if_softc; 940 941 if (ifp->if_flags & IFF_DEBUG) 942 printf("vx%d: device timeout\n", ifp->if_unit); 943 ifp->if_flags &= ~IFF_OACTIVE; 944 vxstart(ifp); 945 vxintr(sc); 946} 947 948void 949vxstop(sc) 950 struct vx_softc *sc; 951{ 952 struct ifnet *ifp = &sc->arpcom.ac_if; 953 954 ifp->if_timer = 0; 955 956 CSR_WRITE_2(sc, VX_COMMAND, RX_DISABLE); 957 CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK); 958 VX_BUSY_WAIT; 959 CSR_WRITE_2(sc, VX_COMMAND, TX_DISABLE); 960 CSR_WRITE_2(sc, VX_COMMAND, STOP_TRANSCEIVER); 961 DELAY(800); 962 CSR_WRITE_2(sc, VX_COMMAND, RX_RESET); 963 VX_BUSY_WAIT; 964 CSR_WRITE_2(sc, VX_COMMAND, TX_RESET); 965 VX_BUSY_WAIT; 966 CSR_WRITE_2(sc, VX_COMMAND, C_INTR_LATCH); 967 CSR_WRITE_2(sc, VX_COMMAND, SET_RD_0_MASK); 968 CSR_WRITE_2(sc, VX_COMMAND, SET_INTR_MASK); 969 CSR_WRITE_2(sc, VX_COMMAND, SET_RX_FILTER); 970 971 vxmbufempty(sc); 972} 973 974int 975vxbusyeeprom(sc) 976 struct vx_softc *sc; 977{ 978 int j, i = 100; 979 980 while (i--) { 981 j = CSR_READ_2(sc, VX_W0_EEPROM_COMMAND); 982 if (j & EEPROM_BUSY) 983 DELAY(100); 984 else 985 break; 986 } 987 if (!i) { 988 printf("vx%d: eeprom failed to come ready\n", sc->unit); 989 return (1); 990 } 991 return (0); 992} 993 994static void 995vxmbuffill(sp) 996 void *sp; 997{ 998 struct vx_softc *sc = (struct vx_softc *) sp; 999 int s, i; 1000 1001 s = splimp(); 1002 i = sc->last_mb; 1003 do { 1004 if (sc->mb[i] == NULL) 1005 MGET(sc->mb[i], M_DONTWAIT, MT_DATA); 1006 if (sc->mb[i] == NULL) 1007 break; 1008 i = (i + 1) % MAX_MBS; 1009 } while (i != sc->next_mb); 1010 sc->last_mb = i; 1011 /* If the queue was not filled, try again. */ 1012 if (sc->last_mb != sc->next_mb) { 1013 sc->ch = timeout(vxmbuffill, sc, 1); 1014 sc->buffill_pending = 1; 1015 } else { 1016 sc->buffill_pending = 0; 1017 } 1018 splx(s); 1019} 1020 1021static void 1022vxmbufempty(sc) 1023 struct vx_softc *sc; 1024{ 1025 int s, i; 1026 1027 s = splimp(); 1028 for (i = 0; i < MAX_MBS; i++) { 1029 if (sc->mb[i]) { 1030 m_freem(sc->mb[i]); 1031 sc->mb[i] = NULL; 1032 } 1033 } 1034 sc->last_mb = sc->next_mb = 0; 1035 if (sc->buffill_pending != 0) 1036 untimeout(vxmbuffill, sc, sc->ch); 1037 splx(s); 1038} 1039