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