1/* $NetBSD: if_le_ledma.c,v 1.26 2005/12/11 12:23:44 christos Exp $ */ 2 3/*- 4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD 5 * 6 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace 11 * Simulation Facility, NASA Ames Research Center; Paul Kranenburg. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD: releng/12.0/sys/dev/le/if_le_ledma.c 326255 2017-11-27 14:52:40Z pfg $"); 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/bus.h> 41#include <sys/endian.h> 42#include <sys/kernel.h> 43#include <sys/lock.h> 44#include <sys/module.h> 45#include <sys/mutex.h> 46#include <sys/resource.h> 47#include <sys/rman.h> 48#include <sys/socket.h> 49 50#include <dev/ofw/ofw_bus.h> 51 52#include <machine/bus.h> 53#include <machine/ofw_machdep.h> 54#include <machine/resource.h> 55 56#include <net/ethernet.h> 57#include <net/if.h> 58#include <net/if_var.h> 59#include <net/if_media.h> 60 61#include <sparc64/sbus/lsi64854reg.h> 62#include <sparc64/sbus/lsi64854var.h> 63 64#include <dev/le/lancereg.h> 65#include <dev/le/lancevar.h> 66#include <dev/le/am7990var.h> 67 68#define LEDMA_ALIGNMENT 8 /* ring desc. alignmet for NCR92C990 */ 69#define LEDMA_BOUNDARY (16*1024*1024) /* must not cross 16MB boundary */ 70#define LEDMA_MEMSIZE (16*1024) /* LANCE memory size */ 71#define LEREG1_RDP 0 /* Register Data Port */ 72#define LEREG1_RAP 2 /* Register Address Port */ 73 74struct le_dma_softc { 75 struct am7990_softc sc_am7990; /* glue to MI code */ 76 77 struct resource *sc_rres; 78 79 struct resource *sc_ires; 80 void *sc_ih; 81 82 bus_dma_tag_t sc_dmat; 83 bus_dmamap_t sc_dmam; 84 bus_addr_t sc_laddr; /* LANCE DMA address */ 85 86 struct lsi64854_softc *sc_dma; /* pointer to DMA engine */ 87}; 88 89static device_probe_t le_dma_probe; 90static device_attach_t le_dma_attach; 91static device_detach_t le_dma_detach; 92static device_resume_t le_dma_resume; 93static device_suspend_t le_dma_suspend; 94 95static device_method_t le_dma_methods[] = { 96 /* Device interface */ 97 DEVMETHOD(device_probe, le_dma_probe), 98 DEVMETHOD(device_attach, le_dma_attach), 99 DEVMETHOD(device_detach, le_dma_detach), 100 /* We can just use the suspend method here. */ 101 DEVMETHOD(device_shutdown, le_dma_suspend), 102 DEVMETHOD(device_suspend, le_dma_suspend), 103 DEVMETHOD(device_resume, le_dma_resume), 104 105 { 0, 0 } 106}; 107 108DEFINE_CLASS_0(le, le_dma_driver, le_dma_methods, sizeof(struct le_dma_softc)); 109DRIVER_MODULE(le, dma, le_dma_driver, le_devclass, 0, 0); 110MODULE_DEPEND(le, dma, 1, 1, 1); 111MODULE_DEPEND(le, ether, 1, 1, 1); 112 113/* 114 * Media types supported 115 */ 116static const int le_dma_supmedia[] = { 117 IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0), 118 IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), 119 IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0) 120}; 121 122static void le_dma_wrcsr(struct lance_softc *, uint16_t, uint16_t); 123static uint16_t le_dma_rdcsr(struct lance_softc *, uint16_t); 124static void le_dma_setutp(struct lance_softc *); 125static void le_dma_setaui(struct lance_softc *); 126static int le_dma_supmediachange(struct lance_softc *); 127static void le_dma_supmediastatus(struct lance_softc *, struct ifmediareq *); 128static void le_dma_hwreset(struct lance_softc *); 129static int le_dma_hwintr(struct lance_softc *); 130static void le_dma_nocarrier(struct lance_softc *); 131static bus_dmamap_callback_t le_dma_dma_callback; 132 133static void 134le_dma_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) 135{ 136 struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 137 138 bus_write_2(lesc->sc_rres, LEREG1_RAP, port); 139 bus_barrier(lesc->sc_rres, LEREG1_RAP, 2, BUS_SPACE_BARRIER_WRITE); 140 bus_write_2(lesc->sc_rres, LEREG1_RDP, val); 141} 142 143static uint16_t 144le_dma_rdcsr(struct lance_softc *sc, uint16_t port) 145{ 146 struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 147 148 bus_write_2(lesc->sc_rres, LEREG1_RAP, port); 149 bus_barrier(lesc->sc_rres, LEREG1_RAP, 2, BUS_SPACE_BARRIER_WRITE); 150 return (bus_read_2(lesc->sc_rres, LEREG1_RDP)); 151} 152 153static void 154le_dma_setutp(struct lance_softc *sc) 155{ 156 struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 157 158 L64854_SCSR(dma, L64854_GCSR(dma) | E_TP_AUI); 159 DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 160} 161 162static void 163le_dma_setaui(struct lance_softc *sc) 164{ 165 struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 166 167 L64854_SCSR(dma, L64854_GCSR(dma) & ~E_TP_AUI); 168 DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 169} 170 171static int 172le_dma_supmediachange(struct lance_softc *sc) 173{ 174 struct ifmedia *ifm = &sc->sc_media; 175 176 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 177 return (EINVAL); 178 179 /* 180 * Switch to the selected media. If autoselect is set, we don't 181 * really have to do anything. We'll switch to the other media 182 * when we detect loss of carrier. 183 */ 184 switch (IFM_SUBTYPE(ifm->ifm_media)) { 185 case IFM_10_T: 186 le_dma_setutp(sc); 187 break; 188 189 case IFM_10_5: 190 le_dma_setaui(sc); 191 break; 192 193 case IFM_AUTO: 194 break; 195 196 default: 197 return (EINVAL); 198 } 199 200 return (0); 201} 202 203static void 204le_dma_supmediastatus(struct lance_softc *sc, struct ifmediareq *ifmr) 205{ 206 struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 207 208 /* 209 * Notify the world which media we're currently using. 210 */ 211 if (L64854_GCSR(dma) & E_TP_AUI) 212 ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0); 213 else 214 ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0); 215} 216 217static void 218le_dma_hwreset(struct lance_softc *sc) 219{ 220 struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 221 struct lsi64854_softc *dma = lesc->sc_dma; 222 uint32_t aui_bit, csr; 223 224 /* 225 * Reset DMA channel. 226 */ 227 csr = L64854_GCSR(dma); 228 aui_bit = csr & E_TP_AUI; 229 DMA_RESET(dma); 230 231 /* Write bits 24-31 of Lance address. */ 232 bus_write_4(dma->sc_res, L64854_REG_ENBAR, 233 lesc->sc_laddr & 0xff000000); 234 235 DMA_ENINTR(dma); 236 237 /* 238 * Disable E-cache invalidates on chip writes. 239 * Retain previous cable selection bit. 240 */ 241 csr = L64854_GCSR(dma); 242 csr |= (E_DSBL_WR_INVAL | aui_bit); 243 L64854_SCSR(dma, csr); 244 DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 245} 246 247static int 248le_dma_hwintr(struct lance_softc *sc) 249{ 250 struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 251 struct lsi64854_softc *dma = lesc->sc_dma; 252 253 return (DMA_INTR(dma)); 254} 255 256static void 257le_dma_nocarrier(struct lance_softc *sc) 258{ 259 struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 260 261 /* 262 * Check if the user has requested a certain cable type, and 263 * if so, honor that request. 264 */ 265 266 if (L64854_GCSR(lesc->sc_dma) & E_TP_AUI) { 267 switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { 268 case IFM_10_5: 269 case IFM_AUTO: 270 if_printf(sc->sc_ifp, "lost carrier on UTP port, " 271 "switching to AUI port\n"); 272 le_dma_setaui(sc); 273 } 274 } else { 275 switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { 276 case IFM_10_T: 277 case IFM_AUTO: 278 if_printf(sc->sc_ifp, "lost carrier on AUI port, " 279 "switching to UTP port\n"); 280 le_dma_setutp(sc); 281 } 282 } 283} 284 285static void 286le_dma_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 287{ 288 struct le_dma_softc *lesc = (struct le_dma_softc *)xsc; 289 290 if (error != 0) 291 return; 292 KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); 293 lesc->sc_laddr = segs[0].ds_addr; 294} 295 296static int 297le_dma_probe(device_t dev) 298{ 299 300 if (strcmp(ofw_bus_get_name(dev), "le") == 0) { 301 device_set_desc(dev, "LANCE Ethernet"); 302 return (BUS_PROBE_DEFAULT); 303 } 304 return (ENXIO); 305} 306 307static int 308le_dma_attach(device_t dev) 309{ 310 struct le_dma_softc *lesc; 311 struct lsi64854_softc *dma; 312 struct lance_softc *sc; 313 int error, i; 314 315 lesc = device_get_softc(dev); 316 sc = &lesc->sc_am7990.lsc; 317 318 LE_LOCK_INIT(sc, device_get_nameunit(dev)); 319 320 /* 321 * Establish link to `ledma' device. 322 * XXX hackery. 323 */ 324 dma = (struct lsi64854_softc *)device_get_softc(device_get_parent(dev)); 325 lesc->sc_dma = dma; 326 lesc->sc_dma->sc_client = lesc; 327 328 i = 0; 329 lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 330 &i, RF_ACTIVE); 331 if (lesc->sc_rres == NULL) { 332 device_printf(dev, "cannot allocate registers\n"); 333 error = ENXIO; 334 goto fail_mtx; 335 } 336 337 i = 0; 338 if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 339 &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 340 device_printf(dev, "cannot allocate interrupt\n"); 341 error = ENXIO; 342 goto fail_rres; 343 } 344 345 /* Attach the DMA engine. */ 346 error = lsi64854_attach(dma); 347 if (error != 0) { 348 device_printf(dev, "lsi64854_attach failed\n"); 349 goto fail_ires; 350 } 351 352 sc->sc_memsize = LEDMA_MEMSIZE; 353 error = bus_dma_tag_create( 354 dma->sc_parent_dmat, /* parent */ 355 LEDMA_ALIGNMENT, /* alignment */ 356 LEDMA_BOUNDARY, /* boundary */ 357 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 358 BUS_SPACE_MAXADDR, /* highaddr */ 359 NULL, NULL, /* filter, filterarg */ 360 sc->sc_memsize, /* maxsize */ 361 1, /* nsegments */ 362 sc->sc_memsize, /* maxsegsize */ 363 0, /* flags */ 364 NULL, NULL, /* lockfunc, lockarg */ 365 &lesc->sc_dmat); 366 if (error != 0) { 367 device_printf(dev, "cannot allocate buffer DMA tag\n"); 368 goto fail_lsi; 369 } 370 371 error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, 372 BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); 373 if (error != 0) { 374 device_printf(dev, "cannot allocate DMA buffer memory\n"); 375 goto fail_dtag; 376 } 377 378 lesc->sc_laddr = 0; 379 error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, 380 sc->sc_memsize, le_dma_dma_callback, lesc, 0); 381 if (error != 0 || lesc->sc_laddr == 0) { 382 device_printf(dev, "cannot load DMA buffer map\n"); 383 goto fail_dmem; 384 } 385 386 sc->sc_addr = lesc->sc_laddr & 0xffffff; 387 sc->sc_flags = 0; 388 sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; 389 390 sc->sc_mediachange = le_dma_supmediachange; 391 sc->sc_mediastatus = le_dma_supmediastatus; 392 sc->sc_supmedia = le_dma_supmedia; 393 sc->sc_nsupmedia = nitems(le_dma_supmedia); 394 sc->sc_defaultmedia = le_dma_supmedia[0]; 395 396 OF_getetheraddr(dev, sc->sc_enaddr); 397 398 sc->sc_copytodesc = lance_copytobuf_contig; 399 sc->sc_copyfromdesc = lance_copyfrombuf_contig; 400 sc->sc_copytobuf = lance_copytobuf_contig; 401 sc->sc_copyfrombuf = lance_copyfrombuf_contig; 402 sc->sc_zerobuf = lance_zerobuf_contig; 403 404 sc->sc_rdcsr = le_dma_rdcsr; 405 sc->sc_wrcsr = le_dma_wrcsr; 406 sc->sc_hwreset = le_dma_hwreset; 407 sc->sc_hwintr = le_dma_hwintr; 408 sc->sc_nocarrier = le_dma_nocarrier; 409 410 error = am7990_config(&lesc->sc_am7990, device_get_name(dev), 411 device_get_unit(dev)); 412 if (error != 0) { 413 device_printf(dev, "cannot attach Am7990\n"); 414 goto fail_dmap; 415 } 416 417 error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, 418 NULL, am7990_intr, sc, &lesc->sc_ih); 419 if (error != 0) { 420 device_printf(dev, "cannot set up interrupt\n"); 421 goto fail_am7990; 422 } 423 424 return (0); 425 426 fail_am7990: 427 am7990_detach(&lesc->sc_am7990); 428 fail_dmap: 429 bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 430 fail_dmem: 431 bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 432 fail_dtag: 433 bus_dma_tag_destroy(lesc->sc_dmat); 434 fail_lsi: 435 lsi64854_detach(dma); 436 fail_ires: 437 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires), 438 lesc->sc_ires); 439 fail_rres: 440 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres), 441 lesc->sc_rres); 442 fail_mtx: 443 LE_LOCK_DESTROY(sc); 444 return (error); 445} 446 447static int 448le_dma_detach(device_t dev) 449{ 450 struct le_dma_softc *lesc; 451 struct lance_softc *sc; 452 int error; 453 454 lesc = device_get_softc(dev); 455 sc = &lesc->sc_am7990.lsc; 456 457 bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); 458 am7990_detach(&lesc->sc_am7990); 459 bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 460 bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 461 bus_dma_tag_destroy(lesc->sc_dmat); 462 error = lsi64854_detach(lesc->sc_dma); 463 if (error != 0) 464 return (error); 465 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires), 466 lesc->sc_ires); 467 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres), 468 lesc->sc_rres); 469 LE_LOCK_DESTROY(sc); 470 471 return (0); 472} 473 474static int 475le_dma_suspend(device_t dev) 476{ 477 struct le_dma_softc *lesc; 478 479 lesc = device_get_softc(dev); 480 481 lance_suspend(&lesc->sc_am7990.lsc); 482 483 return (0); 484} 485 486static int 487le_dma_resume(device_t dev) 488{ 489 struct le_dma_softc *lesc; 490 491 lesc = device_get_softc(dev); 492 493 lance_resume(&lesc->sc_am7990.lsc); 494 495 return (0); 496} 497