if_admsw.c revision 330897
1/* $NetBSD: if_admsw.c,v 1.3 2007/04/22 19:26:25 dyoung Exp $ */ 2 3/*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or 10 * without modification, are permitted provided that the following 11 * conditions are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials provided 17 * with the distribution. 18 * 3. The names of the authors may not be used to endorse or promote 19 * products derived from this software without specific prior 20 * written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY 23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 24 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 27 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 29 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 31 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 33 * OF SUCH DAMAGE. 34 */ 35/* 36 * Copyright (c) 2001 Wasabi Systems, Inc. 37 * All rights reserved. 38 * 39 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. All advertising materials mentioning features or use of this software 50 * must display the following acknowledgement: 51 * This product includes software developed for the NetBSD Project by 52 * Wasabi Systems, Inc. 53 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 54 * or promote products derived from this software without specific prior 55 * written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 59 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 60 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 61 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 62 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 63 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 64 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 65 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 66 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 67 * POSSIBILITY OF SUCH DAMAGE. 68 */ 69 70/* 71 * Device driver for Alchemy Semiconductor Au1x00 Ethernet Media 72 * Access Controller. 73 * 74 * TODO: 75 * 76 * Better Rx buffer management; we want to get new Rx buffers 77 * to the chip more quickly than we currently do. 78 */ 79 80#include <sys/cdefs.h> 81__FBSDID("$FreeBSD: stable/11/sys/mips/adm5120/if_admsw.c 330897 2018-03-14 03:19:51Z eadler $"); 82 83#include <sys/param.h> 84#include <sys/systm.h> 85#include <sys/bus.h> 86#include <sys/kernel.h> 87#include <sys/mbuf.h> 88#include <sys/malloc.h> 89#include <sys/module.h> 90#include <sys/rman.h> 91#include <sys/socket.h> 92#include <sys/sockio.h> 93#include <sys/sysctl.h> 94#include <machine/bus.h> 95 96#include <net/ethernet.h> 97#include <net/if.h> 98#include <net/if_arp.h> 99#include <net/if_dl.h> 100#include <net/if_media.h> 101#include <net/if_mib.h> 102#include <net/if_types.h> 103#include <net/if_var.h> 104 105#ifdef INET 106#include <netinet/in.h> 107#include <netinet/in_systm.h> 108#include <netinet/in_var.h> 109#include <netinet/ip.h> 110#endif 111 112#include <net/bpf.h> 113#include <net/bpfdesc.h> 114 115#include <mips/adm5120/adm5120reg.h> 116#include <mips/adm5120/if_admswreg.h> 117#include <mips/adm5120/if_admswvar.h> 118 119/* TODO: add locking */ 120#define ADMSW_LOCK(sc) do {} while(0); 121#define ADMSW_UNLOCK(sc) do {} while(0); 122 123static uint8_t vlan_matrix[SW_DEVS] = { 124 (1 << 6) | (1 << 0), /* CPU + port0 */ 125 (1 << 6) | (1 << 1), /* CPU + port1 */ 126 (1 << 6) | (1 << 2), /* CPU + port2 */ 127 (1 << 6) | (1 << 3), /* CPU + port3 */ 128 (1 << 6) | (1 << 4), /* CPU + port4 */ 129 (1 << 6) | (1 << 5), /* CPU + port5 */ 130}; 131 132/* ifnet entry points */ 133static void admsw_start(struct ifnet *); 134static void admsw_watchdog(void *); 135static int admsw_ioctl(struct ifnet *, u_long, caddr_t); 136static void admsw_init(void *); 137static void admsw_stop(struct ifnet *, int); 138 139static void admsw_reset(struct admsw_softc *); 140static void admsw_set_filter(struct admsw_softc *); 141 142static void admsw_txintr(struct admsw_softc *, int); 143static void admsw_rxintr(struct admsw_softc *, int); 144static int admsw_add_rxbuf(struct admsw_softc *, int, int); 145#define admsw_add_rxhbuf(sc, idx) admsw_add_rxbuf(sc, idx, 1) 146#define admsw_add_rxlbuf(sc, idx) admsw_add_rxbuf(sc, idx, 0) 147 148static int admsw_mediachange(struct ifnet *); 149static void admsw_mediastatus(struct ifnet *, struct ifmediareq *); 150 151static int admsw_intr(void *); 152 153/* bus entry points */ 154static int admsw_probe(device_t dev); 155static int admsw_attach(device_t dev); 156static int admsw_detach(device_t dev); 157static int admsw_shutdown(device_t dev); 158 159static void 160admsw_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 161{ 162 uint32_t *addr; 163 164 if (error) 165 return; 166 167 KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 168 addr = arg; 169 *addr = segs->ds_addr; 170} 171 172static void 173admsw_rxbuf_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 174{ 175 struct admsw_descsoft *ds; 176 177 if (error) 178 return; 179 180 KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 181 182 ds = arg; 183 ds->ds_nsegs = nseg; 184 ds->ds_addr[0] = segs[0].ds_addr; 185 ds->ds_len[0] = segs[0].ds_len; 186 187} 188 189static void 190admsw_mbuf_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, 191 bus_size_t mapsize, int error) 192{ 193 struct admsw_descsoft *ds; 194 195 if (error) 196 return; 197 198 ds = arg; 199 200 if((nseg != 1) && (nseg != 2)) 201 panic("%s: nseg == %d\n", __func__, nseg); 202 203 ds->ds_nsegs = nseg; 204 ds->ds_addr[0] = segs[0].ds_addr; 205 ds->ds_len[0] = segs[0].ds_len; 206 207 if(nseg > 1) { 208 ds->ds_addr[1] = segs[1].ds_addr; 209 ds->ds_len[1] = segs[1].ds_len; 210 } 211} 212 213 214 215static int 216admsw_probe(device_t dev) 217{ 218 219 device_set_desc(dev, "ADM5120 Switch Engine"); 220 return (0); 221} 222 223#define REG_READ(o) bus_read_4((sc)->mem_res, (o)) 224#define REG_WRITE(o,v) bus_write_4((sc)->mem_res, (o),(v)) 225 226static void 227admsw_init_bufs(struct admsw_softc *sc) 228{ 229 int i; 230 struct admsw_desc *desc; 231 232 for (i = 0; i < ADMSW_NTXHDESC; i++) { 233 if (sc->sc_txhsoft[i].ds_mbuf != NULL) { 234 m_freem(sc->sc_txhsoft[i].ds_mbuf); 235 sc->sc_txhsoft[i].ds_mbuf = NULL; 236 } 237 desc = &sc->sc_txhdescs[i]; 238 desc->data = 0; 239 desc->cntl = 0; 240 desc->len = MAC_BUFLEN; 241 desc->status = 0; 242 ADMSW_CDTXHSYNC(sc, i, 243 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 244 } 245 sc->sc_txhdescs[ADMSW_NTXHDESC - 1].data |= ADM5120_DMA_RINGEND; 246 ADMSW_CDTXHSYNC(sc, ADMSW_NTXHDESC - 1, 247 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 248 249 for (i = 0; i < ADMSW_NRXHDESC; i++) { 250 if (sc->sc_rxhsoft[i].ds_mbuf == NULL) { 251 if (admsw_add_rxhbuf(sc, i) != 0) 252 panic("admsw_init_bufs\n"); 253 } else 254 ADMSW_INIT_RXHDESC(sc, i); 255 } 256 257 for (i = 0; i < ADMSW_NTXLDESC; i++) { 258 if (sc->sc_txlsoft[i].ds_mbuf != NULL) { 259 m_freem(sc->sc_txlsoft[i].ds_mbuf); 260 sc->sc_txlsoft[i].ds_mbuf = NULL; 261 } 262 desc = &sc->sc_txldescs[i]; 263 desc->data = 0; 264 desc->cntl = 0; 265 desc->len = MAC_BUFLEN; 266 desc->status = 0; 267 ADMSW_CDTXLSYNC(sc, i, 268 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 269 } 270 sc->sc_txldescs[ADMSW_NTXLDESC - 1].data |= ADM5120_DMA_RINGEND; 271 ADMSW_CDTXLSYNC(sc, ADMSW_NTXLDESC - 1, 272 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 273 274 for (i = 0; i < ADMSW_NRXLDESC; i++) { 275 if (sc->sc_rxlsoft[i].ds_mbuf == NULL) { 276 if (admsw_add_rxlbuf(sc, i) != 0) 277 panic("admsw_init_bufs\n"); 278 } else 279 ADMSW_INIT_RXLDESC(sc, i); 280 } 281 282 REG_WRITE(SEND_HBADDR_REG, ADMSW_CDTXHADDR(sc, 0)); 283 REG_WRITE(SEND_LBADDR_REG, ADMSW_CDTXLADDR(sc, 0)); 284 REG_WRITE(RECV_HBADDR_REG, ADMSW_CDRXHADDR(sc, 0)); 285 REG_WRITE(RECV_LBADDR_REG, ADMSW_CDRXLADDR(sc, 0)); 286 287 sc->sc_txfree = ADMSW_NTXLDESC; 288 sc->sc_txnext = 0; 289 sc->sc_txdirty = 0; 290 sc->sc_rxptr = 0; 291} 292 293static void 294admsw_setvlan(struct admsw_softc *sc, char matrix[6]) 295{ 296 uint32_t i; 297 298 i = matrix[0] + (matrix[1] << 8) + (matrix[2] << 16) + (matrix[3] << 24); 299 REG_WRITE(VLAN_G1_REG, i); 300 i = matrix[4] + (matrix[5] << 8); 301 REG_WRITE(VLAN_G2_REG, i); 302} 303 304static void 305admsw_reset(struct admsw_softc *sc) 306{ 307 uint32_t wdog1; 308 int i; 309 310 REG_WRITE(PORT_CONF0_REG, 311 REG_READ(PORT_CONF0_REG) | PORT_CONF0_DP_MASK); 312 REG_WRITE(CPUP_CONF_REG, 313 REG_READ(CPUP_CONF_REG) | CPUP_CONF_DCPUP); 314 315 /* Wait for DMA to complete. Overkill. In 3ms, we can 316 * send at least two entire 1500-byte packets at 10 Mb/s. 317 */ 318 DELAY(3000); 319 320 /* The datasheet recommends that we move all PHYs to reset 321 * state prior to software reset. 322 */ 323 REG_WRITE(PHY_CNTL2_REG, 324 REG_READ(PHY_CNTL2_REG) & ~PHY_CNTL2_PHYR_MASK); 325 326 /* Reset the switch. */ 327 REG_WRITE(ADMSW_SW_RES, 0x1); 328 329 DELAY(100 * 1000); 330 331 REG_WRITE(ADMSW_BOOT_DONE, ADMSW_BOOT_DONE_BO); 332 333 /* begin old code */ 334 REG_WRITE(CPUP_CONF_REG, 335 CPUP_CONF_DCPUP | CPUP_CONF_CRCP | CPUP_CONF_DUNP_MASK | 336 CPUP_CONF_DMCP_MASK); 337 338 REG_WRITE(PORT_CONF0_REG, PORT_CONF0_EMCP_MASK | PORT_CONF0_EMBP_MASK); 339 340 REG_WRITE(PHY_CNTL2_REG, 341 REG_READ(PHY_CNTL2_REG) | PHY_CNTL2_ANE_MASK | PHY_CNTL2_PHYR_MASK | 342 PHY_CNTL2_AMDIX_MASK); 343 344 REG_WRITE(PHY_CNTL3_REG, REG_READ(PHY_CNTL3_REG) | PHY_CNTL3_RNT); 345 346 REG_WRITE(ADMSW_INT_MASK, INT_MASK); 347 REG_WRITE(ADMSW_INT_ST, INT_MASK); 348 349 /* 350 * While in DDB, we stop servicing interrupts, RX ring 351 * fills up and when free block counter falls behind FC 352 * threshold, the switch starts to emit 802.3x PAUSE 353 * frames. This can upset peer switches. 354 * 355 * Stop this from happening by disabling FC and D2 356 * thresholds. 357 */ 358 REG_WRITE(FC_TH_REG, 359 REG_READ(FC_TH_REG) & ~(FC_TH_FCS_MASK | FC_TH_D2S_MASK)); 360 361 admsw_setvlan(sc, vlan_matrix); 362 363 for (i = 0; i < SW_DEVS; i++) { 364 REG_WRITE(MAC_WT1_REG, 365 sc->sc_enaddr[2] | 366 (sc->sc_enaddr[3]<<8) | 367 (sc->sc_enaddr[4]<<16) | 368 ((sc->sc_enaddr[5]+i)<<24)); 369 REG_WRITE(MAC_WT0_REG, (i<<MAC_WT0_VLANID_SHIFT) | 370 (sc->sc_enaddr[0]<<16) | (sc->sc_enaddr[1]<<24) | 371 MAC_WT0_WRITE | MAC_WT0_VLANID_EN); 372 373 while (!(REG_READ(MAC_WT0_REG) & MAC_WT0_WRITE_DONE)); 374 } 375 376 wdog1 = REG_READ(ADM5120_WDOG1); 377 REG_WRITE(ADM5120_WDOG1, wdog1 & ~ADM5120_WDOG1_WDE); 378} 379 380static int 381admsw_attach(device_t dev) 382{ 383 uint8_t enaddr[ETHER_ADDR_LEN]; 384 struct admsw_softc *sc = (struct admsw_softc *) device_get_softc(dev); 385 struct ifnet *ifp; 386 int error, i, rid; 387 388 sc->sc_dev = dev; 389 device_printf(dev, "ADM5120 Switch Engine, %d ports\n", SW_DEVS); 390 sc->ndevs = 0; 391 392 /* XXXMIPS: fix it */ 393 enaddr[0] = 0x00; 394 enaddr[1] = 0x0C; 395 enaddr[2] = 0x42; 396 enaddr[3] = 0x07; 397 enaddr[4] = 0xB2; 398 enaddr[5] = 0x4E; 399 400 memcpy(sc->sc_enaddr, enaddr, sizeof(sc->sc_enaddr)); 401 402 device_printf(sc->sc_dev, "base Ethernet address %s\n", 403 ether_sprintf(enaddr)); 404 callout_init(&sc->sc_watchdog, 1); 405 406 rid = 0; 407 if ((sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 408 RF_ACTIVE)) == NULL) { 409 device_printf(dev, "unable to allocate memory resource\n"); 410 return (ENXIO); 411 } 412 413 /* Hook up the interrupt handler. */ 414 rid = 0; 415 if ((sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 416 RF_SHAREABLE | RF_ACTIVE)) == NULL) { 417 device_printf(dev, "unable to allocate IRQ resource\n"); 418 return (ENXIO); 419 } 420 421 if ((error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, 422 admsw_intr, NULL, sc, &sc->sc_ih)) != 0) { 423 device_printf(dev, 424 "WARNING: unable to register interrupt handler\n"); 425 return (error); 426 } 427 428 /* 429 * Allocate the control data structures, and create and load the 430 * DMA map for it. 431 */ 432 if ((error = bus_dma_tag_create(NULL, 4, 0, 433 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 434 NULL, NULL, sizeof(struct admsw_control_data), 1, 435 sizeof(struct admsw_control_data), 0, NULL, NULL, 436 &sc->sc_control_dmat)) != 0) { 437 device_printf(sc->sc_dev, 438 "unable to create control data DMA map, error = %d\n", 439 error); 440 return (error); 441 } 442 443 if ((error = bus_dmamem_alloc(sc->sc_control_dmat, 444 (void **)&sc->sc_control_data, BUS_DMA_NOWAIT, 445 &sc->sc_cddmamap)) != 0) { 446 device_printf(sc->sc_dev, 447 "unable to allocate control data, error = %d\n", error); 448 return (error); 449 } 450 451 if ((error = bus_dmamap_load(sc->sc_control_dmat, sc->sc_cddmamap, 452 sc->sc_control_data, sizeof(struct admsw_control_data), 453 admsw_dma_map_addr, &sc->sc_cddma, 0)) != 0) { 454 device_printf(sc->sc_dev, 455 "unable to load control data DMA map, error = %d\n", error); 456 return (error); 457 } 458 459 /* 460 * Create the transmit buffer DMA maps. 461 */ 462 if ((error = bus_dma_tag_create(NULL, 1, 0, 463 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 464 NULL, NULL, MCLBYTES, 1, MCLBYTES, 0, NULL, NULL, 465 &sc->sc_bufs_dmat)) != 0) { 466 device_printf(sc->sc_dev, 467 "unable to create control data DMA map, error = %d\n", 468 error); 469 return (error); 470 } 471 472 for (i = 0; i < ADMSW_NTXHDESC; i++) { 473 if ((error = bus_dmamap_create(sc->sc_bufs_dmat, 0, 474 &sc->sc_txhsoft[i].ds_dmamap)) != 0) { 475 device_printf(sc->sc_dev, 476 "unable to create txh DMA map %d, error = %d\n", 477 i, error); 478 return (error); 479 } 480 sc->sc_txhsoft[i].ds_mbuf = NULL; 481 } 482 483 for (i = 0; i < ADMSW_NTXLDESC; i++) { 484 if ((error = bus_dmamap_create(sc->sc_bufs_dmat, 0, 485 &sc->sc_txlsoft[i].ds_dmamap)) != 0) { 486 device_printf(sc->sc_dev, 487 "unable to create txl DMA map %d, error = %d\n", 488 i, error); 489 return (error); 490 } 491 sc->sc_txlsoft[i].ds_mbuf = NULL; 492 } 493 494 /* 495 * Create the receive buffer DMA maps. 496 */ 497 for (i = 0; i < ADMSW_NRXHDESC; i++) { 498 if ((error = bus_dmamap_create(sc->sc_bufs_dmat, 0, 499 &sc->sc_rxhsoft[i].ds_dmamap)) != 0) { 500 device_printf(sc->sc_dev, 501 "unable to create rxh DMA map %d, error = %d\n", 502 i, error); 503 return (error); 504 } 505 sc->sc_rxhsoft[i].ds_mbuf = NULL; 506 } 507 508 for (i = 0; i < ADMSW_NRXLDESC; i++) { 509 if ((error = bus_dmamap_create(sc->sc_bufs_dmat, 0, 510 &sc->sc_rxlsoft[i].ds_dmamap)) != 0) { 511 device_printf(sc->sc_dev, 512 "unable to create rxl DMA map %d, error = %d\n", 513 i, error); 514 return (error); 515 } 516 sc->sc_rxlsoft[i].ds_mbuf = NULL; 517 } 518 519 admsw_init_bufs(sc); 520 admsw_reset(sc); 521 522 for (i = 0; i < SW_DEVS; i++) { 523 ifmedia_init(&sc->sc_ifmedia[i], 0, admsw_mediachange, 524 admsw_mediastatus); 525 ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_10_T, 0, NULL); 526 ifmedia_add(&sc->sc_ifmedia[i], 527 IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 528 ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_100_TX, 0, NULL); 529 ifmedia_add(&sc->sc_ifmedia[i], 530 IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); 531 ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_AUTO, 0, NULL); 532 ifmedia_set(&sc->sc_ifmedia[i], IFM_ETHER|IFM_AUTO); 533 534 ifp = sc->sc_ifnet[i] = if_alloc(IFT_ETHER); 535 536 /* Setup interface parameters */ 537 ifp->if_softc = sc; 538 if_initname(ifp, device_get_name(dev), i); 539 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 540 ifp->if_ioctl = admsw_ioctl; 541 ifp->if_output = ether_output; 542 ifp->if_start = admsw_start; 543 ifp->if_init = admsw_init; 544 ifp->if_mtu = ETHERMTU; 545 ifp->if_baudrate = IF_Mbps(100); 546 IFQ_SET_MAXLEN(&ifp->if_snd, max(ADMSW_NTXLDESC, ifqmaxlen)); 547 ifp->if_snd.ifq_drv_maxlen = max(ADMSW_NTXLDESC, ifqmaxlen); 548 IFQ_SET_READY(&ifp->if_snd); 549 ifp->if_capabilities |= IFCAP_VLAN_MTU; 550 551 /* Attach the interface. */ 552 ether_ifattach(ifp, enaddr); 553 enaddr[5]++; 554 } 555 556 /* XXX: admwdog_attach(sc); */ 557 558 /* leave interrupts and cpu port disabled */ 559 return (0); 560} 561 562static int 563admsw_detach(device_t dev) 564{ 565 566 printf("TODO: DETACH\n"); 567 return (0); 568} 569 570/* 571 * admsw_shutdown: 572 * 573 * Make sure the interface is stopped at reboot time. 574 */ 575static int 576admsw_shutdown(device_t dev) 577{ 578 struct admsw_softc *sc; 579 int i; 580 581 sc = device_get_softc(dev); 582 for (i = 0; i < SW_DEVS; i++) 583 admsw_stop(sc->sc_ifnet[i], 1); 584 585 return (0); 586} 587 588/* 589 * admsw_start: [ifnet interface function] 590 * 591 * Start packet transmission on the interface. 592 */ 593static void 594admsw_start(struct ifnet *ifp) 595{ 596 struct admsw_softc *sc = ifp->if_softc; 597 struct mbuf *m0, *m; 598 struct admsw_descsoft *ds; 599 struct admsw_desc *desc; 600 bus_dmamap_t dmamap; 601 struct ether_header *eh; 602 int error, nexttx, len, i; 603 static int vlan = 0; 604 605 /* 606 * Loop through the send queues, setting up transmit descriptors 607 * unitl we drain the queues, or use up all available transmit 608 * descriptors. 609 */ 610 for (;;) { 611 vlan++; 612 if (vlan == SW_DEVS) 613 vlan = 0; 614 i = vlan; 615 for (;;) { 616 ifp = sc->sc_ifnet[i]; 617 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) 618 == IFF_DRV_RUNNING) { 619 /* Grab a packet off the queue. */ 620 IF_DEQUEUE(&ifp->if_snd, m0); 621 if (m0 != NULL) 622 break; 623 } 624 i++; 625 if (i == SW_DEVS) 626 i = 0; 627 if (i == vlan) 628 return; 629 } 630 vlan = i; 631 m = NULL; 632 633 /* Get a spare descriptor. */ 634 if (sc->sc_txfree == 0) { 635 /* No more slots left; notify upper layer. */ 636 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 637 break; 638 } 639 nexttx = sc->sc_txnext; 640 desc = &sc->sc_txldescs[nexttx]; 641 ds = &sc->sc_txlsoft[nexttx]; 642 dmamap = ds->ds_dmamap; 643 644 /* 645 * Load the DMA map. If this fails, the packet either 646 * didn't fit in the alloted number of segments, or we 647 * were short on resources. In this case, we'll copy 648 * and try again. 649 */ 650 if (m0->m_pkthdr.len < ETHER_MIN_LEN || 651 bus_dmamap_load_mbuf(sc->sc_bufs_dmat, dmamap, m0, 652 admsw_mbuf_map_addr, ds, BUS_DMA_NOWAIT) != 0) { 653 MGETHDR(m, M_NOWAIT, MT_DATA); 654 if (m == NULL) { 655 device_printf(sc->sc_dev, 656 "unable to allocate Tx mbuf\n"); 657 break; 658 } 659 if (m0->m_pkthdr.len > MHLEN) { 660 if (!(MCLGET(m, M_NOWAIT))) { 661 device_printf(sc->sc_dev, 662 "unable to allocate Tx cluster\n"); 663 m_freem(m); 664 break; 665 } 666 } 667 m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags; 668 m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *)); 669 m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; 670 if (m->m_pkthdr.len < ETHER_MIN_LEN) { 671 if (M_TRAILINGSPACE(m) < ETHER_MIN_LEN - m->m_pkthdr.len) 672 panic("admsw_start: M_TRAILINGSPACE\n"); 673 memset(mtod(m, uint8_t *) + m->m_pkthdr.len, 0, 674 ETHER_MIN_LEN - ETHER_CRC_LEN - m->m_pkthdr.len); 675 m->m_pkthdr.len = m->m_len = ETHER_MIN_LEN; 676 } 677 error = bus_dmamap_load_mbuf(sc->sc_bufs_dmat, 678 dmamap, m, admsw_mbuf_map_addr, ds, BUS_DMA_NOWAIT); 679 if (error) { 680 device_printf(sc->sc_dev, 681 "unable to load Tx buffer, error = %d\n", 682 error); 683 break; 684 } 685 } 686 687 if (m != NULL) { 688 m_freem(m0); 689 m0 = m; 690 } 691 692 /* 693 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. 694 */ 695 696 /* Sync the DMA map. */ 697 bus_dmamap_sync(sc->sc_bufs_dmat, dmamap, BUS_DMASYNC_PREWRITE); 698 699 if (ds->ds_nsegs != 1 && ds->ds_nsegs != 2) 700 panic("admsw_start: nsegs == %d\n", ds->ds_nsegs); 701 desc->data = ds->ds_addr[0]; 702 desc->len = len = ds->ds_len[0]; 703 if (ds->ds_nsegs > 1) { 704 len += ds->ds_len[1]; 705 desc->cntl = ds->ds_addr[1] | ADM5120_DMA_BUF2ENABLE; 706 } else 707 desc->cntl = 0; 708 desc->status = (len << ADM5120_DMA_LENSHIFT) | (1 << vlan); 709 eh = mtod(m0, struct ether_header *); 710 if (ntohs(eh->ether_type) == ETHERTYPE_IP && 711 m0->m_pkthdr.csum_flags & CSUM_IP) 712 desc->status |= ADM5120_DMA_CSUM; 713 if (nexttx == ADMSW_NTXLDESC - 1) 714 desc->data |= ADM5120_DMA_RINGEND; 715 desc->data |= ADM5120_DMA_OWN; 716 717 /* Sync the descriptor. */ 718 ADMSW_CDTXLSYNC(sc, nexttx, 719 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 720 721 REG_WRITE(SEND_TRIG_REG, 1); 722 /* printf("send slot %d\n",nexttx); */ 723 724 /* 725 * Store a pointer to the packet so we can free it later. 726 */ 727 ds->ds_mbuf = m0; 728 729 /* Advance the Tx pointer. */ 730 sc->sc_txfree--; 731 sc->sc_txnext = ADMSW_NEXTTXL(nexttx); 732 733 /* Pass the packet to any BPF listeners. */ 734 BPF_MTAP(ifp, m0); 735 736 /* Set a watchdog timer in case the chip flakes out. */ 737 sc->sc_timer = 5; 738 } 739} 740 741/* 742 * admsw_watchdog: [ifnet interface function] 743 * 744 * Watchdog timer handler. 745 */ 746static void 747admsw_watchdog(void *arg) 748{ 749 struct admsw_softc *sc = arg; 750 struct ifnet *ifp; 751 int vlan; 752 753 callout_reset(&sc->sc_watchdog, hz, admsw_watchdog, sc); 754 if (sc->sc_timer == 0 || --sc->sc_timer > 0) 755 return; 756 757 /* Check if an interrupt was lost. */ 758 if (sc->sc_txfree == ADMSW_NTXLDESC) { 759 device_printf(sc->sc_dev, "watchdog false alarm\n"); 760 return; 761 } 762 if (sc->sc_timer != 0) 763 device_printf(sc->sc_dev, "watchdog timer is %d!\n", 764 sc->sc_timer); 765 admsw_txintr(sc, 0); 766 if (sc->sc_txfree == ADMSW_NTXLDESC) { 767 device_printf(sc->sc_dev, "tx IRQ lost (queue empty)\n"); 768 return; 769 } 770 if (sc->sc_timer != 0) { 771 device_printf(sc->sc_dev, "tx IRQ lost (timer recharged)\n"); 772 return; 773 } 774 775 device_printf(sc->sc_dev, "device timeout, txfree = %d\n", 776 sc->sc_txfree); 777 for (vlan = 0; vlan < SW_DEVS; vlan++) 778 admsw_stop(sc->sc_ifnet[vlan], 0); 779 admsw_init(sc); 780 781 ifp = sc->sc_ifnet[0]; 782 783 /* Try to get more packets going. */ 784 admsw_start(ifp); 785} 786 787/* 788 * admsw_ioctl: [ifnet interface function] 789 * 790 * Handle control requests from the operator. 791 */ 792static int 793admsw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 794{ 795 struct admsw_softc *sc = ifp->if_softc; 796 struct ifdrv *ifd; 797 int error, port; 798 799 ADMSW_LOCK(sc); 800 801 switch (cmd) { 802 case SIOCSIFMEDIA: 803 case SIOCGIFMEDIA: 804 port = 0; 805 while(port < SW_DEVS) 806 if(ifp == sc->sc_ifnet[port]) 807 break; 808 else 809 port++; 810 if (port >= SW_DEVS) 811 error = EOPNOTSUPP; 812 else 813 error = ifmedia_ioctl(ifp, (struct ifreq *)data, 814 &sc->sc_ifmedia[port], cmd); 815 break; 816 817 case SIOCGDRVSPEC: 818 case SIOCSDRVSPEC: 819 ifd = (struct ifdrv *) data; 820 if (ifd->ifd_cmd != 0 || ifd->ifd_len != sizeof(vlan_matrix)) { 821 error = EINVAL; 822 break; 823 } 824 if (cmd == SIOCGDRVSPEC) { 825 error = copyout(vlan_matrix, ifd->ifd_data, 826 sizeof(vlan_matrix)); 827 } else { 828 error = copyin(ifd->ifd_data, vlan_matrix, 829 sizeof(vlan_matrix)); 830 admsw_setvlan(sc, vlan_matrix); 831 } 832 break; 833 834 default: 835 error = ether_ioctl(ifp, cmd, data); 836 if (error == ENETRESET) { 837 /* 838 * Multicast list has changed; set the hardware filter 839 * accordingly. 840 */ 841 admsw_set_filter(sc); 842 error = 0; 843 } 844 break; 845 } 846 847 /* Try to get more packets going. */ 848 admsw_start(ifp); 849 850 ADMSW_UNLOCK(sc); 851 return (error); 852} 853 854 855/* 856 * admsw_intr: 857 * 858 * Interrupt service routine. 859 */ 860static int 861admsw_intr(void *arg) 862{ 863 struct admsw_softc *sc = arg; 864 uint32_t pending; 865 866 pending = REG_READ(ADMSW_INT_ST); 867 REG_WRITE(ADMSW_INT_ST, pending); 868 869 if (sc->ndevs == 0) 870 return (FILTER_STRAY); 871 872 if ((pending & ADMSW_INTR_RHD) != 0) 873 admsw_rxintr(sc, 1); 874 875 if ((pending & ADMSW_INTR_RLD) != 0) 876 admsw_rxintr(sc, 0); 877 878 if ((pending & ADMSW_INTR_SHD) != 0) 879 admsw_txintr(sc, 1); 880 881 if ((pending & ADMSW_INTR_SLD) != 0) 882 admsw_txintr(sc, 0); 883 884 return (FILTER_HANDLED); 885} 886 887/* 888 * admsw_txintr: 889 * 890 * Helper; handle transmit interrupts. 891 */ 892static void 893admsw_txintr(struct admsw_softc *sc, int prio) 894{ 895 struct ifnet *ifp; 896 struct admsw_desc *desc; 897 struct admsw_descsoft *ds; 898 int i, vlan; 899 int gotone = 0; 900 901 /* printf("txintr: txdirty: %d, txfree: %d\n",sc->sc_txdirty, sc->sc_txfree); */ 902 for (i = sc->sc_txdirty; sc->sc_txfree != ADMSW_NTXLDESC; 903 i = ADMSW_NEXTTXL(i)) { 904 905 ADMSW_CDTXLSYNC(sc, i, 906 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 907 908 desc = &sc->sc_txldescs[i]; 909 ds = &sc->sc_txlsoft[i]; 910 if (desc->data & ADM5120_DMA_OWN) { 911 ADMSW_CDTXLSYNC(sc, i, 912 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 913 break; 914 } 915 916 bus_dmamap_sync(sc->sc_bufs_dmat, ds->ds_dmamap, 917 BUS_DMASYNC_POSTWRITE); 918 bus_dmamap_unload(sc->sc_bufs_dmat, ds->ds_dmamap); 919 m_freem(ds->ds_mbuf); 920 ds->ds_mbuf = NULL; 921 922 vlan = ffs(desc->status & 0x3f) - 1; 923 if (vlan < 0 || vlan >= SW_DEVS) 924 panic("admsw_txintr: bad vlan\n"); 925 ifp = sc->sc_ifnet[vlan]; 926 gotone = 1; 927 /* printf("clear tx slot %d\n",i); */ 928 929 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 930 931 sc->sc_txfree++; 932 } 933 934 if (gotone) { 935 sc->sc_txdirty = i; 936 for (vlan = 0; vlan < SW_DEVS; vlan++) 937 sc->sc_ifnet[vlan]->if_drv_flags &= ~IFF_DRV_OACTIVE; 938 939 ifp = sc->sc_ifnet[0]; 940 941 /* Try to queue more packets. */ 942 admsw_start(ifp); 943 944 /* 945 * If there are no more pending transmissions, 946 * cancel the watchdog timer. 947 */ 948 if (sc->sc_txfree == ADMSW_NTXLDESC) 949 sc->sc_timer = 0; 950 951 } 952 953 /* printf("txintr end: txdirty: %d, txfree: %d\n",sc->sc_txdirty, sc->sc_txfree); */ 954} 955 956/* 957 * admsw_rxintr: 958 * 959 * Helper; handle receive interrupts. 960 */ 961static void 962admsw_rxintr(struct admsw_softc *sc, int high) 963{ 964 struct ifnet *ifp; 965 struct admsw_descsoft *ds; 966 struct mbuf *m; 967 uint32_t stat; 968 int i, len, port, vlan; 969 970 /* printf("rxintr\n"); */ 971 972 if (high) 973 panic("admsw_rxintr: high priority packet\n"); 974 975#if 1 976 ADMSW_CDRXLSYNC(sc, sc->sc_rxptr, 977 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 978 if ((sc->sc_rxldescs[sc->sc_rxptr].data & ADM5120_DMA_OWN) == 0) 979 ADMSW_CDRXLSYNC(sc, sc->sc_rxptr, 980 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 981 else { 982 i = sc->sc_rxptr; 983 do { 984 ADMSW_CDRXLSYNC(sc, i, 985 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 986 i = ADMSW_NEXTRXL(i); 987 /* the ring is empty, just return. */ 988 if (i == sc->sc_rxptr) 989 return; 990 ADMSW_CDRXLSYNC(sc, i, 991 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 992 } while (sc->sc_rxldescs[i].data & ADM5120_DMA_OWN); 993 994 ADMSW_CDRXLSYNC(sc, i, 995 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 996 997 ADMSW_CDRXLSYNC(sc, sc->sc_rxptr, 998 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 999 1000 if ((sc->sc_rxldescs[sc->sc_rxptr].data & ADM5120_DMA_OWN) == 0) 1001 ADMSW_CDRXLSYNC(sc, sc->sc_rxptr, 1002 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1003 else { 1004 ADMSW_CDRXLSYNC(sc, sc->sc_rxptr, 1005 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1006 /* We've fallen behind the chip: catch it. */ 1007#if 0 1008 device_printf(sc->sc_dev, 1009 "RX ring resync, base=%x, work=%x, %d -> %d\n", 1010 REG_READ(RECV_LBADDR_REG), 1011 REG_READ(RECV_LWADDR_REG), sc->sc_rxptr, i); 1012#endif 1013 sc->sc_rxptr = i; 1014 /* ADMSW_EVCNT_INCR(&sc->sc_ev_rxsync); */ 1015 } 1016 } 1017#endif 1018 for (i = sc->sc_rxptr;; i = ADMSW_NEXTRXL(i)) { 1019 ds = &sc->sc_rxlsoft[i]; 1020 1021 ADMSW_CDRXLSYNC(sc, i, 1022 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1023 1024 if (sc->sc_rxldescs[i].data & ADM5120_DMA_OWN) { 1025 ADMSW_CDRXLSYNC(sc, i, 1026 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1027 break; 1028 } 1029 1030 /* printf("process slot %d\n",i); */ 1031 1032 bus_dmamap_sync(sc->sc_bufs_dmat, ds->ds_dmamap, 1033 BUS_DMASYNC_POSTREAD); 1034 1035 stat = sc->sc_rxldescs[i].status; 1036 len = (stat & ADM5120_DMA_LEN) >> ADM5120_DMA_LENSHIFT; 1037 len -= ETHER_CRC_LEN; 1038 port = (stat & ADM5120_DMA_PORTID) >> ADM5120_DMA_PORTSHIFT; 1039 1040 for (vlan = 0; vlan < SW_DEVS; vlan++) 1041 if ((1 << port) & vlan_matrix[vlan]) 1042 break; 1043 1044 if (vlan == SW_DEVS) 1045 vlan = 0; 1046 1047 ifp = sc->sc_ifnet[vlan]; 1048 1049 m = ds->ds_mbuf; 1050 if (admsw_add_rxlbuf(sc, i) != 0) { 1051 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 1052 ADMSW_INIT_RXLDESC(sc, i); 1053 bus_dmamap_sync(sc->sc_bufs_dmat, ds->ds_dmamap, 1054 BUS_DMASYNC_PREREAD); 1055 continue; 1056 } 1057 1058 m->m_pkthdr.rcvif = ifp; 1059 m->m_pkthdr.len = m->m_len = len; 1060 if ((stat & ADM5120_DMA_TYPE) == ADM5120_DMA_TYPE_IP) { 1061 m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 1062 if (!(stat & ADM5120_DMA_CSUMFAIL)) 1063 m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 1064 } 1065 1066 BPF_MTAP(ifp, m); 1067 1068 /* Pass it on. */ 1069 (*ifp->if_input)(ifp, m); 1070 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 1071 } 1072 1073 /* Update the receive pointer. */ 1074 sc->sc_rxptr = i; 1075} 1076 1077/* 1078 * admsw_init: [ifnet interface function] 1079 * 1080 * Initialize the interface. 1081 */ 1082static void 1083admsw_init(void *xsc) 1084{ 1085 struct admsw_softc *sc = xsc; 1086 struct ifnet *ifp; 1087 int i; 1088 1089 for (i = 0; i < SW_DEVS; i++) { 1090 ifp = sc->sc_ifnet[i]; 1091 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1092 if (sc->ndevs == 0) { 1093 admsw_init_bufs(sc); 1094 admsw_reset(sc); 1095 REG_WRITE(CPUP_CONF_REG, 1096 CPUP_CONF_CRCP | CPUP_CONF_DUNP_MASK | 1097 CPUP_CONF_DMCP_MASK); 1098 /* clear all pending interrupts */ 1099 REG_WRITE(ADMSW_INT_ST, INT_MASK); 1100 1101 /* enable needed interrupts */ 1102 REG_WRITE(ADMSW_INT_MASK, 1103 REG_READ(ADMSW_INT_MASK) & 1104 ~(ADMSW_INTR_SHD | ADMSW_INTR_SLD | 1105 ADMSW_INTR_RHD | ADMSW_INTR_RLD | 1106 ADMSW_INTR_HDF | ADMSW_INTR_LDF)); 1107 1108 callout_reset(&sc->sc_watchdog, hz, 1109 admsw_watchdog, sc); 1110 } 1111 sc->ndevs++; 1112 } 1113 1114 1115 /* mark iface as running */ 1116 ifp->if_drv_flags |= IFF_DRV_RUNNING; 1117 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1118 } 1119 1120 /* Set the receive filter. */ 1121 admsw_set_filter(sc); 1122} 1123 1124/* 1125 * admsw_stop: [ifnet interface function] 1126 * 1127 * Stop transmission on the interface. 1128 */ 1129static void 1130admsw_stop(struct ifnet *ifp, int disable) 1131{ 1132 struct admsw_softc *sc = ifp->if_softc; 1133 1134 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 1135 return; 1136 1137 if (--sc->ndevs == 0) { 1138 /* printf("debug: de-initializing hardware\n"); */ 1139 1140 /* disable cpu port */ 1141 REG_WRITE(CPUP_CONF_REG, 1142 CPUP_CONF_DCPUP | CPUP_CONF_CRCP | 1143 CPUP_CONF_DUNP_MASK | CPUP_CONF_DMCP_MASK); 1144 1145 /* XXX We should disable, then clear? --dyoung */ 1146 /* clear all pending interrupts */ 1147 REG_WRITE(ADMSW_INT_ST, INT_MASK); 1148 1149 /* disable interrupts */ 1150 REG_WRITE(ADMSW_INT_MASK, INT_MASK); 1151 1152 /* Cancel the watchdog timer. */ 1153 sc->sc_timer = 0; 1154 callout_stop(&sc->sc_watchdog); 1155 } 1156 1157 /* Mark the interface as down. */ 1158 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1159 1160 return; 1161} 1162 1163/* 1164 * admsw_set_filter: 1165 * 1166 * Set up the receive filter. 1167 */ 1168static void 1169admsw_set_filter(struct admsw_softc *sc) 1170{ 1171 int i; 1172 uint32_t allmc, anymc, conf, promisc; 1173 struct ifnet *ifp; 1174 struct ifmultiaddr *ifma; 1175 1176 /* Find which ports should be operated in promisc mode. */ 1177 allmc = anymc = promisc = 0; 1178 for (i = 0; i < SW_DEVS; i++) { 1179 ifp = sc->sc_ifnet[i]; 1180 if (ifp->if_flags & IFF_PROMISC) 1181 promisc |= vlan_matrix[i]; 1182 1183 ifp->if_flags &= ~IFF_ALLMULTI; 1184 1185 if_maddr_rlock(ifp); 1186 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) 1187 { 1188 if (ifma->ifma_addr->sa_family != AF_LINK) 1189 continue; 1190 1191 anymc |= vlan_matrix[i]; 1192 } 1193 if_maddr_runlock(ifp); 1194 } 1195 1196 conf = REG_READ(CPUP_CONF_REG); 1197 /* 1 Disable forwarding of unknown & multicast packets to 1198 * CPU on all ports. 1199 * 2 Enable forwarding of unknown & multicast packets to 1200 * CPU on ports where IFF_PROMISC or IFF_ALLMULTI is set. 1201 */ 1202 conf |= CPUP_CONF_DUNP_MASK | CPUP_CONF_DMCP_MASK; 1203 /* Enable forwarding of unknown packets to CPU on selected ports. */ 1204 conf ^= ((promisc << CPUP_CONF_DUNP_SHIFT) & CPUP_CONF_DUNP_MASK); 1205 conf ^= ((allmc << CPUP_CONF_DMCP_SHIFT) & CPUP_CONF_DMCP_MASK); 1206 conf ^= ((anymc << CPUP_CONF_DMCP_SHIFT) & CPUP_CONF_DMCP_MASK); 1207 REG_WRITE(CPUP_CONF_REG, conf); 1208} 1209 1210/* 1211 * admsw_add_rxbuf: 1212 * 1213 * Add a receive buffer to the indicated descriptor. 1214 */ 1215int 1216admsw_add_rxbuf(struct admsw_softc *sc, int idx, int high) 1217{ 1218 struct admsw_descsoft *ds; 1219 struct mbuf *m; 1220 int error; 1221 1222 if (high) 1223 ds = &sc->sc_rxhsoft[idx]; 1224 else 1225 ds = &sc->sc_rxlsoft[idx]; 1226 1227 MGETHDR(m, M_NOWAIT, MT_DATA); 1228 if (m == NULL) 1229 return (ENOBUFS); 1230 1231 if (!(MCLGET(m, M_NOWAIT))) { 1232 m_freem(m); 1233 return (ENOBUFS); 1234 } 1235 1236 if (ds->ds_mbuf != NULL) 1237 bus_dmamap_unload(sc->sc_bufs_dmat, ds->ds_dmamap); 1238 1239 ds->ds_mbuf = m; 1240 1241 error = bus_dmamap_load(sc->sc_bufs_dmat, ds->ds_dmamap, 1242 m->m_ext.ext_buf, m->m_ext.ext_size, admsw_rxbuf_map_addr, 1243 ds, BUS_DMA_NOWAIT); 1244 if (error) { 1245 device_printf(sc->sc_dev, 1246 "can't load rx DMA map %d, error = %d\n", idx, error); 1247 panic("admsw_add_rxbuf"); /* XXX */ 1248 } 1249 1250 bus_dmamap_sync(sc->sc_bufs_dmat, ds->ds_dmamap, BUS_DMASYNC_PREREAD); 1251 1252 if (high) 1253 ADMSW_INIT_RXHDESC(sc, idx); 1254 else 1255 ADMSW_INIT_RXLDESC(sc, idx); 1256 1257 return (0); 1258} 1259 1260int 1261admsw_mediachange(struct ifnet *ifp) 1262{ 1263 struct admsw_softc *sc = ifp->if_softc; 1264 int port = 0; 1265 struct ifmedia *ifm; 1266 int old, new, val; 1267 1268 while(port < SW_DEVS) { 1269 if(ifp == sc->sc_ifnet[port]) 1270 break; 1271 else 1272 port++; 1273 } 1274 1275 ifm = &sc->sc_ifmedia[port]; 1276 1277 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1278 return (EINVAL); 1279 1280 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) { 1281 val = PHY_CNTL2_AUTONEG|PHY_CNTL2_100M|PHY_CNTL2_FDX; 1282 } else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) { 1283 if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1284 val = PHY_CNTL2_100M|PHY_CNTL2_FDX; 1285 else 1286 val = PHY_CNTL2_100M; 1287 } else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) { 1288 if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1289 val = PHY_CNTL2_FDX; 1290 else 1291 val = 0; 1292 } else 1293 return (EINVAL); 1294 1295 old = REG_READ(PHY_CNTL2_REG); 1296 new = old & ~((PHY_CNTL2_AUTONEG|PHY_CNTL2_100M|PHY_CNTL2_FDX) << port); 1297 new |= (val << port); 1298 1299 if (new != old) 1300 REG_WRITE(PHY_CNTL2_REG, new); 1301 1302 return (0); 1303} 1304 1305void 1306admsw_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1307{ 1308 struct admsw_softc *sc = ifp->if_softc; 1309 int port = 0; 1310 int status; 1311 1312 while(port < SW_DEVS) { 1313 if(ifp == sc->sc_ifnet[port]) 1314 break; 1315 else 1316 port++; 1317 } 1318 1319 ifmr->ifm_status = IFM_AVALID; 1320 ifmr->ifm_active = IFM_ETHER; 1321 1322 status = REG_READ(PHY_ST_REG) >> port; 1323 1324 if ((status & PHY_ST_LINKUP) == 0) { 1325 ifmr->ifm_active |= IFM_NONE; 1326 return; 1327 } 1328 1329 ifmr->ifm_status |= IFM_ACTIVE; 1330 ifmr->ifm_active |= (status & PHY_ST_100M) ? IFM_100_TX : IFM_10_T; 1331 if (status & PHY_ST_FDX) 1332 ifmr->ifm_active |= IFM_FDX; 1333} 1334 1335static device_method_t admsw_methods[] = { 1336 /* Device interface */ 1337 DEVMETHOD(device_probe, admsw_probe), 1338 DEVMETHOD(device_attach, admsw_attach), 1339 DEVMETHOD(device_detach, admsw_detach), 1340 DEVMETHOD(device_shutdown, admsw_shutdown), 1341 1342 { 0, 0 } 1343}; 1344 1345static devclass_t admsw_devclass; 1346 1347static driver_t admsw_driver = { 1348 "admsw", 1349 admsw_methods, 1350 sizeof(struct admsw_softc), 1351}; 1352 1353DRIVER_MODULE(admsw, obio, admsw_driver, admsw_devclass, 0, 0); 1354MODULE_DEPEND(admsw, ether, 1, 1, 1); 1355