1/* $NetBSD: if_sn.c,v 1.32 2010/01/19 22:06:21 pooka Exp $ */ 2 3/* 4 * National Semiconductor DP8393X SONIC Driver 5 * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk) 6 * You may use, copy, and modify this program so long as you retain the 7 * copyright line. 8 * 9 * This driver has been substantially modified since Algorithmics donated 10 * it. 11 * 12 * Denton Gentry <denny1@home.com> 13 * and also 14 * Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp> 15 * did the work to get this running on the Macintosh. 16 */ 17 18#include <sys/cdefs.h> 19__KERNEL_RCSID(0, "$NetBSD: if_sn.c,v 1.32 2010/01/19 22:06:21 pooka Exp $"); 20 21#include "opt_inet.h" 22 23#include <sys/param.h> 24#include <sys/systm.h> 25#include <sys/mbuf.h> 26#include <sys/buf.h> 27#include <sys/protosw.h> 28#include <sys/socket.h> 29#include <sys/syslog.h> 30#include <sys/ioctl.h> 31#include <sys/errno.h> 32#include <sys/device.h> 33 34#include <net/if.h> 35#include <net/if_dl.h> 36#include <net/if_ether.h> 37 38#ifdef INET 39#include <netinet/in.h> 40#include <netinet/in_systm.h> 41#include <netinet/in_var.h> 42#include <netinet/ip.h> 43#include <netinet/if_inarp.h> 44#endif 45 46#include <uvm/uvm_extern.h> 47 48#include <net/bpf.h> 49#include <net/bpfdesc.h> 50 51#include <machine/cpu.h> 52#include <newsmips/apbus/apbusvar.h> 53#include <newsmips/apbus/if_snreg.h> 54#include <newsmips/apbus/if_snvar.h> 55 56/* #define SONIC_DEBUG */ 57 58#ifdef SONIC_DEBUG 59# define DPRINTF printf 60#else 61# define DPRINTF while (0) printf 62#endif 63 64static void snwatchdog(struct ifnet *); 65static int sninit(struct sn_softc *sc); 66static int snstop(struct sn_softc *sc); 67static int snioctl(struct ifnet *ifp, u_long cmd, void *data); 68static void snstart(struct ifnet *ifp); 69static void snreset(struct sn_softc *sc); 70 71static void caminitialise(struct sn_softc *); 72static void camentry(struct sn_softc *, int, const u_char *ea); 73static void camprogram(struct sn_softc *); 74static void initialise_tda(struct sn_softc *); 75static void initialise_rda(struct sn_softc *); 76static void initialise_rra(struct sn_softc *); 77#ifdef SNDEBUG 78static void camdump(struct sn_softc *sc); 79#endif 80 81static void sonictxint(struct sn_softc *); 82static void sonicrxint(struct sn_softc *); 83 84static inline u_int sonicput(struct sn_softc *sc, struct mbuf *m0, 85 int mtd_next); 86static inline int sonic_read(struct sn_softc *, void *, int); 87static inline struct mbuf *sonic_get(struct sn_softc *, void *, int); 88 89int sndebug = 0; 90 91/* 92 * SONIC buffers need to be aligned 16 or 32 bit aligned. 93 * These macros calculate and verify alignment. 94 */ 95#define SOALIGN(m, array) (m ? (roundup((int)array, 4)) : \ 96 (roundup((int)array, 2))) 97 98#define LOWER(x) ((unsigned)(x) & 0xffff) 99#define UPPER(x) ((unsigned)(x) >> 16) 100 101/* 102 * Interface exists: make available by filling in network interface 103 * record. System will initialize the interface when it is ready 104 * to accept packets. 105 */ 106int 107snsetup(struct sn_softc *sc, uint8_t *lladdr) 108{ 109 struct ifnet *ifp = &sc->sc_if; 110 uint8_t *p; 111 uint8_t *pp; 112 int i; 113 114 if (sc->space == NULL) { 115 aprint_error_dev(sc->sc_dev, 116 "memory allocation for descriptors failed\n"); 117 return 1; 118 } 119 120 /* 121 * Put the pup in reset mode (sninit() will fix it later), 122 * stop the timer, disable all interrupts and clear any interrupts. 123 */ 124 NIC_PUT(sc, SNR_CR, CR_STP); 125 wbflush(); 126 NIC_PUT(sc, SNR_CR, CR_RST); 127 wbflush(); 128 NIC_PUT(sc, SNR_IMR, 0); 129 wbflush(); 130 NIC_PUT(sc, SNR_ISR, ISR_ALL); 131 wbflush(); 132 133 /* 134 * because the SONIC is basically 16bit device it 'concatenates' 135 * a higher buffer address to a 16 bit offset--this will cause wrap 136 * around problems near the end of 64k !! 137 */ 138 p = sc->space; 139 pp = (uint8_t *)roundup((int)p, PAGE_SIZE); 140 p = pp; 141 142 for (i = 0; i < NRRA; i++) { 143 sc->p_rra[i] = (void *)p; 144 sc->v_rra[i] = SONIC_GETDMA(p); 145 p += RXRSRC_SIZE(sc); 146 } 147 sc->v_rea = SONIC_GETDMA(p); 148 149 p = (uint8_t *)SOALIGN(sc, p); 150 151 sc->p_cda = (void *)(p); 152 sc->v_cda = SONIC_GETDMA(p); 153 p += CDA_SIZE(sc); 154 155 p = (uint8_t *)SOALIGN(sc, p); 156 157 for (i = 0; i < NTDA; i++) { 158 struct mtd *mtdp = &sc->mtda[i]; 159 mtdp->mtd_txp = (void *)p; 160 mtdp->mtd_vtxp = SONIC_GETDMA(p); 161 p += TXP_SIZE(sc); 162 } 163 164 p = (uint8_t *)SOALIGN(sc, p); 165 166 if ((p - pp) > PAGE_SIZE) { 167 aprint_error_dev(sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +" 168 "TDA (%ld) > PAGE_SIZE (%d). Punt!\n", 169 (ulong)sc->p_cda - (ulong)sc->p_rra[0], 170 (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_cda, 171 (ulong)p - (ulong)sc->mtda[0].mtd_txp, 172 PAGE_SIZE); 173 return 1; 174 } 175 176 p = pp + PAGE_SIZE; 177 pp = p; 178 179 sc->sc_nrda = PAGE_SIZE / RXPKT_SIZE(sc); 180 sc->p_rda = (void *)p; 181 sc->v_rda = SONIC_GETDMA(p); 182 183 p = pp + PAGE_SIZE; 184 185 for (i = 0; i < NRBA; i++) { 186 sc->rbuf[i] = (void *)p; 187 p += PAGE_SIZE; 188 } 189 190 pp = p; 191 for (i = 0; i < NTDA; i++) { 192 struct mtd *mtdp = &sc->mtda[i]; 193 194 mtdp->mtd_buf = p; 195 mtdp->mtd_vbuf = SONIC_GETDMA(p); 196 p += TXBSIZE; 197 } 198 199#ifdef SNDEBUG 200 camdump(sc); 201#endif 202 aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n", 203 ether_sprintf(lladdr)); 204 205#ifdef SNDEBUG 206 aprint_debug_dev(sc->sc_dev, "buffers: rra=%p cda=%p rda=%p tda=%p\n", 207 sc->sc_dev.dv_xname, sc->p_rra[0], sc->p_cda, 208 sc->p_rda, sc->mtda[0].mtd_txp); 209#endif 210 211 strcpy(ifp->if_xname, device_xname(sc->sc_dev)); 212 ifp->if_softc = sc; 213 ifp->if_ioctl = snioctl; 214 ifp->if_start = snstart; 215 ifp->if_flags = 216 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 217 ifp->if_watchdog = snwatchdog; 218 if_attach(ifp); 219 ether_ifattach(ifp, lladdr); 220 221 return 0; 222} 223 224static int 225snioctl(struct ifnet *ifp, u_long cmd, void *data) 226{ 227 struct ifaddr *ifa; 228 struct sn_softc *sc = ifp->if_softc; 229 int s = splnet(), err = 0; 230 int temp; 231 232 switch (cmd) { 233 234 case SIOCINITIFADDR: 235 ifa = (struct ifaddr *)data; 236 ifp->if_flags |= IFF_UP; 237 (void)sninit(sc); 238 switch (ifa->ifa_addr->sa_family) { 239#ifdef INET 240 case AF_INET: 241 arp_ifinit(ifp, ifa); 242 break; 243#endif 244 default: 245 break; 246 } 247 break; 248 249 case SIOCSIFFLAGS: 250 if ((err = ifioctl_common(ifp, cmd, data)) != 0) 251 break; 252 if ((ifp->if_flags & IFF_UP) == 0 && 253 (ifp->if_flags & IFF_RUNNING) != 0) { 254 /* 255 * If interface is marked down and it is running, 256 * then stop it. 257 */ 258 snstop(sc); 259 ifp->if_flags &= ~IFF_RUNNING; 260 } else if ((ifp->if_flags & IFF_UP) != 0 && 261 (ifp->if_flags & IFF_RUNNING) == 0) { 262 /* 263 * If interface is marked up and it is stopped, 264 * then start it. 265 */ 266 (void)sninit(sc); 267 } else { 268 /* 269 * reset the interface to pick up any other changes 270 * in flags 271 */ 272 temp = ifp->if_flags & IFF_UP; 273 snreset(sc); 274 ifp->if_flags |= temp; 275 snstart(ifp); 276 } 277 break; 278 279 case SIOCADDMULTI: 280 case SIOCDELMULTI: 281 if ((err = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 282 /* 283 * Multicast list has changed; set the hardware 284 * filter accordingly. But remember UP flag! 285 */ 286 if (ifp->if_flags & IFF_RUNNING) { 287 temp = ifp->if_flags & IFF_UP; 288 snreset(sc); 289 ifp->if_flags |= temp; 290 } 291 err = 0; 292 } 293 break; 294 default: 295 err = ether_ioctl(ifp, cmd, data); 296 break; 297 } 298 splx(s); 299 return err; 300} 301 302/* 303 * Encapsulate a packet of type family for the local net. 304 */ 305static void 306snstart(struct ifnet *ifp) 307{ 308 struct sn_softc *sc = ifp->if_softc; 309 struct mbuf *m; 310 int mtd_next; 311 312 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 313 return; 314 315outloop: 316 /* Check for room in the xmit buffer. */ 317 if ((mtd_next = (sc->mtd_free + 1)) == NTDA) 318 mtd_next = 0; 319 320 if (mtd_next == sc->mtd_hw) { 321 ifp->if_flags |= IFF_OACTIVE; 322 return; 323 } 324 325 IF_DEQUEUE(&ifp->if_snd, m); 326 if (m == 0) 327 return; 328 329 /* We need the header for m_pkthdr.len. */ 330 if ((m->m_flags & M_PKTHDR) == 0) 331 panic("%s: snstart: no header mbuf", device_xname(sc->sc_dev)); 332 333 /* 334 * If bpf is listening on this interface, let it 335 * see the packet before we commit it to the wire. 336 */ 337 bpf_mtap(ifp, m); 338 339 /* 340 * If there is nothing in the o/p queue, and there is room in 341 * the Tx ring, then send the packet directly. Otherwise append 342 * it to the o/p queue. 343 */ 344 if ((sonicput(sc, m, mtd_next)) == 0) { 345 IF_PREPEND(&ifp->if_snd, m); 346 return; 347 } 348 349 sc->mtd_prev = sc->mtd_free; 350 sc->mtd_free = mtd_next; 351 352 ifp->if_opackets++; /* # of pkts */ 353 354 /* Jump back for possibly more punishment. */ 355 goto outloop; 356} 357 358/* 359 * reset and restart the SONIC. Called in case of fatal 360 * hardware/software errors. 361 */ 362static void 363snreset(struct sn_softc *sc) 364{ 365 366 snstop(sc); 367 sninit(sc); 368} 369 370static int 371sninit(struct sn_softc *sc) 372{ 373 u_long s_rcr; 374 int s; 375 376 if (sc->sc_if.if_flags & IFF_RUNNING) 377 /* already running */ 378 return 0; 379 380 s = splnet(); 381 382 NIC_PUT(sc, SNR_CR, CR_RST); /* DCR only accessible in reset mode! */ 383 384 /* config it */ 385 NIC_PUT(sc, SNR_DCR, (sc->snr_dcr | 386 (sc->bitmode ? DCR_DW32 : DCR_DW16))); 387 NIC_PUT(sc, SNR_DCR2, sc->snr_dcr2); 388 389 s_rcr = RCR_BRD | RCR_LBNONE; 390 if (sc->sc_if.if_flags & IFF_PROMISC) 391 s_rcr |= RCR_PRO; 392 if (sc->sc_if.if_flags & IFF_ALLMULTI) 393 s_rcr |= RCR_AMC; 394 NIC_PUT(sc, SNR_RCR, s_rcr); 395 396#if 0 397 NIC_PUT(sc, SNR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN)); 398#else 399 NIC_PUT(sc, SNR_IMR, IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN | 400 IMR_BREN | IMR_HBLEN | IMR_RDEEN | IMR_RBEEN | 401 IMR_RBAEEN | IMR_RFOEN); 402#endif 403 404 /* clear pending interrupts */ 405 NIC_PUT(sc, SNR_ISR, ISR_ALL); 406 407 /* clear tally counters */ 408 NIC_PUT(sc, SNR_CRCT, -1); 409 NIC_PUT(sc, SNR_FAET, -1); 410 NIC_PUT(sc, SNR_MPT, -1); 411 412 initialise_tda(sc); 413 initialise_rda(sc); 414 initialise_rra(sc); 415 416 sn_md_init(sc); /* MD initialization */ 417 418 /* enable the chip */ 419 NIC_PUT(sc, SNR_CR, 0); 420 wbflush(); 421 422 /* program the CAM */ 423 camprogram(sc); 424 425 /* get it to read resource descriptors */ 426 NIC_PUT(sc, SNR_CR, CR_RRRA); 427 wbflush(); 428 while ((NIC_GET(sc, SNR_CR)) & CR_RRRA) 429 continue; 430 431 /* enable rx */ 432 NIC_PUT(sc, SNR_CR, CR_RXEN); 433 wbflush(); 434 435 /* flag interface as "running" */ 436 sc->sc_if.if_flags |= IFF_RUNNING; 437 sc->sc_if.if_flags &= ~IFF_OACTIVE; 438 439 splx(s); 440 return 0; 441} 442 443/* 444 * close down an interface and free its buffers 445 * Called on final close of device, or if sninit() fails 446 * part way through. 447 */ 448static int 449snstop(struct sn_softc *sc) 450{ 451 struct mtd *mtd; 452 int s = splnet(); 453 454 /* stick chip in reset */ 455 NIC_PUT(sc, SNR_CR, CR_RST); 456 wbflush(); 457 458 /* free all receive buffers (currently static so nothing to do) */ 459 460 /* free all pending transmit mbufs */ 461 while (sc->mtd_hw != sc->mtd_free) { 462 mtd = &sc->mtda[sc->mtd_hw]; 463 if (mtd->mtd_mbuf) 464 m_freem(mtd->mtd_mbuf); 465 if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0; 466 } 467 468 sc->sc_if.if_timer = 0; 469 sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP); 470 471 splx(s); 472 return 0; 473} 474 475/* 476 * Called if any Tx packets remain unsent after 5 seconds, 477 * In all cases we just reset the chip, and any retransmission 478 * will be handled by higher level protocol timeouts. 479 */ 480static void 481snwatchdog(struct ifnet *ifp) 482{ 483 struct sn_softc *sc = ifp->if_softc; 484 struct mtd *mtd; 485 int temp; 486 487 if (sc->mtd_hw != sc->mtd_free) { 488 /* something still pending for transmit */ 489 mtd = &sc->mtda[sc->mtd_hw]; 490 if (SRO(sc->bitmode, mtd->mtd_txp, TXP_STATUS) == 0) 491 log(LOG_ERR, "%s: Tx - timeout\n", 492 device_xname(sc->sc_dev)); 493 else 494 log(LOG_ERR, "%s: Tx - lost interrupt\n", 495 device_xname(sc->sc_dev)); 496 temp = ifp->if_flags & IFF_UP; 497 snreset(sc); 498 ifp->if_flags |= temp; 499 } 500} 501 502/* 503 * stuff packet into sonic (at splnet) 504 */ 505static inline u_int 506sonicput(struct sn_softc *sc, struct mbuf *m0, int mtd_next) 507{ 508 struct mtd *mtdp; 509 struct mbuf *m; 510 u_char *buff; 511 void *txp; 512 u_int len = 0; 513 u_int totlen = 0; 514 515#ifdef whyonearthwouldyoudothis 516 if (NIC_GET(sc, SNR_CR) & CR_TXP) 517 return 0; 518#endif 519 520 /* grab the replacement mtd */ 521 mtdp = &sc->mtda[sc->mtd_free]; 522 523 buff = mtdp->mtd_buf; 524 525 /* this packet goes to mtdnext fill in the TDA */ 526 mtdp->mtd_mbuf = m0; 527 txp = mtdp->mtd_txp; 528 529 /* Write to the config word. Every (NTDA/2)+1 packets we set an intr */ 530 if (sc->mtd_pint == 0) { 531 sc->mtd_pint = NTDA/2; 532 SWO(sc->bitmode, txp, TXP_CONFIG, TCR_PINT); 533 } else { 534 sc->mtd_pint--; 535 SWO(sc->bitmode, txp, TXP_CONFIG, 0); 536 } 537 538 for (m = m0; m; m = m->m_next) { 539 u_char *data = mtod(m, u_char *); 540 len = m->m_len; 541 totlen += len; 542 memcpy(buff, data, len); 543 buff += len; 544 } 545 if (totlen >= TXBSIZE) { 546 panic("%s: sonicput: packet overflow", 547 device_xname(sc->sc_dev)); 548 } 549 550 SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO, 551 LOWER(mtdp->mtd_vbuf)); 552 SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI, 553 UPPER(mtdp->mtd_vbuf)); 554 555 if (totlen < ETHERMIN + ETHER_HDR_LEN) { 556 int pad = ETHERMIN + ETHER_HDR_LEN - totlen; 557 memset((char *)mtdp->mtd_buf + totlen, 0, pad); 558 totlen = ETHERMIN + ETHER_HDR_LEN; 559 } 560 561 SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE, 562 totlen); 563 SWO(sc->bitmode, txp, TXP_FRAGCNT, 1); 564 SWO(sc->bitmode, txp, TXP_PKTSIZE, totlen); 565 566 /* link onto the next mtd that will be used */ 567 SWO(sc->bitmode, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO, 568 LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL); 569 570 /* 571 * The previous txp.tlink currently contains a pointer to 572 * our txp | EOL. Want to clear the EOL, so write our 573 * pointer to the previous txp. 574 */ 575 SWO(sc->bitmode, sc->mtda[sc->mtd_prev].mtd_txp, sc->mtd_tlinko, 576 LOWER(mtdp->mtd_vtxp)); 577 578 /* make sure chip is running */ 579 wbflush(); 580 NIC_PUT(sc, SNR_CR, CR_TXP); 581 wbflush(); 582 sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */ 583 584 return totlen; 585} 586 587/* 588 * These are called from sonicioctl() when /etc/ifconfig is run to set 589 * the address or switch the i/f on. 590 */ 591/* 592 * CAM support 593 */ 594static void 595caminitialise(struct sn_softc *sc) 596{ 597 void *p_cda = sc->p_cda; 598 int i; 599 int camoffset; 600 601 for (i = 0; i < MAXCAM; i++) { 602 camoffset = i * CDA_CAMDESC; 603 SWO(bitmode, p_cda, (camoffset + CDA_CAMEP), i); 604 SWO(bitmode, p_cda, (camoffset + CDA_CAMAP2), 0); 605 SWO(bitmode, p_cda, (camoffset + CDA_CAMAP1), 0); 606 SWO(bitmode, p_cda, (camoffset + CDA_CAMAP0), 0); 607 } 608 SWO(bitmode, p_cda, CDA_ENABLE, 0); 609} 610 611static void 612camentry(struct sn_softc *sc, int entry, const u_char *ea) 613{ 614 void *p_cda = sc->p_cda; 615 int camoffset = entry * CDA_CAMDESC; 616 617 SWO(bitmode, p_cda, camoffset + CDA_CAMEP, entry); 618 SWO(bitmode, p_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]); 619 SWO(bitmode, p_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]); 620 SWO(bitmode, p_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]); 621 SWO(bitmode, p_cda, CDA_ENABLE, 622 (SRO(bitmode, p_cda, CDA_ENABLE) | (1 << entry))); 623} 624 625static void 626camprogram(struct sn_softc *sc) 627{ 628 struct ether_multistep step; 629 struct ether_multi *enm; 630 struct ifnet *ifp; 631 int timeout; 632 int mcount = 0; 633 634 caminitialise(sc); 635 636 ifp = &sc->sc_if; 637 638 /* Always load our own address first. */ 639 camentry(sc, mcount, CLLADDR(ifp->if_sadl)); 640 mcount++; 641 642 /* Assume we won't need allmulti bit. */ 643 ifp->if_flags &= ~IFF_ALLMULTI; 644 645 /* Loop through multicast addresses */ 646 ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm); 647 while (enm != NULL) { 648 if (mcount == MAXCAM) { 649 ifp->if_flags |= IFF_ALLMULTI; 650 break; 651 } 652 653 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 654 sizeof(enm->enm_addrlo)) != 0) { 655 /* 656 * SONIC's CAM is programmed with specific 657 * addresses. It has no way to specify a range. 658 * (Well, thats not exactly true. If the 659 * range is small one could program each addr 660 * within the range as a separate CAM entry) 661 */ 662 ifp->if_flags |= IFF_ALLMULTI; 663 break; 664 } 665 666 /* program the CAM with the specified entry */ 667 camentry(sc, mcount, enm->enm_addrlo); 668 mcount++; 669 670 ETHER_NEXT_MULTI(step, enm); 671 } 672 673 NIC_PUT(sc, SNR_CDP, LOWER(sc->v_cda)); 674 NIC_PUT(sc, SNR_CDC, MAXCAM); 675 NIC_PUT(sc, SNR_CR, CR_LCAM); 676 wbflush(); 677 678 timeout = 10000; 679 while ((NIC_GET(sc, SNR_CR) & CR_LCAM) && timeout--) 680 delay(10); 681 if (timeout == 0) { 682 /* XXX */ 683 panic("%s: CAM initialisation failed", 684 device_xname(sc->sc_dev)); 685 } 686 timeout = 10000; 687 while (((NIC_GET(sc, SNR_ISR) & ISR_LCD) == 0) && timeout--) 688 delay(10); 689 690 if (NIC_GET(sc, SNR_ISR) & ISR_LCD) 691 NIC_PUT(sc, SNR_ISR, ISR_LCD); 692 else 693 printf("%s: CAM initialisation without interrupt\n", 694 device_xname(sc->sc_dev)); 695} 696 697#ifdef SNDEBUG 698static void 699camdump(struct sn_softc *sc) 700{ 701 int i; 702 703 printf("CAM entries:\n"); 704 NIC_PUT(sc, SNR_CR, CR_RST); 705 wbflush(); 706 707 for (i = 0; i < 16; i++) { 708 ushort ap2, ap1, ap0; 709 NIC_PUT(sc, SNR_CEP, i); 710 wbflush(); 711 ap2 = NIC_GET(sc, SNR_CAP2); 712 ap1 = NIC_GET(sc, SNR_CAP1); 713 ap0 = NIC_GET(sc, SNR_CAP0); 714 printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0); 715 } 716 printf("CAM enable 0x%x\n", NIC_GET(sc, SNR_CEP)); 717 718 NIC_PUT(sc, SNR_CR, 0); 719 wbflush(); 720} 721#endif 722 723static void 724initialise_tda(struct sn_softc *sc) 725{ 726 struct mtd *mtd; 727 int i; 728 729 for (i = 0; i < NTDA; i++) { 730 mtd = &sc->mtda[i]; 731 mtd->mtd_mbuf = 0; 732 } 733 734 sc->mtd_hw = 0; 735 sc->mtd_prev = NTDA - 1; 736 sc->mtd_free = 0; 737 sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO; 738 sc->mtd_pint = NTDA/2; 739 740 NIC_PUT(sc, SNR_UTDA, UPPER(sc->mtda[0].mtd_vtxp)); 741 NIC_PUT(sc, SNR_CTDA, LOWER(sc->mtda[0].mtd_vtxp)); 742} 743 744static void 745initialise_rda(struct sn_softc *sc) 746{ 747 int i; 748 char *p_rda = 0; 749 uint32_t v_rda = 0; 750 751 /* link the RDA's together into a circular list */ 752 for (i = 0; i < (sc->sc_nrda - 1); i++) { 753 p_rda = (char *)sc->p_rda + (i * RXPKT_SIZE(sc)); 754 v_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc)); 755 SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(v_rda)); 756 SWO(bitmode, p_rda, RXPKT_INUSE, 1); 757 } 758 p_rda = (char *)sc->p_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc)); 759 SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL); 760 SWO(bitmode, p_rda, RXPKT_INUSE, 1); 761 762 /* mark end of receive descriptor list */ 763 sc->sc_rdamark = sc->sc_nrda - 1; 764 765 sc->sc_rxmark = 0; 766 767 NIC_PUT(sc, SNR_URDA, UPPER(sc->v_rda)); 768 NIC_PUT(sc, SNR_CRDA, LOWER(sc->v_rda)); 769 wbflush(); 770} 771 772static void 773initialise_rra(struct sn_softc *sc) 774{ 775 int i; 776 u_int v; 777 int bitmode = sc->bitmode; 778 779 if (bitmode) 780 NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 2); 781 else 782 NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 1); 783 784 NIC_PUT(sc, SNR_URRA, UPPER(sc->v_rra[0])); 785 NIC_PUT(sc, SNR_RSA, LOWER(sc->v_rra[0])); 786 /* rea must point just past the end of the rra space */ 787 NIC_PUT(sc, SNR_REA, LOWER(sc->v_rea)); 788 NIC_PUT(sc, SNR_RRP, LOWER(sc->v_rra[0])); 789 NIC_PUT(sc, SNR_RSC, 0); 790 791 /* fill up SOME of the rra with buffers */ 792 for (i = 0; i < NRBA; i++) { 793 v = SONIC_GETDMA(sc->rbuf[i]); 794 SWO(bitmode, sc->p_rra[i], RXRSRC_PTRHI, UPPER(v)); 795 SWO(bitmode, sc->p_rra[i], RXRSRC_PTRLO, LOWER(v)); 796 SWO(bitmode, sc->p_rra[i], RXRSRC_WCHI, UPPER(PAGE_SIZE/2)); 797 SWO(bitmode, sc->p_rra[i], RXRSRC_WCLO, LOWER(PAGE_SIZE/2)); 798 } 799 sc->sc_rramark = NRBA; 800 NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[sc->sc_rramark])); 801 wbflush(); 802} 803 804int 805snintr(void *arg) 806{ 807 struct sn_softc *sc = (struct sn_softc *)arg; 808 int handled = 0; 809 int isr; 810 811 while ((isr = (NIC_GET(sc, SNR_ISR) & ISR_ALL)) != 0) { 812 /* scrub the interrupts that we are going to service */ 813 NIC_PUT(sc, SNR_ISR, isr); 814 handled = 1; 815 wbflush(); 816 817 if (isr & (ISR_BR | ISR_LCD | ISR_TC)) 818 printf("%s: unexpected interrupt status 0x%x\n", 819 device_xname(sc->sc_dev), isr); 820 821 if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT)) 822 sonictxint(sc); 823 824 if (isr & ISR_PKTRX) 825 sonicrxint(sc); 826 827 if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) { 828 if (isr & ISR_HBL) 829 /* 830 * The repeater is not providing a heartbeat. 831 * In itself this isn't harmful, lots of the 832 * cheap repeater hubs don't supply a heartbeat. 833 * So ignore the lack of heartbeat. Its only 834 * if we can't detect a carrier that we have a 835 * problem. 836 */ 837 ; 838 if (isr & ISR_RDE) 839 printf("%s: receive descriptors exhausted\n", 840 device_xname(sc->sc_dev)); 841 if (isr & ISR_RBE) 842 printf("%s: receive buffers exhausted\n", 843 device_xname(sc->sc_dev)); 844 if (isr & ISR_RBAE) 845 printf("%s: receive buffer area exhausted\n", 846 device_xname(sc->sc_dev)); 847 if (isr & ISR_RFO) 848 printf("%s: receive FIFO overrun\n", 849 device_xname(sc->sc_dev)); 850 } 851 if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) { 852#ifdef notdef 853 if (isr & ISR_CRC) 854 sc->sc_crctally++; 855 if (isr & ISR_FAE) 856 sc->sc_faetally++; 857 if (isr & ISR_MP) 858 sc->sc_mptally++; 859#endif 860 } 861 snstart(&sc->sc_if); 862 } 863 return handled; 864} 865 866/* 867 * Transmit interrupt routine 868 */ 869static void 870sonictxint(struct sn_softc *sc) 871{ 872 struct mtd *mtd; 873 void *txp; 874 unsigned short txp_status; 875 int mtd_hw; 876 struct ifnet *ifp = &sc->sc_if; 877 878 mtd_hw = sc->mtd_hw; 879 880 if (mtd_hw == sc->mtd_free) 881 return; 882 883 while (mtd_hw != sc->mtd_free) { 884 mtd = &sc->mtda[mtd_hw]; 885 886 txp = mtd->mtd_txp; 887 888 if (SRO(sc->bitmode, txp, TXP_STATUS) == 0) { 889 break; /* it hasn't really gone yet */ 890 } 891 892#ifdef SNDEBUG 893 { 894 struct ether_header *eh; 895 896 eh = (struct ether_header *) mtd->mtd_buf; 897 printf("%s: xmit status=0x%x len=%d type=0x%x from %s", 898 device_xname(sc->sc_dev), 899 SRO(sc->bitmode, txp, TXP_STATUS), 900 SRO(sc->bitmode, txp, TXP_PKTSIZE), 901 htons(eh->ether_type), 902 ether_sprintf(eh->ether_shost)); 903 printf(" (to %s)\n", ether_sprintf(eh->ether_dhost)); 904 } 905#endif /* SNDEBUG */ 906 907 ifp->if_flags &= ~IFF_OACTIVE; 908 909 if (mtd->mtd_mbuf != 0) { 910 m_freem(mtd->mtd_mbuf); 911 mtd->mtd_mbuf = 0; 912 } 913 if (++mtd_hw == NTDA) mtd_hw = 0; 914 915 txp_status = SRO(sc->bitmode, txp, TXP_STATUS); 916 917 ifp->if_collisions += (txp_status & TCR_EXC) ? 16 : 918 ((txp_status & TCR_NC) >> 12); 919 920 if ((txp_status & TCR_PTX) == 0) { 921 ifp->if_oerrors++; 922 printf("%s: Tx packet status=0x%x\n", 923 device_xname(sc->sc_dev), txp_status); 924 925 /* XXX - DG This looks bogus */ 926 if (mtd_hw != sc->mtd_free) { 927 printf("resubmitting remaining packets\n"); 928 mtd = &sc->mtda[mtd_hw]; 929 NIC_PUT(sc, SNR_CTDA, LOWER(mtd->mtd_vtxp)); 930 NIC_PUT(sc, SNR_CR, CR_TXP); 931 wbflush(); 932 break; 933 } 934 } 935 } 936 937 sc->mtd_hw = mtd_hw; 938 return; 939} 940 941/* 942 * Receive interrupt routine 943 */ 944static void 945sonicrxint(struct sn_softc *sc) 946{ 947 void * rda; 948 int orra; 949 int len; 950 int rramark; 951 int rdamark; 952 uint16_t rxpkt_ptr; 953 954 rda = (char *)sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); 955 956 while (SRO(bitmode, rda, RXPKT_INUSE) == 0) { 957 u_int status = SRO(bitmode, rda, RXPKT_STATUS); 958 959 orra = RBASEQ(SRO(bitmode, rda, RXPKT_SEQNO)) & RRAMASK; 960 rxpkt_ptr = SRO(bitmode, rda, RXPKT_PTRLO); 961 len = SRO(bitmode, rda, RXPKT_BYTEC) - FCSSIZE; 962 if (status & RCR_PRX) { 963 void *pkt = 964 (char *)sc->rbuf[orra & RBAMASK] + 965 (rxpkt_ptr & PGOFSET); 966 if (sonic_read(sc, pkt, len)) 967 sc->sc_if.if_ipackets++; 968 else 969 sc->sc_if.if_ierrors++; 970 } else 971 sc->sc_if.if_ierrors++; 972 973 /* 974 * give receive buffer area back to chip. 975 * 976 * If this was the last packet in the RRA, give the RRA to 977 * the chip again. 978 * If sonic read didnt copy it out then we would have to 979 * wait !! 980 * (dont bother add it back in again straight away) 981 * 982 * Really, we're doing p_rra[rramark] = p_rra[orra] but 983 * we have to use the macros because SONIC might be in 984 * 16 or 32 bit mode. 985 */ 986 if (status & RCR_LPKT) { 987 void *tmp1, *tmp2; 988 989 rramark = sc->sc_rramark; 990 tmp1 = sc->p_rra[rramark]; 991 tmp2 = sc->p_rra[orra]; 992 SWO(bitmode, tmp1, RXRSRC_PTRLO, 993 SRO(bitmode, tmp2, RXRSRC_PTRLO)); 994 SWO(bitmode, tmp1, RXRSRC_PTRHI, 995 SRO(bitmode, tmp2, RXRSRC_PTRHI)); 996 SWO(bitmode, tmp1, RXRSRC_WCLO, 997 SRO(bitmode, tmp2, RXRSRC_WCLO)); 998 SWO(bitmode, tmp1, RXRSRC_WCHI, 999 SRO(bitmode, tmp2, RXRSRC_WCHI)); 1000 1001 /* zap old rra for fun */ 1002 SWO(bitmode, tmp2, RXRSRC_WCHI, 0); 1003 SWO(bitmode, tmp2, RXRSRC_WCLO, 0); 1004 1005 sc->sc_rramark = (++rramark) & RRAMASK; 1006 NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[rramark])); 1007 wbflush(); 1008 } 1009 1010 /* 1011 * give receive descriptor back to chip simple 1012 * list is circular 1013 */ 1014 rdamark = sc->sc_rdamark; 1015 SWO(bitmode, rda, RXPKT_INUSE, 1); 1016 SWO(bitmode, rda, RXPKT_RLINK, 1017 SRO(bitmode, rda, RXPKT_RLINK) | EOL); 1018 SWO(bitmode, ((char *)sc->p_rda + (rdamark * RXPKT_SIZE(sc))), 1019 RXPKT_RLINK, 1020 SRO(bitmode, ((char *)sc->p_rda + 1021 (rdamark * RXPKT_SIZE(sc))), 1022 RXPKT_RLINK) & ~EOL); 1023 sc->sc_rdamark = sc->sc_rxmark; 1024 1025 if (++sc->sc_rxmark >= sc->sc_nrda) 1026 sc->sc_rxmark = 0; 1027 rda = (char *)sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); 1028 } 1029} 1030 1031/* 1032 * sonic_read -- pull packet off interface and forward to 1033 * appropriate protocol handler 1034 */ 1035static inline int 1036sonic_read(struct sn_softc *sc, void *pkt, int len) 1037{ 1038 struct ifnet *ifp = &sc->sc_if; 1039 struct mbuf *m; 1040 1041#ifdef SNDEBUG 1042 { 1043 printf("%s: rcvd %p len=%d type=0x%x from %s", 1044 devoce_xname(sc->sc_dev), et, len, htons(et->ether_type), 1045 ether_sprintf(et->ether_shost)); 1046 printf(" (to %s)\n", ether_sprintf(et->ether_dhost)); 1047 } 1048#endif /* SNDEBUG */ 1049 1050 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN) || 1051 len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) { 1052 printf("%s: invalid packet length %d bytes\n", 1053 device_xname(sc->sc_dev), len); 1054 return 0; 1055 } 1056 1057 m = sonic_get(sc, pkt, len); 1058 if (m == NULL) 1059 return 0; 1060 /* Pass the packet to any BPF listeners. */ 1061 bpf_mtap(ifp, m); 1062 (*ifp->if_input)(ifp, m); 1063 return 1; 1064} 1065 1066/* 1067 * munge the received packet into an mbuf chain 1068 */ 1069static inline struct mbuf * 1070sonic_get(struct sn_softc *sc, void *pkt, int datalen) 1071{ 1072 struct mbuf *m, *top, **mp; 1073 int len; 1074 1075 MGETHDR(m, M_DONTWAIT, MT_DATA); 1076 if (m == 0) 1077 return 0; 1078 m->m_pkthdr.rcvif = &sc->sc_if; 1079 m->m_pkthdr.len = datalen; 1080 len = MHLEN; 1081 top = 0; 1082 mp = ⊤ 1083 1084 while (datalen > 0) { 1085 if (top) { 1086 MGET(m, M_DONTWAIT, MT_DATA); 1087 if (m == 0) { 1088 m_freem(top); 1089 return 0; 1090 } 1091 len = MLEN; 1092 } 1093 if (datalen >= MINCLSIZE) { 1094 MCLGET(m, M_DONTWAIT); 1095 if ((m->m_flags & M_EXT) == 0) { 1096 if (top) m_freem(top); 1097 return 0; 1098 } 1099 len = MCLBYTES; 1100 } 1101 1102 if (mp == &top) { 1103 char *newdata = (char *) 1104 ALIGN((char *)m->m_data + 1105 sizeof(struct ether_header)) - 1106 sizeof(struct ether_header); 1107 len -= newdata - m->m_data; 1108 m->m_data = newdata; 1109 } 1110 1111 m->m_len = len = min(datalen, len); 1112 1113 memcpy(mtod(m, void *), pkt, (unsigned) len); 1114 pkt = (char *)pkt + len; 1115 datalen -= len; 1116 *mp = m; 1117 mp = &m->m_next; 1118 } 1119 1120 return top; 1121} 1122