if_sq.c revision 1.5
1/* $NetBSD: if_sq.c,v 1.5 2001/07/08 20:30:14 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 2001 Rafal K. Boni 5 * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * Portions of this code are derived from software contributed to The 9 * NetBSD Foundation by Jason R. Thorpe of the Numerical Aerospace 10 * Simulation Facility, NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35#include "opt_inet.h" 36#include "opt_ns.h" 37#include "bpfilter.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/device.h> 42#include <sys/callout.h> 43#include <sys/mbuf.h> 44#include <sys/malloc.h> 45#include <sys/kernel.h> 46#include <sys/socket.h> 47#include <sys/ioctl.h> 48#include <sys/errno.h> 49#include <sys/syslog.h> 50 51#include <uvm/uvm_extern.h> 52 53#include <machine/endian.h> 54 55#include <net/if.h> 56#include <net/if_dl.h> 57#include <net/if_media.h> 58#include <net/if_ether.h> 59 60#if NBPFILTER > 0 61#include <net/bpf.h> 62#endif 63 64#ifdef INET 65#include <netinet/in.h> 66#include <netinet/if_inarp.h> 67#endif 68 69#ifdef NS 70#include <netns/ns.h> 71#include <netns/ns_if.h> 72#endif 73 74/* XXXrkb: cheap hack until parents pass in DMA tags */ 75#define _SGIMIPS_BUS_DMA_PRIVATE 76 77#include <machine/bus.h> 78#include <machine/intr.h> 79 80#include <dev/ic/seeq8003reg.h> 81 82#include <sgimips/hpc/sqvar.h> 83#include <sgimips/hpc/hpcvar.h> 84#include <sgimips/hpc/hpcreg.h> 85 86#include <dev/arcbios/arcbios.h> 87#include <dev/arcbios/arcbiosvar.h> 88 89#define static 90 91/* 92 * Short TODO list: 93 * (1) Do counters for bad-RX packets. 94 * (2) Inherit DMA tag via config machinery, don't hard-code it. 95 * (3) Allow multi-segment transmits, instead of copying to a single, 96 * contiguous mbuf. 97 * (4) Verify sq_stop() turns off enough stuff; I was still getting 98 * seeq interrupts after sq_stop(). 99 * (5) Fix up printfs in driver (most should only fire ifdef SQ_DEBUG 100 * or something similar. 101 * (6) Implement EDLC modes: especially packet auto-pad and simplex 102 * mode. 103 * (7) Should the driver filter out its own transmissions in non-EDLC 104 * mode? 105 * (8) Multicast support -- multicast filter, address management, ... 106 * (9) Deal with RB0 (recv buffer overflow) on reception. Will need 107 * to figure out if RB0 is read-only as stated in one spot in the 108 * HPC spec or read-write (ie, is the 'write a one to clear it') 109 * the correct thing? 110 */ 111 112static int sq_match(struct device *, struct cfdata *, void *); 113static void sq_attach(struct device *, struct device *, void *); 114static int sq_init(struct ifnet *); 115static void sq_start(struct ifnet *); 116static void sq_stop(struct ifnet *, int); 117static void sq_watchdog(struct ifnet *); 118static int sq_ioctl(struct ifnet *, u_long, caddr_t); 119 120static void sq_set_filter(struct sq_softc *); 121static int sq_intr(void *); 122static int sq_rxintr(struct sq_softc *); 123static int sq_txintr(struct sq_softc *); 124static void sq_reset(struct sq_softc *); 125static int sq_add_rxbuf(struct sq_softc *, int); 126static void sq_dump_buffer(u_int32_t addr, u_int32_t len); 127 128static void enaddr_aton(const char*, u_int8_t*); 129 130/* Actions */ 131#define SQ_RESET 1 132#define SQ_ADD_TO_DMA 2 133#define SQ_START_DMA 3 134#define SQ_DONE_DMA 4 135#define SQ_RESTART_DMA 5 136#define SQ_TXINTR_ENTER 6 137#define SQ_TXINTR_EXIT 7 138#define SQ_TXINTR_BUSY 8 139 140struct sq_action_trace { 141 int action; 142 int bufno; 143 int status; 144 int freebuf; 145}; 146 147#define SQ_TRACEBUF_SIZE 100 148int sq_trace_idx = 0; 149struct sq_action_trace sq_trace[SQ_TRACEBUF_SIZE]; 150 151void sq_trace_dump(struct sq_softc* sc); 152 153#define SQ_TRACE(act, buf, stat, free) do { \ 154 sq_trace[sq_trace_idx].action = (act); \ 155 sq_trace[sq_trace_idx].bufno = (buf); \ 156 sq_trace[sq_trace_idx].status = (stat); \ 157 sq_trace[sq_trace_idx].freebuf = (free); \ 158 if (++sq_trace_idx == SQ_TRACEBUF_SIZE) { \ 159 bzero(&sq_trace, sizeof(sq_trace)); \ 160 sq_trace_idx = 0; \ 161 } \ 162} while (0) 163 164struct cfattach sq_ca = { 165 sizeof(struct sq_softc), sq_match, sq_attach 166}; 167 168static int 169sq_match(struct device *parent, struct cfdata *match, void *aux) 170{ 171 /* XXX! */ 172 return 1; 173} 174 175static void 176sq_attach(struct device *parent, struct device *self, void *aux) 177{ 178 int i, err; 179 char* macaddr; 180 struct sq_softc *sc = (void *)self; 181 struct hpc_attach_args *haa = aux; 182 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 183 184 sc->sc_hpct = haa->ha_iot; 185 if ((err = bus_space_subregion(haa->ha_iot, haa->ha_ioh, 186 HPC_ENET_REGS, 187 HPC_ENET_REGS_SIZE, 188 &sc->sc_hpch)) != 0) { 189 printf(": unable to map HPC DMA registers, error = %d\n", err); 190 goto fail_0; 191 } 192 193 sc->sc_regt = haa->ha_iot; 194 if ((err = bus_space_subregion(haa->ha_iot, haa->ha_ioh, 195 HPC_ENET_DEVREGS, 196 HPC_ENET_DEVREGS_SIZE, 197 &sc->sc_regh)) != 0) { 198 printf(": unable to map Seeq registers, error = %d\n", err); 199 goto fail_0; 200 } 201 202 /* XXXrkb: should be inherited from parent bus, but works for now */ 203 sc->sc_dmat = &sgimips_default_bus_dma_tag; 204 205 if ((err = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct sq_control), 206 PAGE_SIZE, PAGE_SIZE, &sc->sc_cdseg, 207 1, &sc->sc_ncdseg, BUS_DMA_NOWAIT)) != 0) { 208 printf(": unable to allocate control data, error = %d\n", err); 209 goto fail_0; 210 } 211 212 if ((err = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg, 213 sizeof(struct sq_control), 214 (caddr_t *)&sc->sc_control, 215 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 216 printf(": unable to map control data, error = %d\n", err); 217 goto fail_1; 218 } 219 220 if ((err = bus_dmamap_create(sc->sc_dmat, sizeof(struct sq_control), 221 1, sizeof(struct sq_control), PAGE_SIZE, 222 BUS_DMA_NOWAIT, &sc->sc_cdmap)) != 0) { 223 printf(": unable to create DMA map for control data, error " 224 "= %d\n", err); 225 goto fail_2; 226 } 227 228 if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cdmap, sc->sc_control, 229 sizeof(struct sq_control), 230 NULL, BUS_DMA_NOWAIT)) != 0) { 231 printf(": unable to load DMA map for control data, error " 232 "= %d\n", err); 233 goto fail_3; 234 } 235 236 bzero(sc->sc_control, sizeof(struct sq_control)); 237 238 /* Create transmit buffer DMA maps */ 239 for (i = 0; i < SQ_NTXDESC; i++) { 240 if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 241 0, BUS_DMA_NOWAIT, 242 &sc->sc_txmap[i])) != 0) { 243 printf(": unable to create tx DMA map %d, error = %d\n", 244 i, err); 245 goto fail_4; 246 } 247 } 248 249 /* Create transmit buffer DMA maps */ 250 for (i = 0; i < SQ_NRXDESC; i++) { 251 if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 252 0, BUS_DMA_NOWAIT, 253 &sc->sc_rxmap[i])) != 0) { 254 printf(": unable to create rx DMA map %d, error = %d\n", 255 i, err); 256 goto fail_5; 257 } 258 } 259 260 /* Pre-allocate the receive buffers. */ 261 for (i = 0; i < SQ_NRXDESC; i++) { 262 if ((err = sq_add_rxbuf(sc, i)) != 0) { 263 printf(": unable to allocate or map rx buffer %d\n," 264 " error = %d\n", i, err); 265 goto fail_6; 266 } 267 } 268 269 if ((macaddr = ARCBIOS->GetEnvironmentVariable("eaddr")) == NULL) { 270 printf(": unable to get MAC address!\n"); 271 goto fail_6; 272 } 273 274 if ((cpu_intr_establish(3, IPL_NET, sq_intr, sc)) == NULL) { 275 printf(": unable to establish interrupt!\n"); 276 goto fail_6; 277 } 278 279 /* Reset the chip to a known state. */ 280 sq_reset(sc); 281 282 /* 283 * Determine if we're an 8003 or 80c03 by setting the first 284 * MAC address register to non-zero, and then reading it back. 285 * If it's zero, we have an 80c03, because we will have read 286 * the TxCollLSB register. 287 */ 288 bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCOLLS0, 0xa5); 289 if (bus_space_read_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCOLLS0) == 0) 290 sc->sc_type = SQ_TYPE_80C03; 291 else 292 sc->sc_type = SQ_TYPE_8003; 293 bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCOLLS0, 0x00); 294 295 printf(": SGI Seeq %s\n", 296 sc->sc_type == SQ_TYPE_80C03 ? "80c03" : "8003"); 297 298 enaddr_aton(macaddr, sc->sc_enaddr); 299 300 printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname, 301 ether_sprintf(sc->sc_enaddr)); 302 303 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 304 ifp->if_softc = sc; 305 ifp->if_mtu = ETHERMTU; 306 ifp->if_init = sq_init; 307 ifp->if_stop = sq_stop; 308 ifp->if_start = sq_start; 309 ifp->if_ioctl = sq_ioctl; 310 ifp->if_watchdog = sq_watchdog; 311 ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_MULTICAST; 312 IFQ_SET_READY(&ifp->if_snd); 313 314 if_attach(ifp); 315 ether_ifattach(ifp, sc->sc_enaddr); 316 317 bzero(&sq_trace, sizeof(sq_trace)); 318 /* Done! */ 319 return; 320 321 /* 322 * Free any resources we've allocated during the failed attach 323 * attempt. Do this in reverse order and fall through. 324 */ 325fail_6: 326 for (i = 0; i < SQ_NRXDESC; i++) { 327 if (sc->sc_rxmbuf[i] != NULL) { 328 bus_dmamap_unload(sc->sc_dmat, sc->sc_rxmap[i]); 329 m_freem(sc->sc_rxmbuf[i]); 330 } 331 } 332fail_5: 333 for (i = 0; i < SQ_NRXDESC; i++) { 334 if (sc->sc_rxmap[i] != NULL) 335 bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxmap[i]); 336 } 337fail_4: 338 for (i = 0; i < SQ_NTXDESC; i++) { 339 if (sc->sc_txmap[i] != NULL) 340 bus_dmamap_destroy(sc->sc_dmat, sc->sc_txmap[i]); 341 } 342 bus_dmamap_unload(sc->sc_dmat, sc->sc_cdmap); 343fail_3: 344 bus_dmamap_destroy(sc->sc_dmat, sc->sc_cdmap); 345fail_2: 346 bus_dmamem_unmap(sc->sc_dmat, (caddr_t) sc->sc_control, 347 sizeof(struct sq_control)); 348fail_1: 349 bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg); 350fail_0: 351 return; 352} 353 354/* Set up data to get the interface up and running. */ 355int 356sq_init(struct ifnet *ifp) 357{ 358 int i; 359 u_int32_t reg; 360 struct sq_softc *sc = ifp->if_softc; 361 362 /* Cancel any in-progress I/O */ 363 sq_stop(ifp, 0); 364 365 sc->sc_nextrx = 0; 366 367 sc->sc_nfreetx = SQ_NTXDESC; 368 sc->sc_nexttx = sc->sc_prevtx = 0; 369 370 SQ_TRACE(SQ_RESET, 0, 0, sc->sc_nfreetx); 371 372 /* Set into 8003 mode, bank 0 to program ethernet address */ 373 bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCMD, TXCMD_BANK0); 374 375 /* Now write the address */ 376 for (i = 0; i < ETHER_ADDR_LEN; i++) 377 bus_space_write_1(sc->sc_regt, sc->sc_regh, i, 378 sc->sc_enaddr[i]); 379 380 sc->sc_rxcmd = RXCMD_IE_CRC | 381 RXCMD_IE_DRIB | 382 RXCMD_IE_SHORT | 383 RXCMD_IE_END | 384 RXCMD_IE_GOOD; 385 386 /* 387 * Set the receive filter -- this will add some bits to the 388 * prototype RXCMD register. Do this before setting the 389 * transmit config register, since we might need to switch 390 * banks. 391 */ 392 sq_set_filter(sc); 393 394 /* Set up Seeq transmit command register */ 395 bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCMD, 396 TXCMD_IE_UFLOW | 397 TXCMD_IE_COLL | 398 TXCMD_IE_16COLL | 399 TXCMD_IE_GOOD); 400 401 /* Now write the receive command register. */ 402 bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_RXCMD, sc->sc_rxcmd); 403 404 /* Set up HPC ethernet DMA config */ 405 reg = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_DMACFG); 406 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_DMACFG, 407 reg | ENETR_DMACFG_FIX_RXDC | 408 ENETR_DMACFG_FIX_INTR | 409 ENETR_DMACFG_FIX_EOP); 410 411 /* Pass the start of the receive ring to the HPC */ 412 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_NDBP, 413 SQ_CDRXADDR(sc, 0)); 414 415 /* And turn on the HPC ethernet receive channel */ 416 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_CTL, 417 ENETR_CTL_ACTIVE); 418 419 ifp->if_flags |= IFF_RUNNING; 420 ifp->if_flags &= ~IFF_OACTIVE; 421 422 return 0; 423} 424 425static void 426sq_set_filter(struct sq_softc *sc) 427{ 428 struct ethercom *ec = &sc->sc_ethercom; 429 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 430 struct ether_multi *enm; 431 struct ether_multistep step; 432 433 /* 434 * Check for promiscuous mode. Also implies 435 * all-multicast. 436 */ 437 if (ifp->if_flags & IFF_PROMISC) { 438 sc->sc_rxcmd |= RXCMD_REC_ALL; 439 ifp->if_flags |= IFF_ALLMULTI; 440 return; 441 } 442 443 /* 444 * The 8003 has no hash table. If we have any multicast 445 * addresses on the list, enable reception of all multicast 446 * frames. 447 * 448 * XXX The 80c03 has a hash table. We should use it. 449 */ 450 451 ETHER_FIRST_MULTI(step, ec, enm); 452 453 if (enm == NULL) { 454 sc->sc_rxcmd |= RXCMD_REC_BROAD; 455 return; 456 } 457 458 sc->sc_rxcmd |= RXCMD_REC_MULTI; 459 ifp->if_flags |= IFF_ALLMULTI; 460} 461 462int 463sq_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 464{ 465 int s, error = 0; 466 467 s = splnet(); 468 469 error = ether_ioctl(ifp, cmd, data); 470 if (error == ENETRESET) { 471 /* 472 * Multicast list has changed; set the hardware filter 473 * accordingly. 474 */ 475 error = 0; 476 } 477 478 splx(s); 479 return (error); 480} 481 482void 483sq_start(struct ifnet *ifp) 484{ 485 struct sq_softc *sc = ifp->if_softc; 486 u_int32_t status; 487 struct mbuf *m0, *m; 488 bus_dmamap_t dmamap; 489 int err, totlen, nexttx, firsttx, lasttx, ofree, seg; 490 491 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) 492 return; 493 494 /* 495 * Remember the previous number of free descriptors and 496 * the first descriptor we'll use. 497 */ 498 ofree = sc->sc_nfreetx; 499 firsttx = sc->sc_nexttx; 500 501 /* 502 * Loop through the send queue, setting up transmit descriptors 503 * until we drain the queue, or use up all available transmit 504 * descriptors. 505 */ 506 while (sc->sc_nfreetx != 0) { 507 /* 508 * Grab a packet off the queue. 509 */ 510 IFQ_POLL(&ifp->if_snd, m0); 511 if (m0 == NULL) 512 break; 513 m = NULL; 514 515 dmamap = sc->sc_txmap[sc->sc_nexttx]; 516 517 /* 518 * Load the DMA map. If this fails, the packet either 519 * didn't fit in the alloted number of segments, or we were 520 * short on resources. In this case, we'll copy and try 521 * again. 522 */ 523 if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, 524 BUS_DMA_NOWAIT) != 0) { 525 MGETHDR(m, M_DONTWAIT, MT_DATA); 526 if (m == NULL) { 527 printf("%s: unable to allocate Tx mbuf\n", 528 sc->sc_dev.dv_xname); 529 break; 530 } 531 if (m0->m_pkthdr.len > MHLEN) { 532 MCLGET(m, M_DONTWAIT); 533 if ((m->m_flags & M_EXT) == 0) { 534 printf("%s: unable to allocate Tx " 535 "cluster\n", sc->sc_dev.dv_xname); 536 m_freem(m); 537 break; 538 } 539 } 540 541 m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t)); 542 m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; 543 544 if ((err = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, 545 m, BUS_DMA_NOWAIT)) != 0) { 546 printf("%s: unable to load Tx buffer, " 547 "error = %d\n", sc->sc_dev.dv_xname, err); 548 break; 549 } 550 } 551 552 /* 553 * Ensure we have enough descriptors free to describe 554 * the packet. 555 */ 556 if (dmamap->dm_nsegs > sc->sc_nfreetx) { 557 /* 558 * Not enough free descriptors to transmit this 559 * packet. We haven't committed to anything yet, 560 * so just unload the DMA map, put the packet 561 * back on the queue, and punt. Notify the upper 562 * layer that there are no more slots left. 563 * 564 * XXX We could allocate an mbuf and copy, but 565 * XXX it is worth it? 566 */ 567 ifp->if_flags |= IFF_OACTIVE; 568 bus_dmamap_unload(sc->sc_dmat, dmamap); 569 if (m != NULL) 570 m_freem(m); 571 break; 572 } 573 574 IFQ_DEQUEUE(&ifp->if_snd, m0); 575 if (m != NULL) { 576 m_freem(m0); 577 m0 = m; 578 } 579 580 /* 581 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. 582 */ 583 584 /* Sync the DMA map. */ 585 bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, 586 BUS_DMASYNC_PREWRITE); 587 588 /* 589 * Initialize the transmit descriptors. 590 */ 591 for (nexttx = sc->sc_nexttx, seg = 0, totlen = 0; 592 seg < dmamap->dm_nsegs; 593 seg++, nexttx = SQ_NEXTTX(nexttx)) { 594 sc->sc_txdesc[nexttx].hdd_bufptr = 595 dmamap->dm_segs[seg].ds_addr; 596 sc->sc_txdesc[nexttx].hdd_ctl = 597 dmamap->dm_segs[seg].ds_len; 598 sc->sc_txdesc[nexttx].hdd_descptr= 599 SQ_CDTXADDR(sc, SQ_NEXTTX(nexttx)); 600 lasttx = nexttx; 601 totlen += dmamap->dm_segs[seg].ds_len; 602 } 603 604 /* Last descriptor gets end-of-packet */ 605 sc->sc_txdesc[lasttx].hdd_ctl |= HDD_CTL_EOPACKET; 606 607 /* XXXrkb: if not EDLC, pad to min len manually */ 608 if (totlen < ETHER_MIN_LEN) { 609 sc->sc_txdesc[lasttx].hdd_ctl += (ETHER_MIN_LEN - totlen); 610 totlen = ETHER_MIN_LEN; 611 } 612 613#if 0 614 printf("%s: transmit %d-%d, len %d\n", sc->sc_dev.dv_xname, 615 sc->sc_nexttx, lasttx, 616 totlen); 617#endif 618 619 if (ifp->if_flags & IFF_DEBUG) { 620 printf(" transmit chain:\n"); 621 for (seg = sc->sc_nexttx;; seg = SQ_NEXTTX(seg)) { 622 printf(" descriptor %d:\n", seg); 623 printf(" hdd_bufptr: 0x%08x\n", 624 sc->sc_txdesc[seg].hdd_bufptr); 625 printf(" hdd_ctl: 0x%08x\n", 626 sc->sc_txdesc[seg].hdd_ctl); 627 printf(" hdd_descptr: 0x%08x\n", 628 sc->sc_txdesc[seg].hdd_descptr); 629 630 if (seg == lasttx) 631 break; 632 } 633 } 634 635 /* Sync the descriptors we're using. */ 636 SQ_CDTXSYNC(sc, sc->sc_nexttx, dmamap->dm_nsegs, 637 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 638 639 /* Store a pointer to the packet so we can free it later */ 640 sc->sc_txmbuf[sc->sc_nexttx] = m0; 641 642 /* Advance the tx pointer. */ 643 sc->sc_nfreetx -= dmamap->dm_nsegs; 644 sc->sc_nexttx = nexttx; 645 646#if NBPFILTER > 0 647 /* 648 * Pass the packet to any BPF listeners. 649 */ 650 if (ifp->if_bpf) 651 bpf_mtap(ifp->if_bpf, m0); 652#endif /* NBPFILTER > 0 */ 653 } 654 655 /* All transmit descriptors used up, let upper layers know */ 656 if (sc->sc_nfreetx == 0) 657 ifp->if_flags |= IFF_OACTIVE; 658 659 if (sc->sc_nfreetx != ofree) { 660#if 0 661 printf("%s: %d packets enqueued, first %d, INTR on %d\n", 662 sc->sc_dev.dv_xname, lasttx - firsttx + 1, 663 firsttx, lasttx); 664#endif 665 666 /* 667 * Cause a transmit interrupt to happen on the 668 * last packet we enqueued, mark it as the last 669 * descriptor. 670 */ 671 sc->sc_txdesc[lasttx].hdd_ctl |= (HDD_CTL_INTR | 672 HDD_CTL_EOCHAIN); 673 SQ_CDTXSYNC(sc, lasttx, 1, 674 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 675 676 /* 677 * There is a potential race condition here if the HPC 678 * DMA channel is active and we try and either update 679 * the 'next descriptor' pointer in the HPC PIO space 680 * or the 'next descriptor' pointer in a previous desc- 681 * riptor. 682 * 683 * To avoid this, if the channel is active, we rely on 684 * the transmit interrupt routine noticing that there 685 * are more packets to send and restarting the HPC DMA 686 * engine, rather than mucking with the DMA state here. 687 */ 688 status = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, 689 HPC_ENETX_CTL); 690 691 if ((status & ENETX_CTL_ACTIVE) != 0) { 692 SQ_TRACE(SQ_ADD_TO_DMA, firsttx, status, sc->sc_nfreetx); 693 694 sc->sc_txdesc[SQ_PREVTX(firsttx)].hdd_ctl &= 695 ~HDD_CTL_EOCHAIN; 696 SQ_CDTXSYNC(sc, SQ_PREVTX(firsttx), 1, 697 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 698 } else { 699 SQ_TRACE(SQ_START_DMA, firsttx, status, sc->sc_nfreetx); 700 701 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, 702 HPC_ENETX_NDBP, SQ_CDTXADDR(sc, firsttx)); 703 704 /* Kick DMA channel into life */ 705 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, 706 HPC_ENETX_CTL, ENETX_CTL_ACTIVE); 707 } 708 709 /* Set a watchdog timer in case the chip flakes out. */ 710 ifp->if_timer = 5; 711 } 712} 713 714void 715sq_stop(struct ifnet *ifp, int disable) 716{ 717 int i; 718 struct sq_softc *sc = ifp->if_softc; 719 720 for (i =0; i < SQ_NTXDESC; i++) { 721 if (sc->sc_txmbuf[i] != NULL) { 722 bus_dmamap_unload(sc->sc_dmat, sc->sc_txmap[i]); 723 m_freem(sc->sc_txmbuf[i]); 724 sc->sc_txmbuf[i] = NULL; 725 } 726 } 727 728 /* Clear Seeq transmit/receive command registers */ 729 bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_TXCMD, 0); 730 bus_space_write_1(sc->sc_regt, sc->sc_regh, SEEQ_RXCMD, 0); 731 732 sq_reset(sc); 733 734 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 735 ifp->if_timer = 0; 736} 737 738/* Device timeout/watchdog routine. */ 739void 740sq_watchdog(struct ifnet *ifp) 741{ 742 u_int32_t status; 743 struct sq_softc *sc = ifp->if_softc; 744 745 status = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETX_CTL); 746 log(LOG_ERR, "%s: device timeout (prev %d, next %d, free %d, " 747 "status %08x)\n", sc->sc_dev.dv_xname, sc->sc_prevtx, 748 sc->sc_nexttx, sc->sc_nfreetx, status); 749 750 sq_trace_dump(sc); 751 752 bzero(&sq_trace, sizeof(sq_trace)); 753 sq_trace_idx = 0; 754 755 ++ifp->if_oerrors; 756 757 sq_init(ifp); 758} 759 760void sq_trace_dump(struct sq_softc* sc) 761{ 762 int i; 763 764 for(i = 0; i < sq_trace_idx; i++) { 765 printf("%s: [%d] action %d, buf %d, free %d, status %08x\n", 766 sc->sc_dev.dv_xname, i, sq_trace[i].action, 767 sq_trace[i].bufno, sq_trace[i].freebuf, 768 sq_trace[i].status); 769 } 770} 771 772static int 773sq_intr(void * arg) 774{ 775 struct sq_softc *sc = arg; 776 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 777 int handled = 0; 778 u_int32_t stat; 779 780 stat = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_RESET); 781 782 if ((stat & 2) == 0) { 783 printf("%s: Unexpected interrupt!\n", sc->sc_dev.dv_xname); 784 return 0; 785 } 786 787 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_RESET, 2); 788 789 /* 790 * If the interface isn't running, the interrupt couldn't 791 * possibly have come from us. 792 */ 793 if ((ifp->if_flags & IFF_RUNNING) == 0) 794 return 0; 795 796 /* Always check for received packets */ 797 if (sq_rxintr(sc) != 0) 798 handled++; 799 800 /* Only handle transmit interrupts if we actually sent something */ 801 if (sc->sc_nfreetx < SQ_NTXDESC) { 802 sq_txintr(sc); 803 handled++; 804 } 805 806#if NRND > 0 807 if (handled) 808 rnd_add_uint32(&sc->rnd_source, stat); 809#endif 810 return (handled); 811} 812 813static int 814sq_rxintr(struct sq_softc *sc) 815{ 816 int count = 0; 817 struct mbuf* m; 818 int i, framelen; 819 u_int8_t pktstat; 820 u_int32_t status; 821 int new_end, orig_end; 822 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 823 824 for(i = sc->sc_nextrx;; i = SQ_NEXTRX(i)) { 825 SQ_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 826 827 /* If this is a CPU-owned buffer, we're at the end of the list */ 828 if (sc->sc_rxdesc[i].hdd_ctl & HDD_CTL_OWN) { 829#if 0 830 u_int32_t reg; 831 832 reg = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_CTL); 833 printf("%s: rxintr: done at %d (ctl %08x)\n", 834 sc->sc_dev.dv_xname, i, reg); 835#endif 836 break; 837 } 838 839 count++; 840 841 m = sc->sc_rxmbuf[i]; 842 framelen = m->m_ext.ext_size - 843 HDD_CTL_BYTECNT(sc->sc_rxdesc[i].hdd_ctl) - 3; 844 845 /* Now sync the actual packet data */ 846 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[i], 0, 847 sc->sc_rxmap[i]->dm_mapsize, BUS_DMASYNC_POSTREAD); 848 849 pktstat = *((u_int8_t*)m->m_data + framelen + 2); 850 851 if ((pktstat & RXSTAT_GOOD) == 0) { 852 ifp->if_ierrors++; 853 854 if (pktstat & RXSTAT_OFLOW) 855 printf("%s: receive FIFO overflow\n", sc->sc_dev.dv_xname); 856 857 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[i], 0, 858 sc->sc_rxmap[i]->dm_mapsize, 859 BUS_DMASYNC_PREREAD); 860 SQ_INIT_RXDESC(sc, i); 861 continue; 862 } 863 864 if (sq_add_rxbuf(sc, i) != 0) { 865 ifp->if_ierrors++; 866 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[i], 0, 867 sc->sc_rxmap[i]->dm_mapsize, 868 BUS_DMASYNC_PREREAD); 869 SQ_INIT_RXDESC(sc, i); 870 continue; 871 } 872 873 874 m->m_data += 2; 875 m->m_pkthdr.rcvif = ifp; 876 m->m_pkthdr.len = m->m_len = framelen; 877 878 ifp->if_ipackets++; 879 880#if 0 881 printf("%s: sq_rxintr: buf %d len %d\n", sc->sc_dev.dv_xname, 882 i, framelen); 883#endif 884 885#if NBPFILTER > 0 886 if (ifp->if_bpf) 887 bpf_mtap(ifp->if_bpf, m); 888#endif 889 (*ifp->if_input)(ifp, m); 890 } 891 892 893 /* If anything happened, move ring start/end pointers to new spot */ 894 if (i != sc->sc_nextrx) { 895 new_end = SQ_PREVRX(i); 896 sc->sc_rxdesc[new_end].hdd_ctl |= HDD_CTL_EOCHAIN; 897 SQ_CDRXSYNC(sc, new_end, BUS_DMASYNC_PREREAD | 898 BUS_DMASYNC_PREWRITE); 899 900 orig_end = SQ_PREVRX(sc->sc_nextrx); 901 sc->sc_rxdesc[orig_end].hdd_ctl &= ~HDD_CTL_EOCHAIN; 902 SQ_CDRXSYNC(sc, orig_end, BUS_DMASYNC_PREREAD | 903 BUS_DMASYNC_PREWRITE); 904 905 sc->sc_nextrx = i; 906 } 907 908 status = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, 909 HPC_ENETR_CTL); 910 911 /* If receive channel is stopped, restart it... */ 912 if ((status & ENETR_CTL_ACTIVE) == 0) { 913 /* Pass the start of the receive ring to the HPC */ 914 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, 915 HPC_ENETR_NDBP, SQ_CDRXADDR(sc, sc->sc_nextrx)); 916 917 /* And turn on the HPC ethernet receive channel */ 918 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_CTL, 919 ENETR_CTL_ACTIVE); 920 } 921 922 return count; 923} 924 925static int 926sq_txintr(struct sq_softc *sc) 927{ 928 int i; 929 u_int32_t status; 930 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 931 932 status = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETX_CTL); 933 934 SQ_TRACE(SQ_TXINTR_ENTER, sc->sc_prevtx, status, sc->sc_nfreetx); 935 936 if ((status & (ENETX_CTL_ACTIVE | TXSTAT_GOOD)) == 0) { 937 if (status & TXSTAT_COLL) 938 ifp->if_collisions++; 939 940 if (status & TXSTAT_UFLOW) { 941 printf("%s: transmit underflow\n", sc->sc_dev.dv_xname); 942 ifp->if_oerrors++; 943 } 944 945 if (status & TXSTAT_16COLL) { 946 printf("%s: max collisions reached\n", sc->sc_dev.dv_xname); 947 ifp->if_oerrors++; 948 ifp->if_collisions += 16; 949 } 950 } 951 952 i = sc->sc_prevtx; 953 while (sc->sc_nfreetx < SQ_NTXDESC) { 954 /* 955 * Check status first so we don't end up with a case of 956 * the buffer not being finished while the DMA channel 957 * has gone idle. 958 */ 959 status = bus_space_read_4(sc->sc_hpct, sc->sc_hpch, 960 HPC_ENETX_CTL); 961 962 SQ_CDTXSYNC(sc, i, sc->sc_txmap[i]->dm_nsegs, 963 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 964 965 /* If not yet transmitted, try and start DMA engine again */ 966 if ((sc->sc_txdesc[i].hdd_ctl & HDD_CTL_XMITDONE) == 0) { 967 if ((status & ENETX_CTL_ACTIVE) == 0) { 968 SQ_TRACE(SQ_RESTART_DMA, i, status, sc->sc_nfreetx); 969 970 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, 971 HPC_ENETX_NDBP, SQ_CDTXADDR(sc, i)); 972 973 /* Kick DMA channel into life */ 974 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, 975 HPC_ENETX_CTL, ENETX_CTL_ACTIVE); 976 977 /* Set a watchdog timer in case the chip flakes out. */ 978 ifp->if_timer = 5; 979 } else { 980 SQ_TRACE(SQ_TXINTR_BUSY, i, status, sc->sc_nfreetx); 981 } 982 break; 983 } 984 985 /* Sync the packet data, unload DMA map, free mbuf */ 986 bus_dmamap_sync(sc->sc_dmat, sc->sc_txmap[i], 0, 987 sc->sc_txmap[i]->dm_mapsize, 988 BUS_DMASYNC_POSTWRITE); 989 bus_dmamap_unload(sc->sc_dmat, sc->sc_txmap[i]); 990 m_freem(sc->sc_txmbuf[i]); 991 sc->sc_txmbuf[i] = NULL; 992 993 ifp->if_opackets++; 994 sc->sc_nfreetx++; 995 996 SQ_TRACE(SQ_DONE_DMA, i, status, sc->sc_nfreetx); 997 i = SQ_NEXTTX(i); 998 } 999 1000 /* prevtx now points to next xmit packet not yet finished */ 1001 sc->sc_prevtx = i; 1002 1003 /* If we have buffers free, let upper layers know */ 1004 if (sc->sc_nfreetx > 0) 1005 ifp->if_flags &= ~IFF_OACTIVE; 1006 1007 /* If all packets have left the coop, cancel watchdog */ 1008 if (sc->sc_nfreetx == SQ_NTXDESC) 1009 ifp->if_timer = 0; 1010 1011 SQ_TRACE(SQ_TXINTR_EXIT, sc->sc_prevtx, status, sc->sc_nfreetx); 1012 sq_start(ifp); 1013 1014 return 1; 1015} 1016 1017 1018void 1019sq_reset(struct sq_softc *sc) 1020{ 1021 /* Stop HPC dma channels */ 1022 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_CTL, 0); 1023 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETX_CTL, 0); 1024 1025 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_RESET, 3); 1026 delay(20); 1027 bus_space_write_4(sc->sc_hpct, sc->sc_hpch, HPC_ENETR_RESET, 0); 1028} 1029 1030/* sq_add_rxbuf: Add a receive buffer to the indicated descriptor. */ 1031int 1032sq_add_rxbuf(struct sq_softc *sc, int idx) 1033{ 1034 int err; 1035 struct mbuf *m; 1036 1037 MGETHDR(m, M_DONTWAIT, MT_DATA); 1038 if (m == NULL) 1039 return (ENOBUFS); 1040 1041 MCLGET(m, M_DONTWAIT); 1042 if ((m->m_flags & M_EXT) == 0) { 1043 m_freem(m); 1044 return (ENOBUFS); 1045 } 1046 1047 if (sc->sc_rxmbuf[idx] != NULL) 1048 bus_dmamap_unload(sc->sc_dmat, sc->sc_rxmap[idx]); 1049 1050 sc->sc_rxmbuf[idx] = m; 1051 1052 if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_rxmap[idx], 1053 m->m_ext.ext_buf, m->m_ext.ext_size, 1054 NULL, BUS_DMA_NOWAIT)) != 0) { 1055 printf("%s: can't load rx DMA map %d, error = %d\n", 1056 sc->sc_dev.dv_xname, idx, err); 1057 panic("sq_add_rxbuf"); /* XXX */ 1058 } 1059 1060 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[idx], 0, 1061 sc->sc_rxmap[idx]->dm_mapsize, BUS_DMASYNC_PREREAD); 1062 1063 SQ_INIT_RXDESC(sc, idx); 1064 1065 return 0; 1066} 1067 1068void 1069sq_dump_buffer(u_int32_t addr, u_int32_t len) 1070{ 1071 int i; 1072 u_char* physaddr = (char*) MIPS_PHYS_TO_KSEG1((caddr_t)addr); 1073 1074 if (len == 0) 1075 return; 1076 1077 printf("%p: ", physaddr); 1078 1079 for(i = 0; i < len; i++) { 1080 printf("%02x ", *(physaddr + i) & 0xff); 1081 if ((i % 16) == 15 && i != len - 1) 1082 printf("\n%p: ", physaddr + i); 1083 } 1084 1085 printf("\n"); 1086} 1087 1088 1089void 1090enaddr_aton(const char* str, u_int8_t* eaddr) 1091{ 1092 int i; 1093 char c; 1094 1095 for(i = 0; i < ETHER_ADDR_LEN; i++) { 1096 if (*str == ':') 1097 str++; 1098 1099 c = *str++; 1100 if (isdigit(c)) { 1101 eaddr[i] = (c - '0'); 1102 } else if (isxdigit(c)) { 1103 eaddr[i] = (toupper(c) + 10 - 'A'); 1104 } 1105 1106 c = *str++; 1107 if (isdigit(c)) { 1108 eaddr[i] = (eaddr[i] << 4) | (c - '0'); 1109 } else if (isxdigit(c)) { 1110 eaddr[i] = (eaddr[i] << 4) | (toupper(c) + 10 - 'A'); 1111 } 1112 } 1113} 1114