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