1 /* $OpenBSD: if_bm.c,v 1.27 2009/08/25 20:39:36 miod Exp $ */ 2 /* $NetBSD: if_bm.c,v 1.1 1999/01/01 01:27:52 tsubai Exp $ */ 3 4 /*- 5 * Copyright (C) 1998, 1999 Tsubai Masanari. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "bpfilter.h" 31 32 #include <sys/param.h> 33 #include <sys/device.h> 34 #include <sys/ioctl.h> 35 #include <sys/mbuf.h> 36 #include <sys/socket.h> 37 #include <sys/systm.h> 38 #include <sys/timeout.h> 39 #include <sys/kernel.h> 40 41 #include <net/if.h> 42 #include <netinet/in.h> 43 #include <netinet/if_ether.h> 44 #include <net/if_media.h> 45 46 #if NBPFILTER > 0 47 #include <net/bpf.h> 48 #include <net/bpfdesc.h> 49 #endif 50 51 #include <uvm/uvm_extern.h> 52 53 #include <dev/mii/mii.h> 54 #include <dev/mii/miivar.h> 55 #include <dev/mii/mii_bitbang.h> 56 57 #include <dev/ofw/openfirm.h> 58 59 #include <machine/bus.h> 60 #include <machine/autoconf.h> 61 62 #include <macppc/dev/dbdma.h> 63 #include <macppc/dev/if_bmreg.h> 64 65 #define BMAC_TXBUFS 2 66 #define BMAC_RXBUFS 16 67 #define BMAC_BUFLEN 2048 68 #define BMAC_BUFSZ ((BMAC_RXBUFS + BMAC_TXBUFS + 2) * BMAC_BUFLEN) 69 70 struct bmac_softc { 71 struct device sc_dev; 72 struct arpcom arpcom; /* per-instance network data */ 73 struct timeout sc_tick_ch; 74 vaddr_t sc_regs; 75 bus_dma_tag_t sc_dmat; 76 bus_dmamap_t sc_bufmap; 77 bus_dma_segment_t sc_bufseg[1]; 78 dbdma_regmap_t *sc_txdma, *sc_rxdma; 79 dbdma_command_t *sc_txcmd, *sc_rxcmd; 80 dbdma_t sc_rxdbdma, sc_txdbdma; 81 caddr_t sc_txbuf; 82 paddr_t sc_txbuf_pa; 83 caddr_t sc_rxbuf; 84 paddr_t sc_rxbuf_pa; 85 int sc_rxlast; 86 int sc_flags; 87 int sc_debug; 88 int txcnt_outstanding; 89 struct mii_data sc_mii; 90 }; 91 92 #define BMAC_BMACPLUS 0x01 93 94 extern u_int *heathrow_FCR; 95 96 static __inline int bmac_read_reg(struct bmac_softc *, int); 97 static __inline void bmac_write_reg(struct bmac_softc *, int, int); 98 static __inline void bmac_set_bits(struct bmac_softc *, int, int); 99 static __inline void bmac_reset_bits(struct bmac_softc *, int, int); 100 101 static int bmac_match(struct device *, void *, void *); 102 static void bmac_attach(struct device *, struct device *, void *); 103 static void bmac_reset_chip(struct bmac_softc *); 104 static void bmac_init(struct bmac_softc *); 105 static void bmac_init_dma(struct bmac_softc *); 106 static int bmac_intr(void *); 107 static int bmac_rint(void *); 108 static void bmac_reset(struct bmac_softc *); 109 static void bmac_stop(struct bmac_softc *); 110 static void bmac_start(struct ifnet *); 111 static void bmac_transmit_packet(struct bmac_softc *, paddr_t, int); 112 static int bmac_put(struct bmac_softc *, caddr_t, struct mbuf *); 113 static struct mbuf *bmac_get(struct bmac_softc *, caddr_t, int); 114 static void bmac_watchdog(struct ifnet *); 115 static int bmac_ioctl(struct ifnet *, u_long, caddr_t); 116 static int bmac_mediachange(struct ifnet *); 117 static void bmac_mediastatus(struct ifnet *, struct ifmediareq *); 118 static void bmac_setladrf(struct bmac_softc *); 119 120 int bmac_mii_readreg(struct device *, int, int); 121 void bmac_mii_writereg(struct device *, int, int, int); 122 void bmac_mii_statchg(struct device *); 123 void bmac_mii_tick(void *); 124 u_int32_t bmac_mbo_read(struct device *); 125 void bmac_mbo_write(struct device *, u_int32_t); 126 127 struct cfattach bm_ca = { 128 sizeof(struct bmac_softc), bmac_match, bmac_attach 129 }; 130 131 struct mii_bitbang_ops bmac_mbo = { 132 bmac_mbo_read, bmac_mbo_write, 133 { MIFDO, MIFDI, MIFDC, MIFDIR, 0 } 134 }; 135 136 struct cfdriver bm_cd = { 137 NULL, "bm", DV_IFNET 138 }; 139 140 int 141 bmac_read_reg(struct bmac_softc *sc, int off) 142 { 143 return in16rb(sc->sc_regs + off); 144 } 145 146 void 147 bmac_write_reg(struct bmac_softc *sc, int off, int val) 148 { 149 out16rb(sc->sc_regs + off, val); 150 } 151 152 void 153 bmac_set_bits(struct bmac_softc *sc, int off, int val) 154 { 155 val |= bmac_read_reg(sc, off); 156 bmac_write_reg(sc, off, val); 157 } 158 159 void 160 bmac_reset_bits(struct bmac_softc *sc, int off, int val) 161 { 162 bmac_write_reg(sc, off, bmac_read_reg(sc, off) & ~val); 163 } 164 165 int 166 bmac_match(struct device *parent, void *cf, void *aux) 167 { 168 struct confargs *ca = aux; 169 170 if (ca->ca_nreg < 24 || ca->ca_nintr < 12) 171 return (0); 172 173 if (strcmp(ca->ca_name, "bmac") == 0) /* bmac */ 174 return (1); 175 if (strcmp(ca->ca_name, "ethernet") == 0) /* bmac+ */ 176 return (1); 177 178 return (0); 179 } 180 181 void 182 bmac_attach(struct device *parent, struct device *self, void *aux) 183 { 184 struct confargs *ca = aux; 185 struct bmac_softc *sc = (void *)self; 186 struct ifnet *ifp = &sc->arpcom.ac_if; 187 struct mii_data *mii = &sc->sc_mii; 188 u_char laddr[6]; 189 int nseg, error; 190 191 timeout_set(&sc->sc_tick_ch, bmac_mii_tick, sc); 192 193 sc->sc_flags =0; 194 if (strcmp(ca->ca_name, "ethernet") == 0) { 195 sc->sc_flags |= BMAC_BMACPLUS; 196 } 197 198 ca->ca_reg[0] += ca->ca_baseaddr; 199 ca->ca_reg[2] += ca->ca_baseaddr; 200 ca->ca_reg[4] += ca->ca_baseaddr; 201 202 sc->sc_regs = (vaddr_t)mapiodev(ca->ca_reg[0], NBPG); 203 204 bmac_write_reg(sc, INTDISABLE, NoEventsMask); 205 206 if (OF_getprop(ca->ca_node, "local-mac-address", laddr, 6) == -1 && 207 OF_getprop(ca->ca_node, "mac-address", laddr, 6) == -1) { 208 printf(": cannot get mac-address\n"); 209 return; 210 } 211 bcopy(laddr, sc->arpcom.ac_enaddr, 6); 212 213 sc->sc_dmat = ca->ca_dmat; 214 sc->sc_txdma = mapiodev(ca->ca_reg[2], 0x100); 215 sc->sc_rxdma = mapiodev(ca->ca_reg[4], 0x100); 216 sc->sc_txdbdma = dbdma_alloc(sc->sc_dmat, BMAC_TXBUFS); 217 sc->sc_txcmd = sc->sc_txdbdma->d_addr; 218 sc->sc_rxdbdma = dbdma_alloc(sc->sc_dmat, BMAC_RXBUFS + 1); 219 sc->sc_rxcmd = sc->sc_rxdbdma->d_addr; 220 221 error = bus_dmamem_alloc(sc->sc_dmat, BMAC_BUFSZ, 222 PAGE_SIZE, 0, sc->sc_bufseg, 1, &nseg, BUS_DMA_NOWAIT); 223 if (error) { 224 printf(": cannot allocate buffers (%d)\n", error); 225 return; 226 } 227 228 error = bus_dmamem_map(sc->sc_dmat, sc->sc_bufseg, nseg, 229 BMAC_BUFSZ, &sc->sc_txbuf, BUS_DMA_NOWAIT); 230 if (error) { 231 printf(": cannot map buffers (%d)\n", error); 232 bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, 1); 233 return; 234 } 235 236 error = bus_dmamap_create(sc->sc_dmat, BMAC_BUFSZ, 1, BMAC_BUFSZ, 0, 237 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_bufmap); 238 if (error) { 239 printf(": cannot create buffer dmamap (%d)\n", error); 240 bus_dmamem_unmap(sc->sc_dmat, sc->sc_txbuf, BMAC_BUFSZ); 241 bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, 1); 242 return; 243 } 244 245 error = bus_dmamap_load(sc->sc_dmat, sc->sc_bufmap, sc->sc_txbuf, 246 BMAC_BUFSZ, NULL, BUS_DMA_NOWAIT); 247 if (error) { 248 printf(": cannot load buffers dmamap (%d)\n", error); 249 bus_dmamap_destroy(sc->sc_dmat, sc->sc_bufmap); 250 bus_dmamem_unmap(sc->sc_dmat, sc->sc_txbuf, BMAC_BUFSZ); 251 bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, nseg); 252 return; 253 } 254 255 sc->sc_txbuf_pa = sc->sc_bufmap->dm_segs->ds_addr; 256 sc->sc_rxbuf = sc->sc_txbuf + BMAC_BUFLEN * BMAC_TXBUFS; 257 sc->sc_rxbuf_pa = sc->sc_txbuf_pa + BMAC_BUFLEN * BMAC_TXBUFS; 258 259 printf(" irq %d,%d: address %s\n", ca->ca_intr[0], ca->ca_intr[2], 260 ether_sprintf(laddr)); 261 262 mac_intr_establish(parent, ca->ca_intr[0], IST_LEVEL, IPL_NET, 263 bmac_intr, sc, sc->sc_dev.dv_xname); 264 mac_intr_establish(parent, ca->ca_intr[2], IST_LEVEL, IPL_NET, 265 bmac_rint, sc, sc->sc_dev.dv_xname); 266 267 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 268 ifp->if_softc = sc; 269 ifp->if_ioctl = bmac_ioctl; 270 ifp->if_start = bmac_start; 271 ifp->if_flags = 272 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 273 ifp->if_watchdog = bmac_watchdog; 274 IFQ_SET_READY(&ifp->if_snd); 275 276 mii->mii_ifp = ifp; 277 mii->mii_readreg = bmac_mii_readreg; 278 mii->mii_writereg = bmac_mii_writereg; 279 mii->mii_statchg = bmac_mii_statchg; 280 281 ifmedia_init(&mii->mii_media, 0, bmac_mediachange, bmac_mediastatus); 282 mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, 283 MII_OFFSET_ANY, 0); 284 285 /* Choose a default media. */ 286 if (LIST_FIRST(&mii->mii_phys) == NULL) { 287 ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_10_T, 0, NULL); 288 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_10_T); 289 } else 290 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); 291 292 bmac_reset_chip(sc); 293 294 if_attach(ifp); 295 ether_ifattach(ifp); 296 } 297 298 /* 299 * Reset and enable bmac by heathrow FCR. 300 */ 301 void 302 bmac_reset_chip(struct bmac_softc *sc) 303 { 304 u_int v; 305 306 dbdma_reset(sc->sc_txdma); 307 dbdma_reset(sc->sc_rxdma); 308 309 v = in32rb(heathrow_FCR); 310 311 v |= EnetEnable; 312 out32rb(heathrow_FCR, v); 313 delay(50000); 314 315 /* assert reset */ 316 v |= ResetEnetCell; 317 out32rb(heathrow_FCR, v); 318 delay(50000); 319 320 /* deassert reset */ 321 v &= ~ResetEnetCell; 322 out32rb(heathrow_FCR, v); 323 delay(50000); 324 325 /* enable */ 326 v |= EnetEnable; 327 out32rb(heathrow_FCR, v); 328 delay(50000); 329 330 /* make certain they stay set? */ 331 out32rb(heathrow_FCR, v); 332 v = in32rb(heathrow_FCR); 333 } 334 335 void 336 bmac_init(struct bmac_softc *sc) 337 { 338 struct ifnet *ifp = &sc->arpcom.ac_if; 339 struct ether_header *eh; 340 caddr_t data; 341 int tb; 342 int i, bmcr; 343 u_short *p; 344 345 bmac_reset_chip(sc); 346 347 /* XXX */ 348 bmcr = bmac_mii_readreg((struct device *)sc, 0, MII_BMCR); 349 bmcr &= ~BMCR_ISO; 350 bmac_mii_writereg((struct device *)sc, 0, MII_BMCR, bmcr); 351 352 bmac_write_reg(sc, RXRST, RxResetValue); 353 bmac_write_reg(sc, TXRST, TxResetBit); 354 355 /* Wait for reset completion. */ 356 for (i = 1000; i > 0; i -= 10) { 357 if ((bmac_read_reg(sc, TXRST) & TxResetBit) == 0) 358 break; 359 delay(10); 360 } 361 if (i <= 0) 362 printf("%s: reset timeout\n", ifp->if_xname); 363 364 if (! (sc->sc_flags & BMAC_BMACPLUS)) 365 bmac_set_bits(sc, XCVRIF, ClkBit|SerialMode|COLActiveLow); 366 367 tb = ppc_mftbl(); 368 bmac_write_reg(sc, RSEED, tb); 369 bmac_set_bits(sc, XIFC, TxOutputEnable); 370 bmac_read_reg(sc, PAREG); 371 372 /* Reset various counters. */ 373 bmac_write_reg(sc, NCCNT, 0); 374 bmac_write_reg(sc, NTCNT, 0); 375 bmac_write_reg(sc, EXCNT, 0); 376 bmac_write_reg(sc, LTCNT, 0); 377 bmac_write_reg(sc, FRCNT, 0); 378 bmac_write_reg(sc, LECNT, 0); 379 bmac_write_reg(sc, AECNT, 0); 380 bmac_write_reg(sc, FECNT, 0); 381 bmac_write_reg(sc, RXCV, 0); 382 383 /* Set tx fifo information. */ 384 bmac_write_reg(sc, TXTH, 4); /* 4 octets before tx starts */ 385 386 bmac_write_reg(sc, TXFIFOCSR, 0); 387 bmac_write_reg(sc, TXFIFOCSR, TxFIFOEnable); 388 389 /* Set rx fifo information. */ 390 bmac_write_reg(sc, RXFIFOCSR, 0); 391 bmac_write_reg(sc, RXFIFOCSR, RxFIFOEnable); 392 393 /* Clear status register. */ 394 bmac_read_reg(sc, STATUS); 395 396 bmac_write_reg(sc, HASH3, 0); 397 bmac_write_reg(sc, HASH2, 0); 398 bmac_write_reg(sc, HASH1, 0); 399 bmac_write_reg(sc, HASH0, 0); 400 401 /* Set MAC address. */ 402 p = (u_short *)sc->arpcom.ac_enaddr; 403 bmac_write_reg(sc, MADD0, *p++); 404 bmac_write_reg(sc, MADD1, *p++); 405 bmac_write_reg(sc, MADD2, *p); 406 407 bmac_write_reg(sc, RXCFG, 408 RxCRCEnable | RxHashFilterEnable | RxRejectOwnPackets); 409 410 if (ifp->if_flags & IFF_PROMISC) 411 bmac_set_bits(sc, RXCFG, RxPromiscEnable); 412 413 bmac_init_dma(sc); 414 415 /* Configure Media. */ 416 mii_mediachg(&sc->sc_mii); 417 418 /* Enable TX/RX */ 419 bmac_set_bits(sc, RXCFG, RxMACEnable); 420 bmac_set_bits(sc, TXCFG, TxMACEnable); 421 422 bmac_write_reg(sc, INTDISABLE, NormalIntEvents); 423 424 ifp->if_flags |= IFF_RUNNING; 425 ifp->if_flags &= ~IFF_OACTIVE; 426 ifp->if_timer = 0; 427 428 data = sc->sc_txbuf; 429 eh = (struct ether_header *)data; 430 431 bzero(data, sizeof(*eh) + ETHERMIN); 432 bcopy(sc->arpcom.ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN); 433 bcopy(sc->arpcom.ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN); 434 bmac_transmit_packet(sc, sc->sc_txbuf_pa, sizeof(*eh) + ETHERMIN); 435 436 bmac_start(ifp); 437 438 timeout_add_sec(&sc->sc_tick_ch, 1); 439 } 440 441 void 442 bmac_init_dma(struct bmac_softc *sc) 443 { 444 dbdma_command_t *cmd = sc->sc_rxcmd; 445 int i; 446 447 dbdma_reset(sc->sc_txdma); 448 dbdma_reset(sc->sc_rxdma); 449 450 bzero(sc->sc_txcmd, BMAC_TXBUFS * sizeof(dbdma_command_t)); 451 bzero(sc->sc_rxcmd, (BMAC_RXBUFS + 1) * sizeof(dbdma_command_t)); 452 453 for (i = 0; i < BMAC_RXBUFS; i++) { 454 DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, BMAC_BUFLEN, 455 sc->sc_rxbuf_pa + BMAC_BUFLEN * i, 456 DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 457 cmd++; 458 } 459 DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0, 460 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS); 461 dbdma_st32(&cmd->d_cmddep, sc->sc_rxdbdma->d_paddr); 462 463 sc->sc_rxlast = 0; 464 465 dbdma_start(sc->sc_rxdma, sc->sc_rxdbdma); 466 } 467 468 int 469 bmac_intr(void *v) 470 { 471 struct bmac_softc *sc = v; 472 struct ifnet *ifp = &sc->arpcom.ac_if; 473 int stat; 474 475 #ifdef BMAC_DEBUG 476 printf("bmac_intr called\n"); 477 #endif 478 stat = bmac_read_reg(sc, STATUS); 479 if (stat == 0) 480 return (0); 481 482 #ifdef BMAC_DEBUG 483 printf("bmac_intr status = 0x%x\n", stat); 484 #endif 485 486 if (stat & IntFrameSent) { 487 ifp->if_flags &= ~IFF_OACTIVE; 488 ifp->if_timer = 0; 489 ifp->if_opackets++; 490 bmac_start(ifp); 491 } 492 493 /* XXX should do more! */ 494 495 return (1); 496 } 497 498 int 499 bmac_rint(void *v) 500 { 501 struct bmac_softc *sc = v; 502 struct ifnet *ifp = &sc->arpcom.ac_if; 503 struct mbuf *m; 504 dbdma_command_t *cmd; 505 int status, resid, count, datalen; 506 int i, n; 507 void *data; 508 #ifdef BMAC_DEBUG 509 printf("bmac_rint() called\n"); 510 #endif 511 512 i = sc->sc_rxlast; 513 for (n = 0; n < BMAC_RXBUFS; n++, i++) { 514 if (i == BMAC_RXBUFS) 515 i = 0; 516 cmd = &sc->sc_rxcmd[i]; 517 status = dbdma_ld16(&cmd->d_status); 518 resid = dbdma_ld16(&cmd->d_resid); 519 520 #ifdef BMAC_DEBUG 521 if (status != 0 && status != 0x8440 && status != 0x9440) 522 printf("bmac_rint status = 0x%x\n", status); 523 #endif 524 525 if ((status & DBDMA_CNTRL_ACTIVE) == 0) /* 0x9440 | 0x8440 */ 526 continue; 527 count = dbdma_ld16(&cmd->d_count); 528 datalen = count - resid; /* 2 == framelen */ 529 if (datalen < sizeof(struct ether_header)) { 530 printf("%s: short packet len = %d\n", 531 ifp->if_xname, datalen); 532 goto next; 533 } 534 DBDMA_BUILD_CMD(cmd, DBDMA_CMD_STOP, 0, 0, 0, 0); 535 data = sc->sc_rxbuf + BMAC_BUFLEN * i; 536 537 /* XXX Sometimes bmac reads one extra byte. */ 538 if (datalen == ETHER_MAX_LEN + 1) 539 datalen--; 540 541 /* Trim the CRC. */ 542 datalen -= ETHER_CRC_LEN; 543 544 m = bmac_get(sc, data, datalen); 545 if (m == NULL) { 546 ifp->if_ierrors++; 547 goto next; 548 } 549 550 #if NBPFILTER > 0 551 /* 552 * Check if there's a BPF listener on this interface. 553 * If so, hand off the raw packet to BPF. 554 */ 555 if (ifp->if_bpf) 556 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 557 #endif 558 ether_input_mbuf(ifp, m); 559 ifp->if_ipackets++; 560 561 next: 562 DBDMA_BUILD_CMD(cmd, DBDMA_CMD_IN_LAST, 0, DBDMA_INT_ALWAYS, 563 DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 564 565 cmd->d_status = 0; 566 cmd->d_resid = 0; 567 sc->sc_rxlast = i + 1; 568 } 569 dbdma_continue(sc->sc_rxdma); 570 571 return (1); 572 } 573 574 void 575 bmac_reset(struct bmac_softc *sc) 576 { 577 int s; 578 579 s = splnet(); 580 bmac_init(sc); 581 splx(s); 582 } 583 584 void 585 bmac_stop(struct bmac_softc *sc) 586 { 587 struct ifnet *ifp = &sc->arpcom.ac_if; 588 int s; 589 590 s = splnet(); 591 592 /* timeout */ 593 timeout_del(&sc->sc_tick_ch); 594 mii_down(&sc->sc_mii); 595 596 /* Disable TX/RX. */ 597 bmac_reset_bits(sc, TXCFG, TxMACEnable); 598 bmac_reset_bits(sc, RXCFG, RxMACEnable); 599 600 /* Disable all interrupts. */ 601 bmac_write_reg(sc, INTDISABLE, NoEventsMask); 602 603 dbdma_stop(sc->sc_txdma); 604 dbdma_stop(sc->sc_rxdma); 605 606 ifp->if_flags &= ~(IFF_UP | IFF_RUNNING); 607 ifp->if_timer = 0; 608 609 splx(s); 610 } 611 612 void 613 bmac_start(struct ifnet *ifp) 614 { 615 struct bmac_softc *sc = ifp->if_softc; 616 struct mbuf *m; 617 int tlen; 618 619 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 620 return; 621 622 while (1) { 623 if (ifp->if_flags & IFF_OACTIVE) 624 return; 625 626 IFQ_DEQUEUE(&ifp->if_snd, m); 627 if (m == 0) 628 break; 629 #if NBPFILTER > 0 630 /* 631 * If BPF is listening on this interface, let it see the 632 * packet before we commit it to the wire. 633 */ 634 if (ifp->if_bpf) 635 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 636 #endif 637 638 ifp->if_flags |= IFF_OACTIVE; 639 tlen = bmac_put(sc, sc->sc_txbuf, m); 640 641 /* 5 seconds to watch for failing to transmit */ 642 ifp->if_timer = 5; 643 ifp->if_opackets++; /* # of pkts */ 644 645 bmac_transmit_packet(sc, sc->sc_txbuf_pa, tlen); 646 } 647 } 648 649 void 650 bmac_transmit_packet(struct bmac_softc *sc, paddr_t pa, int len) 651 { 652 dbdma_command_t *cmd = sc->sc_txcmd; 653 654 DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, len, pa, 655 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 656 cmd++; 657 DBDMA_BUILD(cmd, DBDMA_CMD_STOP, 0, 0, 0, 658 DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 659 660 dbdma_start(sc->sc_txdma, sc->sc_txdbdma); 661 } 662 663 int 664 bmac_put(struct bmac_softc *sc, caddr_t buff, struct mbuf *m) 665 { 666 struct mbuf *n; 667 int len, tlen = 0; 668 669 for (; m; m = n) { 670 len = m->m_len; 671 if (len == 0) { 672 MFREE(m, n); 673 continue; 674 } 675 bcopy(mtod(m, caddr_t), buff, len); 676 buff += len; 677 tlen += len; 678 MFREE(m, n); 679 } 680 if (tlen > NBPG) 681 panic("%s: putpacket packet overflow", sc->sc_dev.dv_xname); 682 683 return (tlen); 684 } 685 686 struct mbuf * 687 bmac_get(struct bmac_softc *sc, caddr_t pkt, int totlen) 688 { 689 struct mbuf *m; 690 struct mbuf *top, **mp; 691 int len; 692 693 MGETHDR(m, M_DONTWAIT, MT_DATA); 694 if (m == 0) 695 return (0); 696 m->m_pkthdr.rcvif = &sc->arpcom.ac_if; 697 m->m_pkthdr.len = totlen; 698 len = MHLEN; 699 top = 0; 700 mp = ⊤ 701 702 while (totlen > 0) { 703 if (top) { 704 MGET(m, M_DONTWAIT, MT_DATA); 705 if (m == 0) { 706 m_freem(top); 707 return (0); 708 } 709 len = MLEN; 710 } 711 if (totlen >= MINCLSIZE) { 712 MCLGET(m, M_DONTWAIT); 713 if ((m->m_flags & M_EXT) == 0) { 714 m_free(m); 715 m_freem(top); 716 return (0); 717 } 718 len = MCLBYTES; 719 } 720 m->m_len = len = min(totlen, len); 721 bcopy(pkt, mtod(m, caddr_t), len); 722 pkt += len; 723 totlen -= len; 724 *mp = m; 725 mp = &m->m_next; 726 } 727 728 return (top); 729 } 730 731 void 732 bmac_watchdog(struct ifnet *ifp) 733 { 734 struct bmac_softc *sc = ifp->if_softc; 735 736 bmac_reset_bits(sc, RXCFG, RxMACEnable); 737 bmac_reset_bits(sc, TXCFG, TxMACEnable); 738 739 printf("%s: device timeout\n", ifp->if_xname); 740 ifp->if_oerrors++; 741 742 bmac_reset(sc); 743 } 744 745 int 746 bmac_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 747 { 748 struct bmac_softc *sc = ifp->if_softc; 749 struct ifaddr *ifa = (struct ifaddr *)data; 750 struct ifreq *ifr = (struct ifreq *)data; 751 int s, error = 0; 752 753 s = splnet(); 754 755 switch (cmd) { 756 case SIOCSIFADDR: 757 ifp->if_flags |= IFF_UP; 758 759 switch (ifa->ifa_addr->sa_family) { 760 #ifdef INET 761 case AF_INET: 762 bmac_init(sc); 763 arp_ifinit(&sc->arpcom, ifa); 764 break; 765 #endif 766 default: 767 bmac_init(sc); 768 break; 769 } 770 break; 771 772 case SIOCSIFFLAGS: 773 if ((ifp->if_flags & IFF_UP) == 0 && 774 (ifp->if_flags & IFF_RUNNING) != 0) { 775 /* 776 * If interface is marked down and it is running, then 777 * stop it. 778 */ 779 bmac_stop(sc); 780 ifp->if_flags &= ~IFF_RUNNING; 781 } else if ((ifp->if_flags & IFF_UP) != 0 && 782 (ifp->if_flags & IFF_RUNNING) == 0) { 783 /* 784 * If interface is marked up and it is stopped, then 785 * start it. 786 */ 787 bmac_init(sc); 788 } else { 789 /* 790 * Reset the interface to pick up changes in any other 791 * flags that affect hardware registers. 792 */ 793 /*bmac_stop(sc);*/ 794 bmac_init(sc); 795 } 796 #ifdef BMAC_DEBUG 797 if (ifp->if_flags & IFF_DEBUG) 798 sc->sc_debug = 1; 799 else 800 sc->sc_debug = 0; 801 #endif 802 break; 803 804 case SIOCGIFMEDIA: 805 case SIOCSIFMEDIA: 806 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); 807 break; 808 809 default: 810 error = ether_ioctl(ifp, &sc->arpcom, cmd, data); 811 } 812 813 if (error == ENETRESET) { 814 if (ifp->if_flags & IFF_RUNNING) { 815 bmac_init(sc); 816 bmac_setladrf(sc); 817 } 818 error = 0; 819 } 820 821 splx(s); 822 return (error); 823 } 824 825 int 826 bmac_mediachange(struct ifnet *ifp) 827 { 828 struct bmac_softc *sc = ifp->if_softc; 829 830 return mii_mediachg(&sc->sc_mii); 831 } 832 833 void 834 bmac_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 835 { 836 struct bmac_softc *sc = ifp->if_softc; 837 838 mii_pollstat(&sc->sc_mii); 839 840 ifmr->ifm_status = sc->sc_mii.mii_media_status; 841 ifmr->ifm_active = sc->sc_mii.mii_media_active; 842 } 843 844 /* 845 * Set up the logical address filter. 846 */ 847 void 848 bmac_setladrf(struct bmac_softc *sc) 849 { 850 struct ifnet *ifp = &sc->arpcom.ac_if; 851 struct ether_multi *enm; 852 struct ether_multistep step; 853 u_int32_t crc; 854 u_int16_t hash[4]; 855 int x; 856 857 /* 858 * Set up multicast address filter by passing all multicast addresses 859 * through a crc generator, and then using the high order 6 bits as an 860 * index into the 64 bit logical address filter. The high order bit 861 * selects the word, while the rest of the bits select the bit within 862 * the word. 863 */ 864 865 if (ifp->if_flags & IFF_PROMISC) { 866 bmac_set_bits(sc, RXCFG, RxPromiscEnable); 867 return; 868 } 869 870 if (ifp->if_flags & IFF_ALLMULTI) { 871 hash[3] = hash[2] = hash[1] = hash[0] = 0xffff; 872 goto chipit; 873 } 874 875 hash[3] = hash[2] = hash[1] = hash[0] = 0; 876 ETHER_FIRST_MULTI(step, &sc->arpcom, enm); 877 while (enm != NULL) { 878 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 879 /* 880 * We must listen to a range of multicast addresses. 881 * For now, just accept all multicasts, rather than 882 * trying to set only those filter bits needed to match 883 * the range. (At this time, the only use of address 884 * ranges is for IP multicast routing, for which the 885 * range is big enough to require all bits set.) 886 */ 887 hash[3] = hash[2] = hash[1] = hash[0] = 0xffff; 888 ifp->if_flags |= IFF_ALLMULTI; 889 goto chipit; 890 } 891 892 crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); 893 894 /* Just want the 6 most significant bits. */ 895 crc >>= 26; 896 897 /* Set the corresponding bit in the filter. */ 898 hash[crc >> 4] |= 1 << (crc & 0xf); 899 900 ETHER_NEXT_MULTI(step, enm); 901 } 902 903 ifp->if_flags &= ~IFF_ALLMULTI; 904 905 chipit: 906 bmac_write_reg(sc, HASH0, hash[0]); 907 bmac_write_reg(sc, HASH1, hash[1]); 908 bmac_write_reg(sc, HASH2, hash[2]); 909 bmac_write_reg(sc, HASH3, hash[3]); 910 x = bmac_read_reg(sc, RXCFG); 911 x &= ~RxPromiscEnable; 912 x |= RxHashFilterEnable; 913 bmac_write_reg(sc, RXCFG, x); 914 } 915 916 int 917 bmac_mii_readreg(struct device *dev, int phy, int reg) 918 { 919 return mii_bitbang_readreg(dev, &bmac_mbo, phy, reg); 920 } 921 922 void 923 bmac_mii_writereg(struct device *dev, int phy, int reg, int val) 924 { 925 mii_bitbang_writereg(dev, &bmac_mbo, phy, reg, val); 926 } 927 928 u_int32_t 929 bmac_mbo_read(struct device *dev) 930 { 931 struct bmac_softc *sc = (void *)dev; 932 933 return bmac_read_reg(sc, MIFCSR); 934 } 935 936 void 937 bmac_mbo_write(struct device *dev, u_int32_t val) 938 { 939 struct bmac_softc *sc = (void *)dev; 940 941 bmac_write_reg(sc, MIFCSR, val); 942 } 943 944 void 945 bmac_mii_statchg(struct device *dev) 946 { 947 struct bmac_softc *sc = (void *)dev; 948 int x; 949 950 /* Update duplex mode in TX configuration */ 951 x = bmac_read_reg(sc, TXCFG); 952 if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) 953 x |= TxFullDuplex; 954 else 955 x &= ~TxFullDuplex; 956 bmac_write_reg(sc, TXCFG, x); 957 958 #ifdef BMAC_DEBUG 959 printf("bmac_mii_statchg 0x%x\n", 960 IFM_OPTIONS(sc->sc_mii.mii_media_active)); 961 #endif 962 } 963 964 void 965 bmac_mii_tick(void *v) 966 { 967 struct bmac_softc *sc = v; 968 int s; 969 970 s = splnet(); 971 mii_tick(&sc->sc_mii); 972 splx(s); 973 974 timeout_add_sec(&sc->sc_tick_ch, 1); 975 } 976