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