1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-NetBSD 3 * 4 * Copyright (c) 2006 Marius Strobl <[email protected]> 5 * 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/endian.h> 36 #include <sys/kernel.h> 37 #include <sys/lock.h> 38 #include <sys/module.h> 39 #include <sys/mutex.h> 40 #include <sys/resource.h> 41 #include <sys/rman.h> 42 #include <sys/socket.h> 43 44 #include <dev/ofw/ofw_bus.h> 45 46 #include <machine/bus.h> 47 #include <machine/ofw_machdep.h> 48 #include <machine/resource.h> 49 50 #include <net/ethernet.h> 51 #include <net/if.h> 52 #include <net/if_media.h> 53 54 #include <dev/le/lancereg.h> 55 #include <dev/le/lancevar.h> 56 #include <dev/le/am7990reg.h> 57 #include <dev/le/am7990var.h> 58 59 /* 60 * LANCE registers 61 */ 62 #define LEREG1_RDP 0 /* Register Data port */ 63 #define LEREG1_RAP 2 /* Register Address port */ 64 65 struct le_lebuffer_softc { 66 struct am7990_softc sc_am7990; /* glue to MI code */ 67 68 struct resource *sc_bres; 69 70 struct resource *sc_rres; 71 72 struct resource *sc_ires; 73 void *sc_ih; 74 }; 75 76 static devclass_t le_lebuffer_devclass; 77 78 static device_probe_t le_lebuffer_probe; 79 static device_attach_t le_lebuffer_attach; 80 static device_detach_t le_lebuffer_detach; 81 static device_resume_t le_buffer_resume; 82 static device_suspend_t le_buffer_suspend; 83 84 static device_method_t le_lebuffer_methods[] = { 85 /* Device interface */ 86 DEVMETHOD(device_probe, le_lebuffer_probe), 87 DEVMETHOD(device_attach, le_lebuffer_attach), 88 DEVMETHOD(device_detach, le_lebuffer_detach), 89 /* We can just use the suspend method here. */ 90 DEVMETHOD(device_shutdown, le_buffer_suspend), 91 DEVMETHOD(device_suspend, le_buffer_suspend), 92 DEVMETHOD(device_resume, le_buffer_resume), 93 94 { 0, 0 } 95 }; 96 97 DEFINE_CLASS_0(le, le_lebuffer_driver, le_lebuffer_methods, 98 sizeof(struct le_lebuffer_softc)); 99 DRIVER_MODULE(le, lebuffer, le_lebuffer_driver, le_lebuffer_devclass, 0, 0); 100 MODULE_DEPEND(le, ether, 1, 1, 1); 101 MODULE_DEPEND(le, lebuffer, 1, 1, 1); 102 103 /* 104 * Media types supported 105 */ 106 static const int le_lebuffer_media[] = { 107 IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0) 108 }; 109 #define NLEMEDIA nitems(le_lebuffer_media) 110 111 static void le_lebuffer_wrcsr(struct lance_softc *, uint16_t, uint16_t); 112 static uint16_t le_lebuffer_rdcsr(struct lance_softc *, uint16_t); 113 static void le_lebuffer_copytodesc(struct lance_softc *, void *, int, int); 114 static void le_lebuffer_copyfromdesc(struct lance_softc *, void *, int, int); 115 static void le_lebuffer_copytobuf(struct lance_softc *, void *, int, int); 116 static void le_lebuffer_copyfrombuf(struct lance_softc *, void *, int, int); 117 static void le_lebuffer_zerobuf(struct lance_softc *, int, int); 118 119 static void 120 le_lebuffer_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) 121 { 122 struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; 123 124 bus_write_2(lesc->sc_rres, LEREG1_RAP, port); 125 bus_barrier(lesc->sc_rres, LEREG1_RAP, 2, BUS_SPACE_BARRIER_WRITE); 126 bus_write_2(lesc->sc_rres, LEREG1_RDP, val); 127 } 128 129 static uint16_t 130 le_lebuffer_rdcsr(struct lance_softc *sc, uint16_t port) 131 { 132 struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; 133 134 bus_write_2(lesc->sc_rres, LEREG1_RAP, port); 135 bus_barrier(lesc->sc_rres, LEREG1_RAP, 2, BUS_SPACE_BARRIER_WRITE); 136 return (bus_read_2(lesc->sc_rres, LEREG1_RDP)); 137 } 138 139 /* 140 * It turns out that using bus_space(9) to access the buffers and the 141 * descriptors yields way more throughput than accessing them via the 142 * KVA returned by rman_get_virtual(9). The descriptor rings can be 143 * accessed using 8-bit up to 64-bit operations while the buffers can 144 * be only accessed using 8-bit and 16-bit operations. 145 * NB: For whatever reason setting LE_C3_BSWP has no effect with at 146 * least the 501-2981 (although their 'busmaster-regval' property 147 * indicates to set LE_C3_BSWP also for these cards), so we need 148 * to manually byte swap access to the buffers, i.e. the accesses 149 * going through the RX/TX FIFOs. 150 */ 151 152 static void 153 le_lebuffer_copytodesc(struct lance_softc *sc, void *fromv, int off, int len) 154 { 155 struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; 156 caddr_t from = fromv; 157 158 for (; len >= 8; len -= 8, off += 8, from += 8) 159 bus_write_8(lesc->sc_bres, off, be64dec(from)); 160 for (; len >= 4; len -= 4, off += 4, from += 4) 161 bus_write_4(lesc->sc_bres, off, be32dec(from)); 162 for (; len >= 2; len -= 2, off += 2, from += 2) 163 bus_write_2(lesc->sc_bres, off, be16dec(from)); 164 if (len == 1) 165 bus_write_1(lesc->sc_bres, off, *from); 166 } 167 168 static void 169 le_lebuffer_copyfromdesc(struct lance_softc *sc, void *tov, int off, int len) 170 { 171 struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; 172 caddr_t to = tov; 173 174 for (; len >= 8; len -= 8, off += 8, to += 8) 175 be64enc(to, 176 bus_read_8(lesc->sc_bres, off)); 177 for (; len >= 4; len -= 4, off += 4, to += 4) 178 be32enc(to, 179 bus_read_4(lesc->sc_bres, off)); 180 for (; len >= 2; len -= 2, off += 2, to += 2) 181 be16enc(to, 182 bus_read_2(lesc->sc_bres, off)); 183 if (len == 1) 184 *to = bus_read_1(lesc->sc_bres, off); 185 } 186 187 static void 188 le_lebuffer_copytobuf(struct lance_softc *sc, void *fromv, int off, int len) 189 { 190 struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; 191 caddr_t from = fromv; 192 193 for (; len >= 2; len -= 2, off += 2, from += 2) 194 bus_write_2(lesc->sc_bres, off, le16dec(from)); 195 if (len == 1) 196 bus_write_1(lesc->sc_bres, off + 1, *from); 197 } 198 199 static void 200 le_lebuffer_copyfrombuf(struct lance_softc *sc, void *tov, int off, int len) 201 { 202 struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; 203 caddr_t to = tov; 204 205 for (; len >= 2; len -= 2, off += 2, to += 2) 206 le16enc(to, 207 bus_read_2(lesc->sc_bres, off)); 208 if (len == 1) 209 *to = bus_read_1(lesc->sc_bres, off + 1); 210 } 211 212 static void 213 le_lebuffer_zerobuf(struct lance_softc *sc, int off, int len) 214 { 215 struct le_lebuffer_softc *lesc = (struct le_lebuffer_softc *)sc; 216 217 for (; len >= 2; len -= 2, off += 2) 218 bus_write_2(lesc->sc_bres, off, 0); 219 if (len == 1) 220 bus_write_1(lesc->sc_bres, off + 1, 0); 221 } 222 223 static int 224 le_lebuffer_probe(device_t dev) 225 { 226 227 if (strcmp(ofw_bus_get_name(dev), "le") == 0) { 228 device_set_desc(dev, "LANCE Ethernet"); 229 return (BUS_PROBE_DEFAULT); 230 } 231 return (ENXIO); 232 } 233 234 static int 235 le_lebuffer_attach(device_t dev) 236 { 237 struct le_lebuffer_softc *lesc; 238 struct lance_softc *sc; 239 int error, i; 240 241 lesc = device_get_softc(dev); 242 sc = &lesc->sc_am7990.lsc; 243 244 LE_LOCK_INIT(sc, device_get_nameunit(dev)); 245 246 /* 247 * The "register space" of the parent is just a buffer where the 248 * the LANCE descriptor rings and the RX/TX buffers can be stored. 249 */ 250 i = 0; 251 lesc->sc_bres = bus_alloc_resource_any(device_get_parent(dev), 252 SYS_RES_MEMORY, &i, RF_ACTIVE); 253 if (lesc->sc_bres == NULL) { 254 device_printf(dev, "cannot allocate LANCE buffer\n"); 255 error = ENXIO; 256 goto fail_mtx; 257 } 258 259 /* Allocate LANCE registers. */ 260 i = 0; 261 lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 262 &i, RF_ACTIVE); 263 if (lesc->sc_rres == NULL) { 264 device_printf(dev, "cannot allocate LANCE registers\n"); 265 error = ENXIO; 266 goto fail_bres; 267 } 268 269 /* Allocate LANCE interrupt. */ 270 i = 0; 271 if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 272 &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 273 device_printf(dev, "cannot allocate interrupt\n"); 274 error = ENXIO; 275 goto fail_rres; 276 } 277 278 /* 279 * LANCE view is offset by buffer location. 280 * Note that we don't use sc->sc_mem. 281 */ 282 sc->sc_addr = 0; 283 sc->sc_memsize = rman_get_size(lesc->sc_bres); 284 sc->sc_flags = 0; 285 286 /* That old black magic... */ 287 if (OF_getprop(ofw_bus_get_node(dev), "busmaster-regval", 288 &sc->sc_conf3, sizeof(sc->sc_conf3)) == -1) 289 sc->sc_conf3 = LE_C3_ACON | LE_C3_BCON; 290 /* 291 * Make sure LE_C3_BSWP is cleared so that for cards where 292 * that flag actually works le_lebuffer_copy{from,to}buf() 293 * don't fail... 294 */ 295 sc->sc_conf3 &= ~LE_C3_BSWP; 296 297 OF_getetheraddr(dev, sc->sc_enaddr); 298 299 sc->sc_copytodesc = le_lebuffer_copytodesc; 300 sc->sc_copyfromdesc = le_lebuffer_copyfromdesc; 301 sc->sc_copytobuf = le_lebuffer_copytobuf; 302 sc->sc_copyfrombuf = le_lebuffer_copyfrombuf; 303 sc->sc_zerobuf = le_lebuffer_zerobuf; 304 305 sc->sc_rdcsr = le_lebuffer_rdcsr; 306 sc->sc_wrcsr = le_lebuffer_wrcsr; 307 sc->sc_hwreset = NULL; 308 sc->sc_hwinit = NULL; 309 sc->sc_hwintr = NULL; 310 sc->sc_nocarrier = NULL; 311 sc->sc_mediachange = NULL; 312 sc->sc_mediastatus = NULL; 313 sc->sc_supmedia = le_lebuffer_media; 314 sc->sc_nsupmedia = NLEMEDIA; 315 sc->sc_defaultmedia = le_lebuffer_media[0]; 316 317 error = am7990_config(&lesc->sc_am7990, device_get_name(dev), 318 device_get_unit(dev)); 319 if (error != 0) { 320 device_printf(dev, "cannot attach Am7990\n"); 321 goto fail_ires; 322 } 323 324 error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, 325 NULL, am7990_intr, sc, &lesc->sc_ih); 326 if (error != 0) { 327 device_printf(dev, "cannot set up interrupt\n"); 328 goto fail_am7990; 329 } 330 331 return (0); 332 333 fail_am7990: 334 am7990_detach(&lesc->sc_am7990); 335 fail_ires: 336 bus_release_resource(dev, SYS_RES_IRQ, 337 rman_get_rid(lesc->sc_ires), lesc->sc_ires); 338 fail_rres: 339 bus_release_resource(dev, SYS_RES_MEMORY, 340 rman_get_rid(lesc->sc_rres), lesc->sc_rres); 341 fail_bres: 342 bus_release_resource(device_get_parent(dev), SYS_RES_MEMORY, 343 rman_get_rid(lesc->sc_bres), lesc->sc_bres); 344 fail_mtx: 345 LE_LOCK_DESTROY(sc); 346 return (error); 347 } 348 349 static int 350 le_lebuffer_detach(device_t dev) 351 { 352 struct le_lebuffer_softc *lesc; 353 struct lance_softc *sc; 354 355 lesc = device_get_softc(dev); 356 sc = &lesc->sc_am7990.lsc; 357 358 bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); 359 am7990_detach(&lesc->sc_am7990); 360 bus_release_resource(dev, SYS_RES_IRQ, 361 rman_get_rid(lesc->sc_ires), lesc->sc_ires); 362 bus_release_resource(dev, SYS_RES_MEMORY, 363 rman_get_rid(lesc->sc_rres), lesc->sc_rres); 364 bus_release_resource(device_get_parent(dev), SYS_RES_MEMORY, 365 rman_get_rid(lesc->sc_bres), lesc->sc_bres); 366 LE_LOCK_DESTROY(sc); 367 368 return (0); 369 } 370 371 static int 372 le_buffer_suspend(device_t dev) 373 { 374 struct le_lebuffer_softc *lesc; 375 376 lesc = device_get_softc(dev); 377 378 lance_suspend(&lesc->sc_am7990.lsc); 379 380 return (0); 381 } 382 383 static int 384 le_buffer_resume(device_t dev) 385 { 386 struct le_lebuffer_softc *lesc; 387 388 lesc = device_get_softc(dev); 389 390 lance_resume(&lesc->sc_am7990.lsc); 391 392 return (0); 393 } 394