1/* $FreeBSD: head/sys/dev/snc/dp83932.c 147316 2005-06-12 15:25:19Z scottl $ */
| 1/* $FreeBSD: head/sys/dev/snc/dp83932.c 148654 2005-08-03 00:18:35Z rwatson $ */
|
2/* $NecBSD: dp83932.c,v 1.5 1999/07/29 05:08:44 kmatsuda Exp $ */ 3/* $NetBSD: if_snc.c,v 1.18 1998/04/25 21:27:40 scottr Exp $ */ 4 5/*- 6 * Copyright (c) 1997, 1998, 1999 7 * Kouichi Matsuda. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Kouichi Matsuda for 20 * NetBSD/pc98. 21 * 4. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36/* 37 * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki. 38 */ 39 40/* 41 * Modified for NetBSD/pc98 1.2G from NetBSD/mac68k 1.2G by Kouichi Matsuda. 42 * Make adapted for NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and 43 * PC-9801N-J02, J02R, which uses National Semiconductor DP83934AVQB as 44 * Ethernet Controller and National Semiconductor NS46C46 as 45 * (64 * 16 bits) Microwire Serial EEPROM. 46 */ 47 48/*- 49 * National Semiconductor DP8393X SONIC Driver 50 * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk) 51 * You may use, copy, and modify this program so long as you retain the 52 * copyright line. 53 * 54 * This driver has been substantially modified since Algorithmics donated 55 * it. 56 * 57 * Denton Gentry <denny1@home.com> 58 * and also 59 * Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp> 60 * did the work to get this running on the Macintosh. 61 */ 62 63#include "opt_inet.h" 64 65#include <sys/param.h> 66#include <sys/systm.h> 67#include <sys/sockio.h> 68#include <sys/mbuf.h> 69#include <sys/protosw.h> 70#include <sys/socket.h> 71#include <sys/syslog.h> 72#include <sys/errno.h> 73#if NRND > 0 74#include <sys/rnd.h> 75#endif 76 77#include <net/ethernet.h> 78#include <net/if.h> 79#include <net/if_arp.h> 80#include <net/if_dl.h> 81#include <net/if_media.h> 82#include <net/if_types.h> 83 84#include <net/bpf.h> 85 86#include <sys/bus.h> 87#include <machine/bus.h> 88#include <dev/snc/dp83932reg.h> 89#include <dev/snc/dp83932var.h> 90 91hide void sncwatchdog(struct ifnet *); 92hide void sncinit(void *); 93hide int sncstop(struct snc_softc *sc); 94hide int sncioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 95hide void sncstart(struct ifnet *ifp); 96hide void sncreset(struct snc_softc *sc); 97 98hide void caminitialise(struct snc_softc *); 99hide void camentry(struct snc_softc *, int, u_char *ea); 100hide void camprogram(struct snc_softc *); 101hide void initialise_tda(struct snc_softc *); 102hide void initialise_rda(struct snc_softc *); 103hide void initialise_rra(struct snc_softc *); 104#ifdef SNCDEBUG 105hide void camdump(struct snc_softc *sc); 106#endif 107 108hide void sonictxint(struct snc_softc *); 109hide void sonicrxint(struct snc_softc *); 110 111hide u_int sonicput(struct snc_softc *sc, struct mbuf *m0, int mtd_next); 112hide int sonic_read(struct snc_softc *, u_int32_t, int); 113hide struct mbuf *sonic_get(struct snc_softc *, u_int32_t, int); 114 115int snc_enable(struct snc_softc *); 116void snc_disable(struct snc_softc *); 117 118int snc_mediachange(struct ifnet *); 119void snc_mediastatus(struct ifnet *, struct ifmediareq *); 120 121#ifdef NetBSD 122#if NetBSD <= 199714 123struct cfdriver snc_cd = { 124 NULL, "snc", DV_IFNET 125}; 126#endif 127#endif 128 129#undef assert 130#undef _assert 131 132#ifdef NDEBUG 133#define assert(e) ((void)0) 134#define _assert(e) ((void)0) 135#else 136#define _assert(e) assert(e) 137#ifdef __STDC__ 138#define assert(e) ((e) ? (void)0 : __assert("snc ", __FILE__, __LINE__, #e)) 139#else /* PCC */ 140#define assert(e) ((e) ? (void)0 : __assert("snc "__FILE__, __LINE__, "e")) 141#endif 142#endif 143 144#ifdef SNCDEBUG 145#define SNC_SHOWTXHDR 0x01 /* show tx ether_header */ 146#define SNC_SHOWRXHDR 0x02 /* show rx ether_header */ 147#define SNC_SHOWCAMENT 0x04 /* show CAM entry */ 148#endif /* SNCDEBUG */ 149int sncdebug = 0; 150 151 152void 153sncconfig(sc, media, nmedia, defmedia, myea) 154 struct snc_softc *sc; 155 int *media, nmedia, defmedia; 156 u_int8_t *myea; 157{ 158 struct ifnet *ifp; 159 int i; 160 161#ifdef SNCDEBUG 162 if ((sncdebug & SNC_SHOWCAMENT) != 0) { 163 camdump(sc); 164 } 165#endif 166 167 ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 168 if (ifp == NULL) 169 panic("%s: can not if_alloc()\n", 170 device_get_nameunit(sc->sc_dev)); 171 172#ifdef SNCDEBUG 173 device_printf(sc->sc_dev, 174 "buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x\n", 175 sc->v_rra[0], sc->v_cda, 176 sc->v_rda, sc->mtda[0].mtd_vtxp); 177#endif 178 179 ifp->if_softc = sc; 180 if_initname(ifp, device_get_name(sc->sc_dev), 181 device_get_unit(sc->sc_dev)); 182 ifp->if_ioctl = sncioctl; 183 ifp->if_start = sncstart; 184 ifp->if_flags = 185 IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_NEEDSGIANT; 186 ifp->if_watchdog = sncwatchdog; 187 ifp->if_init = sncinit; 188 ifp->if_mtu = ETHERMTU; 189 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 190 191 /* Initialize media goo. */ 192 ifmedia_init(&sc->sc_media, 0, snc_mediachange, 193 snc_mediastatus); 194 if (media != NULL) { 195 for (i = 0; i < nmedia; i++) 196 ifmedia_add(&sc->sc_media, media[i], 0, NULL); 197 ifmedia_set(&sc->sc_media, defmedia); 198 } else { 199 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); 200 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); 201 } 202 203 ether_ifattach(ifp, myea); 204 205#if NRND > 0 206 rnd_attach_source(&sc->rnd_source, device_get_nameunit(sc->sc_dev), 207 RND_TYPE_NET, 0); 208#endif 209} 210 211void 212sncshutdown(arg) 213 void *arg; 214{ 215 216 sncstop((struct snc_softc *)arg); 217} 218 219/* 220 * Media change callback. 221 */ 222int 223snc_mediachange(ifp) 224 struct ifnet *ifp; 225{ 226 struct snc_softc *sc = ifp->if_softc; 227 228 if (sc->sc_mediachange) 229 return ((*sc->sc_mediachange)(sc)); 230 return (EINVAL); 231} 232 233/* 234 * Media status callback. 235 */ 236void 237snc_mediastatus(ifp, ifmr) 238 struct ifnet *ifp; 239 struct ifmediareq *ifmr; 240{ 241 struct snc_softc *sc = ifp->if_softc; 242 243 if (sc->sc_enabled == 0) { 244 ifmr->ifm_active = IFM_ETHER | IFM_NONE; 245 ifmr->ifm_status = 0; 246 return; 247 } 248 249 if (sc->sc_mediastatus) 250 (*sc->sc_mediastatus)(sc, ifmr); 251} 252 253 254hide int 255sncioctl(ifp, cmd, data) 256 struct ifnet *ifp; 257 u_long cmd; 258 caddr_t data; 259{ 260 struct ifreq *ifr; 261 struct snc_softc *sc = ifp->if_softc; 262 int s = splhardnet(), err = 0; 263 int temp; 264 265 switch (cmd) { 266 267 case SIOCSIFFLAGS: 268 if ((ifp->if_flags & IFF_UP) == 0 && 269 (ifp->if_flags & IFF_RUNNING) != 0) { 270 /* 271 * If interface is marked down and it is running, 272 * then stop it. 273 */ 274 sncstop(sc); 275 ifp->if_flags &= ~IFF_RUNNING; 276 snc_disable(sc); 277 } else if ((ifp->if_flags & IFF_UP) != 0 && 278 (ifp->if_flags & IFF_RUNNING) == 0) { 279 /* 280 * If interface is marked up and it is stopped, 281 * then start it. 282 */ 283 if ((err = snc_enable(sc)) != 0) 284 break; 285 sncinit(sc); 286 } else if (sc->sc_enabled) { 287 /* 288 * reset the interface to pick up any other changes 289 * in flags 290 */ 291 temp = ifp->if_flags & IFF_UP; 292 sncreset(sc); 293 ifp->if_flags |= temp; 294 sncstart(ifp); 295 } 296 break; 297 298 case SIOCADDMULTI: 299 case SIOCDELMULTI: 300 if (sc->sc_enabled == 0) { 301 err = EIO; 302 break; 303 } 304 temp = ifp->if_flags & IFF_UP; 305 sncreset(sc); 306 ifp->if_flags |= temp; 307 err = 0; 308 break; 309 case SIOCGIFMEDIA: 310 case SIOCSIFMEDIA: 311 ifr = (struct ifreq *) data; 312 err = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 313 break; 314 default: 315 err = ether_ioctl(ifp, cmd, data); 316 break; 317 } 318 splx(s); 319 return (err); 320} 321 322/* 323 * Encapsulate a packet of type family for the local net. 324 */ 325hide void 326sncstart(ifp) 327 struct ifnet *ifp; 328{ 329 struct snc_softc *sc = ifp->if_softc; 330 struct mbuf *m; 331 int mtd_next; 332 333 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 334 return; 335 336outloop: 337 /* Check for room in the xmit buffer. */ 338 if ((mtd_next = (sc->mtd_free + 1)) == NTDA) 339 mtd_next = 0; 340 341 if (mtd_next == sc->mtd_hw) { 342 ifp->if_flags |= IFF_OACTIVE; 343 return; 344 } 345 346 IF_DEQUEUE(&ifp->if_snd, m); 347 if (m == 0) 348 return; 349 350 /* We need the header for m_pkthdr.len. */ 351 M_ASSERTPKTHDR(m); 352 353 /* 354 * If there is nothing in the o/p queue, and there is room in 355 * the Tx ring, then send the packet directly. Otherwise append 356 * it to the o/p queue. 357 */ 358 if ((sonicput(sc, m, mtd_next)) == 0) { 359 IF_PREPEND(&ifp->if_snd, m); 360 return; 361 } 362 363 /* 364 * If bpf is listening on this interface, let it see the packet 365 * before we commit it to the wire, but only if we are really 366 * committed to send it. 367 * 368 * XXX: Locking must protect m against premature m_freem() in 369 * sonictxint(). 370 */ 371 BPF_MTAP(ifp, m); 372 373 sc->mtd_prev = sc->mtd_free; 374 sc->mtd_free = mtd_next; 375 376 ifp->if_opackets++; /* # of pkts */ 377 378 /* Jump back for possibly more punishment. */ 379 goto outloop; 380} 381 382/* 383 * reset and restart the SONIC. Called in case of fatal 384 * hardware/software errors. 385 */ 386hide void 387sncreset(sc) 388 struct snc_softc *sc; 389{ 390 sncstop(sc); 391 sncinit(sc); 392} 393 394hide void 395sncinit(xsc) 396 void *xsc; 397{ 398 struct snc_softc *sc = xsc; 399 u_long s_rcr; 400 int s; 401 402 if (sc->sc_ifp->if_flags & IFF_RUNNING) 403 /* already running */ 404 return; 405 406 s = splhardnet(); 407 408 NIC_PUT(sc, SNCR_CR, CR_RST); /* DCR only accessable in reset mode! */ 409 410 /* config it */ 411 NIC_PUT(sc, SNCR_DCR, (sc->sncr_dcr | 412 (sc->bitmode ? DCR_DW32 : DCR_DW16))); 413 NIC_PUT(sc, SNCR_DCR2, sc->sncr_dcr2); 414 415 s_rcr = RCR_BRD | RCR_LBNONE; 416 if (sc->sc_ifp->if_flags & IFF_PROMISC) 417 s_rcr |= RCR_PRO; 418 if (sc->sc_ifp->if_flags & IFF_ALLMULTI) 419 s_rcr |= RCR_AMC; 420 NIC_PUT(sc, SNCR_RCR, s_rcr); 421 422 NIC_PUT(sc, SNCR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN)); 423 424 /* clear pending interrupts */ 425 NIC_PUT(sc, SNCR_ISR, ISR_ALL); 426 427 /* clear tally counters */ 428 NIC_PUT(sc, SNCR_CRCT, -1); 429 NIC_PUT(sc, SNCR_FAET, -1); 430 NIC_PUT(sc, SNCR_MPT, -1); 431 432 initialise_tda(sc); 433 initialise_rda(sc); 434 initialise_rra(sc); 435 436 /* enable the chip */ 437 NIC_PUT(sc, SNCR_CR, 0); 438 wbflush(); 439 440 /* program the CAM */ 441 camprogram(sc); 442 443 /* get it to read resource descriptors */ 444 NIC_PUT(sc, SNCR_CR, CR_RRRA); 445 wbflush(); 446 while ((NIC_GET(sc, SNCR_CR)) & CR_RRRA) 447 continue; 448 449 /* enable rx */ 450 NIC_PUT(sc, SNCR_CR, CR_RXEN); 451 wbflush(); 452 453 /* flag interface as "running" */ 454 sc->sc_ifp->if_flags |= IFF_RUNNING; 455 sc->sc_ifp->if_flags &= ~IFF_OACTIVE; 456 457 splx(s); 458 return; 459} 460 461/* 462 * close down an interface and free its buffers 463 * Called on final close of device, or if sncinit() fails 464 * part way through. 465 */ 466hide int 467sncstop(sc) 468 struct snc_softc *sc; 469{ 470 struct mtd *mtd; 471 int s = splhardnet(); 472 473 /* stick chip in reset */ 474 NIC_PUT(sc, SNCR_CR, CR_RST); 475 wbflush(); 476 477 /* free all receive buffers (currently static so nothing to do) */ 478 479 /* free all pending transmit mbufs */ 480 while (sc->mtd_hw != sc->mtd_free) { 481 mtd = &sc->mtda[sc->mtd_hw]; 482 if (mtd->mtd_mbuf) 483 m_freem(mtd->mtd_mbuf); 484 if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0; 485 } 486 487 sc->sc_ifp->if_timer = 0; 488 sc->sc_ifp->if_flags &= ~(IFF_RUNNING | IFF_UP); 489 490 splx(s); 491 return (0); 492} 493 494/* 495 * Called if any Tx packets remain unsent after 5 seconds, 496 * In all cases we just reset the chip, and any retransmission 497 * will be handled by higher level protocol timeouts. 498 */ 499hide void 500sncwatchdog(ifp) 501 struct ifnet *ifp; 502{ 503 struct snc_softc *sc = ifp->if_softc; 504 struct mtd *mtd; 505 int temp; 506 507 if (sc->mtd_hw != sc->mtd_free) { 508 /* something still pending for transmit */ 509 mtd = &sc->mtda[sc->mtd_hw]; 510 if (SRO(sc, mtd->mtd_vtxp, TXP_STATUS) == 0) 511 log(LOG_ERR, "%s: Tx - timeout\n", 512 device_get_nameunit(sc->sc_dev)); 513 else 514 log(LOG_ERR, "%s: Tx - lost interrupt\n", 515 device_get_nameunit(sc->sc_dev)); 516 temp = ifp->if_flags & IFF_UP; 517 sncreset(sc); 518 ifp->if_flags |= temp; 519 } 520} 521 522/* 523 * stuff packet into sonic (at splnet) 524 */ 525hide u_int 526sonicput(sc, m0, mtd_next) 527 struct snc_softc *sc; 528 struct mbuf *m0; 529 int mtd_next; 530{ 531 struct mtd *mtdp; 532 struct mbuf *m; 533 u_int32_t buff; 534 u_int32_t txp; 535 u_int len = 0; 536 u_int totlen = 0; 537 538#ifdef whyonearthwouldyoudothis 539 if (NIC_GET(sc, SNCR_CR) & CR_TXP) 540 return (0); 541#endif 542 543 /* grab the replacement mtd */ 544 mtdp = &sc->mtda[sc->mtd_free]; 545 546 buff = mtdp->mtd_vbuf; 547 548 /* this packet goes to mtdnext fill in the TDA */ 549 mtdp->mtd_mbuf = m0; 550 txp = mtdp->mtd_vtxp; 551 552 /* Write to the config word. Every (NTDA/2)+1 packets we set an intr */ 553 if (sc->mtd_pint == 0) { 554 sc->mtd_pint = NTDA/2; 555 SWO(sc, txp, TXP_CONFIG, TCR_PINT); 556 } else { 557 sc->mtd_pint--; 558 SWO(sc, txp, TXP_CONFIG, 0); 559 } 560 561 for (m = m0; m; m = m->m_next) { 562 len = m->m_len; 563 totlen += len; 564 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), buff, len); 565 buff += len; 566 } 567 if (totlen >= TXBSIZE) { 568 panic("%s: sonicput: packet overflow", 569 device_get_nameunit(sc->sc_dev)); 570 } 571 572 SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO, 573 LOWER(mtdp->mtd_vbuf)); 574 SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI, 575 UPPER(mtdp->mtd_vbuf)); 576 577 if (totlen < ETHERMIN + sizeof(struct ether_header)) { 578 int pad = ETHERMIN + sizeof(struct ether_header) - totlen; 579 (*sc->sc_zerobuf)(sc, mtdp->mtd_vbuf + totlen, pad); 580 totlen = ETHERMIN + sizeof(struct ether_header); 581 } 582 583 SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE, 584 totlen); 585 SWO(sc, txp, TXP_FRAGCNT, 1); 586 SWO(sc, txp, TXP_PKTSIZE, totlen); 587 588 /* link onto the next mtd that will be used */ 589 SWO(sc, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO, 590 LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL); 591 592 /* 593 * The previous txp.tlink currently contains a pointer to 594 * our txp | EOL. Want to clear the EOL, so write our 595 * pointer to the previous txp. 596 */ 597 SWO(sc, sc->mtda[sc->mtd_prev].mtd_vtxp, sc->mtd_tlinko, 598 LOWER(mtdp->mtd_vtxp)); 599 600 /* make sure chip is running */ 601 wbflush(); 602 NIC_PUT(sc, SNCR_CR, CR_TXP); 603 wbflush(); 604 sc->sc_ifp->if_timer = 5; /* 5 seconds to watch for failing to transmit */ 605 606 return (totlen); 607} 608 609/* 610 * These are called from sonicioctl() when /etc/ifconfig is run to set 611 * the address or switch the i/f on. 612 */ 613/* 614 * CAM support 615 */ 616hide void 617caminitialise(sc) 618 struct snc_softc *sc; 619{ 620 u_int32_t v_cda = sc->v_cda; 621 int i; 622 int camoffset; 623 624 for (i = 0; i < MAXCAM; i++) { 625 camoffset = i * CDA_CAMDESC; 626 SWO(sc, v_cda, (camoffset + CDA_CAMEP), i); 627 SWO(sc, v_cda, (camoffset + CDA_CAMAP2), 0); 628 SWO(sc, v_cda, (camoffset + CDA_CAMAP1), 0); 629 SWO(sc, v_cda, (camoffset + CDA_CAMAP0), 0); 630 } 631 SWO(sc, v_cda, CDA_ENABLE, 0); 632 633#ifdef SNCDEBUG 634 if ((sncdebug & SNC_SHOWCAMENT) != 0) { 635 camdump(sc); 636 } 637#endif 638} 639 640hide void 641camentry(sc, entry, ea) 642 int entry; 643 u_char *ea; 644 struct snc_softc *sc; 645{ 646 u_int32_t v_cda = sc->v_cda; 647 int camoffset = entry * CDA_CAMDESC; 648 649 SWO(sc, v_cda, camoffset + CDA_CAMEP, entry); 650 SWO(sc, v_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]); 651 SWO(sc, v_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]); 652 SWO(sc, v_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]); 653 SWO(sc, v_cda, CDA_ENABLE, 654 (SRO(sc, v_cda, CDA_ENABLE) | (1 << entry))); 655} 656 657hide void 658camprogram(sc) 659 struct snc_softc *sc; 660{ 661 struct ifmultiaddr *ifma; 662 struct ifnet *ifp; 663 int timeout; 664 int mcount = 0; 665 666 caminitialise(sc); 667 668 ifp = sc->sc_ifp; 669 670 /* Always load our own address first. */ 671 camentry (sc, mcount, IFP2ENADDR(sc->sc_ifp)); 672 mcount++; 673 674 /* Assume we won't need allmulti bit. */ 675 ifp->if_flags &= ~IFF_ALLMULTI; 676 677 /* Loop through multicast addresses */
| 2/* $NecBSD: dp83932.c,v 1.5 1999/07/29 05:08:44 kmatsuda Exp $ */ 3/* $NetBSD: if_snc.c,v 1.18 1998/04/25 21:27:40 scottr Exp $ */ 4 5/*- 6 * Copyright (c) 1997, 1998, 1999 7 * Kouichi Matsuda. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Kouichi Matsuda for 20 * NetBSD/pc98. 21 * 4. The name of the author may not be used to endorse or promote products 22 * derived from this software without specific prior written permission 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36/* 37 * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki. 38 */ 39 40/* 41 * Modified for NetBSD/pc98 1.2G from NetBSD/mac68k 1.2G by Kouichi Matsuda. 42 * Make adapted for NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and 43 * PC-9801N-J02, J02R, which uses National Semiconductor DP83934AVQB as 44 * Ethernet Controller and National Semiconductor NS46C46 as 45 * (64 * 16 bits) Microwire Serial EEPROM. 46 */ 47 48/*- 49 * National Semiconductor DP8393X SONIC Driver 50 * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk) 51 * You may use, copy, and modify this program so long as you retain the 52 * copyright line. 53 * 54 * This driver has been substantially modified since Algorithmics donated 55 * it. 56 * 57 * Denton Gentry <denny1@home.com> 58 * and also 59 * Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp> 60 * did the work to get this running on the Macintosh. 61 */ 62 63#include "opt_inet.h" 64 65#include <sys/param.h> 66#include <sys/systm.h> 67#include <sys/sockio.h> 68#include <sys/mbuf.h> 69#include <sys/protosw.h> 70#include <sys/socket.h> 71#include <sys/syslog.h> 72#include <sys/errno.h> 73#if NRND > 0 74#include <sys/rnd.h> 75#endif 76 77#include <net/ethernet.h> 78#include <net/if.h> 79#include <net/if_arp.h> 80#include <net/if_dl.h> 81#include <net/if_media.h> 82#include <net/if_types.h> 83 84#include <net/bpf.h> 85 86#include <sys/bus.h> 87#include <machine/bus.h> 88#include <dev/snc/dp83932reg.h> 89#include <dev/snc/dp83932var.h> 90 91hide void sncwatchdog(struct ifnet *); 92hide void sncinit(void *); 93hide int sncstop(struct snc_softc *sc); 94hide int sncioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 95hide void sncstart(struct ifnet *ifp); 96hide void sncreset(struct snc_softc *sc); 97 98hide void caminitialise(struct snc_softc *); 99hide void camentry(struct snc_softc *, int, u_char *ea); 100hide void camprogram(struct snc_softc *); 101hide void initialise_tda(struct snc_softc *); 102hide void initialise_rda(struct snc_softc *); 103hide void initialise_rra(struct snc_softc *); 104#ifdef SNCDEBUG 105hide void camdump(struct snc_softc *sc); 106#endif 107 108hide void sonictxint(struct snc_softc *); 109hide void sonicrxint(struct snc_softc *); 110 111hide u_int sonicput(struct snc_softc *sc, struct mbuf *m0, int mtd_next); 112hide int sonic_read(struct snc_softc *, u_int32_t, int); 113hide struct mbuf *sonic_get(struct snc_softc *, u_int32_t, int); 114 115int snc_enable(struct snc_softc *); 116void snc_disable(struct snc_softc *); 117 118int snc_mediachange(struct ifnet *); 119void snc_mediastatus(struct ifnet *, struct ifmediareq *); 120 121#ifdef NetBSD 122#if NetBSD <= 199714 123struct cfdriver snc_cd = { 124 NULL, "snc", DV_IFNET 125}; 126#endif 127#endif 128 129#undef assert 130#undef _assert 131 132#ifdef NDEBUG 133#define assert(e) ((void)0) 134#define _assert(e) ((void)0) 135#else 136#define _assert(e) assert(e) 137#ifdef __STDC__ 138#define assert(e) ((e) ? (void)0 : __assert("snc ", __FILE__, __LINE__, #e)) 139#else /* PCC */ 140#define assert(e) ((e) ? (void)0 : __assert("snc "__FILE__, __LINE__, "e")) 141#endif 142#endif 143 144#ifdef SNCDEBUG 145#define SNC_SHOWTXHDR 0x01 /* show tx ether_header */ 146#define SNC_SHOWRXHDR 0x02 /* show rx ether_header */ 147#define SNC_SHOWCAMENT 0x04 /* show CAM entry */ 148#endif /* SNCDEBUG */ 149int sncdebug = 0; 150 151 152void 153sncconfig(sc, media, nmedia, defmedia, myea) 154 struct snc_softc *sc; 155 int *media, nmedia, defmedia; 156 u_int8_t *myea; 157{ 158 struct ifnet *ifp; 159 int i; 160 161#ifdef SNCDEBUG 162 if ((sncdebug & SNC_SHOWCAMENT) != 0) { 163 camdump(sc); 164 } 165#endif 166 167 ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 168 if (ifp == NULL) 169 panic("%s: can not if_alloc()\n", 170 device_get_nameunit(sc->sc_dev)); 171 172#ifdef SNCDEBUG 173 device_printf(sc->sc_dev, 174 "buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x\n", 175 sc->v_rra[0], sc->v_cda, 176 sc->v_rda, sc->mtda[0].mtd_vtxp); 177#endif 178 179 ifp->if_softc = sc; 180 if_initname(ifp, device_get_name(sc->sc_dev), 181 device_get_unit(sc->sc_dev)); 182 ifp->if_ioctl = sncioctl; 183 ifp->if_start = sncstart; 184 ifp->if_flags = 185 IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_NEEDSGIANT; 186 ifp->if_watchdog = sncwatchdog; 187 ifp->if_init = sncinit; 188 ifp->if_mtu = ETHERMTU; 189 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 190 191 /* Initialize media goo. */ 192 ifmedia_init(&sc->sc_media, 0, snc_mediachange, 193 snc_mediastatus); 194 if (media != NULL) { 195 for (i = 0; i < nmedia; i++) 196 ifmedia_add(&sc->sc_media, media[i], 0, NULL); 197 ifmedia_set(&sc->sc_media, defmedia); 198 } else { 199 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); 200 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); 201 } 202 203 ether_ifattach(ifp, myea); 204 205#if NRND > 0 206 rnd_attach_source(&sc->rnd_source, device_get_nameunit(sc->sc_dev), 207 RND_TYPE_NET, 0); 208#endif 209} 210 211void 212sncshutdown(arg) 213 void *arg; 214{ 215 216 sncstop((struct snc_softc *)arg); 217} 218 219/* 220 * Media change callback. 221 */ 222int 223snc_mediachange(ifp) 224 struct ifnet *ifp; 225{ 226 struct snc_softc *sc = ifp->if_softc; 227 228 if (sc->sc_mediachange) 229 return ((*sc->sc_mediachange)(sc)); 230 return (EINVAL); 231} 232 233/* 234 * Media status callback. 235 */ 236void 237snc_mediastatus(ifp, ifmr) 238 struct ifnet *ifp; 239 struct ifmediareq *ifmr; 240{ 241 struct snc_softc *sc = ifp->if_softc; 242 243 if (sc->sc_enabled == 0) { 244 ifmr->ifm_active = IFM_ETHER | IFM_NONE; 245 ifmr->ifm_status = 0; 246 return; 247 } 248 249 if (sc->sc_mediastatus) 250 (*sc->sc_mediastatus)(sc, ifmr); 251} 252 253 254hide int 255sncioctl(ifp, cmd, data) 256 struct ifnet *ifp; 257 u_long cmd; 258 caddr_t data; 259{ 260 struct ifreq *ifr; 261 struct snc_softc *sc = ifp->if_softc; 262 int s = splhardnet(), err = 0; 263 int temp; 264 265 switch (cmd) { 266 267 case SIOCSIFFLAGS: 268 if ((ifp->if_flags & IFF_UP) == 0 && 269 (ifp->if_flags & IFF_RUNNING) != 0) { 270 /* 271 * If interface is marked down and it is running, 272 * then stop it. 273 */ 274 sncstop(sc); 275 ifp->if_flags &= ~IFF_RUNNING; 276 snc_disable(sc); 277 } else if ((ifp->if_flags & IFF_UP) != 0 && 278 (ifp->if_flags & IFF_RUNNING) == 0) { 279 /* 280 * If interface is marked up and it is stopped, 281 * then start it. 282 */ 283 if ((err = snc_enable(sc)) != 0) 284 break; 285 sncinit(sc); 286 } else if (sc->sc_enabled) { 287 /* 288 * reset the interface to pick up any other changes 289 * in flags 290 */ 291 temp = ifp->if_flags & IFF_UP; 292 sncreset(sc); 293 ifp->if_flags |= temp; 294 sncstart(ifp); 295 } 296 break; 297 298 case SIOCADDMULTI: 299 case SIOCDELMULTI: 300 if (sc->sc_enabled == 0) { 301 err = EIO; 302 break; 303 } 304 temp = ifp->if_flags & IFF_UP; 305 sncreset(sc); 306 ifp->if_flags |= temp; 307 err = 0; 308 break; 309 case SIOCGIFMEDIA: 310 case SIOCSIFMEDIA: 311 ifr = (struct ifreq *) data; 312 err = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 313 break; 314 default: 315 err = ether_ioctl(ifp, cmd, data); 316 break; 317 } 318 splx(s); 319 return (err); 320} 321 322/* 323 * Encapsulate a packet of type family for the local net. 324 */ 325hide void 326sncstart(ifp) 327 struct ifnet *ifp; 328{ 329 struct snc_softc *sc = ifp->if_softc; 330 struct mbuf *m; 331 int mtd_next; 332 333 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 334 return; 335 336outloop: 337 /* Check for room in the xmit buffer. */ 338 if ((mtd_next = (sc->mtd_free + 1)) == NTDA) 339 mtd_next = 0; 340 341 if (mtd_next == sc->mtd_hw) { 342 ifp->if_flags |= IFF_OACTIVE; 343 return; 344 } 345 346 IF_DEQUEUE(&ifp->if_snd, m); 347 if (m == 0) 348 return; 349 350 /* We need the header for m_pkthdr.len. */ 351 M_ASSERTPKTHDR(m); 352 353 /* 354 * If there is nothing in the o/p queue, and there is room in 355 * the Tx ring, then send the packet directly. Otherwise append 356 * it to the o/p queue. 357 */ 358 if ((sonicput(sc, m, mtd_next)) == 0) { 359 IF_PREPEND(&ifp->if_snd, m); 360 return; 361 } 362 363 /* 364 * If bpf is listening on this interface, let it see the packet 365 * before we commit it to the wire, but only if we are really 366 * committed to send it. 367 * 368 * XXX: Locking must protect m against premature m_freem() in 369 * sonictxint(). 370 */ 371 BPF_MTAP(ifp, m); 372 373 sc->mtd_prev = sc->mtd_free; 374 sc->mtd_free = mtd_next; 375 376 ifp->if_opackets++; /* # of pkts */ 377 378 /* Jump back for possibly more punishment. */ 379 goto outloop; 380} 381 382/* 383 * reset and restart the SONIC. Called in case of fatal 384 * hardware/software errors. 385 */ 386hide void 387sncreset(sc) 388 struct snc_softc *sc; 389{ 390 sncstop(sc); 391 sncinit(sc); 392} 393 394hide void 395sncinit(xsc) 396 void *xsc; 397{ 398 struct snc_softc *sc = xsc; 399 u_long s_rcr; 400 int s; 401 402 if (sc->sc_ifp->if_flags & IFF_RUNNING) 403 /* already running */ 404 return; 405 406 s = splhardnet(); 407 408 NIC_PUT(sc, SNCR_CR, CR_RST); /* DCR only accessable in reset mode! */ 409 410 /* config it */ 411 NIC_PUT(sc, SNCR_DCR, (sc->sncr_dcr | 412 (sc->bitmode ? DCR_DW32 : DCR_DW16))); 413 NIC_PUT(sc, SNCR_DCR2, sc->sncr_dcr2); 414 415 s_rcr = RCR_BRD | RCR_LBNONE; 416 if (sc->sc_ifp->if_flags & IFF_PROMISC) 417 s_rcr |= RCR_PRO; 418 if (sc->sc_ifp->if_flags & IFF_ALLMULTI) 419 s_rcr |= RCR_AMC; 420 NIC_PUT(sc, SNCR_RCR, s_rcr); 421 422 NIC_PUT(sc, SNCR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN)); 423 424 /* clear pending interrupts */ 425 NIC_PUT(sc, SNCR_ISR, ISR_ALL); 426 427 /* clear tally counters */ 428 NIC_PUT(sc, SNCR_CRCT, -1); 429 NIC_PUT(sc, SNCR_FAET, -1); 430 NIC_PUT(sc, SNCR_MPT, -1); 431 432 initialise_tda(sc); 433 initialise_rda(sc); 434 initialise_rra(sc); 435 436 /* enable the chip */ 437 NIC_PUT(sc, SNCR_CR, 0); 438 wbflush(); 439 440 /* program the CAM */ 441 camprogram(sc); 442 443 /* get it to read resource descriptors */ 444 NIC_PUT(sc, SNCR_CR, CR_RRRA); 445 wbflush(); 446 while ((NIC_GET(sc, SNCR_CR)) & CR_RRRA) 447 continue; 448 449 /* enable rx */ 450 NIC_PUT(sc, SNCR_CR, CR_RXEN); 451 wbflush(); 452 453 /* flag interface as "running" */ 454 sc->sc_ifp->if_flags |= IFF_RUNNING; 455 sc->sc_ifp->if_flags &= ~IFF_OACTIVE; 456 457 splx(s); 458 return; 459} 460 461/* 462 * close down an interface and free its buffers 463 * Called on final close of device, or if sncinit() fails 464 * part way through. 465 */ 466hide int 467sncstop(sc) 468 struct snc_softc *sc; 469{ 470 struct mtd *mtd; 471 int s = splhardnet(); 472 473 /* stick chip in reset */ 474 NIC_PUT(sc, SNCR_CR, CR_RST); 475 wbflush(); 476 477 /* free all receive buffers (currently static so nothing to do) */ 478 479 /* free all pending transmit mbufs */ 480 while (sc->mtd_hw != sc->mtd_free) { 481 mtd = &sc->mtda[sc->mtd_hw]; 482 if (mtd->mtd_mbuf) 483 m_freem(mtd->mtd_mbuf); 484 if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0; 485 } 486 487 sc->sc_ifp->if_timer = 0; 488 sc->sc_ifp->if_flags &= ~(IFF_RUNNING | IFF_UP); 489 490 splx(s); 491 return (0); 492} 493 494/* 495 * Called if any Tx packets remain unsent after 5 seconds, 496 * In all cases we just reset the chip, and any retransmission 497 * will be handled by higher level protocol timeouts. 498 */ 499hide void 500sncwatchdog(ifp) 501 struct ifnet *ifp; 502{ 503 struct snc_softc *sc = ifp->if_softc; 504 struct mtd *mtd; 505 int temp; 506 507 if (sc->mtd_hw != sc->mtd_free) { 508 /* something still pending for transmit */ 509 mtd = &sc->mtda[sc->mtd_hw]; 510 if (SRO(sc, mtd->mtd_vtxp, TXP_STATUS) == 0) 511 log(LOG_ERR, "%s: Tx - timeout\n", 512 device_get_nameunit(sc->sc_dev)); 513 else 514 log(LOG_ERR, "%s: Tx - lost interrupt\n", 515 device_get_nameunit(sc->sc_dev)); 516 temp = ifp->if_flags & IFF_UP; 517 sncreset(sc); 518 ifp->if_flags |= temp; 519 } 520} 521 522/* 523 * stuff packet into sonic (at splnet) 524 */ 525hide u_int 526sonicput(sc, m0, mtd_next) 527 struct snc_softc *sc; 528 struct mbuf *m0; 529 int mtd_next; 530{ 531 struct mtd *mtdp; 532 struct mbuf *m; 533 u_int32_t buff; 534 u_int32_t txp; 535 u_int len = 0; 536 u_int totlen = 0; 537 538#ifdef whyonearthwouldyoudothis 539 if (NIC_GET(sc, SNCR_CR) & CR_TXP) 540 return (0); 541#endif 542 543 /* grab the replacement mtd */ 544 mtdp = &sc->mtda[sc->mtd_free]; 545 546 buff = mtdp->mtd_vbuf; 547 548 /* this packet goes to mtdnext fill in the TDA */ 549 mtdp->mtd_mbuf = m0; 550 txp = mtdp->mtd_vtxp; 551 552 /* Write to the config word. Every (NTDA/2)+1 packets we set an intr */ 553 if (sc->mtd_pint == 0) { 554 sc->mtd_pint = NTDA/2; 555 SWO(sc, txp, TXP_CONFIG, TCR_PINT); 556 } else { 557 sc->mtd_pint--; 558 SWO(sc, txp, TXP_CONFIG, 0); 559 } 560 561 for (m = m0; m; m = m->m_next) { 562 len = m->m_len; 563 totlen += len; 564 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), buff, len); 565 buff += len; 566 } 567 if (totlen >= TXBSIZE) { 568 panic("%s: sonicput: packet overflow", 569 device_get_nameunit(sc->sc_dev)); 570 } 571 572 SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO, 573 LOWER(mtdp->mtd_vbuf)); 574 SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI, 575 UPPER(mtdp->mtd_vbuf)); 576 577 if (totlen < ETHERMIN + sizeof(struct ether_header)) { 578 int pad = ETHERMIN + sizeof(struct ether_header) - totlen; 579 (*sc->sc_zerobuf)(sc, mtdp->mtd_vbuf + totlen, pad); 580 totlen = ETHERMIN + sizeof(struct ether_header); 581 } 582 583 SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE, 584 totlen); 585 SWO(sc, txp, TXP_FRAGCNT, 1); 586 SWO(sc, txp, TXP_PKTSIZE, totlen); 587 588 /* link onto the next mtd that will be used */ 589 SWO(sc, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO, 590 LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL); 591 592 /* 593 * The previous txp.tlink currently contains a pointer to 594 * our txp | EOL. Want to clear the EOL, so write our 595 * pointer to the previous txp. 596 */ 597 SWO(sc, sc->mtda[sc->mtd_prev].mtd_vtxp, sc->mtd_tlinko, 598 LOWER(mtdp->mtd_vtxp)); 599 600 /* make sure chip is running */ 601 wbflush(); 602 NIC_PUT(sc, SNCR_CR, CR_TXP); 603 wbflush(); 604 sc->sc_ifp->if_timer = 5; /* 5 seconds to watch for failing to transmit */ 605 606 return (totlen); 607} 608 609/* 610 * These are called from sonicioctl() when /etc/ifconfig is run to set 611 * the address or switch the i/f on. 612 */ 613/* 614 * CAM support 615 */ 616hide void 617caminitialise(sc) 618 struct snc_softc *sc; 619{ 620 u_int32_t v_cda = sc->v_cda; 621 int i; 622 int camoffset; 623 624 for (i = 0; i < MAXCAM; i++) { 625 camoffset = i * CDA_CAMDESC; 626 SWO(sc, v_cda, (camoffset + CDA_CAMEP), i); 627 SWO(sc, v_cda, (camoffset + CDA_CAMAP2), 0); 628 SWO(sc, v_cda, (camoffset + CDA_CAMAP1), 0); 629 SWO(sc, v_cda, (camoffset + CDA_CAMAP0), 0); 630 } 631 SWO(sc, v_cda, CDA_ENABLE, 0); 632 633#ifdef SNCDEBUG 634 if ((sncdebug & SNC_SHOWCAMENT) != 0) { 635 camdump(sc); 636 } 637#endif 638} 639 640hide void 641camentry(sc, entry, ea) 642 int entry; 643 u_char *ea; 644 struct snc_softc *sc; 645{ 646 u_int32_t v_cda = sc->v_cda; 647 int camoffset = entry * CDA_CAMDESC; 648 649 SWO(sc, v_cda, camoffset + CDA_CAMEP, entry); 650 SWO(sc, v_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]); 651 SWO(sc, v_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]); 652 SWO(sc, v_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]); 653 SWO(sc, v_cda, CDA_ENABLE, 654 (SRO(sc, v_cda, CDA_ENABLE) | (1 << entry))); 655} 656 657hide void 658camprogram(sc) 659 struct snc_softc *sc; 660{ 661 struct ifmultiaddr *ifma; 662 struct ifnet *ifp; 663 int timeout; 664 int mcount = 0; 665 666 caminitialise(sc); 667 668 ifp = sc->sc_ifp; 669 670 /* Always load our own address first. */ 671 camentry (sc, mcount, IFP2ENADDR(sc->sc_ifp)); 672 mcount++; 673 674 /* Assume we won't need allmulti bit. */ 675 ifp->if_flags &= ~IFF_ALLMULTI; 676 677 /* Loop through multicast addresses */
|
| 678 IF_ADDR_LOCK(ifp);
|
678 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 679 if (ifma->ifma_addr->sa_family != AF_LINK) 680 continue; 681 if (mcount == MAXCAM) { 682 ifp->if_flags |= IFF_ALLMULTI; 683 break; 684 } 685 686 /* program the CAM with the specified entry */ 687 camentry(sc, mcount, 688 LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); 689 mcount++; 690 }
| 679 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 680 if (ifma->ifma_addr->sa_family != AF_LINK) 681 continue; 682 if (mcount == MAXCAM) { 683 ifp->if_flags |= IFF_ALLMULTI; 684 break; 685 } 686 687 /* program the CAM with the specified entry */ 688 camentry(sc, mcount, 689 LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); 690 mcount++; 691 }
|
| 692 IF_ADDR_UNLOCK(ifp);
|
691 692 NIC_PUT(sc, SNCR_CDP, LOWER(sc->v_cda)); 693 NIC_PUT(sc, SNCR_CDC, MAXCAM); 694 NIC_PUT(sc, SNCR_CR, CR_LCAM); 695 wbflush(); 696 697 timeout = 10000; 698 while ((NIC_GET(sc, SNCR_CR) & CR_LCAM) && timeout--) 699 continue; 700 if (timeout == 0) { 701 /* XXX */ 702 panic("%s: CAM initialisation failed\n", 703 device_get_nameunit(sc->sc_dev)); 704 } 705 timeout = 10000; 706 while (((NIC_GET(sc, SNCR_ISR) & ISR_LCD) == 0) && timeout--) 707 continue; 708 709 if (NIC_GET(sc, SNCR_ISR) & ISR_LCD) 710 NIC_PUT(sc, SNCR_ISR, ISR_LCD); 711 else 712 device_printf(sc->sc_dev, 713 "CAM initialisation without interrupt\n"); 714} 715 716#ifdef SNCDEBUG 717hide void 718camdump(sc) 719 struct snc_softc *sc; 720{ 721 int i; 722 723 printf("CAM entries:\n"); 724 NIC_PUT(sc, SNCR_CR, CR_RST); 725 wbflush(); 726 727 for (i = 0; i < 16; i++) { 728 u_short ap2, ap1, ap0; 729 NIC_PUT(sc, SNCR_CEP, i); 730 wbflush(); 731 ap2 = NIC_GET(sc, SNCR_CAP2); 732 ap1 = NIC_GET(sc, SNCR_CAP1); 733 ap0 = NIC_GET(sc, SNCR_CAP0); 734 printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0); 735 } 736 printf("CAM enable 0x%x\n", NIC_GET(sc, SNCR_CEP)); 737 738 NIC_PUT(sc, SNCR_CR, 0); 739 wbflush(); 740} 741#endif 742 743hide void 744initialise_tda(sc) 745 struct snc_softc *sc; 746{ 747 struct mtd *mtd; 748 int i; 749 750 for (i = 0; i < NTDA; i++) { 751 mtd = &sc->mtda[i]; 752 mtd->mtd_mbuf = 0; 753 } 754 755 sc->mtd_hw = 0; 756 sc->mtd_prev = NTDA - 1; 757 sc->mtd_free = 0; 758 sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO; 759 sc->mtd_pint = NTDA/2; 760 761 NIC_PUT(sc, SNCR_UTDA, UPPER(sc->mtda[0].mtd_vtxp)); 762 NIC_PUT(sc, SNCR_CTDA, LOWER(sc->mtda[0].mtd_vtxp)); 763} 764 765hide void 766initialise_rda(sc) 767 struct snc_softc *sc; 768{ 769 int i; 770 u_int32_t vv_rda = 0; 771 u_int32_t v_rda = 0; 772 773 /* link the RDA's together into a circular list */ 774 for (i = 0; i < (sc->sc_nrda - 1); i++) { 775 v_rda = sc->v_rda + (i * RXPKT_SIZE(sc)); 776 vv_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc)); 777 SWO(sc, v_rda, RXPKT_RLINK, LOWER(vv_rda)); 778 SWO(sc, v_rda, RXPKT_INUSE, 1); 779 } 780 v_rda = sc->v_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc)); 781 SWO(sc, v_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL); 782 SWO(sc, v_rda, RXPKT_INUSE, 1); 783 784 /* mark end of receive descriptor list */ 785 sc->sc_rdamark = sc->sc_nrda - 1; 786 787 sc->sc_rxmark = 0; 788 789 NIC_PUT(sc, SNCR_URDA, UPPER(sc->v_rda)); 790 NIC_PUT(sc, SNCR_CRDA, LOWER(sc->v_rda)); 791 wbflush(); 792} 793 794hide void 795initialise_rra(sc) 796 struct snc_softc *sc; 797{ 798 int i; 799 u_int v; 800 int bitmode = sc->bitmode; 801 802 if (bitmode) 803 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 2); 804 else 805 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 1); 806 807 NIC_PUT(sc, SNCR_URRA, UPPER(sc->v_rra[0])); 808 NIC_PUT(sc, SNCR_RSA, LOWER(sc->v_rra[0])); 809 /* rea must point just past the end of the rra space */ 810 NIC_PUT(sc, SNCR_REA, LOWER(sc->v_rea)); 811 NIC_PUT(sc, SNCR_RRP, LOWER(sc->v_rra[0])); 812 NIC_PUT(sc, SNCR_RSC, 0); 813 814 /* fill up SOME of the rra with buffers */ 815 for (i = 0; i < NRBA; i++) { 816 v = SONIC_GETDMA(sc->rbuf[i]); 817 SWO(sc, sc->v_rra[i], RXRSRC_PTRHI, UPPER(v)); 818 SWO(sc, sc->v_rra[i], RXRSRC_PTRLO, LOWER(v)); 819 SWO(sc, sc->v_rra[i], RXRSRC_WCHI, UPPER(NBPG/2)); 820 SWO(sc, sc->v_rra[i], RXRSRC_WCLO, LOWER(NBPG/2)); 821 } 822 sc->sc_rramark = NRBA; 823 NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[sc->sc_rramark])); 824 wbflush(); 825} 826 827void 828sncintr(arg) 829 void *arg; 830{ 831 struct snc_softc *sc = (struct snc_softc *)arg; 832 int isr; 833 834 if (sc->sc_enabled == 0) 835 return; 836 837 while ((isr = (NIC_GET(sc, SNCR_ISR) & ISR_ALL)) != 0) { 838 /* scrub the interrupts that we are going to service */ 839 NIC_PUT(sc, SNCR_ISR, isr); 840 wbflush(); 841 842 if (isr & (ISR_BR | ISR_LCD | ISR_TC)) 843 device_printf(sc->sc_dev, 844 "unexpected interrupt status 0x%x\n", 845 isr); 846 847 if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT)) 848 sonictxint(sc); 849 850 if (isr & ISR_PKTRX) 851 sonicrxint(sc); 852 853 if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) { 854 if (isr & ISR_HBL) 855 /* 856 * The repeater is not providing a heartbeat. 857 * In itself this isn't harmful, lots of the 858 * cheap repeater hubs don't supply a heartbeat. 859 * So ignore the lack of heartbeat. Its only 860 * if we can't detect a carrier that we have a 861 * problem. 862 */ 863 ; 864 if (isr & ISR_RDE) 865 device_printf(sc->sc_dev, 866 "receive descriptors exhausted\n"); 867 if (isr & ISR_RBE) 868 device_printf(sc->sc_dev, 869 "receive buffers exhausted\n"); 870 if (isr & ISR_RBAE) 871 device_printf(sc->sc_dev, 872 "receive buffer area exhausted\n"); 873 if (isr & ISR_RFO) 874 device_printf(sc->sc_dev, 875 "receive FIFO overrun\n"); 876 } 877 if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) { 878#ifdef notdef 879 if (isr & ISR_CRC) 880 sc->sc_crctally++; 881 if (isr & ISR_FAE) 882 sc->sc_faetally++; 883 if (isr & ISR_MP) 884 sc->sc_mptally++; 885#endif 886 } 887 sncstart(sc->sc_ifp); 888 889#if NRND > 0 890 if (isr) 891 rnd_add_uint32(&sc->rnd_source, isr); 892#endif 893 } 894 return; 895} 896 897/* 898 * Transmit interrupt routine 899 */ 900hide void 901sonictxint(sc) 902 struct snc_softc *sc; 903{ 904 struct mtd *mtd; 905 u_int32_t txp; 906 unsigned short txp_status; 907 int mtd_hw; 908 struct ifnet *ifp = sc->sc_ifp; 909 910 mtd_hw = sc->mtd_hw; 911 912 if (mtd_hw == sc->mtd_free) 913 return; 914 915 while (mtd_hw != sc->mtd_free) { 916 mtd = &sc->mtda[mtd_hw]; 917 918 txp = mtd->mtd_vtxp; 919 920 if (SRO(sc, txp, TXP_STATUS) == 0) { 921 break; /* it hasn't really gone yet */ 922 } 923 924#ifdef SNCDEBUG 925 if ((sncdebug & SNC_SHOWTXHDR) != 0) 926 { 927 struct ether_header eh; 928 929 (*sc->sc_copyfrombuf)(sc, &eh, mtd->mtd_vbuf, sizeof(eh)); 930 device_printf(sc->sc_dev, 931 "xmit status=0x%x len=%d type=0x%x from %6D", 932 SRO(sc, txp, TXP_STATUS), 933 SRO(sc, txp, TXP_PKTSIZE), 934 htons(eh.ether_type), 935 eh.ether_shost, ":"); 936 printf(" (to %6D)\n", eh.ether_dhost, ":"); 937 } 938#endif /* SNCDEBUG */ 939 940 ifp->if_flags &= ~IFF_OACTIVE; 941 942 if (mtd->mtd_mbuf != 0) { 943 m_freem(mtd->mtd_mbuf); 944 mtd->mtd_mbuf = 0; 945 } 946 if (++mtd_hw == NTDA) mtd_hw = 0; 947 948 txp_status = SRO(sc, txp, TXP_STATUS); 949 950 ifp->if_collisions += (txp_status & TCR_EXC) ? 16 : 951 ((txp_status & TCR_NC) >> 12); 952 953 if ((txp_status & TCR_PTX) == 0) { 954 ifp->if_oerrors++; 955 device_printf(sc->sc_dev, "Tx packet status=0x%x\n", 956 txp_status); 957 958 /* XXX - DG This looks bogus */ 959 if (mtd_hw != sc->mtd_free) { 960 printf("resubmitting remaining packets\n"); 961 mtd = &sc->mtda[mtd_hw]; 962 NIC_PUT(sc, SNCR_CTDA, LOWER(mtd->mtd_vtxp)); 963 NIC_PUT(sc, SNCR_CR, CR_TXP); 964 wbflush(); 965 break; 966 } 967 } 968 } 969 970 sc->mtd_hw = mtd_hw; 971 return; 972} 973 974/* 975 * Receive interrupt routine 976 */ 977hide void 978sonicrxint(sc) 979 struct snc_softc *sc; 980{ 981 u_int32_t rda; 982 int orra; 983 int len; 984 int rramark; 985 int rdamark; 986 u_int16_t rxpkt_ptr; 987 988 rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); 989 990 while (SRO(sc, rda, RXPKT_INUSE) == 0) { 991 u_int status = SRO(sc, rda, RXPKT_STATUS); 992 993 orra = RBASEQ(SRO(sc, rda, RXPKT_SEQNO)) & RRAMASK; 994 rxpkt_ptr = SRO(sc, rda, RXPKT_PTRLO); 995 /* 996 * Do not trunc ether_header length. 997 * Our sonic_read() and sonic_get() require it. 998 */ 999 len = SRO(sc, rda, RXPKT_BYTEC) - FCSSIZE; 1000 if (status & RCR_PRX) { 1001 /* XXX: Does PGOFSET require? */ 1002 u_int32_t pkt = 1003 sc->rbuf[orra & RBAMASK] + (rxpkt_ptr & PGOFSET); 1004 if (sonic_read(sc, pkt, len)) 1005 sc->sc_ifp->if_ipackets++; 1006 else 1007 sc->sc_ifp->if_ierrors++; 1008 } else 1009 sc->sc_ifp->if_ierrors++; 1010 1011 /* 1012 * give receive buffer area back to chip. 1013 * 1014 * If this was the last packet in the RRA, give the RRA to 1015 * the chip again. 1016 * If sonic read didnt copy it out then we would have to 1017 * wait !! 1018 * (dont bother add it back in again straight away) 1019 * 1020 * Really, we're doing v_rra[rramark] = v_rra[orra] but 1021 * we have to use the macros because SONIC might be in 1022 * 16 or 32 bit mode. 1023 */ 1024 if (status & RCR_LPKT) { 1025 u_int32_t tmp1, tmp2; 1026 1027 rramark = sc->sc_rramark; 1028 tmp1 = sc->v_rra[rramark]; 1029 tmp2 = sc->v_rra[orra]; 1030 SWO(sc, tmp1, RXRSRC_PTRLO, 1031 SRO(sc, tmp2, RXRSRC_PTRLO)); 1032 SWO(sc, tmp1, RXRSRC_PTRHI, 1033 SRO(sc, tmp2, RXRSRC_PTRHI)); 1034 SWO(sc, tmp1, RXRSRC_WCLO, 1035 SRO(sc, tmp2, RXRSRC_WCLO)); 1036 SWO(sc, tmp1, RXRSRC_WCHI, 1037 SRO(sc, tmp2, RXRSRC_WCHI)); 1038 1039 /* zap old rra for fun */ 1040 SWO(sc, tmp2, RXRSRC_WCHI, 0); 1041 SWO(sc, tmp2, RXRSRC_WCLO, 0); 1042 1043 sc->sc_rramark = (++rramark) & RRAMASK; 1044 NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[rramark])); 1045 wbflush(); 1046 } 1047 1048 /* 1049 * give receive descriptor back to chip simple 1050 * list is circular 1051 */ 1052 rdamark = sc->sc_rdamark; 1053 SWO(sc, rda, RXPKT_INUSE, 1); 1054 SWO(sc, rda, RXPKT_RLINK, 1055 SRO(sc, rda, RXPKT_RLINK) | EOL); 1056 SWO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK, 1057 SRO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), 1058 RXPKT_RLINK) & ~EOL); 1059 sc->sc_rdamark = sc->sc_rxmark; 1060 1061 if (++sc->sc_rxmark >= sc->sc_nrda) 1062 sc->sc_rxmark = 0; 1063 rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); 1064 } 1065} 1066 1067/* 1068 * sonic_read -- pull packet off interface and forward to 1069 * appropriate protocol handler 1070 */ 1071hide int 1072sonic_read(sc, pkt, len) 1073 struct snc_softc *sc; 1074 u_int32_t pkt; 1075 int len; 1076{ 1077 struct ifnet *ifp = sc->sc_ifp; 1078 struct ether_header *et; 1079 struct mbuf *m; 1080 1081 if (len <= sizeof(struct ether_header) || 1082 len > ETHERMTU + sizeof(struct ether_header)) { 1083 device_printf(sc->sc_dev, 1084 "invalid packet length %d bytes\n", len); 1085 return (0); 1086 } 1087 1088 /* Pull packet off interface. */ 1089 m = sonic_get(sc, pkt, len); 1090 if (m == 0) { 1091 return (0); 1092 } 1093 1094 /* We assume that the header fit entirely in one mbuf. */ 1095 et = mtod(m, struct ether_header *); 1096 1097#ifdef SNCDEBUG 1098 if ((sncdebug & SNC_SHOWRXHDR) != 0) 1099 { 1100 device_printf(sc->sc_dev, "rcvd 0x%x len=%d type=0x%x from %6D", 1101 pkt, len, htons(et->ether_type), 1102 et->ether_shost, ":"); 1103 printf(" (to %6D)\n", et->ether_dhost, ":"); 1104 } 1105#endif /* SNCDEBUG */ 1106 1107 /* Pass the packet up. */ 1108 (*ifp->if_input)(ifp, m); 1109 return (1); 1110} 1111 1112 1113/* 1114 * munge the received packet into an mbuf chain 1115 */ 1116hide struct mbuf * 1117sonic_get(sc, pkt, datalen) 1118 struct snc_softc *sc; 1119 u_int32_t pkt; 1120 int datalen; 1121{ 1122 struct mbuf *m, *top, **mp; 1123 int len; 1124 /* 1125 * Do not trunc ether_header length. 1126 * Our sonic_read() and sonic_get() require it. 1127 */ 1128 1129 MGETHDR(m, M_DONTWAIT, MT_DATA); 1130 if (m == 0) 1131 return (0); 1132 m->m_pkthdr.rcvif = sc->sc_ifp; 1133 m->m_pkthdr.len = datalen; 1134 len = MHLEN; 1135 top = 0; 1136 mp = ⊤ 1137 1138 while (datalen > 0) { 1139 if (top) { 1140 MGET(m, M_DONTWAIT, MT_DATA); 1141 if (m == 0) { 1142 m_freem(top); 1143 return (0); 1144 } 1145 len = MLEN; 1146 } 1147 if (datalen >= MINCLSIZE) { 1148 MCLGET(m, M_DONTWAIT); 1149 if ((m->m_flags & M_EXT) == 0) { 1150 if (top) m_freem(top); 1151 return (0); 1152 } 1153 len = MCLBYTES; 1154 } 1155#if 0 1156 /* XXX: Require? */ 1157 if (!top) { 1158 register int pad = 1159 ALIGN(sizeof(struct ether_header)) - 1160 sizeof(struct ether_header); 1161 m->m_data += pad; 1162 len -= pad; 1163 } 1164#endif 1165 m->m_len = len = min(datalen, len); 1166 1167 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), pkt, len); 1168 pkt += len; 1169 datalen -= len; 1170 *mp = m; 1171 mp = &m->m_next; 1172 } 1173 1174 return (top); 1175} 1176/* 1177 * Enable power on the interface. 1178 */ 1179int 1180snc_enable(sc) 1181 struct snc_softc *sc; 1182{ 1183 1184#ifdef SNCDEBUG 1185 device_printf(sc->sc_dev, "snc_enable()\n"); 1186#endif /* SNCDEBUG */ 1187 1188 if (sc->sc_enabled == 0 && sc->sc_enable != NULL) { 1189 if ((*sc->sc_enable)(sc) != 0) { 1190 device_printf(sc->sc_dev, "device enable failed\n"); 1191 return (EIO); 1192 } 1193 } 1194 1195 sc->sc_enabled = 1; 1196 return (0); 1197} 1198 1199/* 1200 * Disable power on the interface. 1201 */ 1202void 1203snc_disable(sc) 1204 struct snc_softc *sc; 1205{ 1206 1207#ifdef SNCDEBUG 1208 device_printf(sc->sc_dev, "snc_disable()\n"); 1209#endif /* SNCDEBUG */ 1210 1211 if (sc->sc_enabled != 0 && sc->sc_disable != NULL) { 1212 (*sc->sc_disable)(sc); 1213 sc->sc_enabled = 0; 1214 } 1215} 1216 1217
| 693 694 NIC_PUT(sc, SNCR_CDP, LOWER(sc->v_cda)); 695 NIC_PUT(sc, SNCR_CDC, MAXCAM); 696 NIC_PUT(sc, SNCR_CR, CR_LCAM); 697 wbflush(); 698 699 timeout = 10000; 700 while ((NIC_GET(sc, SNCR_CR) & CR_LCAM) && timeout--) 701 continue; 702 if (timeout == 0) { 703 /* XXX */ 704 panic("%s: CAM initialisation failed\n", 705 device_get_nameunit(sc->sc_dev)); 706 } 707 timeout = 10000; 708 while (((NIC_GET(sc, SNCR_ISR) & ISR_LCD) == 0) && timeout--) 709 continue; 710 711 if (NIC_GET(sc, SNCR_ISR) & ISR_LCD) 712 NIC_PUT(sc, SNCR_ISR, ISR_LCD); 713 else 714 device_printf(sc->sc_dev, 715 "CAM initialisation without interrupt\n"); 716} 717 718#ifdef SNCDEBUG 719hide void 720camdump(sc) 721 struct snc_softc *sc; 722{ 723 int i; 724 725 printf("CAM entries:\n"); 726 NIC_PUT(sc, SNCR_CR, CR_RST); 727 wbflush(); 728 729 for (i = 0; i < 16; i++) { 730 u_short ap2, ap1, ap0; 731 NIC_PUT(sc, SNCR_CEP, i); 732 wbflush(); 733 ap2 = NIC_GET(sc, SNCR_CAP2); 734 ap1 = NIC_GET(sc, SNCR_CAP1); 735 ap0 = NIC_GET(sc, SNCR_CAP0); 736 printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0); 737 } 738 printf("CAM enable 0x%x\n", NIC_GET(sc, SNCR_CEP)); 739 740 NIC_PUT(sc, SNCR_CR, 0); 741 wbflush(); 742} 743#endif 744 745hide void 746initialise_tda(sc) 747 struct snc_softc *sc; 748{ 749 struct mtd *mtd; 750 int i; 751 752 for (i = 0; i < NTDA; i++) { 753 mtd = &sc->mtda[i]; 754 mtd->mtd_mbuf = 0; 755 } 756 757 sc->mtd_hw = 0; 758 sc->mtd_prev = NTDA - 1; 759 sc->mtd_free = 0; 760 sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO; 761 sc->mtd_pint = NTDA/2; 762 763 NIC_PUT(sc, SNCR_UTDA, UPPER(sc->mtda[0].mtd_vtxp)); 764 NIC_PUT(sc, SNCR_CTDA, LOWER(sc->mtda[0].mtd_vtxp)); 765} 766 767hide void 768initialise_rda(sc) 769 struct snc_softc *sc; 770{ 771 int i; 772 u_int32_t vv_rda = 0; 773 u_int32_t v_rda = 0; 774 775 /* link the RDA's together into a circular list */ 776 for (i = 0; i < (sc->sc_nrda - 1); i++) { 777 v_rda = sc->v_rda + (i * RXPKT_SIZE(sc)); 778 vv_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc)); 779 SWO(sc, v_rda, RXPKT_RLINK, LOWER(vv_rda)); 780 SWO(sc, v_rda, RXPKT_INUSE, 1); 781 } 782 v_rda = sc->v_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc)); 783 SWO(sc, v_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL); 784 SWO(sc, v_rda, RXPKT_INUSE, 1); 785 786 /* mark end of receive descriptor list */ 787 sc->sc_rdamark = sc->sc_nrda - 1; 788 789 sc->sc_rxmark = 0; 790 791 NIC_PUT(sc, SNCR_URDA, UPPER(sc->v_rda)); 792 NIC_PUT(sc, SNCR_CRDA, LOWER(sc->v_rda)); 793 wbflush(); 794} 795 796hide void 797initialise_rra(sc) 798 struct snc_softc *sc; 799{ 800 int i; 801 u_int v; 802 int bitmode = sc->bitmode; 803 804 if (bitmode) 805 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 2); 806 else 807 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 1); 808 809 NIC_PUT(sc, SNCR_URRA, UPPER(sc->v_rra[0])); 810 NIC_PUT(sc, SNCR_RSA, LOWER(sc->v_rra[0])); 811 /* rea must point just past the end of the rra space */ 812 NIC_PUT(sc, SNCR_REA, LOWER(sc->v_rea)); 813 NIC_PUT(sc, SNCR_RRP, LOWER(sc->v_rra[0])); 814 NIC_PUT(sc, SNCR_RSC, 0); 815 816 /* fill up SOME of the rra with buffers */ 817 for (i = 0; i < NRBA; i++) { 818 v = SONIC_GETDMA(sc->rbuf[i]); 819 SWO(sc, sc->v_rra[i], RXRSRC_PTRHI, UPPER(v)); 820 SWO(sc, sc->v_rra[i], RXRSRC_PTRLO, LOWER(v)); 821 SWO(sc, sc->v_rra[i], RXRSRC_WCHI, UPPER(NBPG/2)); 822 SWO(sc, sc->v_rra[i], RXRSRC_WCLO, LOWER(NBPG/2)); 823 } 824 sc->sc_rramark = NRBA; 825 NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[sc->sc_rramark])); 826 wbflush(); 827} 828 829void 830sncintr(arg) 831 void *arg; 832{ 833 struct snc_softc *sc = (struct snc_softc *)arg; 834 int isr; 835 836 if (sc->sc_enabled == 0) 837 return; 838 839 while ((isr = (NIC_GET(sc, SNCR_ISR) & ISR_ALL)) != 0) { 840 /* scrub the interrupts that we are going to service */ 841 NIC_PUT(sc, SNCR_ISR, isr); 842 wbflush(); 843 844 if (isr & (ISR_BR | ISR_LCD | ISR_TC)) 845 device_printf(sc->sc_dev, 846 "unexpected interrupt status 0x%x\n", 847 isr); 848 849 if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT)) 850 sonictxint(sc); 851 852 if (isr & ISR_PKTRX) 853 sonicrxint(sc); 854 855 if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) { 856 if (isr & ISR_HBL) 857 /* 858 * The repeater is not providing a heartbeat. 859 * In itself this isn't harmful, lots of the 860 * cheap repeater hubs don't supply a heartbeat. 861 * So ignore the lack of heartbeat. Its only 862 * if we can't detect a carrier that we have a 863 * problem. 864 */ 865 ; 866 if (isr & ISR_RDE) 867 device_printf(sc->sc_dev, 868 "receive descriptors exhausted\n"); 869 if (isr & ISR_RBE) 870 device_printf(sc->sc_dev, 871 "receive buffers exhausted\n"); 872 if (isr & ISR_RBAE) 873 device_printf(sc->sc_dev, 874 "receive buffer area exhausted\n"); 875 if (isr & ISR_RFO) 876 device_printf(sc->sc_dev, 877 "receive FIFO overrun\n"); 878 } 879 if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) { 880#ifdef notdef 881 if (isr & ISR_CRC) 882 sc->sc_crctally++; 883 if (isr & ISR_FAE) 884 sc->sc_faetally++; 885 if (isr & ISR_MP) 886 sc->sc_mptally++; 887#endif 888 } 889 sncstart(sc->sc_ifp); 890 891#if NRND > 0 892 if (isr) 893 rnd_add_uint32(&sc->rnd_source, isr); 894#endif 895 } 896 return; 897} 898 899/* 900 * Transmit interrupt routine 901 */ 902hide void 903sonictxint(sc) 904 struct snc_softc *sc; 905{ 906 struct mtd *mtd; 907 u_int32_t txp; 908 unsigned short txp_status; 909 int mtd_hw; 910 struct ifnet *ifp = sc->sc_ifp; 911 912 mtd_hw = sc->mtd_hw; 913 914 if (mtd_hw == sc->mtd_free) 915 return; 916 917 while (mtd_hw != sc->mtd_free) { 918 mtd = &sc->mtda[mtd_hw]; 919 920 txp = mtd->mtd_vtxp; 921 922 if (SRO(sc, txp, TXP_STATUS) == 0) { 923 break; /* it hasn't really gone yet */ 924 } 925 926#ifdef SNCDEBUG 927 if ((sncdebug & SNC_SHOWTXHDR) != 0) 928 { 929 struct ether_header eh; 930 931 (*sc->sc_copyfrombuf)(sc, &eh, mtd->mtd_vbuf, sizeof(eh)); 932 device_printf(sc->sc_dev, 933 "xmit status=0x%x len=%d type=0x%x from %6D", 934 SRO(sc, txp, TXP_STATUS), 935 SRO(sc, txp, TXP_PKTSIZE), 936 htons(eh.ether_type), 937 eh.ether_shost, ":"); 938 printf(" (to %6D)\n", eh.ether_dhost, ":"); 939 } 940#endif /* SNCDEBUG */ 941 942 ifp->if_flags &= ~IFF_OACTIVE; 943 944 if (mtd->mtd_mbuf != 0) { 945 m_freem(mtd->mtd_mbuf); 946 mtd->mtd_mbuf = 0; 947 } 948 if (++mtd_hw == NTDA) mtd_hw = 0; 949 950 txp_status = SRO(sc, txp, TXP_STATUS); 951 952 ifp->if_collisions += (txp_status & TCR_EXC) ? 16 : 953 ((txp_status & TCR_NC) >> 12); 954 955 if ((txp_status & TCR_PTX) == 0) { 956 ifp->if_oerrors++; 957 device_printf(sc->sc_dev, "Tx packet status=0x%x\n", 958 txp_status); 959 960 /* XXX - DG This looks bogus */ 961 if (mtd_hw != sc->mtd_free) { 962 printf("resubmitting remaining packets\n"); 963 mtd = &sc->mtda[mtd_hw]; 964 NIC_PUT(sc, SNCR_CTDA, LOWER(mtd->mtd_vtxp)); 965 NIC_PUT(sc, SNCR_CR, CR_TXP); 966 wbflush(); 967 break; 968 } 969 } 970 } 971 972 sc->mtd_hw = mtd_hw; 973 return; 974} 975 976/* 977 * Receive interrupt routine 978 */ 979hide void 980sonicrxint(sc) 981 struct snc_softc *sc; 982{ 983 u_int32_t rda; 984 int orra; 985 int len; 986 int rramark; 987 int rdamark; 988 u_int16_t rxpkt_ptr; 989 990 rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); 991 992 while (SRO(sc, rda, RXPKT_INUSE) == 0) { 993 u_int status = SRO(sc, rda, RXPKT_STATUS); 994 995 orra = RBASEQ(SRO(sc, rda, RXPKT_SEQNO)) & RRAMASK; 996 rxpkt_ptr = SRO(sc, rda, RXPKT_PTRLO); 997 /* 998 * Do not trunc ether_header length. 999 * Our sonic_read() and sonic_get() require it. 1000 */ 1001 len = SRO(sc, rda, RXPKT_BYTEC) - FCSSIZE; 1002 if (status & RCR_PRX) { 1003 /* XXX: Does PGOFSET require? */ 1004 u_int32_t pkt = 1005 sc->rbuf[orra & RBAMASK] + (rxpkt_ptr & PGOFSET); 1006 if (sonic_read(sc, pkt, len)) 1007 sc->sc_ifp->if_ipackets++; 1008 else 1009 sc->sc_ifp->if_ierrors++; 1010 } else 1011 sc->sc_ifp->if_ierrors++; 1012 1013 /* 1014 * give receive buffer area back to chip. 1015 * 1016 * If this was the last packet in the RRA, give the RRA to 1017 * the chip again. 1018 * If sonic read didnt copy it out then we would have to 1019 * wait !! 1020 * (dont bother add it back in again straight away) 1021 * 1022 * Really, we're doing v_rra[rramark] = v_rra[orra] but 1023 * we have to use the macros because SONIC might be in 1024 * 16 or 32 bit mode. 1025 */ 1026 if (status & RCR_LPKT) { 1027 u_int32_t tmp1, tmp2; 1028 1029 rramark = sc->sc_rramark; 1030 tmp1 = sc->v_rra[rramark]; 1031 tmp2 = sc->v_rra[orra]; 1032 SWO(sc, tmp1, RXRSRC_PTRLO, 1033 SRO(sc, tmp2, RXRSRC_PTRLO)); 1034 SWO(sc, tmp1, RXRSRC_PTRHI, 1035 SRO(sc, tmp2, RXRSRC_PTRHI)); 1036 SWO(sc, tmp1, RXRSRC_WCLO, 1037 SRO(sc, tmp2, RXRSRC_WCLO)); 1038 SWO(sc, tmp1, RXRSRC_WCHI, 1039 SRO(sc, tmp2, RXRSRC_WCHI)); 1040 1041 /* zap old rra for fun */ 1042 SWO(sc, tmp2, RXRSRC_WCHI, 0); 1043 SWO(sc, tmp2, RXRSRC_WCLO, 0); 1044 1045 sc->sc_rramark = (++rramark) & RRAMASK; 1046 NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[rramark])); 1047 wbflush(); 1048 } 1049 1050 /* 1051 * give receive descriptor back to chip simple 1052 * list is circular 1053 */ 1054 rdamark = sc->sc_rdamark; 1055 SWO(sc, rda, RXPKT_INUSE, 1); 1056 SWO(sc, rda, RXPKT_RLINK, 1057 SRO(sc, rda, RXPKT_RLINK) | EOL); 1058 SWO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK, 1059 SRO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), 1060 RXPKT_RLINK) & ~EOL); 1061 sc->sc_rdamark = sc->sc_rxmark; 1062 1063 if (++sc->sc_rxmark >= sc->sc_nrda) 1064 sc->sc_rxmark = 0; 1065 rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); 1066 } 1067} 1068 1069/* 1070 * sonic_read -- pull packet off interface and forward to 1071 * appropriate protocol handler 1072 */ 1073hide int 1074sonic_read(sc, pkt, len) 1075 struct snc_softc *sc; 1076 u_int32_t pkt; 1077 int len; 1078{ 1079 struct ifnet *ifp = sc->sc_ifp; 1080 struct ether_header *et; 1081 struct mbuf *m; 1082 1083 if (len <= sizeof(struct ether_header) || 1084 len > ETHERMTU + sizeof(struct ether_header)) { 1085 device_printf(sc->sc_dev, 1086 "invalid packet length %d bytes\n", len); 1087 return (0); 1088 } 1089 1090 /* Pull packet off interface. */ 1091 m = sonic_get(sc, pkt, len); 1092 if (m == 0) { 1093 return (0); 1094 } 1095 1096 /* We assume that the header fit entirely in one mbuf. */ 1097 et = mtod(m, struct ether_header *); 1098 1099#ifdef SNCDEBUG 1100 if ((sncdebug & SNC_SHOWRXHDR) != 0) 1101 { 1102 device_printf(sc->sc_dev, "rcvd 0x%x len=%d type=0x%x from %6D", 1103 pkt, len, htons(et->ether_type), 1104 et->ether_shost, ":"); 1105 printf(" (to %6D)\n", et->ether_dhost, ":"); 1106 } 1107#endif /* SNCDEBUG */ 1108 1109 /* Pass the packet up. */ 1110 (*ifp->if_input)(ifp, m); 1111 return (1); 1112} 1113 1114 1115/* 1116 * munge the received packet into an mbuf chain 1117 */ 1118hide struct mbuf * 1119sonic_get(sc, pkt, datalen) 1120 struct snc_softc *sc; 1121 u_int32_t pkt; 1122 int datalen; 1123{ 1124 struct mbuf *m, *top, **mp; 1125 int len; 1126 /* 1127 * Do not trunc ether_header length. 1128 * Our sonic_read() and sonic_get() require it. 1129 */ 1130 1131 MGETHDR(m, M_DONTWAIT, MT_DATA); 1132 if (m == 0) 1133 return (0); 1134 m->m_pkthdr.rcvif = sc->sc_ifp; 1135 m->m_pkthdr.len = datalen; 1136 len = MHLEN; 1137 top = 0; 1138 mp = ⊤ 1139 1140 while (datalen > 0) { 1141 if (top) { 1142 MGET(m, M_DONTWAIT, MT_DATA); 1143 if (m == 0) { 1144 m_freem(top); 1145 return (0); 1146 } 1147 len = MLEN; 1148 } 1149 if (datalen >= MINCLSIZE) { 1150 MCLGET(m, M_DONTWAIT); 1151 if ((m->m_flags & M_EXT) == 0) { 1152 if (top) m_freem(top); 1153 return (0); 1154 } 1155 len = MCLBYTES; 1156 } 1157#if 0 1158 /* XXX: Require? */ 1159 if (!top) { 1160 register int pad = 1161 ALIGN(sizeof(struct ether_header)) - 1162 sizeof(struct ether_header); 1163 m->m_data += pad; 1164 len -= pad; 1165 } 1166#endif 1167 m->m_len = len = min(datalen, len); 1168 1169 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), pkt, len); 1170 pkt += len; 1171 datalen -= len; 1172 *mp = m; 1173 mp = &m->m_next; 1174 } 1175 1176 return (top); 1177} 1178/* 1179 * Enable power on the interface. 1180 */ 1181int 1182snc_enable(sc) 1183 struct snc_softc *sc; 1184{ 1185 1186#ifdef SNCDEBUG 1187 device_printf(sc->sc_dev, "snc_enable()\n"); 1188#endif /* SNCDEBUG */ 1189 1190 if (sc->sc_enabled == 0 && sc->sc_enable != NULL) { 1191 if ((*sc->sc_enable)(sc) != 0) { 1192 device_printf(sc->sc_dev, "device enable failed\n"); 1193 return (EIO); 1194 } 1195 } 1196 1197 sc->sc_enabled = 1; 1198 return (0); 1199} 1200 1201/* 1202 * Disable power on the interface. 1203 */ 1204void 1205snc_disable(sc) 1206 struct snc_softc *sc; 1207{ 1208 1209#ifdef SNCDEBUG 1210 device_printf(sc->sc_dev, "snc_disable()\n"); 1211#endif /* SNCDEBUG */ 1212 1213 if (sc->sc_enabled != 0 && sc->sc_disable != NULL) { 1214 (*sc->sc_disable)(sc); 1215 sc->sc_enabled = 0; 1216 } 1217} 1218 1219
|