1 /* $NetBSD: sbmac.c,v 1.26 2007/10/17 19:55:40 garbled Exp $ */ 2 3 /* 4 * Copyright 2000, 2001, 2004 5 * Broadcom Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and copied only 8 * in accordance with the following terms and conditions. Subject to these 9 * conditions, you may download, copy, install, use, modify and distribute 10 * modified or unmodified copies of this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce and 14 * retain this copyright notice and list of conditions as they appear in 15 * the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Broadcom Corporation. The "Broadcom Corporation" name may not be 19 * used to endorse or promote products derived from this software 20 * without the prior written permission of Broadcom Corporation. 21 * 22 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 25 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 26 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 27 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 32 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: sbmac.c,v 1.26 2007/10/17 19:55:40 garbled Exp $"); 37 38 #include "bpfilter.h" 39 #include "opt_inet.h" 40 #include "opt_ns.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/sockio.h> 45 #include <sys/mbuf.h> 46 #include <sys/malloc.h> 47 #include <sys/kernel.h> 48 #include <sys/socket.h> 49 #include <sys/queue.h> 50 #include <sys/device.h> 51 52 #include <net/if.h> 53 #include <net/if_arp.h> 54 #include <net/if_ether.h> 55 #include <net/if_dl.h> 56 #include <net/if_media.h> 57 58 #if NBPFILTER > 0 59 #include <net/bpf.h> 60 #endif 61 62 #ifdef INET 63 #include <netinet/in.h> 64 #include <netinet/if_inarp.h> 65 #endif 66 67 #ifdef NS 68 #include <netns/ns.h> 69 #include <netns/ns_if.h> 70 #endif 71 72 #include <machine/locore.h> 73 74 #include "sbobiovar.h" 75 76 #include <dev/mii/mii.h> 77 #include <dev/mii/miivar.h> 78 #include <dev/mii/mii_bitbang.h> 79 80 #include <mips/sibyte/include/sb1250_defs.h> 81 #include <mips/sibyte/include/sb1250_regs.h> 82 #include <mips/sibyte/include/sb1250_mac.h> 83 #include <mips/sibyte/include/sb1250_dma.h> 84 #include <mips/sibyte/include/sb1250_scd.h> 85 86 /* Simple types */ 87 88 typedef u_long sbmac_port_t; 89 typedef uint64_t sbmac_physaddr_t; 90 typedef uint64_t sbmac_enetaddr_t; 91 92 typedef enum { sbmac_speed_auto, sbmac_speed_10, 93 sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t; 94 95 typedef enum { sbmac_duplex_auto, sbmac_duplex_half, 96 sbmac_duplex_full } sbmac_duplex_t; 97 98 typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame, 99 sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t; 100 101 typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on, 102 sbmac_state_broken } sbmac_state_t; 103 104 105 /* Macros */ 106 107 #define SBMAC_EVENT_COUNTERS /* Include counters for various events */ 108 109 #define SBDMA_NEXTBUF(d, f) ((f + 1) & (d)->sbdma_dscr_mask) 110 111 #define CACHELINESIZE 32 112 #define NUMCACHEBLKS(x) (((x)+CACHELINESIZE-1)/CACHELINESIZE) 113 #define KMALLOC(x) malloc((x), M_DEVBUF, M_DONTWAIT) 114 #define KVTOPHYS(x) kvtophys((vaddr_t)(x)) 115 116 #ifdef SBMACDEBUG 117 #define dprintf(x) printf x 118 #else 119 #define dprintf(x) 120 #endif 121 122 #define SBMAC_READCSR(t) mips3_ld((uint64_t *) (t)) 123 #define SBMAC_WRITECSR(t, v) mips3_sd((uint64_t *) (t), (v)) 124 125 #define PKSEG1(x) ((sbmac_port_t) MIPS_PHYS_TO_KSEG1(x)) 126 127 /* These are limited to fit within one virtual page, and must be 2**N. */ 128 #define SBMAC_MAX_TXDESCR 256 /* should be 1024 */ 129 #define SBMAC_MAX_RXDESCR 256 /* should be 512 */ 130 131 #define ETHER_ALIGN 2 132 133 /* DMA Descriptor structure */ 134 135 typedef struct sbdmadscr_s { 136 uint64_t dscr_a; 137 uint64_t dscr_b; 138 } sbdmadscr_t; 139 140 141 /* DMA Controller structure */ 142 143 typedef struct sbmacdma_s { 144 145 /* 146 * This stuff is used to identify the channel and the registers 147 * associated with it. 148 */ 149 150 struct sbmac_softc *sbdma_eth; /* back pointer to associated MAC */ 151 int sbdma_channel; /* channel number */ 152 int sbdma_txdir; /* direction (1=transmit) */ 153 int sbdma_maxdescr; /* total # of descriptors in ring */ 154 sbmac_port_t sbdma_config0; /* DMA config register 0 */ 155 sbmac_port_t sbdma_config1; /* DMA config register 1 */ 156 sbmac_port_t sbdma_dscrbase; /* Descriptor base address */ 157 sbmac_port_t sbdma_dscrcnt; /* Descriptor count register */ 158 sbmac_port_t sbdma_curdscr; /* current descriptor address */ 159 160 /* 161 * This stuff is for maintenance of the ring 162 */ 163 sbdmadscr_t *sbdma_dscrtable; /* base of descriptor table */ 164 struct mbuf **sbdma_ctxtable; /* context table, one per descr */ 165 unsigned int sbdma_dscr_mask; /* sbdma_maxdescr - 1 */ 166 paddr_t sbdma_dscrtable_phys; /* and also the phys addr */ 167 unsigned int sbdma_add_index; /* next dscr for sw to add */ 168 unsigned int sbdma_rem_index; /* next dscr for sw to remove */ 169 } sbmacdma_t; 170 171 172 /* Ethernet softc structure */ 173 174 struct sbmac_softc { 175 176 /* 177 * NetBSD-specific things 178 */ 179 struct device sc_dev; /* base device (must be first) */ 180 struct ethercom sc_ethercom; /* Ethernet common part */ 181 struct mii_data sc_mii; 182 struct callout sc_tick_ch; 183 184 int sbm_if_flags; 185 void *sbm_intrhand; 186 187 /* 188 * Controller-specific things 189 */ 190 191 sbmac_port_t sbm_base; /* MAC's base address */ 192 sbmac_state_t sbm_state; /* current state */ 193 194 sbmac_port_t sbm_macenable; /* MAC Enable Register */ 195 sbmac_port_t sbm_maccfg; /* MAC Configuration Register */ 196 sbmac_port_t sbm_fifocfg; /* FIFO configuration register */ 197 sbmac_port_t sbm_framecfg; /* Frame configuration register */ 198 sbmac_port_t sbm_rxfilter; /* receive filter register */ 199 sbmac_port_t sbm_isr; /* Interrupt status register */ 200 sbmac_port_t sbm_imr; /* Interrupt mask register */ 201 202 sbmac_speed_t sbm_speed; /* current speed */ 203 sbmac_duplex_t sbm_duplex; /* current duplex */ 204 sbmac_fc_t sbm_fc; /* current flow control setting */ 205 int sbm_rxflags; /* received packet flags */ 206 207 u_char sbm_hwaddr[ETHER_ADDR_LEN]; 208 209 sbmacdma_t sbm_txdma; /* for now, only use channel 0 */ 210 sbmacdma_t sbm_rxdma; 211 212 int sbm_pass3_dma; /* chip has pass3 SOC DMA features */ 213 214 #ifdef SBMAC_EVENT_COUNTERS 215 struct evcnt sbm_ev_rxintr; /* Rx interrupts */ 216 struct evcnt sbm_ev_txintr; /* Tx interrupts */ 217 struct evcnt sbm_ev_txdrop; /* Tx dropped due to no mbuf alloc failed */ 218 struct evcnt sbm_ev_txstall; /* Tx stalled due to no descriptors free */ 219 220 struct evcnt sbm_ev_txsplit; /* pass3 Tx split mbuf */ 221 struct evcnt sbm_ev_txkeep; /* pass3 Tx didn't split mbuf */ 222 #endif 223 }; 224 225 226 #ifdef SBMAC_EVENT_COUNTERS 227 #define SBMAC_EVCNT_INCR(ev) (ev).ev_count++ 228 #else 229 #define SBMAC_EVCNT_INCR(ev) do { /* nothing */ } while (0) 230 #endif 231 232 /* Externs */ 233 234 extern paddr_t kvtophys(vaddr_t); 235 236 /* Prototypes */ 237 238 static void sbdma_initctx(sbmacdma_t *d, struct sbmac_softc *s, int chan, 239 int txrx, int maxdescr); 240 static void sbdma_channel_start(sbmacdma_t *d); 241 static int sbdma_add_rcvbuffer(sbmacdma_t *d, struct mbuf *m); 242 static int sbdma_add_txbuffer(sbmacdma_t *d, struct mbuf *m); 243 static void sbdma_emptyring(sbmacdma_t *d); 244 static void sbdma_fillring(sbmacdma_t *d); 245 static void sbdma_rx_process(struct sbmac_softc *sc, sbmacdma_t *d); 246 static void sbdma_tx_process(struct sbmac_softc *sc, sbmacdma_t *d); 247 static void sbmac_initctx(struct sbmac_softc *s); 248 static void sbmac_channel_start(struct sbmac_softc *s); 249 static void sbmac_channel_stop(struct sbmac_softc *s); 250 static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *, 251 sbmac_state_t); 252 static void sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff); 253 static void sbmac_init_and_start(struct sbmac_softc *sc); 254 static uint64_t sbmac_addr2reg(u_char *ptr); 255 static void sbmac_intr(void *xsc, uint32_t status, uint32_t pc); 256 static void sbmac_start(struct ifnet *ifp); 257 static void sbmac_setmulti(struct sbmac_softc *sc); 258 static int sbmac_ether_ioctl(struct ifnet *ifp, u_long cmd, void *data); 259 static int sbmac_ioctl(struct ifnet *ifp, u_long command, void *data); 260 static int sbmac_mediachange(struct ifnet *ifp); 261 static void sbmac_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr); 262 static void sbmac_watchdog(struct ifnet *ifp); 263 static int sbmac_match(struct device *parent, struct cfdata *match, void *aux); 264 static void sbmac_attach(struct device *parent, struct device *self, void *aux); 265 static int sbmac_set_speed(struct sbmac_softc *s, sbmac_speed_t speed); 266 static int sbmac_set_duplex(struct sbmac_softc *s, sbmac_duplex_t duplex, 267 sbmac_fc_t fc); 268 static void sbmac_tick(void *arg); 269 270 271 /* Globals */ 272 273 CFATTACH_DECL(sbmac, sizeof(struct sbmac_softc), 274 sbmac_match, sbmac_attach, NULL, NULL); 275 276 static uint32_t sbmac_mii_bitbang_read(struct device *self); 277 static void sbmac_mii_bitbang_write(struct device *self, uint32_t val); 278 279 static const struct mii_bitbang_ops sbmac_mii_bitbang_ops = { 280 sbmac_mii_bitbang_read, 281 sbmac_mii_bitbang_write, 282 { 283 (uint32_t)M_MAC_MDIO_OUT, /* MII_BIT_MDO */ 284 (uint32_t)M_MAC_MDIO_IN, /* MII_BIT_MDI */ 285 (uint32_t)M_MAC_MDC, /* MII_BIT_MDC */ 286 0, /* MII_BIT_DIR_HOST_PHY */ 287 (uint32_t)M_MAC_MDIO_DIR /* MII_BIT_DIR_PHY_HOST */ 288 } 289 }; 290 291 static uint32_t 292 sbmac_mii_bitbang_read(struct device *self) 293 { 294 struct sbmac_softc *sc = (void *) self; 295 sbmac_port_t reg; 296 297 reg = PKSEG1(sc->sbm_base + R_MAC_MDIO); 298 return (uint32_t) SBMAC_READCSR(reg); 299 } 300 301 static void 302 sbmac_mii_bitbang_write(struct device *self, uint32_t val) 303 { 304 struct sbmac_softc *sc = (void *) self; 305 sbmac_port_t reg; 306 307 reg = PKSEG1(sc->sbm_base + R_MAC_MDIO); 308 309 SBMAC_WRITECSR(reg, (val & 310 (M_MAC_MDC|M_MAC_MDIO_DIR|M_MAC_MDIO_OUT|M_MAC_MDIO_IN))); 311 } 312 313 /* 314 * Read an PHY register through the MII. 315 */ 316 static int 317 sbmac_mii_readreg(struct device *self, int phy, int reg) 318 { 319 320 return (mii_bitbang_readreg(self, &sbmac_mii_bitbang_ops, phy, reg)); 321 } 322 323 /* 324 * Write to a PHY register through the MII. 325 */ 326 static void 327 sbmac_mii_writereg(struct device *self, int phy, int reg, int val) 328 { 329 330 mii_bitbang_writereg(self, &sbmac_mii_bitbang_ops, phy, reg, val); 331 } 332 333 static void 334 sbmac_mii_statchg(struct device *self) 335 { 336 struct sbmac_softc *sc = (struct sbmac_softc *)self; 337 sbmac_state_t oldstate; 338 339 /* Stop the MAC in preparation for changing all of the parameters. */ 340 oldstate = sbmac_set_channel_state(sc, sbmac_state_off); 341 342 switch (sc->sc_ethercom.ec_if.if_baudrate) { 343 default: /* if autonegotiation fails, assume 10Mbit */ 344 case IF_Mbps(10): 345 sbmac_set_speed(sc, sbmac_speed_10); 346 break; 347 348 case IF_Mbps(100): 349 sbmac_set_speed(sc, sbmac_speed_100); 350 break; 351 352 case IF_Mbps(1000): 353 sbmac_set_speed(sc, sbmac_speed_1000); 354 break; 355 } 356 357 if (sc->sc_mii.mii_media_active & IFM_FDX) { 358 /* Configure for full-duplex */ 359 /* XXX: is flow control right for 10, 100? */ 360 sbmac_set_duplex(sc, sbmac_duplex_full, sbmac_fc_frame); 361 } else { 362 /* Configure for half-duplex */ 363 /* XXX: is flow control right? */ 364 sbmac_set_duplex(sc, sbmac_duplex_half, sbmac_fc_disabled); 365 } 366 367 /* And put it back into its former state. */ 368 sbmac_set_channel_state(sc, oldstate); 369 } 370 371 /* 372 * SBDMA_INITCTX(d, s, chan, txrx, maxdescr) 373 * 374 * Initialize a DMA channel context. Since there are potentially 375 * eight DMA channels per MAC, it's nice to do this in a standard 376 * way. 377 * 378 * Input parameters: 379 * d - sbmacdma_t structure (DMA channel context) 380 * s - sbmac_softc structure (pointer to a MAC) 381 * chan - channel number (0..1 right now) 382 * txrx - Identifies DMA_TX or DMA_RX for channel direction 383 * maxdescr - number of descriptors 384 * 385 * Return value: 386 * nothing 387 */ 388 389 static void 390 sbdma_initctx(sbmacdma_t *d, struct sbmac_softc *s, int chan, int txrx, 391 int maxdescr) 392 { 393 /* 394 * Save away interesting stuff in the structure 395 */ 396 397 d->sbdma_eth = s; 398 d->sbdma_channel = chan; 399 d->sbdma_txdir = txrx; 400 401 /* 402 * initialize register pointers 403 */ 404 405 d->sbdma_config0 = PKSEG1(s->sbm_base + 406 R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_CONFIG0)); 407 d->sbdma_config1 = PKSEG1(s->sbm_base + 408 R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_CONFIG1)); 409 d->sbdma_dscrbase = PKSEG1(s->sbm_base + 410 R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_DSCR_BASE)); 411 d->sbdma_dscrcnt = PKSEG1(s->sbm_base + 412 R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_DSCR_CNT)); 413 d->sbdma_curdscr = PKSEG1(s->sbm_base + 414 R_MAC_DMA_REGISTER(txrx, chan, R_MAC_DMA_CUR_DSCRADDR)); 415 416 /* 417 * Allocate memory for the ring 418 */ 419 420 d->sbdma_maxdescr = maxdescr; 421 d->sbdma_dscr_mask = d->sbdma_maxdescr - 1; 422 423 d->sbdma_dscrtable = (sbdmadscr_t *) 424 KMALLOC(d->sbdma_maxdescr * sizeof(sbdmadscr_t)); 425 426 bzero(d->sbdma_dscrtable, d->sbdma_maxdescr*sizeof(sbdmadscr_t)); 427 428 d->sbdma_dscrtable_phys = KVTOPHYS(d->sbdma_dscrtable); 429 430 /* 431 * And context table 432 */ 433 434 d->sbdma_ctxtable = (struct mbuf **) 435 KMALLOC(d->sbdma_maxdescr*sizeof(struct mbuf *)); 436 437 bzero(d->sbdma_ctxtable, d->sbdma_maxdescr*sizeof(struct mbuf *)); 438 } 439 440 /* 441 * SBDMA_CHANNEL_START(d) 442 * 443 * Initialize the hardware registers for a DMA channel. 444 * 445 * Input parameters: 446 * d - DMA channel to init (context must be previously init'd 447 * 448 * Return value: 449 * nothing 450 */ 451 452 static void 453 sbdma_channel_start(sbmacdma_t *d) 454 { 455 /* 456 * Turn on the DMA channel 457 */ 458 459 SBMAC_WRITECSR(d->sbdma_config1, 0); 460 461 SBMAC_WRITECSR(d->sbdma_dscrbase, d->sbdma_dscrtable_phys); 462 463 SBMAC_WRITECSR(d->sbdma_config0, V_DMA_RINGSZ(d->sbdma_maxdescr) | 0); 464 465 /* 466 * Initialize ring pointers 467 */ 468 469 d->sbdma_add_index = 0; 470 d->sbdma_rem_index = 0; 471 } 472 473 /* 474 * SBDMA_ADD_RCVBUFFER(d, m) 475 * 476 * Add a buffer to the specified DMA channel. For receive channels, 477 * this queues a buffer for inbound packets. 478 * 479 * Input parameters: 480 * d - DMA channel descriptor 481 * m - mbuf to add, or NULL if we should allocate one. 482 * 483 * Return value: 484 * 0 if buffer could not be added (ring is full) 485 * 1 if buffer added successfully 486 */ 487 488 static int 489 sbdma_add_rcvbuffer(sbmacdma_t *d, struct mbuf *m) 490 { 491 unsigned int dsc, nextdsc; 492 struct mbuf *m_new = NULL; 493 494 /* get pointer to our current place in the ring */ 495 496 dsc = d->sbdma_add_index; 497 nextdsc = SBDMA_NEXTBUF(d, d->sbdma_add_index); 498 499 /* 500 * figure out if the ring is full - if the next descriptor 501 * is the same as the one that we're going to remove from 502 * the ring, the ring is full 503 */ 504 505 if (nextdsc == d->sbdma_rem_index) 506 return ENOSPC; 507 508 /* 509 * Allocate an mbuf if we don't already have one. 510 * If we do have an mbuf, reset it so that it's empty. 511 */ 512 513 if (m == NULL) { 514 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 515 if (m_new == NULL) { 516 printf("%s: mbuf allocation failed\n", 517 d->sbdma_eth->sc_dev.dv_xname); 518 return ENOBUFS; 519 } 520 521 MCLGET(m_new, M_DONTWAIT); 522 if (!(m_new->m_flags & M_EXT)) { 523 printf("%s: mbuf cluster allocation failed\n", 524 d->sbdma_eth->sc_dev.dv_xname); 525 m_freem(m_new); 526 return ENOBUFS; 527 } 528 529 m_new->m_len = m_new->m_pkthdr.len= MCLBYTES; 530 m_adj(m_new, ETHER_ALIGN); 531 } else { 532 m_new = m; 533 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 534 m_new->m_data = m_new->m_ext.ext_buf; 535 m_adj(m_new, ETHER_ALIGN); 536 } 537 538 /* 539 * fill in the descriptor 540 */ 541 542 d->sbdma_dscrtable[dsc].dscr_a = KVTOPHYS(mtod(m_new, void *)) | 543 V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(ETHER_ALIGN + m_new->m_len)) | 544 M_DMA_DSCRA_INTERRUPT; 545 546 /* receiving: no options */ 547 d->sbdma_dscrtable[dsc].dscr_b = 0; 548 549 /* 550 * fill in the context 551 */ 552 553 d->sbdma_ctxtable[dsc] = m_new; 554 555 /* 556 * point at next packet 557 */ 558 559 d->sbdma_add_index = nextdsc; 560 561 /* 562 * Give the buffer to the DMA engine. 563 */ 564 565 SBMAC_WRITECSR(d->sbdma_dscrcnt, 1); 566 567 return 0; /* we did it */ 568 } 569 570 /* 571 * SBDMA_ADD_TXBUFFER(d, m) 572 * 573 * Add a transmit buffer to the specified DMA channel, causing a 574 * transmit to start. 575 * 576 * Input parameters: 577 * d - DMA channel descriptor 578 * m - mbuf to add 579 * 580 * Return value: 581 * 0 transmit queued successfully 582 * otherwise error code 583 */ 584 585 static int 586 sbdma_add_txbuffer(sbmacdma_t *d, struct mbuf *m) 587 { 588 unsigned int dsc, nextdsc, prevdsc, origdesc; 589 int length; 590 int num_mbufs = 0; 591 struct sbmac_softc *sc = d->sbdma_eth; 592 593 /* get pointer to our current place in the ring */ 594 595 dsc = d->sbdma_add_index; 596 nextdsc = SBDMA_NEXTBUF(d, d->sbdma_add_index); 597 598 /* 599 * figure out if the ring is full - if the next descriptor 600 * is the same as the one that we're going to remove from 601 * the ring, the ring is full 602 */ 603 604 if (nextdsc == d->sbdma_rem_index) { 605 SBMAC_EVCNT_INCR(sc->sbm_ev_txstall); 606 return ENOSPC; 607 } 608 609 /* 610 * PASS3 parts do not have buffer alignment restriction. 611 * No need to copy/coalesce to new mbuf. Also has different 612 * descriptor format 613 */ 614 if (sc->sbm_pass3_dma) { 615 struct mbuf *m_temp = NULL; 616 617 /* 618 * Loop thru this mbuf record. 619 * The head mbuf will have SOP set. 620 */ 621 d->sbdma_dscrtable[dsc].dscr_a = KVTOPHYS(mtod(m,void *)) | 622 M_DMA_ETHTX_SOP; 623 624 /* 625 * transmitting: set outbound options,buffer A size(+ low 5 626 * bits of start addr),and packet length. 627 */ 628 d->sbdma_dscrtable[dsc].dscr_b = 629 V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) | 630 V_DMA_DSCRB_A_SIZE((m->m_len + 631 (mtod(m,unsigned int) & 0x0000001F))) | 632 V_DMA_DSCRB_PKT_SIZE_MSB((m->m_pkthdr.len & 0xc000) >> 14) | 633 V_DMA_DSCRB_PKT_SIZE(m->m_pkthdr.len & 0x3fff); 634 635 d->sbdma_add_index = nextdsc; 636 origdesc = prevdsc = dsc; 637 dsc = d->sbdma_add_index; 638 num_mbufs++; 639 640 /* Start with first non-head mbuf */ 641 for(m_temp = m->m_next; m_temp != 0; m_temp = m_temp->m_next) { 642 int len, next_len; 643 uint64_t addr; 644 645 if (m_temp->m_len == 0) 646 continue; /* Skip 0-length mbufs */ 647 648 len = m_temp->m_len; 649 addr = KVTOPHYS(mtod(m_temp, void *)); 650 651 /* 652 * Check to see if the mbuf spans a page boundary. If 653 * it does, and the physical pages behind the virtual 654 * pages are not contiguous, split it so that each 655 * virtual page uses it's own Tx descriptor. 656 */ 657 if (trunc_page(addr) != trunc_page(addr + len - 1)) { 658 next_len = (addr + len) - trunc_page(addr + len); 659 660 len -= next_len; 661 662 if (addr + len == 663 KVTOPHYS(mtod(m_temp, char *) + len)) { 664 SBMAC_EVCNT_INCR(sc->sbm_ev_txkeep); 665 len += next_len; 666 next_len = 0; 667 } else { 668 SBMAC_EVCNT_INCR(sc->sbm_ev_txsplit); 669 } 670 } else { 671 next_len = 0; 672 } 673 674 again: 675 /* 676 * fill in the descriptor 677 */ 678 d->sbdma_dscrtable[dsc].dscr_a = addr; 679 680 /* 681 * transmitting: set outbound options,buffer A 682 * size(+ low 5 bits of start addr) 683 */ 684 d->sbdma_dscrtable[dsc].dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_NOTSOP) | 685 V_DMA_DSCRB_A_SIZE((len + (addr & 0x0000001F))); 686 687 d->sbdma_ctxtable[dsc] = NULL; 688 689 /* 690 * point at next descriptor 691 */ 692 nextdsc = SBDMA_NEXTBUF(d, d->sbdma_add_index); 693 if (nextdsc == d->sbdma_rem_index) { 694 d->sbdma_add_index = origdesc; 695 SBMAC_EVCNT_INCR(sc->sbm_ev_txstall); 696 return ENOSPC; 697 } 698 d->sbdma_add_index = nextdsc; 699 700 prevdsc = dsc; 701 dsc = d->sbdma_add_index; 702 num_mbufs++; 703 704 if (next_len != 0) { 705 addr = KVTOPHYS(mtod(m_temp, char *) + len); 706 len = next_len; 707 708 next_len = 0; 709 goto again; 710 } 711 712 } 713 /* Set head mbuf to last context index */ 714 d->sbdma_ctxtable[prevdsc] = m; 715 716 /* Interrupt on last dscr of packet. */ 717 d->sbdma_dscrtable[prevdsc].dscr_a |= M_DMA_DSCRA_INTERRUPT; 718 } else { 719 struct mbuf *m_new = NULL; 720 /* 721 * [BEGIN XXX] 722 * XXX Copy/coalesce the mbufs into a single mbuf cluster (we 723 * assume it will fit). This is a temporary hack to get us 724 * going. 725 */ 726 727 MGETHDR(m_new,M_DONTWAIT,MT_DATA); 728 if (m_new == NULL) { 729 printf("%s: mbuf allocation failed\n", 730 d->sbdma_eth->sc_dev.dv_xname); 731 SBMAC_EVCNT_INCR(sc->sbm_ev_txdrop); 732 return ENOBUFS; 733 } 734 735 MCLGET(m_new,M_DONTWAIT); 736 if (!(m_new->m_flags & M_EXT)) { 737 printf("%s: mbuf cluster allocation failed\n", 738 d->sbdma_eth->sc_dev.dv_xname); 739 m_freem(m_new); 740 SBMAC_EVCNT_INCR(sc->sbm_ev_txdrop); 741 return ENOBUFS; 742 } 743 744 m_new->m_len = m_new->m_pkthdr.len= MCLBYTES; 745 /*m_adj(m_new,ETHER_ALIGN);*/ 746 747 /* 748 * XXX Don't forget to include the offset portion in the 749 * XXX cache block calculation when this code is rewritten! 750 */ 751 752 /* 753 * Copy data 754 */ 755 756 m_copydata(m,0,m->m_pkthdr.len,mtod(m_new,void *)); 757 m_new->m_len = m_new->m_pkthdr.len = m->m_pkthdr.len; 758 759 /* Free old mbuf 'm', actual mbuf is now 'm_new' */ 760 761 // XXX: CALLERS WILL FREE, they might have to bpf_mtap() if this 762 // XXX: function succeeds. 763 // m_freem(m); 764 length = m_new->m_len; 765 766 /* [END XXX] */ 767 /* 768 * fill in the descriptor 769 */ 770 771 d->sbdma_dscrtable[dsc].dscr_a = KVTOPHYS(mtod(m_new,void *)) | 772 V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(m_new->m_len)) | 773 M_DMA_DSCRA_INTERRUPT | 774 M_DMA_ETHTX_SOP; 775 776 /* transmitting: set outbound options and length */ 777 d->sbdma_dscrtable[dsc].dscr_b = 778 V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) | 779 V_DMA_DSCRB_PKT_SIZE(length); 780 781 num_mbufs++; 782 783 /* 784 * fill in the context 785 */ 786 787 d->sbdma_ctxtable[dsc] = m_new; 788 789 /* 790 * point at next packet 791 */ 792 d->sbdma_add_index = nextdsc; 793 } 794 795 /* 796 * Give the buffer to the DMA engine. 797 */ 798 799 SBMAC_WRITECSR(d->sbdma_dscrcnt, num_mbufs); 800 801 return 0; /* we did it */ 802 } 803 804 /* 805 * SBDMA_EMPTYRING(d) 806 * 807 * Free all allocated mbufs on the specified DMA channel; 808 * 809 * Input parameters: 810 * d - DMA channel 811 * 812 * Return value: 813 * nothing 814 */ 815 816 static void 817 sbdma_emptyring(sbmacdma_t *d) 818 { 819 int idx; 820 struct mbuf *m; 821 822 for (idx = 0; idx < d->sbdma_maxdescr; idx++) { 823 m = d->sbdma_ctxtable[idx]; 824 if (m) { 825 m_freem(m); 826 d->sbdma_ctxtable[idx] = NULL; 827 } 828 } 829 } 830 831 /* 832 * SBDMA_FILLRING(d) 833 * 834 * Fill the specified DMA channel (must be receive channel) 835 * with mbufs 836 * 837 * Input parameters: 838 * d - DMA channel 839 * 840 * Return value: 841 * nothing 842 */ 843 844 static void 845 sbdma_fillring(sbmacdma_t *d) 846 { 847 int idx; 848 849 for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) 850 if (sbdma_add_rcvbuffer(d, NULL) != 0) 851 break; 852 } 853 854 /* 855 * SBDMA_RX_PROCESS(sc, d) 856 * 857 * Process "completed" receive buffers on the specified DMA channel. 858 * Note that this isn't really ideal for priority channels, since 859 * it processes all of the packets on a given channel before 860 * returning. 861 * 862 * Input parameters: 863 * sc - softc structure 864 * d - DMA channel context 865 * 866 * Return value: 867 * nothing 868 */ 869 870 static void 871 sbdma_rx_process(struct sbmac_softc *sc, sbmacdma_t *d) 872 { 873 int curidx; 874 int hwidx; 875 sbdmadscr_t *dscp; 876 struct mbuf *m; 877 int len; 878 879 struct ifnet *ifp = &(sc->sc_ethercom.ec_if); 880 881 for (;;) { 882 /* 883 * figure out where we are (as an index) and where 884 * the hardware is (also as an index) 885 * 886 * This could be done faster if (for example) the 887 * descriptor table was page-aligned and contiguous in 888 * both virtual and physical memory -- you could then 889 * just compare the low-order bits of the virtual address 890 * (sbdma_rem_index) and the physical address 891 * (sbdma_curdscr CSR). 892 */ 893 894 curidx = d->sbdma_rem_index; 895 hwidx = (int) 896 (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - 897 d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t)); 898 899 /* 900 * If they're the same, that means we've processed all 901 * of the descriptors up to (but not including) the one that 902 * the hardware is working on right now. 903 */ 904 905 if (curidx == hwidx) 906 break; 907 908 /* 909 * Otherwise, get the packet's mbuf ptr back 910 */ 911 912 dscp = &(d->sbdma_dscrtable[curidx]); 913 m = d->sbdma_ctxtable[curidx]; 914 d->sbdma_ctxtable[curidx] = NULL; 915 916 len = (int)G_DMA_DSCRB_PKT_SIZE(dscp->dscr_b) - 4; 917 918 /* 919 * Check packet status. If good, process it. 920 * If not, silently drop it and put it back on the 921 * receive ring. 922 */ 923 924 if (! (dscp->dscr_a & M_DMA_ETHRX_BAD)) { 925 926 /* 927 * Set length into the packet 928 * XXX do we remove the CRC here? 929 */ 930 m->m_pkthdr.len = m->m_len = len; 931 932 ifp->if_ipackets++; 933 m->m_pkthdr.rcvif = ifp; 934 935 936 /* 937 * Add a new buffer to replace the old one. 938 */ 939 sbdma_add_rcvbuffer(d, NULL); 940 941 #if (NBPFILTER > 0) 942 /* 943 * Handle BPF listeners. Let the BPF user see the 944 * packet, but don't pass it up to the ether_input() 945 * layer unless it's a broadcast packet, multicast 946 * packet, matches our ethernet address or the 947 * interface is in promiscuous mode. 948 */ 949 950 if (ifp->if_bpf) 951 bpf_mtap(ifp->if_bpf, m); 952 #endif 953 /* 954 * Pass the buffer to the kernel 955 */ 956 (*ifp->if_input)(ifp, m); 957 } else { 958 /* 959 * Packet was mangled somehow. Just drop it and 960 * put it back on the receive ring. 961 */ 962 sbdma_add_rcvbuffer(d, m); 963 } 964 965 /* 966 * .. and advance to the next buffer. 967 */ 968 969 d->sbdma_rem_index = SBDMA_NEXTBUF(d, d->sbdma_rem_index); 970 } 971 } 972 973 /* 974 * SBDMA_TX_PROCESS(sc, d) 975 * 976 * Process "completed" transmit buffers on the specified DMA channel. 977 * This is normally called within the interrupt service routine. 978 * Note that this isn't really ideal for priority channels, since 979 * it processes all of the packets on a given channel before 980 * returning. 981 * 982 * Input parameters: 983 * sc - softc structure 984 * d - DMA channel context 985 * 986 * Return value: 987 * nothing 988 */ 989 990 static void 991 sbdma_tx_process(struct sbmac_softc *sc, sbmacdma_t *d) 992 { 993 int curidx; 994 int hwidx; 995 struct mbuf *m; 996 997 struct ifnet *ifp = &(sc->sc_ethercom.ec_if); 998 999 for (;;) { 1000 /* 1001 * figure out where we are (as an index) and where 1002 * the hardware is (also as an index) 1003 * 1004 * This could be done faster if (for example) the 1005 * descriptor table was page-aligned and contiguous in 1006 * both virtual and physical memory -- you could then 1007 * just compare the low-order bits of the virtual address 1008 * (sbdma_rem_index) and the physical address 1009 * (sbdma_curdscr CSR). 1010 */ 1011 1012 curidx = d->sbdma_rem_index; 1013 hwidx = (int) 1014 (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - 1015 d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t)); 1016 1017 /* 1018 * If they're the same, that means we've processed all 1019 * of the descriptors up to (but not including) the one that 1020 * the hardware is working on right now. 1021 */ 1022 1023 if (curidx == hwidx) 1024 break; 1025 1026 /* 1027 * Otherwise, get the packet's mbuf ptr back 1028 */ 1029 1030 m = d->sbdma_ctxtable[curidx]; 1031 d->sbdma_ctxtable[curidx] = NULL; 1032 1033 /* 1034 * for transmits we just free buffers and count packets. 1035 */ 1036 ifp->if_opackets++; 1037 m_freem(m); 1038 1039 /* 1040 * .. and advance to the next buffer. 1041 */ 1042 1043 d->sbdma_rem_index = SBDMA_NEXTBUF(d, d->sbdma_rem_index); 1044 } 1045 1046 /* 1047 * Decide what to set the IFF_OACTIVE bit in the interface to. 1048 * It's supposed to reflect if the interface is actively 1049 * transmitting, but that's really hard to do quickly. 1050 */ 1051 1052 ifp->if_flags &= ~IFF_OACTIVE; 1053 } 1054 1055 /* 1056 * SBMAC_INITCTX(s) 1057 * 1058 * Initialize an Ethernet context structure - this is called 1059 * once per MAC on the 1250. Memory is allocated here, so don't 1060 * call it again from inside the ioctl routines that bring the 1061 * interface up/down 1062 * 1063 * Input parameters: 1064 * s - sbmac context structure 1065 * 1066 * Return value: 1067 * 0 1068 */ 1069 1070 static void 1071 sbmac_initctx(struct sbmac_softc *s) 1072 { 1073 uint64_t sysrev; 1074 1075 /* 1076 * figure out the addresses of some ports 1077 */ 1078 1079 s->sbm_macenable = PKSEG1(s->sbm_base + R_MAC_ENABLE); 1080 s->sbm_maccfg = PKSEG1(s->sbm_base + R_MAC_CFG); 1081 s->sbm_fifocfg = PKSEG1(s->sbm_base + R_MAC_THRSH_CFG); 1082 s->sbm_framecfg = PKSEG1(s->sbm_base + R_MAC_FRAMECFG); 1083 s->sbm_rxfilter = PKSEG1(s->sbm_base + R_MAC_ADFILTER_CFG); 1084 s->sbm_isr = PKSEG1(s->sbm_base + R_MAC_STATUS); 1085 s->sbm_imr = PKSEG1(s->sbm_base + R_MAC_INT_MASK); 1086 1087 /* 1088 * Initialize the DMA channels. Right now, only one per MAC is used 1089 * Note: Only do this _once_, as it allocates memory from the kernel! 1090 */ 1091 1092 sbdma_initctx(&(s->sbm_txdma), s, 0, DMA_TX, SBMAC_MAX_TXDESCR); 1093 sbdma_initctx(&(s->sbm_rxdma), s, 0, DMA_RX, SBMAC_MAX_RXDESCR); 1094 1095 /* 1096 * initial state is OFF 1097 */ 1098 1099 s->sbm_state = sbmac_state_off; 1100 1101 /* 1102 * Initial speed is (XXX TEMP) 10MBit/s HDX no FC 1103 */ 1104 1105 s->sbm_speed = sbmac_speed_10; 1106 s->sbm_duplex = sbmac_duplex_half; 1107 s->sbm_fc = sbmac_fc_disabled; 1108 1109 /* 1110 * Determine SOC type. 112x has Pass3 SOC features. 1111 */ 1112 sysrev = SBMAC_READCSR( PKSEG1(A_SCD_SYSTEM_REVISION) ); 1113 s->sbm_pass3_dma = (SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1120 || 1114 SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1125 || 1115 SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1125H || 1116 (SYS_SOC_TYPE(sysrev) == K_SYS_SOC_TYPE_BCM1250 && 1117 G_SYS_REVISION(sysrev) >= K_SYS_REVISION_BCM1250_PASS3)); 1118 #ifdef SBMAC_EVENT_COUNTERS 1119 evcnt_attach_dynamic(&s->sbm_ev_rxintr, EVCNT_TYPE_INTR, 1120 NULL, s->sc_dev.dv_xname, "rxintr"); 1121 evcnt_attach_dynamic(&s->sbm_ev_txintr, EVCNT_TYPE_INTR, 1122 NULL, s->sc_dev.dv_xname, "txintr"); 1123 evcnt_attach_dynamic(&s->sbm_ev_txdrop, EVCNT_TYPE_MISC, 1124 NULL, s->sc_dev.dv_xname, "txdrop"); 1125 evcnt_attach_dynamic(&s->sbm_ev_txstall, EVCNT_TYPE_MISC, 1126 NULL, s->sc_dev.dv_xname, "txstall"); 1127 if (s->sbm_pass3_dma) { 1128 evcnt_attach_dynamic(&s->sbm_ev_txsplit, EVCNT_TYPE_MISC, 1129 NULL, s->sc_dev.dv_xname, "pass3tx-split"); 1130 evcnt_attach_dynamic(&s->sbm_ev_txkeep, EVCNT_TYPE_MISC, 1131 NULL, s->sc_dev.dv_xname, "pass3tx-keep"); 1132 } 1133 #endif 1134 } 1135 1136 /* 1137 * SBMAC_CHANNEL_START(s) 1138 * 1139 * Start packet processing on this MAC. 1140 * 1141 * Input parameters: 1142 * s - sbmac structure 1143 * 1144 * Return value: 1145 * nothing 1146 */ 1147 1148 static void 1149 sbmac_channel_start(struct sbmac_softc *s) 1150 { 1151 uint64_t reg; 1152 sbmac_port_t port; 1153 uint64_t cfg, fifo, framecfg; 1154 int idx; 1155 uint64_t dma_cfg0, fifo_cfg; 1156 sbmacdma_t *txdma; 1157 1158 /* 1159 * Don't do this if running 1160 */ 1161 1162 if (s->sbm_state == sbmac_state_on) 1163 return; 1164 1165 /* 1166 * Bring the controller out of reset, but leave it off. 1167 */ 1168 1169 SBMAC_WRITECSR(s->sbm_macenable, 0); 1170 1171 /* 1172 * Ignore all received packets 1173 */ 1174 1175 SBMAC_WRITECSR(s->sbm_rxfilter, 0); 1176 1177 /* 1178 * Calculate values for various control registers. 1179 */ 1180 1181 cfg = M_MAC_RETRY_EN | 1182 M_MAC_TX_HOLD_SOP_EN | 1183 V_MAC_TX_PAUSE_CNT_16K | 1184 M_MAC_AP_STAT_EN | 1185 M_MAC_SS_EN | 1186 0; 1187 1188 fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ 1189 V_MAC_TX_RD_THRSH(4) | 1190 V_MAC_TX_RL_THRSH(4) | 1191 V_MAC_RX_PL_THRSH(4) | 1192 V_MAC_RX_RD_THRSH(4) | /* Must be '4' */ 1193 V_MAC_RX_PL_THRSH(4) | 1194 V_MAC_RX_RL_THRSH(8) | 1195 0; 1196 1197 framecfg = V_MAC_MIN_FRAMESZ_DEFAULT | 1198 V_MAC_MAX_FRAMESZ_DEFAULT | 1199 V_MAC_BACKOFF_SEL(1); 1200 1201 /* 1202 * Clear out the hash address map 1203 */ 1204 1205 port = PKSEG1(s->sbm_base + R_MAC_HASH_BASE); 1206 for (idx = 0; idx < MAC_HASH_COUNT; idx++) { 1207 SBMAC_WRITECSR(port, 0); 1208 port += sizeof(uint64_t); 1209 } 1210 1211 /* 1212 * Clear out the exact-match table 1213 */ 1214 1215 port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE); 1216 for (idx = 0; idx < MAC_ADDR_COUNT; idx++) { 1217 SBMAC_WRITECSR(port, 0); 1218 port += sizeof(uint64_t); 1219 } 1220 1221 /* 1222 * Clear out the DMA Channel mapping table registers 1223 */ 1224 1225 port = PKSEG1(s->sbm_base + R_MAC_CHUP0_BASE); 1226 for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { 1227 SBMAC_WRITECSR(port, 0); 1228 port += sizeof(uint64_t); 1229 } 1230 1231 port = PKSEG1(s->sbm_base + R_MAC_CHLO0_BASE); 1232 for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { 1233 SBMAC_WRITECSR(port, 0); 1234 port += sizeof(uint64_t); 1235 } 1236 1237 /* 1238 * Program the hardware address. It goes into the hardware-address 1239 * register as well as the first filter register. 1240 */ 1241 1242 reg = sbmac_addr2reg(s->sbm_hwaddr); 1243 1244 port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE); 1245 SBMAC_WRITECSR(port, reg); 1246 port = PKSEG1(s->sbm_base + R_MAC_ETHERNET_ADDR); 1247 SBMAC_WRITECSR(port, 0); // pass1 workaround 1248 1249 /* 1250 * Set the receive filter for no packets, and write values 1251 * to the various config registers 1252 */ 1253 1254 SBMAC_WRITECSR(s->sbm_rxfilter, 0); 1255 SBMAC_WRITECSR(s->sbm_imr, 0); 1256 SBMAC_WRITECSR(s->sbm_framecfg, framecfg); 1257 SBMAC_WRITECSR(s->sbm_fifocfg, fifo); 1258 SBMAC_WRITECSR(s->sbm_maccfg, cfg); 1259 1260 /* 1261 * Initialize DMA channels (rings should be ok now) 1262 */ 1263 1264 sbdma_channel_start(&(s->sbm_rxdma)); 1265 sbdma_channel_start(&(s->sbm_txdma)); 1266 1267 /* 1268 * Configure the speed, duplex, and flow control 1269 */ 1270 1271 sbmac_set_speed(s, s->sbm_speed); 1272 sbmac_set_duplex(s, s->sbm_duplex, s->sbm_fc); 1273 1274 /* 1275 * Fill the receive ring 1276 */ 1277 1278 sbdma_fillring(&(s->sbm_rxdma)); 1279 1280 /* 1281 * Turn on the rest of the bits in the enable register 1282 */ 1283 1284 SBMAC_WRITECSR(s->sbm_macenable, M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 | 1285 M_MAC_RX_ENABLE | M_MAC_TX_ENABLE); 1286 1287 1288 /* 1289 * Accept any kind of interrupt on TX and RX DMA channel 0 1290 */ 1291 SBMAC_WRITECSR(s->sbm_imr, 1292 (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | 1293 (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)); 1294 1295 /* 1296 * Enable receiving unicasts and broadcasts 1297 */ 1298 1299 SBMAC_WRITECSR(s->sbm_rxfilter, M_MAC_UCAST_EN | M_MAC_BCAST_EN); 1300 1301 /* 1302 * On chips which support unaligned DMA features, set the descriptor 1303 * ring for transmit channels to use the unaligned buffer format. 1304 */ 1305 txdma = &(s->sbm_txdma); 1306 1307 if (s->sbm_pass3_dma) { 1308 dma_cfg0 = SBMAC_READCSR(txdma->sbdma_config0); 1309 dma_cfg0 |= V_DMA_DESC_TYPE(K_DMA_DESC_TYPE_RING_UAL_RMW) | 1310 M_DMA_TBX_EN | M_DMA_TDX_EN; 1311 SBMAC_WRITECSR(txdma->sbdma_config0,dma_cfg0); 1312 1313 fifo_cfg = SBMAC_READCSR(s->sbm_fifocfg); 1314 fifo_cfg |= V_MAC_TX_WR_THRSH(8) | 1315 V_MAC_TX_RD_THRSH(8) | V_MAC_TX_RL_THRSH(8); 1316 SBMAC_WRITECSR(s->sbm_fifocfg,fifo_cfg); 1317 } 1318 1319 /* 1320 * we're running now. 1321 */ 1322 1323 s->sbm_state = sbmac_state_on; 1324 s->sc_ethercom.ec_if.if_flags |= IFF_RUNNING; 1325 1326 /* 1327 * Program multicast addresses 1328 */ 1329 1330 sbmac_setmulti(s); 1331 1332 /* 1333 * If channel was in promiscuous mode before, turn that on 1334 */ 1335 1336 if (s->sc_ethercom.ec_if.if_flags & IFF_PROMISC) 1337 sbmac_promiscuous_mode(s, 1); 1338 1339 /* 1340 * Turn on the once-per-second timer 1341 */ 1342 1343 callout_reset(&(s->sc_tick_ch), hz, sbmac_tick, s); 1344 } 1345 1346 /* 1347 * SBMAC_CHANNEL_STOP(s) 1348 * 1349 * Stop packet processing on this MAC. 1350 * 1351 * Input parameters: 1352 * s - sbmac structure 1353 * 1354 * Return value: 1355 * nothing 1356 */ 1357 1358 static void 1359 sbmac_channel_stop(struct sbmac_softc *s) 1360 { 1361 uint64_t ctl; 1362 1363 /* don't do this if already stopped */ 1364 1365 if (s->sbm_state == sbmac_state_off) 1366 return; 1367 1368 /* don't accept any packets, disable all interrupts */ 1369 1370 SBMAC_WRITECSR(s->sbm_rxfilter, 0); 1371 SBMAC_WRITECSR(s->sbm_imr, 0); 1372 1373 /* Turn off ticker */ 1374 1375 callout_stop(&(s->sc_tick_ch)); 1376 1377 /* turn off receiver and transmitter */ 1378 1379 ctl = SBMAC_READCSR(s->sbm_macenable); 1380 ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0); 1381 SBMAC_WRITECSR(s->sbm_macenable, ctl); 1382 1383 /* We're stopped now. */ 1384 1385 s->sbm_state = sbmac_state_off; 1386 s->sc_ethercom.ec_if.if_flags &= ~IFF_RUNNING; 1387 1388 /* Empty the receive and transmit rings */ 1389 1390 sbdma_emptyring(&(s->sbm_rxdma)); 1391 sbdma_emptyring(&(s->sbm_txdma)); 1392 } 1393 1394 /* 1395 * SBMAC_SET_CHANNEL_STATE(state) 1396 * 1397 * Set the channel's state ON or OFF 1398 * 1399 * Input parameters: 1400 * state - new state 1401 * 1402 * Return value: 1403 * old state 1404 */ 1405 1406 static sbmac_state_t 1407 sbmac_set_channel_state(struct sbmac_softc *sc, sbmac_state_t state) 1408 { 1409 sbmac_state_t oldstate = sc->sbm_state; 1410 1411 /* 1412 * If same as previous state, return 1413 */ 1414 1415 if (state == oldstate) 1416 return oldstate; 1417 1418 /* 1419 * If new state is ON, turn channel on 1420 */ 1421 1422 if (state == sbmac_state_on) 1423 sbmac_channel_start(sc); 1424 else 1425 sbmac_channel_stop(sc); 1426 1427 /* 1428 * Return previous state 1429 */ 1430 1431 return oldstate; 1432 } 1433 1434 /* 1435 * SBMAC_PROMISCUOUS_MODE(sc, onoff) 1436 * 1437 * Turn on or off promiscuous mode 1438 * 1439 * Input parameters: 1440 * sc - softc 1441 * onoff - 1 to turn on, 0 to turn off 1442 * 1443 * Return value: 1444 * nothing 1445 */ 1446 1447 static void 1448 sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff) 1449 { 1450 uint64_t reg; 1451 1452 if (sc->sbm_state != sbmac_state_on) 1453 return; 1454 1455 if (onoff) { 1456 reg = SBMAC_READCSR(sc->sbm_rxfilter); 1457 reg |= M_MAC_ALLPKT_EN; 1458 SBMAC_WRITECSR(sc->sbm_rxfilter, reg); 1459 } else { 1460 reg = SBMAC_READCSR(sc->sbm_rxfilter); 1461 reg &= ~M_MAC_ALLPKT_EN; 1462 SBMAC_WRITECSR(sc->sbm_rxfilter, reg); 1463 } 1464 } 1465 1466 /* 1467 * SBMAC_INIT_AND_START(sc) 1468 * 1469 * Stop the channel and restart it. This is generally used 1470 * when we have to do something to the channel that requires 1471 * a swift kick. 1472 * 1473 * Input parameters: 1474 * sc - softc 1475 */ 1476 1477 static void 1478 sbmac_init_and_start(struct sbmac_softc *sc) 1479 { 1480 int s; 1481 1482 s = splnet(); 1483 1484 mii_pollstat(&sc->sc_mii); /* poll phy for current speed */ 1485 sbmac_mii_statchg((struct device *) sc); /* set state to new speed */ 1486 sbmac_set_channel_state(sc, sbmac_state_on); 1487 1488 splx(s); 1489 } 1490 1491 /* 1492 * SBMAC_ADDR2REG(ptr) 1493 * 1494 * Convert six bytes into the 64-bit register value that 1495 * we typically write into the SBMAC's address/mcast registers 1496 * 1497 * Input parameters: 1498 * ptr - pointer to 6 bytes 1499 * 1500 * Return value: 1501 * register value 1502 */ 1503 1504 static uint64_t 1505 sbmac_addr2reg(u_char *ptr) 1506 { 1507 uint64_t reg = 0; 1508 1509 ptr += 6; 1510 1511 reg |= (uint64_t) *(--ptr); 1512 reg <<= 8; 1513 reg |= (uint64_t) *(--ptr); 1514 reg <<= 8; 1515 reg |= (uint64_t) *(--ptr); 1516 reg <<= 8; 1517 reg |= (uint64_t) *(--ptr); 1518 reg <<= 8; 1519 reg |= (uint64_t) *(--ptr); 1520 reg <<= 8; 1521 reg |= (uint64_t) *(--ptr); 1522 1523 return reg; 1524 } 1525 1526 /* 1527 * SBMAC_SET_SPEED(s, speed) 1528 * 1529 * Configure LAN speed for the specified MAC. 1530 * Warning: must be called when MAC is off! 1531 * 1532 * Input parameters: 1533 * s - sbmac structure 1534 * speed - speed to set MAC to (see sbmac_speed_t enum) 1535 * 1536 * Return value: 1537 * 1 if successful 1538 * 0 indicates invalid parameters 1539 */ 1540 1541 static int 1542 sbmac_set_speed(struct sbmac_softc *s, sbmac_speed_t speed) 1543 { 1544 uint64_t cfg; 1545 uint64_t framecfg; 1546 1547 /* 1548 * Save new current values 1549 */ 1550 1551 s->sbm_speed = speed; 1552 1553 if (s->sbm_state != sbmac_state_off) 1554 panic("sbmac_set_speed while MAC not off"); 1555 1556 /* 1557 * Read current register values 1558 */ 1559 1560 cfg = SBMAC_READCSR(s->sbm_maccfg); 1561 framecfg = SBMAC_READCSR(s->sbm_framecfg); 1562 1563 /* 1564 * Mask out the stuff we want to change 1565 */ 1566 1567 cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL); 1568 framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH | 1569 M_MAC_SLOT_SIZE); 1570 1571 /* 1572 * Now add in the new bits 1573 */ 1574 1575 switch (speed) { 1576 case sbmac_speed_10: 1577 framecfg |= V_MAC_IFG_RX_10 | 1578 V_MAC_IFG_TX_10 | 1579 K_MAC_IFG_THRSH_10 | 1580 V_MAC_SLOT_SIZE_10; 1581 cfg |= V_MAC_SPEED_SEL_10MBPS; 1582 break; 1583 1584 case sbmac_speed_100: 1585 framecfg |= V_MAC_IFG_RX_100 | 1586 V_MAC_IFG_TX_100 | 1587 V_MAC_IFG_THRSH_100 | 1588 V_MAC_SLOT_SIZE_100; 1589 cfg |= V_MAC_SPEED_SEL_100MBPS ; 1590 break; 1591 1592 case sbmac_speed_1000: 1593 framecfg |= V_MAC_IFG_RX_1000 | 1594 V_MAC_IFG_TX_1000 | 1595 V_MAC_IFG_THRSH_1000 | 1596 V_MAC_SLOT_SIZE_1000; 1597 cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; 1598 break; 1599 1600 case sbmac_speed_auto: /* XXX not implemented */ 1601 /* fall through */ 1602 default: 1603 return 0; 1604 } 1605 1606 /* 1607 * Send the bits back to the hardware 1608 */ 1609 1610 SBMAC_WRITECSR(s->sbm_framecfg, framecfg); 1611 SBMAC_WRITECSR(s->sbm_maccfg, cfg); 1612 1613 return 1; 1614 } 1615 1616 /* 1617 * SBMAC_SET_DUPLEX(s, duplex, fc) 1618 * 1619 * Set Ethernet duplex and flow control options for this MAC 1620 * Warning: must be called when MAC is off! 1621 * 1622 * Input parameters: 1623 * s - sbmac structure 1624 * duplex - duplex setting (see sbmac_duplex_t) 1625 * fc - flow control setting (see sbmac_fc_t) 1626 * 1627 * Return value: 1628 * 1 if ok 1629 * 0 if an invalid parameter combination was specified 1630 */ 1631 1632 static int 1633 sbmac_set_duplex(struct sbmac_softc *s, sbmac_duplex_t duplex, sbmac_fc_t fc) 1634 { 1635 uint64_t cfg; 1636 1637 /* 1638 * Save new current values 1639 */ 1640 1641 s->sbm_duplex = duplex; 1642 s->sbm_fc = fc; 1643 1644 if (s->sbm_state != sbmac_state_off) 1645 panic("sbmac_set_duplex while MAC not off"); 1646 1647 /* 1648 * Read current register values 1649 */ 1650 1651 cfg = SBMAC_READCSR(s->sbm_maccfg); 1652 1653 /* 1654 * Mask off the stuff we're about to change 1655 */ 1656 1657 cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN); 1658 1659 switch (duplex) { 1660 case sbmac_duplex_half: 1661 switch (fc) { 1662 case sbmac_fc_disabled: 1663 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED; 1664 break; 1665 1666 case sbmac_fc_collision: 1667 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED; 1668 break; 1669 1670 case sbmac_fc_carrier: 1671 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR; 1672 break; 1673 1674 case sbmac_fc_auto: /* XXX not implemented */ 1675 /* fall through */ 1676 case sbmac_fc_frame: /* not valid in half duplex */ 1677 default: /* invalid selection */ 1678 panic("%s: invalid half duplex fc selection %d", 1679 s->sc_dev.dv_xname, fc); 1680 return 0; 1681 } 1682 break; 1683 1684 case sbmac_duplex_full: 1685 switch (fc) { 1686 case sbmac_fc_disabled: 1687 cfg |= V_MAC_FC_CMD_DISABLED; 1688 break; 1689 1690 case sbmac_fc_frame: 1691 cfg |= V_MAC_FC_CMD_ENABLED; 1692 break; 1693 1694 case sbmac_fc_collision: /* not valid in full duplex */ 1695 case sbmac_fc_carrier: /* not valid in full duplex */ 1696 case sbmac_fc_auto: /* XXX not implemented */ 1697 /* fall through */ 1698 default: 1699 panic("%s: invalid full duplex fc selection %d", 1700 s->sc_dev.dv_xname, fc); 1701 return 0; 1702 } 1703 break; 1704 1705 default: 1706 /* fall through */ 1707 case sbmac_duplex_auto: 1708 panic("%s: bad duplex %d", s->sc_dev.dv_xname, duplex); 1709 /* XXX not implemented */ 1710 break; 1711 } 1712 1713 /* 1714 * Send the bits back to the hardware 1715 */ 1716 1717 SBMAC_WRITECSR(s->sbm_maccfg, cfg); 1718 1719 return 1; 1720 } 1721 1722 /* 1723 * SBMAC_INTR() 1724 * 1725 * Interrupt handler for MAC interrupts 1726 * 1727 * Input parameters: 1728 * MAC structure 1729 * 1730 * Return value: 1731 * nothing 1732 */ 1733 1734 /* ARGSUSED */ 1735 static void 1736 sbmac_intr(void *xsc, uint32_t status, uint32_t pc) 1737 { 1738 struct sbmac_softc *sc = (struct sbmac_softc *) xsc; 1739 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1740 uint64_t isr; 1741 1742 for (;;) { 1743 1744 /* 1745 * Read the ISR (this clears the bits in the real register) 1746 */ 1747 1748 isr = SBMAC_READCSR(sc->sbm_isr); 1749 1750 if (isr == 0) 1751 break; 1752 1753 /* 1754 * Transmits on channel 0 1755 */ 1756 1757 if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) { 1758 sbdma_tx_process(sc, &(sc->sbm_txdma)); 1759 SBMAC_EVCNT_INCR(sc->sbm_ev_txintr); 1760 } 1761 1762 /* 1763 * Receives on channel 0 1764 */ 1765 1766 if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { 1767 sbdma_rx_process(sc, &(sc->sbm_rxdma)); 1768 SBMAC_EVCNT_INCR(sc->sbm_ev_rxintr); 1769 } 1770 } 1771 1772 /* try to get more packets going */ 1773 sbmac_start(ifp); 1774 } 1775 1776 1777 /* 1778 * SBMAC_START(ifp) 1779 * 1780 * Start output on the specified interface. Basically, we 1781 * queue as many buffers as we can until the ring fills up, or 1782 * we run off the end of the queue, whichever comes first. 1783 * 1784 * Input parameters: 1785 * ifp - interface 1786 * 1787 * Return value: 1788 * nothing 1789 */ 1790 1791 static void 1792 sbmac_start(struct ifnet *ifp) 1793 { 1794 struct sbmac_softc *sc; 1795 struct mbuf *m_head = NULL; 1796 int rv; 1797 1798 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) 1799 return; 1800 1801 sc = ifp->if_softc; 1802 1803 for (;;) { 1804 1805 IF_DEQUEUE(&ifp->if_snd, m_head); 1806 if (m_head == NULL) 1807 break; 1808 1809 /* 1810 * Put the buffer on the transmit ring. If we 1811 * don't have room, set the OACTIVE flag and wait 1812 * for the NIC to drain the ring. 1813 */ 1814 1815 rv = sbdma_add_txbuffer(&(sc->sbm_txdma), m_head); 1816 1817 if (rv == 0) { 1818 /* 1819 * If there's a BPF listener, bounce a copy of this 1820 * frame to it. 1821 */ 1822 #if (NBPFILTER > 0) 1823 if (ifp->if_bpf) 1824 bpf_mtap(ifp->if_bpf, m_head); 1825 #endif 1826 if (!sc->sbm_pass3_dma) { 1827 /* 1828 * Don't free mbuf if we're not copying to new 1829 * mbuf in sbdma_add_txbuffer. It will be 1830 * freed in sbdma_tx_process. 1831 */ 1832 m_freem(m_head); 1833 } 1834 } else { 1835 IF_PREPEND(&ifp->if_snd, m_head); 1836 ifp->if_flags |= IFF_OACTIVE; 1837 break; 1838 } 1839 } 1840 } 1841 1842 /* 1843 * SBMAC_SETMULTI(sc) 1844 * 1845 * Reprogram the multicast table into the hardware, given 1846 * the list of multicasts associated with the interface 1847 * structure. 1848 * 1849 * Input parameters: 1850 * sc - softc 1851 * 1852 * Return value: 1853 * nothing 1854 */ 1855 1856 static void 1857 sbmac_setmulti(struct sbmac_softc *sc) 1858 { 1859 struct ifnet *ifp; 1860 uint64_t reg; 1861 sbmac_port_t port; 1862 int idx; 1863 struct ether_multi *enm; 1864 struct ether_multistep step; 1865 1866 ifp = &sc->sc_ethercom.ec_if; 1867 1868 /* 1869 * Clear out entire multicast table. We do this by nuking 1870 * the entire hash table and all the direct matches except 1871 * the first one, which is used for our station address 1872 */ 1873 1874 for (idx = 1; idx < MAC_ADDR_COUNT; idx++) { 1875 port = PKSEG1(sc->sbm_base + 1876 R_MAC_ADDR_BASE+(idx*sizeof(uint64_t))); 1877 SBMAC_WRITECSR(port, 0); 1878 } 1879 1880 for (idx = 0; idx < MAC_HASH_COUNT; idx++) { 1881 port = PKSEG1(sc->sbm_base + 1882 R_MAC_HASH_BASE+(idx*sizeof(uint64_t))); 1883 SBMAC_WRITECSR(port, 0); 1884 } 1885 1886 /* 1887 * Clear the filter to say we don't want any multicasts. 1888 */ 1889 1890 reg = SBMAC_READCSR(sc->sbm_rxfilter); 1891 reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN); 1892 SBMAC_WRITECSR(sc->sbm_rxfilter, reg); 1893 1894 if (ifp->if_flags & IFF_ALLMULTI) { 1895 /* 1896 * Enable ALL multicasts. Do this by inverting the 1897 * multicast enable bit. 1898 */ 1899 reg = SBMAC_READCSR(sc->sbm_rxfilter); 1900 reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN); 1901 SBMAC_WRITECSR(sc->sbm_rxfilter, reg); 1902 return; 1903 } 1904 1905 /* 1906 * Progam new multicast entries. For now, only use the 1907 * perfect filter. In the future we'll need to use the 1908 * hash filter if the perfect filter overflows 1909 */ 1910 1911 /* 1912 * XXX only using perfect filter for now, need to use hash 1913 * XXX if the table overflows 1914 */ 1915 1916 idx = 1; /* skip station address */ 1917 ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm); 1918 while ((enm != NULL) && (idx < MAC_ADDR_COUNT)) { 1919 reg = sbmac_addr2reg(enm->enm_addrlo); 1920 port = PKSEG1(sc->sbm_base + 1921 R_MAC_ADDR_BASE+(idx*sizeof(uint64_t))); 1922 SBMAC_WRITECSR(port, reg); 1923 idx++; 1924 ETHER_NEXT_MULTI(step, enm); 1925 } 1926 1927 /* 1928 * Enable the "accept multicast bits" if we programmed at least one 1929 * multicast. 1930 */ 1931 1932 if (idx > 1) { 1933 reg = SBMAC_READCSR(sc->sbm_rxfilter); 1934 reg |= M_MAC_MCAST_EN; 1935 SBMAC_WRITECSR(sc->sbm_rxfilter, reg); 1936 } 1937 } 1938 1939 /* 1940 * SBMAC_ETHER_IOCTL(ifp, cmd, data) 1941 * 1942 * Generic IOCTL requests for this interface. The basic 1943 * stuff is handled here for bringing the interface up, 1944 * handling multicasts, etc. 1945 * 1946 * Input parameters: 1947 * ifp - interface structure 1948 * cmd - command code 1949 * data - pointer to data 1950 * 1951 * Return value: 1952 * return value (0 is success) 1953 */ 1954 1955 static int 1956 sbmac_ether_ioctl(struct ifnet *ifp, u_long cmd, void *data) 1957 { 1958 struct ifaddr *ifa = (struct ifaddr *) data; 1959 struct sbmac_softc *sc = ifp->if_softc; 1960 1961 switch (cmd) { 1962 case SIOCSIFADDR: 1963 ifp->if_flags |= IFF_UP; 1964 1965 switch (ifa->ifa_addr->sa_family) { 1966 #ifdef INET 1967 case AF_INET: 1968 sbmac_init_and_start(sc); 1969 arp_ifinit(ifp, ifa); 1970 break; 1971 #endif 1972 #ifdef NS 1973 case AF_NS: 1974 { 1975 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 1976 1977 if (ns_nullhost(*ina)) 1978 ina->x_host = 1979 *(union ns_host *)LLADDR(ifp->if_sadl); 1980 else 1981 bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl), 1982 ifp->if_addrlen); 1983 /* Set new address. */ 1984 sbmac_init_and_start(sc); 1985 break; 1986 } 1987 #endif 1988 default: 1989 sbmac_init_and_start(sc); 1990 break; 1991 } 1992 break; 1993 1994 default: 1995 return (EINVAL); 1996 } 1997 1998 return (0); 1999 } 2000 2001 /* 2002 * SBMAC_IOCTL(ifp, command, data) 2003 * 2004 * Main IOCTL handler - dispatches to other IOCTLs for various 2005 * types of requests. 2006 * 2007 * Input parameters: 2008 * ifp - interface pointer 2009 * command - command code 2010 * data - pointer to argument data 2011 * 2012 * Return value: 2013 * 0 if ok 2014 * else error code 2015 */ 2016 2017 static int 2018 sbmac_ioctl(struct ifnet *ifp, u_long command, void *data) 2019 { 2020 struct sbmac_softc *sc = ifp->if_softc; 2021 struct ifreq *ifr = (struct ifreq *) data; 2022 int s, error = 0; 2023 2024 s = splnet(); 2025 2026 switch(command) { 2027 case SIOCSIFADDR: 2028 case SIOCGIFADDR: 2029 error = sbmac_ether_ioctl(ifp, command, data); 2030 break; 2031 case SIOCSIFMTU: 2032 if (ifr->ifr_mtu > ETHER_MAX_LEN) 2033 error = EINVAL; 2034 else { 2035 ifp->if_mtu = ifr->ifr_mtu; 2036 /* XXX Program new MTU here */ 2037 } 2038 break; 2039 case SIOCSIFFLAGS: 2040 if (ifp->if_flags & IFF_UP) { 2041 /* 2042 * If only the state of the PROMISC flag changed, 2043 * just tweak the hardware registers. 2044 */ 2045 if ((ifp->if_flags & IFF_RUNNING) && 2046 (ifp->if_flags & IFF_PROMISC)) { 2047 /* turn on promiscuous mode */ 2048 sbmac_promiscuous_mode(sc, 1); 2049 } else if (ifp->if_flags & IFF_RUNNING && 2050 !(ifp->if_flags & IFF_PROMISC)) { 2051 /* turn off promiscuous mode */ 2052 sbmac_promiscuous_mode(sc, 0); 2053 } else 2054 sbmac_set_channel_state(sc, sbmac_state_on); 2055 } else { 2056 if (ifp->if_flags & IFF_RUNNING) 2057 sbmac_set_channel_state(sc, sbmac_state_off); 2058 } 2059 2060 sc->sbm_if_flags = ifp->if_flags; 2061 error = 0; 2062 break; 2063 2064 case SIOCADDMULTI: 2065 case SIOCDELMULTI: 2066 if (ifp->if_flags & IFF_RUNNING) { 2067 sbmac_setmulti(sc); 2068 error = 0; 2069 } 2070 break; 2071 case SIOCSIFMEDIA: 2072 case SIOCGIFMEDIA: 2073 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command); 2074 break; 2075 default: 2076 error = EINVAL; 2077 break; 2078 } 2079 2080 (void)splx(s); 2081 2082 return(error); 2083 } 2084 2085 /* 2086 * SBMAC_IFMEDIA_UPD(ifp) 2087 * 2088 * Configure an appropriate media type for this interface, 2089 * given the data in the interface structure 2090 * 2091 * Input parameters: 2092 * ifp - interface 2093 * 2094 * Return value: 2095 * 0 if ok 2096 * else error code 2097 */ 2098 2099 static int 2100 sbmac_mediachange(struct ifnet *ifp) 2101 { 2102 struct sbmac_softc *sc = ifp->if_softc; 2103 2104 if (ifp->if_flags & IFF_UP) 2105 mii_mediachg(&sc->sc_mii); 2106 return(0); 2107 } 2108 2109 /* 2110 * SBMAC_IFMEDIA_STS(ifp, ifmr) 2111 * 2112 * Report current media status (used by ifconfig, for example) 2113 * 2114 * Input parameters: 2115 * ifp - interface structure 2116 * ifmr - media request structure 2117 * 2118 * Return value: 2119 * nothing 2120 */ 2121 2122 static void 2123 sbmac_mediastatus(struct ifnet *ifp, struct ifmediareq *req) 2124 { 2125 struct sbmac_softc *sc = ifp->if_softc; 2126 2127 mii_pollstat(&sc->sc_mii); 2128 req->ifm_status = sc->sc_mii.mii_media_status; 2129 req->ifm_active = sc->sc_mii.mii_media_active; 2130 } 2131 2132 /* 2133 * SBMAC_WATCHDOG(ifp) 2134 * 2135 * Called periodically to make sure we're still happy. 2136 * 2137 * Input parameters: 2138 * ifp - interface structure 2139 * 2140 * Return value: 2141 * nothing 2142 */ 2143 2144 static void 2145 sbmac_watchdog(struct ifnet *ifp) 2146 { 2147 2148 /* XXX do something */ 2149 } 2150 2151 /* 2152 * One second timer, used to tick MII. 2153 */ 2154 static void 2155 sbmac_tick(void *arg) 2156 { 2157 struct sbmac_softc *sc = arg; 2158 int s; 2159 2160 s = splnet(); 2161 mii_tick(&sc->sc_mii); 2162 splx(s); 2163 2164 callout_reset(&sc->sc_tick_ch, hz, sbmac_tick, sc); 2165 } 2166 2167 2168 /* 2169 * SBMAC_MATCH(parent, match, aux) 2170 * 2171 * Part of the config process - see if this device matches the 2172 * info about what we expect to find on the bus. 2173 * 2174 * Input parameters: 2175 * parent - parent bus structure 2176 * match - 2177 * aux - bus-specific args 2178 * 2179 * Return value: 2180 * 1 if we match 2181 * 0 if we don't match 2182 */ 2183 2184 static int 2185 sbmac_match(struct device *parent, struct cfdata *match, void *aux) 2186 { 2187 struct sbobio_attach_args *sap = aux; 2188 2189 /* 2190 * Make sure it's a MAC 2191 */ 2192 2193 if (sap->sa_locs.sa_type != SBOBIO_DEVTYPE_MAC) 2194 return 0; 2195 2196 /* 2197 * Yup, it is. 2198 */ 2199 2200 return 1; 2201 } 2202 2203 /* 2204 * SBMAC_PARSE_XDIGIT(str) 2205 * 2206 * Parse a hex digit, returning its value 2207 * 2208 * Input parameters: 2209 * str - character 2210 * 2211 * Return value: 2212 * hex value, or -1 if invalid 2213 */ 2214 2215 static int 2216 sbmac_parse_xdigit(char str) 2217 { 2218 int digit; 2219 2220 if ((str >= '0') && (str <= '9')) 2221 digit = str - '0'; 2222 else if ((str >= 'a') && (str <= 'f')) 2223 digit = str - 'a' + 10; 2224 else if ((str >= 'A') && (str <= 'F')) 2225 digit = str - 'A' + 10; 2226 else 2227 digit = -1; 2228 2229 return digit; 2230 } 2231 2232 /* 2233 * SBMAC_PARSE_HWADDR(str, hwaddr) 2234 * 2235 * Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte 2236 * Ethernet address. 2237 * 2238 * Input parameters: 2239 * str - string 2240 * hwaddr - pointer to hardware address 2241 * 2242 * Return value: 2243 * 0 if ok, else -1 2244 */ 2245 2246 static int 2247 sbmac_parse_hwaddr(const char *str, u_char *hwaddr) 2248 { 2249 int digit1, digit2; 2250 int idx = 6; 2251 2252 while (*str && (idx > 0)) { 2253 digit1 = sbmac_parse_xdigit(*str); 2254 if (digit1 < 0) 2255 return -1; 2256 str++; 2257 if (!*str) 2258 return -1; 2259 2260 if ((*str == ':') || (*str == '-')) { 2261 digit2 = digit1; 2262 digit1 = 0; 2263 } else { 2264 digit2 = sbmac_parse_xdigit(*str); 2265 if (digit2 < 0) 2266 return -1; 2267 str++; 2268 } 2269 2270 *hwaddr++ = (digit1 << 4) | digit2; 2271 idx--; 2272 2273 if (*str == '-') 2274 str++; 2275 if (*str == ':') 2276 str++; 2277 } 2278 return 0; 2279 } 2280 2281 /* 2282 * SBMAC_ATTACH(parent, self, aux) 2283 * 2284 * Attach routine - init hardware and hook ourselves into NetBSD. 2285 * 2286 * Input parameters: 2287 * parent - parent bus device 2288 * self - our softc 2289 * aux - attach data 2290 * 2291 * Return value: 2292 * nothing 2293 */ 2294 2295 static void 2296 sbmac_attach(struct device *parent, struct device *self, void *aux) 2297 { 2298 struct ifnet *ifp; 2299 struct sbmac_softc *sc; 2300 struct sbobio_attach_args *sap = aux; 2301 u_char *eaddr; 2302 static int unit = 0; /* XXX */ 2303 uint64_t ea_reg; 2304 int idx; 2305 2306 sc = (struct sbmac_softc *)self; 2307 2308 /* Determine controller base address */ 2309 2310 sc->sbm_base = (sbmac_port_t) sap->sa_base + sap->sa_locs.sa_offset; 2311 2312 eaddr = sc->sbm_hwaddr; 2313 2314 /* 2315 * Initialize context (get pointers to registers and stuff), then 2316 * allocate the memory for the descriptor tables. 2317 */ 2318 2319 sbmac_initctx(sc); 2320 2321 callout_init(&(sc->sc_tick_ch), 0); 2322 2323 /* 2324 * Read the ethernet address. The firwmare left this programmed 2325 * for us in the ethernet address register for each mac. 2326 */ 2327 2328 ea_reg = SBMAC_READCSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR)); 2329 for (idx = 0; idx < 6; idx++) { 2330 eaddr[idx] = (uint8_t) (ea_reg & 0xFF); 2331 ea_reg >>= 8; 2332 } 2333 2334 #define SBMAC_DEFAULT_HWADDR "40:00:00:00:01:00" 2335 if (eaddr[0] == 0 && eaddr[1] == 0 && eaddr[2] == 0 && 2336 eaddr[3] == 0 && eaddr[4] == 0 && eaddr[5] == 0) { 2337 sbmac_parse_hwaddr(SBMAC_DEFAULT_HWADDR, eaddr); 2338 eaddr[5] = unit; 2339 } 2340 2341 #ifdef SBMAC_ETH0_HWADDR 2342 if (unit == 0) 2343 sbmac_parse_hwaddr(SBMAC_ETH0_HWADDR, eaddr); 2344 #endif 2345 #ifdef SBMAC_ETH1_HWADDR 2346 if (unit == 1) 2347 sbmac_parse_hwaddr(SBMAC_ETH1_HWADDR, eaddr); 2348 #endif 2349 #ifdef SBMAC_ETH2_HWADDR 2350 if (unit == 2) 2351 sbmac_parse_hwaddr(SBMAC_ETH2_HWADDR, eaddr); 2352 #endif 2353 unit++; 2354 2355 /* 2356 * Display Ethernet address (this is called during the config process 2357 * so we need to finish off the config message that was being displayed) 2358 */ 2359 printf(": Ethernet%s\n", 2360 sc->sbm_pass3_dma ? ", using unaligned tx DMA" : ""); 2361 printf("%s: Ethernet address: %s\n", self->dv_xname, 2362 ether_sprintf(eaddr)); 2363 2364 2365 /* 2366 * Set up ifnet structure 2367 */ 2368 2369 ifp = &sc->sc_ethercom.ec_if; 2370 ifp->if_softc = sc; 2371 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 2372 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | 2373 IFF_NOTRAILERS; 2374 ifp->if_ioctl = sbmac_ioctl; 2375 ifp->if_start = sbmac_start; 2376 ifp->if_watchdog = sbmac_watchdog; 2377 ifp->if_snd.ifq_maxlen = SBMAC_MAX_TXDESCR - 1; 2378 2379 /* 2380 * Set up ifmedia support. 2381 */ 2382 2383 /* 2384 * Initialize MII/media info. 2385 */ 2386 sc->sc_mii.mii_ifp = ifp; 2387 sc->sc_mii.mii_readreg = sbmac_mii_readreg; 2388 sc->sc_mii.mii_writereg = sbmac_mii_writereg; 2389 sc->sc_mii.mii_statchg = sbmac_mii_statchg; 2390 ifmedia_init(&sc->sc_mii.mii_media, 0, sbmac_mediachange, 2391 sbmac_mediastatus); 2392 mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, 2393 MII_OFFSET_ANY, 0); 2394 2395 if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { 2396 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); 2397 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); 2398 } else { 2399 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); 2400 } 2401 2402 2403 /* 2404 * map/route interrupt 2405 */ 2406 2407 sc->sbm_intrhand = cpu_intr_establish(sap->sa_locs.sa_intr[0], IPL_NET, 2408 sbmac_intr, sc); 2409 2410 /* 2411 * Call MI attach routines. 2412 */ 2413 if_attach(ifp); 2414 ether_ifattach(ifp, eaddr); 2415 } 2416