1 /* $OpenBSD: smc91cxx.c,v 1.13 2001/07/08 23:38:06 fgsch Exp $ */ 2 /* $NetBSD: smc91cxx.c,v 1.11 1998/08/08 23:51:41 mycroft Exp $ */ 3 4 /*- 5 * Copyright (c) 1997 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10 * NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 /* 42 * Copyright (c) 1996 Gardner Buchanan <gbuchanan@shl.com> 43 * All rights reserved. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by Gardner Buchanan. 56 * 4. The name of Gardner Buchanan may not be used to endorse or promote 57 * products derived from this software without specific prior written 58 * permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 61 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 62 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 63 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 64 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 65 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 66 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 67 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 68 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 69 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 70 * 71 * from FreeBSD Id: if_sn.c,v 1.4 1996/03/18 15:47:16 gardner Exp 72 */ 73 74 /* 75 * Core driver for the SMC 91Cxx family of Ethernet chips. 76 * 77 * Memory allocation interrupt logic is drived from an SMC 91C90 driver 78 * written for NetBSD/amiga by Michael Hitch. 79 */ 80 81 #include "bpfilter.h" 82 83 #include <sys/param.h> 84 #include <sys/systm.h> 85 #include <sys/mbuf.h> 86 #include <sys/syslog.h> 87 #include <sys/socket.h> 88 #include <sys/device.h> 89 #include <sys/malloc.h> 90 #include <sys/ioctl.h> 91 #include <sys/errno.h> 92 #if NRND > 0 93 #include <sys/rnd.h> 94 #endif 95 96 #include <machine/bus.h> 97 #include <machine/intr.h> 98 99 #include <net/if.h> 100 #include <net/if_dl.h> 101 #include <net/if_media.h> 102 103 #ifdef INET 104 #include <netinet/in.h> 105 #include <netinet/if_ether.h> 106 #include <netinet/in_systm.h> 107 #include <netinet/in_var.h> 108 #include <netinet/ip.h> 109 #endif 110 111 #ifdef NS 112 #include <netns/ns.h> 113 #include <netns/ns_if.h> 114 #endif 115 116 #if defined(CCITT) && defined(LLC) 117 #include <sys/socketvar.h> 118 #include <netccitt/x25.h> 119 #include <netccitt/pk.h> 120 #include <netccitt/pk_var.h> 121 #include <netccitt/pk_extern.h> 122 #endif 123 124 #if NBPFILTER > 0 125 #include <net/bpf.h> 126 #include <net/bpfdesc.h> 127 #endif 128 129 #include <dev/ic/smc91cxxreg.h> 130 #include <dev/ic/smc91cxxvar.h> 131 132 /* XXX Hardware padding doesn't work yet(?) */ 133 #define SMC91CXX_SW_PAD 134 135 #ifdef SMC_DEBUG 136 const char *smc91cxx_idstrs[] = { 137 NULL, /* 0 */ 138 NULL, /* 1 */ 139 NULL, /* 2 */ 140 "SMC91C90/91C92", /* 3 */ 141 "SMC91C94", /* 4 */ 142 "SMC91C95", /* 5 */ 143 NULL, /* 6 */ 144 "SMC91C100", /* 7 */ 145 NULL, /* 8 */ 146 NULL, /* 9 */ 147 NULL, /* 10 */ 148 NULL, /* 11 */ 149 NULL, /* 12 */ 150 NULL, /* 13 */ 151 NULL, /* 14 */ 152 NULL, /* 15 */ 153 }; 154 #endif 155 156 /* Supported media types. */ 157 const int smc91cxx_media[] = { 158 IFM_ETHER|IFM_10_T, 159 IFM_ETHER|IFM_10_5, 160 }; 161 #define NSMC91CxxMEDIA (sizeof(smc91cxx_media) / sizeof(smc91cxx_media[0])) 162 163 struct cfdriver sm_cd = { 164 NULL, "sm", DV_IFNET 165 }; 166 167 int smc91cxx_mediachange __P((struct ifnet *)); 168 void smc91cxx_mediastatus __P((struct ifnet *, struct ifmediareq *)); 169 170 int smc91cxx_set_media __P((struct smc91cxx_softc *, int)); 171 172 void smc91cxx_read __P((struct smc91cxx_softc *)); 173 void smc91cxx_reset __P((struct smc91cxx_softc *)); 174 void smc91cxx_start __P((struct ifnet *)); 175 void smc91cxx_resume __P((struct smc91cxx_softc *)); 176 void smc91cxx_watchdog __P((struct ifnet *)); 177 int smc91cxx_ioctl __P((struct ifnet *, u_long, caddr_t)); 178 179 int smc91cxx_enable __P((struct smc91cxx_softc *)); 180 void smc91cxx_disable __P((struct smc91cxx_softc *)); 181 182 static __inline int ether_cmp __P((void *, void *)); 183 static __inline int 184 ether_cmp(va, vb) 185 void *va, *vb; 186 { 187 u_int8_t *a = va; 188 u_int8_t *b = vb; 189 190 return ((a[5] != b[5]) || (a[4] != b[4]) || (a[3] != b[3]) || 191 (a[2] != b[2]) || (a[1] != b[1]) || (a[0] != b[0])); 192 } 193 194 void 195 smc91cxx_attach(sc, myea) 196 struct smc91cxx_softc *sc; 197 u_int8_t *myea; 198 { 199 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 200 bus_space_tag_t bst = sc->sc_bst; 201 bus_space_handle_t bsh = sc->sc_bsh; 202 u_int16_t tmp; 203 int i, aui; 204 #ifdef SMC_DEBUG 205 const char *idstr; 206 #endif 207 208 /* Make sure the chip is stopped. */ 209 smc91cxx_stop(sc); 210 211 #ifdef SMC_DEBUG 212 SMC_SELECT_BANK(sc, 3); 213 tmp = bus_space_read_2(bst, bsh, REVISION_REG_W); 214 idstr = smc91cxx_idstrs[RR_ID(tmp)]; 215 printf("%s: ", sc->sc_dev.dv_xname); 216 if (idstr != NULL) 217 printf("%s, ", idstr); 218 else 219 printf("unknown chip id %d, ", RR_ID(tmp)); 220 printf("revision %d\n", RR_REV(tmp)); 221 #endif 222 223 /* Read the station address from the chip. */ 224 SMC_SELECT_BANK(sc, 1); 225 if (myea == NULL) { 226 for (i = 0; i < ETHER_ADDR_LEN; i += 2) { 227 tmp = bus_space_read_2(bst, bsh, IAR_ADDR0_REG_W + i); 228 sc->sc_arpcom.ac_enaddr[i + 1] = (tmp >>8) & 0xff; 229 sc->sc_arpcom.ac_enaddr[i] = tmp & 0xff; 230 } 231 } else { 232 bcopy(myea, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); 233 } 234 235 printf(": address %s, ", 236 ether_sprintf(sc->sc_arpcom.ac_enaddr)); 237 238 /* ..and default media. */ 239 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W); 240 printf("utp/aui (default %s)\n", (aui = (tmp & CR_AUI_SELECT)) ? 241 "aui" : "utp"); 242 243 /* Initialize the ifnet structure. */ 244 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 245 ifp->if_softc = sc; 246 ifp->if_start = smc91cxx_start; 247 ifp->if_ioctl = smc91cxx_ioctl; 248 ifp->if_watchdog = smc91cxx_watchdog; 249 ifp->if_flags = 250 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 251 IFQ_SET_READY(&ifp->if_snd); 252 253 /* Attach the interface. */ 254 if_attach(ifp); 255 ether_ifattach(ifp); 256 257 /* Initialize the media structures. */ 258 ifmedia_init(&sc->sc_media, 0, smc91cxx_mediachange, 259 smc91cxx_mediastatus); 260 for (i = 0; i < NSMC91CxxMEDIA; i++) 261 ifmedia_add(&sc->sc_media, smc91cxx_media[i], 0, NULL); 262 ifmedia_set(&sc->sc_media, IFM_ETHER | (aui ? IFM_10_5 : IFM_10_T)); 263 264 #if NRND > 0 265 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, RND_TYPE_NET); 266 #endif 267 } 268 269 /* 270 * Change media according to request. 271 */ 272 int 273 smc91cxx_mediachange(ifp) 274 struct ifnet *ifp; 275 { 276 struct smc91cxx_softc *sc = ifp->if_softc; 277 278 return (smc91cxx_set_media(sc, sc->sc_media.ifm_media)); 279 } 280 281 int 282 smc91cxx_set_media(sc, media) 283 struct smc91cxx_softc *sc; 284 int media; 285 { 286 bus_space_tag_t bst = sc->sc_bst; 287 bus_space_handle_t bsh = sc->sc_bsh; 288 u_int16_t tmp; 289 290 /* 291 * If the interface is not currently powered on, just return. 292 * When it is enabled later, smc91cxx_init() will properly set 293 * up the media for us. 294 */ 295 if (sc->sc_enabled == 0) 296 return (0); 297 298 if (IFM_TYPE(media) != IFM_ETHER) 299 return (EINVAL); 300 301 switch (IFM_SUBTYPE(media)) { 302 case IFM_10_T: 303 case IFM_10_5: 304 SMC_SELECT_BANK(sc, 1); 305 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W); 306 if (IFM_SUBTYPE(media) == IFM_10_5) 307 tmp |= CR_AUI_SELECT; 308 else 309 tmp &= ~CR_AUI_SELECT; 310 bus_space_write_2(bst, bsh, CONFIG_REG_W, tmp); 311 delay(20000); /* XXX is this needed? */ 312 break; 313 314 default: 315 return (EINVAL); 316 } 317 318 return (0); 319 } 320 321 /* 322 * Notify the world which media we're using. 323 */ 324 void 325 smc91cxx_mediastatus(ifp, ifmr) 326 struct ifnet *ifp; 327 struct ifmediareq *ifmr; 328 { 329 struct smc91cxx_softc *sc = ifp->if_softc; 330 bus_space_tag_t bst = sc->sc_bst; 331 bus_space_handle_t bsh = sc->sc_bsh; 332 u_int16_t tmp; 333 334 if (sc->sc_enabled == 0) { 335 ifmr->ifm_active = IFM_ETHER | IFM_NONE; 336 ifmr->ifm_status = 0; 337 return; 338 } 339 340 SMC_SELECT_BANK(sc, 1); 341 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W); 342 ifmr->ifm_active = 343 IFM_ETHER | ((tmp & CR_AUI_SELECT) ? IFM_10_5 : IFM_10_T); 344 } 345 346 /* 347 * Reset and initialize the chip. 348 */ 349 void 350 smc91cxx_init(sc) 351 struct smc91cxx_softc *sc; 352 { 353 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 354 bus_space_tag_t bst = sc->sc_bst; 355 bus_space_handle_t bsh = sc->sc_bsh; 356 u_int16_t tmp; 357 int s, i; 358 359 s = splnet(); 360 361 /* 362 * This resets the registersmostly to defaults, but doesn't 363 * affect the EEPROM. After the reset cycle, we pause briefly 364 * for the chip to recover. 365 * 366 * XXX how long are we really supposed to delay? --thorpej 367 */ 368 SMC_SELECT_BANK(sc, 0); 369 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET); 370 delay(100); 371 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0); 372 delay(200); 373 374 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0); 375 376 /* Set the Ethernet address. */ 377 SMC_SELECT_BANK(sc, 1); 378 for (i = 0; i < ETHER_ADDR_LEN; i++ ) 379 bus_space_write_1(bst, bsh, IAR_ADDR0_REG_W + i, 380 sc->sc_arpcom.ac_enaddr[i]); 381 382 /* 383 * Set the control register to automatically release successfully 384 * transmitted packets (making the best use of our limited memory) 385 * and enable the EPH interrupt on certain TX errors. 386 */ 387 bus_space_write_2(bst, bsh, CONTROL_REG_W, (CTR_AUTO_RELEASE | 388 CTR_TE_ENABLE | CTR_CR_ENABLE | CTR_LE_ENABLE)); 389 390 /* 391 * Reset the MMU and wait for it to be un-busy. 392 */ 393 SMC_SELECT_BANK(sc, 2); 394 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET); 395 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY) 396 /* XXX bound this loop! */ ; 397 398 /* 399 * Disable all interrupts. 400 */ 401 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0); 402 403 /* 404 * Set current media. 405 */ 406 smc91cxx_set_media(sc, sc->sc_media.ifm_cur->ifm_media); 407 408 /* 409 * Set the receive filter. We want receive enable and auto 410 * strip of CRC from received packet. If we are in promisc. mode, 411 * then set that bit as well. 412 * 413 * XXX Initialize multicast filter. For now, we just accept 414 * XXX all multicast. 415 */ 416 SMC_SELECT_BANK(sc, 0); 417 418 tmp = RCR_ENABLE | RCR_STRIP_CRC | RCR_ALMUL; 419 if (ifp->if_flags & IFF_PROMISC) 420 tmp |= RCR_PROMISC; 421 422 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, tmp); 423 424 /* 425 * Set transmitter control to "enabled". 426 */ 427 tmp = TCR_ENABLE; 428 429 #ifndef SMC91CXX_SW_PAD 430 /* 431 * Enable hardware padding of transmitted packets. 432 * XXX doesn't work? 433 */ 434 tmp |= TCR_PAD_ENABLE; 435 #endif 436 437 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, tmp); 438 439 /* 440 * Now, enable interrupts. 441 */ 442 SMC_SELECT_BANK(sc, 2); 443 444 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 445 IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT); 446 447 /* Interface is now running, with no output active. */ 448 ifp->if_flags |= IFF_RUNNING; 449 ifp->if_flags &= ~IFF_OACTIVE; 450 451 /* 452 * Attempt to start any pending transmission. 453 */ 454 smc91cxx_start(ifp); 455 456 splx(s); 457 } 458 459 /* 460 * Start output on an interface. 461 * Must be called at splnet or interrupt level. 462 */ 463 void 464 smc91cxx_start(ifp) 465 struct ifnet *ifp; 466 { 467 struct smc91cxx_softc *sc = ifp->if_softc; 468 bus_space_tag_t bst = sc->sc_bst; 469 bus_space_handle_t bsh = sc->sc_bsh; 470 u_int len; 471 struct mbuf *m, *top; 472 u_int16_t length, npages; 473 u_int8_t packetno; 474 int timo, pad; 475 476 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) 477 return; 478 479 again: 480 /* 481 * Peek at the next packet. 482 */ 483 IFQ_POLL(&ifp->if_snd, m); 484 if (m == NULL) 485 return; 486 487 /* 488 * Compute the frame length and set pad to give an overall even 489 * number of bytes. Below, we assume that the packet length 490 * is even. 491 */ 492 for (len = 0, top = m; m != NULL; m = m->m_next) 493 len += m->m_len; 494 pad = (len & 1); 495 496 /* 497 * We drop packets that are too large. Perhaps we should 498 * truncate them instead? 499 */ 500 if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) { 501 printf("%s: large packet discarded\n", sc->sc_dev.dv_xname); 502 ifp->if_oerrors++; 503 IFQ_DEQUEUE(&ifp->if_snd, m); 504 m_freem(m); 505 goto readcheck; 506 } 507 508 #ifdef SMC91CXX_SW_PAD 509 /* 510 * Not using hardware padding; pad to ETHER_MIN_LEN. 511 */ 512 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) 513 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len; 514 #endif 515 516 length = pad + len; 517 518 /* 519 * The MMU has a 256 byte page size. The MMU expects us to 520 * ask for "npages - 1". We include space for the status word, 521 * byte count, and control bytes in the allocation request. 522 */ 523 npages = (length + 6) >> 8; 524 525 /* 526 * Now allocate the memory. 527 */ 528 SMC_SELECT_BANK(sc, 2); 529 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages); 530 531 timo = MEMORY_WAIT_TIME; 532 do { 533 if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT) 534 break; 535 delay(1); 536 } while (--timo); 537 538 packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B); 539 540 if (packetno & ARR_FAILED || timo == 0) { 541 /* 542 * No transmit memory is available. Record the number 543 * of requestd pages and enable the allocation completion 544 * interrupt. Set up the watchdog timer in case we miss 545 * the interrupt. Mark the interface as active so that 546 * no one else attempts to transmit while we're allocating 547 * memory. 548 */ 549 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 550 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT); 551 552 ifp->if_timer = 5; 553 ifp->if_flags |= IFF_OACTIVE; 554 555 return; 556 } 557 558 /* 559 * We have a packet number - set the data window. 560 */ 561 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno); 562 563 /* 564 * Point to the beginning of the packet. 565 */ 566 bus_space_write_2(bst, bsh, POINTER_REG_W, PTR_AUTOINC /* | 0x0000 */); 567 568 /* 569 * Send the packet length (+6 for stats, length, and control bytes) 570 * and the status word (set to zeros). 571 */ 572 bus_space_write_2(bst, bsh, DATA_REG_W, 0); 573 bus_space_write_1(bst, bsh, DATA_REG_B, (length + 6) & 0xff); 574 bus_space_write_1(bst, bsh, DATA_REG_B, ((length + 6) >> 8) & 0xff); 575 576 /* 577 * Get the packet from the kernel. This will include the Ethernet 578 * frame header, MAC address, etc. 579 */ 580 IFQ_DEQUEUE(&ifp->if_snd, m); 581 582 /* 583 * Push the packet out to the card. 584 */ 585 for (top = m; m != NULL; m = m->m_next) { 586 /* Words... */ 587 bus_space_write_multi_2(bst, bsh, DATA_REG_W, 588 mtod(m, u_int16_t *), m->m_len >> 1); 589 590 /* ...and the remaining byte, if any. */ 591 if (m->m_len & 1) 592 bus_space_write_1(bst, bsh, DATA_REG_B, 593 *(u_int8_t *)(mtod(m, u_int8_t *) + (m->m_len - 1))); 594 } 595 596 #ifdef SMC91CXX_SW_PAD 597 /* 598 * Push out padding. 599 */ 600 while (pad > 1) { 601 bus_space_write_2(bst, bsh, DATA_REG_W, 0); 602 pad -= 2; 603 } 604 if (pad) 605 bus_space_write_1(bst, bsh, DATA_REG_B, 0); 606 #endif 607 608 /* 609 * Push out control byte and unused packet byte. The control byte 610 * is 0, meaning the packet is even lengthed and no special 611 * CRC handling is necessary. 612 */ 613 bus_space_write_2(bst, bsh, DATA_REG_W, 0); 614 615 /* 616 * Enable transmit interrupts and let the chip go. Set a watchdog 617 * in case we miss the interrupt. 618 */ 619 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 620 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | 621 IM_TX_INT | IM_TX_EMPTY_INT); 622 623 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE); 624 625 ifp->if_timer = 5; 626 627 #if NBPFILTER > 0 628 /* Hand off a copy to the bpf. */ 629 if (ifp->if_bpf) 630 bpf_mtap(ifp->if_bpf, top); 631 #endif 632 633 ifp->if_opackets++; 634 m_freem(top); 635 636 readcheck: 637 /* 638 * Check for incoming pcakets. We don't want to overflow the small 639 * RX FIFO. If nothing has arrived, attempt to queue another 640 * transmit packet. 641 */ 642 if (bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & FIFO_REMPTY) 643 goto again; 644 } 645 646 /* 647 * Interrupt service routine. 648 */ 649 int 650 smc91cxx_intr(arg) 651 void *arg; 652 { 653 struct smc91cxx_softc *sc = arg; 654 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 655 bus_space_tag_t bst = sc->sc_bst; 656 bus_space_handle_t bsh = sc->sc_bsh; 657 u_int8_t mask, interrupts, status; 658 u_int16_t packetno, tx_status, card_stats; 659 660 if (sc->sc_enabled == 0) 661 return (0); 662 663 SMC_SELECT_BANK(sc, 2); 664 665 /* 666 * Obtain the current interrupt mask. 667 */ 668 mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B); 669 670 /* 671 * Get the set of interrupt which occurred and eliminate any 672 * which are not enabled. 673 */ 674 interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B); 675 status = interrupts & mask; 676 677 /* Ours? */ 678 if (status == 0) 679 return (0); 680 681 /* 682 * It's ours; disable all interrupts while we process them. 683 */ 684 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0); 685 686 /* 687 * Receive overrun interrupts. 688 */ 689 if (status & IM_RX_OVRN_INT) { 690 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT); 691 ifp->if_ierrors++; 692 } 693 694 /* 695 * Receive interrupts. 696 */ 697 if (status & IM_RCV_INT) { 698 #if 1 /* DIAGNOSTIC */ 699 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W); 700 if (packetno & FIFO_REMPTY) 701 printf("%s: receive interrupt on empty fifo\n", 702 sc->sc_dev.dv_xname); 703 else 704 #endif 705 smc91cxx_read(sc); 706 } 707 708 /* 709 * Memory allocation interrupts. 710 */ 711 if (status & IM_ALLOC_INT) { 712 /* Disable this interrupt. */ 713 mask &= ~IM_ALLOC_INT; 714 715 /* 716 * Release the just-allocated memory. We will reallocate 717 * it through the normal start logic. 718 */ 719 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY) 720 /* XXX bound this loop! */ ; 721 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT); 722 723 ifp->if_flags &= ~IFF_OACTIVE; 724 ifp->if_timer = 0; 725 } 726 727 /* 728 * Transmit complete interrupt. Handle transmission error messages. 729 * This will only be called on error condition because of AUTO RELEASE 730 * mode. 731 */ 732 if (status & IM_TX_INT) { 733 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT); 734 735 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & 736 FIFO_TX_MASK; 737 738 /* 739 * Select this as the packet to read from. 740 */ 741 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno); 742 743 /* 744 * Position the pointer to the beginning of the packet. 745 */ 746 bus_space_write_2(bst, bsh, POINTER_REG_W, 747 PTR_AUTOINC | PTR_READ /* | 0x0000 */); 748 749 /* 750 * Fetch the TX status word. This will be a copy of 751 * the EPH_STATUS_REG_W at the time of the transmission 752 * failure. 753 */ 754 tx_status = bus_space_read_2(bst, bsh, DATA_REG_W); 755 756 if (tx_status & EPHSR_TX_SUC) 757 printf("%s: successful packet caused TX interrupt?!\n", 758 sc->sc_dev.dv_xname); 759 else 760 ifp->if_oerrors++; 761 762 if (tx_status & EPHSR_LATCOL) 763 ifp->if_collisions++; 764 765 /* 766 * Some of these errors disable the transmitter; reenable it. 767 */ 768 SMC_SELECT_BANK(sc, 0); 769 #ifdef SMC91CXX_SW_PAD 770 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, TCR_ENABLE); 771 #else 772 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 773 TCR_ENABLE | TCR_PAD_ENABLE); 774 #endif 775 776 /* 777 * Kill the failed packet and wait for the MMU to unbusy. 778 */ 779 SMC_SELECT_BANK(sc, 2); 780 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY) 781 /* XXX bound this loop! */ ; 782 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT); 783 784 ifp->if_timer = 0; 785 } 786 787 /* 788 * Transmit underrun interrupts. We use this opportunity to 789 * update transmit statistics from the card. 790 */ 791 if (status & IM_TX_EMPTY_INT) { 792 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT); 793 794 /* Disable this interrupt. */ 795 mask &= ~IM_TX_EMPTY_INT; 796 797 SMC_SELECT_BANK(sc, 0); 798 card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W); 799 800 /* Single collisions. */ 801 ifp->if_collisions += card_stats & ECR_COLN_MASK; 802 803 /* Multiple collisions. */ 804 ifp->if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4; 805 806 SMC_SELECT_BANK(sc, 2); 807 808 ifp->if_timer = 0; 809 } 810 811 /* 812 * Other errors. Reset the interface. 813 */ 814 if (status & IM_EPH_INT) { 815 smc91cxx_stop(sc); 816 smc91cxx_init(sc); 817 } 818 819 /* 820 * Attempt to queue more packets for transmission. 821 */ 822 smc91cxx_start(ifp); 823 824 /* 825 * Reenable the interrupts we wish to receive now that processing 826 * is complete. 827 */ 828 mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B); 829 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask); 830 831 #if NRND > 0 832 if (status) 833 rnd_add_uint32(&sc->rnd_source, status); 834 #endif 835 836 return (1); 837 } 838 839 /* 840 * Read a packet from the card and pass it up to the kernel. 841 * NOTE! WE EXPECT TO BE IN REGISTER WINDOW 2! 842 */ 843 void 844 smc91cxx_read(sc) 845 struct smc91cxx_softc *sc; 846 { 847 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 848 bus_space_tag_t bst = sc->sc_bst; 849 bus_space_handle_t bsh = sc->sc_bsh; 850 struct mbuf *m; 851 u_int16_t status, packetno, packetlen; 852 u_int8_t *data; 853 854 again: 855 /* 856 * Set data pointer to the beginning of the packet. Since 857 * PTR_RCV is set, the packet number will be found automatically 858 * in FIFO_PORTS_REG_W, FIFO_RX_MASK. 859 */ 860 bus_space_write_2(bst, bsh, POINTER_REG_W, 861 PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */); 862 863 /* 864 * First two words are status and packet length. 865 */ 866 status = bus_space_read_2(bst, bsh, DATA_REG_W); 867 packetlen = bus_space_read_2(bst, bsh, DATA_REG_W); 868 869 /* 870 * The packet length includes 3 extra words: status, length, 871 * and an extra word that includes the control byte. 872 */ 873 packetlen -= 6; 874 875 /* 876 * Account for receive errors and discard. 877 */ 878 if (status & RS_ERRORS) { 879 ifp->if_ierrors++; 880 goto out; 881 } 882 883 /* 884 * Adjust for odd-length packet. 885 */ 886 if (status & RS_ODDFRAME) 887 packetlen++; 888 889 /* 890 * Allocate a header mbuf. 891 */ 892 MGETHDR(m, M_DONTWAIT, MT_DATA); 893 if (m == NULL) 894 goto out; 895 896 m->m_pkthdr.rcvif = ifp; 897 m->m_pkthdr.len = m->m_len = packetlen; 898 899 /* 900 * Always put the packet in a cluster. 901 * XXX should chain small mbufs if less than threshold. 902 */ 903 MCLGET(m, M_DONTWAIT); 904 if ((m->m_flags & M_EXT) == 0) { 905 m_freem(m); 906 ifp->if_ierrors++; 907 printf("%s: can't allocate cluster for incoming packet\n", 908 sc->sc_dev.dv_xname); 909 goto out; 910 } 911 912 /* 913 * Pull the packet off the interface. 914 */ 915 data = mtod(m, u_int8_t *); 916 bus_space_read_multi_2(bst, bsh, DATA_REG_W, (u_int16_t *)data, 917 packetlen >> 1); 918 if (packetlen & 1) { 919 data += packetlen & ~1; 920 *data = bus_space_read_1(bst, bsh, DATA_REG_B); 921 } 922 923 ifp->if_ipackets++; 924 925 #if NBPFILTER > 0 926 /* 927 * Hand the packet off to bpf listeners. If there's a bpf listener, 928 * we need to check if the packet is ours. 929 */ 930 if (ifp->if_bpf) 931 bpf_mtap(ifp->if_bpf, m); 932 #endif 933 934 m->m_pkthdr.len = m->m_len = packetlen; 935 ether_input_mbuf(ifp, m); 936 937 out: 938 /* 939 * Tell the card to free the memory occupied by this packet. 940 */ 941 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY) 942 /* XXX bound this loop! */ ; 943 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RELEASE); 944 945 /* 946 * Check for another packet. 947 */ 948 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W); 949 if (packetno & FIFO_REMPTY) 950 return; 951 goto again; 952 } 953 954 /* 955 * Process an ioctl request. 956 */ 957 int 958 smc91cxx_ioctl(ifp, cmd, data) 959 struct ifnet *ifp; 960 u_long cmd; 961 caddr_t data; 962 { 963 struct smc91cxx_softc *sc = ifp->if_softc; 964 struct ifaddr *ifa = (struct ifaddr *)data; 965 struct ifreq *ifr = (struct ifreq *)data; 966 int s, error = 0; 967 968 s = splnet(); 969 970 switch (cmd) { 971 case SIOCSIFADDR: 972 if ((error = smc91cxx_enable(sc)) != 0) 973 break; 974 ifp->if_flags |= IFF_UP; 975 switch (ifa->ifa_addr->sa_family) { 976 #ifdef INET 977 case AF_INET: 978 smc91cxx_init(sc); 979 arp_ifinit(&sc->sc_arpcom, ifa); 980 break; 981 #endif 982 #ifdef NS 983 case AF_NS: 984 { 985 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 986 987 if (ns_nullhost(*ina)) 988 ina->x_host = 989 *(union ns_host *)LLADDR(ifp->if_sadl); 990 else { 991 bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl), 992 ETHER_ADDR_LEN); 993 } 994 995 /* 996 * Set new address. Reset, because the receiver 997 * has to be stopped before we can set the new 998 * MAC address. 999 */ 1000 smc91cxx_reset(sc); 1001 break; 1002 } 1003 #endif 1004 default: 1005 smc91cxx_init(sc); 1006 break; 1007 } 1008 break; 1009 1010 #if defined(CCITT) && defined(LLC) 1011 case SIOCSIFCONF_X25: 1012 if ((error = smc91cxx_enable(sc)) != 0) 1013 break; 1014 ifp->if_flags |= IFF_UP; 1015 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */ 1016 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); 1017 if (error == 0) 1018 smc91cxx_init(sc); 1019 break; 1020 #endif 1021 1022 case SIOCSIFFLAGS: 1023 if ((ifp->if_flags & IFF_UP) == 0 && 1024 (ifp->if_flags & IFF_RUNNING) != 0) { 1025 /* 1026 * If interface is marked down and it is running, 1027 * stop it. 1028 */ 1029 smc91cxx_stop(sc); 1030 ifp->if_flags &= ~IFF_RUNNING; 1031 smc91cxx_disable(sc); 1032 } else if ((ifp->if_flags & IFF_UP) != 0 && 1033 (ifp->if_flags & IFF_RUNNING) == 0) { 1034 /* 1035 * If interface is marked up and it is stopped, 1036 * start it. 1037 */ 1038 if ((error = smc91cxx_enable(sc)) != 0) 1039 break; 1040 smc91cxx_init(sc); 1041 } else if (sc->sc_enabled) { 1042 /* 1043 * Reset the interface to pick up changes in any 1044 * other flags that affect hardware registers. 1045 */ 1046 smc91cxx_reset(sc); 1047 } 1048 break; 1049 1050 case SIOCADDMULTI: 1051 case SIOCDELMULTI: 1052 if (sc->sc_enabled == 0) { 1053 error = EIO; 1054 break; 1055 } 1056 1057 error = (cmd == SIOCADDMULTI) ? 1058 ether_addmulti(ifr, &sc->sc_arpcom) : 1059 ether_delmulti(ifr, &sc->sc_arpcom); 1060 if (error == ENETRESET) { 1061 /* 1062 * Multicast list has changed; set the hardware 1063 * filter accordingly. 1064 */ 1065 smc91cxx_reset(sc); 1066 error = 0; 1067 } 1068 break; 1069 1070 case SIOCGIFMEDIA: 1071 case SIOCSIFMEDIA: 1072 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 1073 break; 1074 1075 default: 1076 error = EINVAL; 1077 break; 1078 } 1079 1080 splx(s); 1081 return (error); 1082 } 1083 1084 /* 1085 * Reset the interface. 1086 */ 1087 void 1088 smc91cxx_reset(sc) 1089 struct smc91cxx_softc *sc; 1090 { 1091 int s; 1092 1093 s = splnet(); 1094 smc91cxx_stop(sc); 1095 smc91cxx_init(sc); 1096 splx(s); 1097 } 1098 1099 /* 1100 * Watchdog timer. 1101 */ 1102 void 1103 smc91cxx_watchdog(ifp) 1104 struct ifnet *ifp; 1105 { 1106 struct smc91cxx_softc *sc = ifp->if_softc; 1107 1108 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 1109 ++sc->sc_arpcom.ac_if.if_oerrors; 1110 1111 smc91cxx_reset(sc); 1112 } 1113 1114 /* 1115 * Stop output on the interface. 1116 */ 1117 void 1118 smc91cxx_stop(sc) 1119 struct smc91cxx_softc *sc; 1120 { 1121 bus_space_tag_t bst = sc->sc_bst; 1122 bus_space_handle_t bsh = sc->sc_bsh; 1123 1124 /* 1125 * Clear interrupt mask; disable all interrupts. 1126 */ 1127 SMC_SELECT_BANK(sc, 2); 1128 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0); 1129 1130 /* 1131 * Disable transmitter and receiver. 1132 */ 1133 SMC_SELECT_BANK(sc, 0); 1134 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0); 1135 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0); 1136 1137 /* 1138 * Cancel watchdog timer. 1139 */ 1140 sc->sc_arpcom.ac_if.if_timer = 0; 1141 } 1142 1143 /* 1144 * Enable power on the interface. 1145 */ 1146 int 1147 smc91cxx_enable(sc) 1148 struct smc91cxx_softc *sc; 1149 { 1150 1151 if (sc->sc_enabled == 0 && sc->sc_enable != NULL) { 1152 if ((*sc->sc_enable)(sc) != 0) { 1153 printf("%s: device enable failed\n", 1154 sc->sc_dev.dv_xname); 1155 return (EIO); 1156 } 1157 } 1158 1159 sc->sc_enabled = 1; 1160 return (0); 1161 } 1162 1163 /* 1164 * Disable power on the interface. 1165 */ 1166 void 1167 smc91cxx_disable(sc) 1168 struct smc91cxx_softc *sc; 1169 { 1170 1171 if (sc->sc_enabled != 0 && sc->sc_disable != NULL) { 1172 (*sc->sc_disable)(sc); 1173 sc->sc_enabled = 0; 1174 } 1175 } 1176