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