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