1 /* $OpenBSD: if_bm.c,v 1.43 2020/07/10 13:22:19 patrick 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 bmac_start(ifp); 488 } 489 490 /* XXX should do more! */ 491 492 return (1); 493 } 494 495 int 496 bmac_rint(void *v) 497 { 498 struct bmac_softc *sc = v; 499 struct ifnet *ifp = &sc->arpcom.ac_if; 500 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 501 struct mbuf *m; 502 dbdma_command_t *cmd; 503 int status, resid, count, datalen; 504 int i, n; 505 void *data; 506 #ifdef BMAC_DEBUG 507 printf("bmac_rint() called\n"); 508 #endif 509 510 i = sc->sc_rxlast; 511 for (n = 0; n < BMAC_RXBUFS; n++, i++) { 512 if (i == BMAC_RXBUFS) 513 i = 0; 514 cmd = &sc->sc_rxcmd[i]; 515 status = dbdma_ld16(&cmd->d_status); 516 resid = dbdma_ld16(&cmd->d_resid); 517 518 #ifdef BMAC_DEBUG 519 if (status != 0 && status != 0x8440 && status != 0x9440) 520 printf("bmac_rint status = 0x%x\n", status); 521 #endif 522 523 if ((status & DBDMA_CNTRL_ACTIVE) == 0) /* 0x9440 | 0x8440 */ 524 continue; 525 count = dbdma_ld16(&cmd->d_count); 526 datalen = count - resid; /* 2 == framelen */ 527 if (datalen < sizeof(struct ether_header)) { 528 printf("%s: short packet len = %d\n", 529 ifp->if_xname, datalen); 530 goto next; 531 } 532 DBDMA_BUILD_CMD(cmd, DBDMA_CMD_STOP, 0, 0, 0, 0); 533 data = sc->sc_rxbuf + BMAC_BUFLEN * i; 534 535 /* XXX Sometimes bmac reads one extra byte. */ 536 if (datalen == ETHER_MAX_LEN + 1) 537 datalen--; 538 539 /* Trim the CRC. */ 540 datalen -= ETHER_CRC_LEN; 541 542 m = bmac_get(sc, data, datalen); 543 if (m == NULL) { 544 ifp->if_ierrors++; 545 goto next; 546 } 547 548 ml_enqueue(&ml, m); 549 550 next: 551 DBDMA_BUILD_CMD(cmd, DBDMA_CMD_IN_LAST, 0, DBDMA_INT_ALWAYS, 552 DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 553 554 cmd->d_status = 0; 555 cmd->d_resid = 0; 556 sc->sc_rxlast = i + 1; 557 } 558 bmac_mediachange(ifp); 559 560 dbdma_continue(sc->sc_rxdma); 561 562 if_input(ifp, &ml); 563 return (1); 564 } 565 566 void 567 bmac_reset(struct bmac_softc *sc) 568 { 569 int s; 570 571 s = splnet(); 572 bmac_init(sc); 573 splx(s); 574 } 575 576 void 577 bmac_stop(struct bmac_softc *sc) 578 { 579 struct ifnet *ifp = &sc->arpcom.ac_if; 580 int s; 581 582 s = splnet(); 583 584 /* timeout */ 585 timeout_del(&sc->sc_tick_ch); 586 mii_down(&sc->sc_mii); 587 588 /* Disable TX/RX. */ 589 bmac_reset_bits(sc, TXCFG, TxMACEnable); 590 bmac_reset_bits(sc, RXCFG, RxMACEnable); 591 592 /* Disable all interrupts. */ 593 bmac_write_reg(sc, INTDISABLE, NoEventsMask); 594 595 dbdma_stop(sc->sc_txdma); 596 dbdma_stop(sc->sc_rxdma); 597 598 ifp->if_flags &= ~IFF_RUNNING; 599 ifp->if_timer = 0; 600 601 splx(s); 602 } 603 604 void 605 bmac_start(struct ifnet *ifp) 606 { 607 struct bmac_softc *sc = ifp->if_softc; 608 struct mbuf *m; 609 int tlen; 610 611 if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) 612 return; 613 614 while (1) { 615 if (ifq_is_oactive(&ifp->if_snd)) 616 return; 617 618 m = ifq_dequeue(&ifp->if_snd); 619 if (m == NULL) 620 break; 621 #if NBPFILTER > 0 622 /* 623 * If BPF is listening on this interface, let it see the 624 * packet before we commit it to the wire. 625 */ 626 if (ifp->if_bpf) 627 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 628 #endif 629 630 ifq_set_oactive(&ifp->if_snd); 631 tlen = bmac_put(sc, sc->sc_txbuf, m); 632 633 /* 5 seconds to watch for failing to transmit */ 634 ifp->if_timer = 5; 635 636 bmac_transmit_packet(sc, sc->sc_txbuf_pa, tlen); 637 } 638 } 639 640 void 641 bmac_transmit_packet(struct bmac_softc *sc, paddr_t pa, int len) 642 { 643 dbdma_command_t *cmd = sc->sc_txcmd; 644 645 DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, len, pa, 646 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 647 cmd++; 648 DBDMA_BUILD(cmd, DBDMA_CMD_STOP, 0, 0, 0, 649 DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 650 651 dbdma_start(sc->sc_txdma, sc->sc_txdbdma); 652 } 653 654 int 655 bmac_put(struct bmac_softc *sc, caddr_t buff, struct mbuf *m) 656 { 657 struct mbuf *n; 658 int len, tlen = 0; 659 660 for (; m; m = n) { 661 len = m->m_len; 662 if (len == 0) { 663 n = m_free(m); 664 continue; 665 } 666 bcopy(mtod(m, caddr_t), buff, len); 667 buff += len; 668 tlen += len; 669 n = m_free(m); 670 } 671 if (tlen > NBPG) 672 panic("%s: putpacket packet overflow", sc->sc_dev.dv_xname); 673 674 return (tlen); 675 } 676 677 struct mbuf * 678 bmac_get(struct bmac_softc *sc, caddr_t pkt, int totlen) 679 { 680 struct mbuf *m; 681 struct mbuf *top, **mp; 682 int len; 683 684 MGETHDR(m, M_DONTWAIT, MT_DATA); 685 if (m == NULL) 686 return (0); 687 m->m_pkthdr.len = totlen; 688 len = MHLEN; 689 top = 0; 690 mp = ⊤ 691 692 while (totlen > 0) { 693 if (top) { 694 MGET(m, M_DONTWAIT, MT_DATA); 695 if (m == NULL) { 696 m_freem(top); 697 return (0); 698 } 699 len = MLEN; 700 } 701 if (totlen >= MINCLSIZE) { 702 MCLGET(m, M_DONTWAIT); 703 if ((m->m_flags & M_EXT) == 0) { 704 m_free(m); 705 m_freem(top); 706 return (0); 707 } 708 len = MCLBYTES; 709 } 710 m->m_len = len = min(totlen, len); 711 bcopy(pkt, mtod(m, caddr_t), len); 712 pkt += len; 713 totlen -= len; 714 *mp = m; 715 mp = &m->m_next; 716 } 717 718 return (top); 719 } 720 721 void 722 bmac_watchdog(struct ifnet *ifp) 723 { 724 struct bmac_softc *sc = ifp->if_softc; 725 726 bmac_reset_bits(sc, RXCFG, RxMACEnable); 727 bmac_reset_bits(sc, TXCFG, TxMACEnable); 728 729 printf("%s: device timeout\n", ifp->if_xname); 730 ifp->if_oerrors++; 731 732 bmac_reset(sc); 733 } 734 735 int 736 bmac_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 737 { 738 struct bmac_softc *sc = ifp->if_softc; 739 struct ifreq *ifr = (struct ifreq *)data; 740 int s, error = 0; 741 742 s = splnet(); 743 744 switch (cmd) { 745 case SIOCSIFADDR: 746 ifp->if_flags |= IFF_UP; 747 bmac_init(sc); 748 break; 749 750 case SIOCSIFFLAGS: 751 if ((ifp->if_flags & IFF_UP) == 0 && 752 (ifp->if_flags & IFF_RUNNING) != 0) { 753 /* 754 * If interface is marked down and it is running, then 755 * stop it. 756 */ 757 bmac_stop(sc); 758 ifp->if_flags &= ~IFF_RUNNING; 759 } else if ((ifp->if_flags & IFF_UP) != 0 && 760 (ifp->if_flags & IFF_RUNNING) == 0) { 761 /* 762 * If interface is marked up and it is stopped, then 763 * start it. 764 */ 765 bmac_init(sc); 766 } else { 767 /* 768 * Reset the interface to pick up changes in any other 769 * flags that affect hardware registers. 770 */ 771 /*bmac_stop(sc);*/ 772 bmac_init(sc); 773 } 774 #ifdef BMAC_DEBUG 775 if (ifp->if_flags & IFF_DEBUG) 776 sc->sc_debug = 1; 777 else 778 sc->sc_debug = 0; 779 #endif 780 break; 781 782 case SIOCGIFMEDIA: 783 case SIOCSIFMEDIA: 784 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd); 785 break; 786 787 default: 788 error = ether_ioctl(ifp, &sc->arpcom, cmd, data); 789 } 790 791 if (error == ENETRESET) { 792 if (ifp->if_flags & IFF_RUNNING) { 793 bmac_init(sc); 794 bmac_setladrf(sc); 795 } 796 error = 0; 797 } 798 799 splx(s); 800 return (error); 801 } 802 803 int 804 bmac_mediachange(struct ifnet *ifp) 805 { 806 struct bmac_softc *sc = ifp->if_softc; 807 808 return mii_mediachg(&sc->sc_mii); 809 } 810 811 void 812 bmac_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 813 { 814 struct bmac_softc *sc = ifp->if_softc; 815 816 mii_pollstat(&sc->sc_mii); 817 818 ifmr->ifm_status = sc->sc_mii.mii_media_status; 819 ifmr->ifm_active = sc->sc_mii.mii_media_active; 820 } 821 822 /* 823 * Set up the logical address filter. 824 */ 825 void 826 bmac_setladrf(struct bmac_softc *sc) 827 { 828 struct arpcom *ac = &sc->arpcom; 829 struct ifnet *ifp = &sc->arpcom.ac_if; 830 struct ether_multi *enm; 831 struct ether_multistep step; 832 u_int32_t crc; 833 u_int16_t hash[4]; 834 int x; 835 836 /* 837 * Set up multicast address filter by passing all multicast addresses 838 * through a crc generator, and then using the high order 6 bits as an 839 * index into the 64 bit logical address filter. The high order bit 840 * selects the word, while the rest of the bits select the bit within 841 * the word. 842 */ 843 844 if (ifp->if_flags & IFF_PROMISC) { 845 bmac_set_bits(sc, RXCFG, RxPromiscEnable); 846 return; 847 } 848 849 if (ac->ac_multirangecnt > 0) 850 ifp->if_flags |= IFF_ALLMULTI; 851 852 if (ifp->if_flags & IFF_ALLMULTI) { 853 hash[3] = hash[2] = hash[1] = hash[0] = 0xffff; 854 goto chipit; 855 } 856 857 hash[3] = hash[2] = hash[1] = hash[0] = 0; 858 ETHER_FIRST_MULTI(step, ac, enm); 859 while (enm != NULL) { 860 crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); 861 862 /* Just want the 6 most significant bits. */ 863 crc >>= 26; 864 865 /* Set the corresponding bit in the filter. */ 866 hash[crc >> 4] |= 1 << (crc & 0xf); 867 868 ETHER_NEXT_MULTI(step, enm); 869 } 870 871 ifp->if_flags &= ~IFF_ALLMULTI; 872 873 chipit: 874 bmac_write_reg(sc, HASH0, hash[0]); 875 bmac_write_reg(sc, HASH1, hash[1]); 876 bmac_write_reg(sc, HASH2, hash[2]); 877 bmac_write_reg(sc, HASH3, hash[3]); 878 x = bmac_read_reg(sc, RXCFG); 879 x &= ~RxPromiscEnable; 880 x |= RxHashFilterEnable; 881 bmac_write_reg(sc, RXCFG, x); 882 } 883 884 int 885 bmac_mii_readreg(struct device *dev, int phy, int reg) 886 { 887 return mii_bitbang_readreg(dev, &bmac_mbo, phy, reg); 888 } 889 890 void 891 bmac_mii_writereg(struct device *dev, int phy, int reg, int val) 892 { 893 mii_bitbang_writereg(dev, &bmac_mbo, phy, reg, val); 894 } 895 896 u_int32_t 897 bmac_mbo_read(struct device *dev) 898 { 899 struct bmac_softc *sc = (void *)dev; 900 901 return bmac_read_reg(sc, MIFCSR); 902 } 903 904 void 905 bmac_mbo_write(struct device *dev, u_int32_t val) 906 { 907 struct bmac_softc *sc = (void *)dev; 908 909 bmac_write_reg(sc, MIFCSR, val); 910 } 911 912 void 913 bmac_mii_statchg(struct device *dev) 914 { 915 struct bmac_softc *sc = (void *)dev; 916 int x; 917 918 /* Update duplex mode in TX configuration */ 919 x = bmac_read_reg(sc, TXCFG); 920 if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) 921 x |= TxFullDuplex; 922 else 923 x &= ~TxFullDuplex; 924 bmac_write_reg(sc, TXCFG, x); 925 926 #ifdef BMAC_DEBUG 927 printf("bmac_mii_statchg 0x%x\n", 928 IFM_OPTIONS(sc->sc_mii.mii_media_active)); 929 #endif 930 } 931 932 void 933 bmac_mii_tick(void *v) 934 { 935 struct bmac_softc *sc = v; 936 int s; 937 938 s = splnet(); 939 mii_tick(&sc->sc_mii); 940 splx(s); 941 942 timeout_add_sec(&sc->sc_tick_ch, 1); 943 } 944