1*85debf7fSRuslan Bukin /*- 2*85debf7fSRuslan Bukin * Copyright (c) 2016 Ruslan Bukin <br@bsdpad.com> 3*85debf7fSRuslan Bukin * All rights reserved. 4*85debf7fSRuslan Bukin * 5*85debf7fSRuslan Bukin * This software was developed by SRI International and the University of 6*85debf7fSRuslan Bukin * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 7*85debf7fSRuslan Bukin * ("CTSRD"), as part of the DARPA CRASH research programme. 8*85debf7fSRuslan Bukin * 9*85debf7fSRuslan Bukin * Redistribution and use in source and binary forms, with or without 10*85debf7fSRuslan Bukin * modification, are permitted provided that the following conditions 11*85debf7fSRuslan Bukin * are met: 12*85debf7fSRuslan Bukin * 1. Redistributions of source code must retain the above copyright 13*85debf7fSRuslan Bukin * notice, this list of conditions and the following disclaimer. 14*85debf7fSRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright 15*85debf7fSRuslan Bukin * notice, this list of conditions and the following disclaimer in the 16*85debf7fSRuslan Bukin * documentation and/or other materials provided with the distribution. 17*85debf7fSRuslan Bukin * 18*85debf7fSRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19*85debf7fSRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*85debf7fSRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*85debf7fSRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22*85debf7fSRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23*85debf7fSRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24*85debf7fSRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25*85debf7fSRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26*85debf7fSRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27*85debf7fSRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*85debf7fSRuslan Bukin * SUCH DAMAGE. 29*85debf7fSRuslan Bukin */ 30*85debf7fSRuslan Bukin 31*85debf7fSRuslan Bukin /* xDMA memcpy test driver. */ 32*85debf7fSRuslan Bukin 33*85debf7fSRuslan Bukin #include <sys/cdefs.h> 34*85debf7fSRuslan Bukin __FBSDID("$FreeBSD$"); 35*85debf7fSRuslan Bukin 36*85debf7fSRuslan Bukin #include <sys/param.h> 37*85debf7fSRuslan Bukin #include <sys/systm.h> 38*85debf7fSRuslan Bukin #include <sys/conf.h> 39*85debf7fSRuslan Bukin #include <sys/bus.h> 40*85debf7fSRuslan Bukin #include <sys/kernel.h> 41*85debf7fSRuslan Bukin #include <sys/kthread.h> 42*85debf7fSRuslan Bukin #include <sys/module.h> 43*85debf7fSRuslan Bukin #include <sys/lock.h> 44*85debf7fSRuslan Bukin #include <sys/mutex.h> 45*85debf7fSRuslan Bukin #include <sys/resource.h> 46*85debf7fSRuslan Bukin #include <sys/rman.h> 47*85debf7fSRuslan Bukin 48*85debf7fSRuslan Bukin #include <machine/bus.h> 49*85debf7fSRuslan Bukin 50*85debf7fSRuslan Bukin #include <dev/xdma/xdma.h> 51*85debf7fSRuslan Bukin 52*85debf7fSRuslan Bukin #include <dev/fdt/fdt_common.h> 53*85debf7fSRuslan Bukin #include <dev/ofw/ofw_bus.h> 54*85debf7fSRuslan Bukin #include <dev/ofw/ofw_bus_subr.h> 55*85debf7fSRuslan Bukin 56*85debf7fSRuslan Bukin /* 57*85debf7fSRuslan Bukin * To use this test add a compatible node to your dts, e.g. 58*85debf7fSRuslan Bukin * 59*85debf7fSRuslan Bukin * xdma_test { 60*85debf7fSRuslan Bukin * compatible = "freebsd,xdma-test"; 61*85debf7fSRuslan Bukin * 62*85debf7fSRuslan Bukin * dmas = <&dma 0 0 0xffffffff>; 63*85debf7fSRuslan Bukin * dma-names = "test"; 64*85debf7fSRuslan Bukin * }; 65*85debf7fSRuslan Bukin */ 66*85debf7fSRuslan Bukin 67*85debf7fSRuslan Bukin struct xdmatest_softc { 68*85debf7fSRuslan Bukin device_t dev; 69*85debf7fSRuslan Bukin xdma_controller_t *xdma; 70*85debf7fSRuslan Bukin xdma_channel_t *xchan; 71*85debf7fSRuslan Bukin void *ih; 72*85debf7fSRuslan Bukin struct intr_config_hook config_intrhook; 73*85debf7fSRuslan Bukin char *src; 74*85debf7fSRuslan Bukin char *dst; 75*85debf7fSRuslan Bukin uint32_t len; 76*85debf7fSRuslan Bukin uintptr_t src_phys; 77*85debf7fSRuslan Bukin uintptr_t dst_phys; 78*85debf7fSRuslan Bukin bus_dma_tag_t src_dma_tag; 79*85debf7fSRuslan Bukin bus_dmamap_t src_dma_map; 80*85debf7fSRuslan Bukin bus_dma_tag_t dst_dma_tag; 81*85debf7fSRuslan Bukin bus_dmamap_t dst_dma_map; 82*85debf7fSRuslan Bukin struct mtx mtx; 83*85debf7fSRuslan Bukin int done; 84*85debf7fSRuslan Bukin struct proc *newp; 85*85debf7fSRuslan Bukin }; 86*85debf7fSRuslan Bukin 87*85debf7fSRuslan Bukin static int xdmatest_probe(device_t dev); 88*85debf7fSRuslan Bukin static int xdmatest_attach(device_t dev); 89*85debf7fSRuslan Bukin static int xdmatest_detach(device_t dev); 90*85debf7fSRuslan Bukin 91*85debf7fSRuslan Bukin static int 92*85debf7fSRuslan Bukin xdmatest_intr(void *arg) 93*85debf7fSRuslan Bukin { 94*85debf7fSRuslan Bukin struct xdmatest_softc *sc; 95*85debf7fSRuslan Bukin 96*85debf7fSRuslan Bukin sc = arg; 97*85debf7fSRuslan Bukin 98*85debf7fSRuslan Bukin sc->done = 1; 99*85debf7fSRuslan Bukin 100*85debf7fSRuslan Bukin mtx_lock(&sc->mtx); 101*85debf7fSRuslan Bukin wakeup(sc); 102*85debf7fSRuslan Bukin mtx_unlock(&sc->mtx); 103*85debf7fSRuslan Bukin 104*85debf7fSRuslan Bukin return (0); 105*85debf7fSRuslan Bukin } 106*85debf7fSRuslan Bukin 107*85debf7fSRuslan Bukin static void 108*85debf7fSRuslan Bukin xdmatest_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) 109*85debf7fSRuslan Bukin { 110*85debf7fSRuslan Bukin bus_addr_t *addr; 111*85debf7fSRuslan Bukin 112*85debf7fSRuslan Bukin if (err) 113*85debf7fSRuslan Bukin return; 114*85debf7fSRuslan Bukin 115*85debf7fSRuslan Bukin addr = (bus_addr_t*)arg; 116*85debf7fSRuslan Bukin *addr = segs[0].ds_addr; 117*85debf7fSRuslan Bukin } 118*85debf7fSRuslan Bukin 119*85debf7fSRuslan Bukin static int 120*85debf7fSRuslan Bukin xdmatest_alloc_test_memory(struct xdmatest_softc *sc) 121*85debf7fSRuslan Bukin { 122*85debf7fSRuslan Bukin int err; 123*85debf7fSRuslan Bukin 124*85debf7fSRuslan Bukin sc->len = (0x1000000 - 8); /* 16mb */ 125*85debf7fSRuslan Bukin sc->len = 8; 126*85debf7fSRuslan Bukin 127*85debf7fSRuslan Bukin /* Source memory. */ 128*85debf7fSRuslan Bukin 129*85debf7fSRuslan Bukin err = bus_dma_tag_create( 130*85debf7fSRuslan Bukin bus_get_dma_tag(sc->dev), 131*85debf7fSRuslan Bukin 1024, 0, /* alignment, boundary */ 132*85debf7fSRuslan Bukin BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 133*85debf7fSRuslan Bukin BUS_SPACE_MAXADDR, /* highaddr */ 134*85debf7fSRuslan Bukin NULL, NULL, /* filter, filterarg */ 135*85debf7fSRuslan Bukin sc->len, 1, /* maxsize, nsegments*/ 136*85debf7fSRuslan Bukin sc->len, 0, /* maxsegsize, flags */ 137*85debf7fSRuslan Bukin NULL, NULL, /* lockfunc, lockarg */ 138*85debf7fSRuslan Bukin &sc->src_dma_tag); 139*85debf7fSRuslan Bukin if (err) { 140*85debf7fSRuslan Bukin device_printf(sc->dev, 141*85debf7fSRuslan Bukin "%s: Can't create bus_dma tag.\n", __func__); 142*85debf7fSRuslan Bukin return (-1); 143*85debf7fSRuslan Bukin } 144*85debf7fSRuslan Bukin 145*85debf7fSRuslan Bukin err = bus_dmamem_alloc(sc->src_dma_tag, (void **)&sc->src, 146*85debf7fSRuslan Bukin BUS_DMA_WAITOK | BUS_DMA_COHERENT, &sc->src_dma_map); 147*85debf7fSRuslan Bukin if (err) { 148*85debf7fSRuslan Bukin device_printf(sc->dev, 149*85debf7fSRuslan Bukin "%s: Can't allocate memory.\n", __func__); 150*85debf7fSRuslan Bukin return (-1); 151*85debf7fSRuslan Bukin } 152*85debf7fSRuslan Bukin 153*85debf7fSRuslan Bukin err = bus_dmamap_load(sc->src_dma_tag, sc->src_dma_map, sc->src, 154*85debf7fSRuslan Bukin sc->len, xdmatest_dmamap_cb, &sc->src_phys, BUS_DMA_WAITOK); 155*85debf7fSRuslan Bukin if (err) { 156*85debf7fSRuslan Bukin device_printf(sc->dev, 157*85debf7fSRuslan Bukin "%s: Can't load DMA map.\n", __func__); 158*85debf7fSRuslan Bukin return (-1); 159*85debf7fSRuslan Bukin } 160*85debf7fSRuslan Bukin 161*85debf7fSRuslan Bukin /* Destination memory. */ 162*85debf7fSRuslan Bukin 163*85debf7fSRuslan Bukin err = bus_dma_tag_create( 164*85debf7fSRuslan Bukin bus_get_dma_tag(sc->dev), 165*85debf7fSRuslan Bukin 1024, 0, /* alignment, boundary */ 166*85debf7fSRuslan Bukin BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 167*85debf7fSRuslan Bukin BUS_SPACE_MAXADDR, /* highaddr */ 168*85debf7fSRuslan Bukin NULL, NULL, /* filter, filterarg */ 169*85debf7fSRuslan Bukin sc->len, 1, /* maxsize, nsegments*/ 170*85debf7fSRuslan Bukin sc->len, 0, /* maxsegsize, flags */ 171*85debf7fSRuslan Bukin NULL, NULL, /* lockfunc, lockarg */ 172*85debf7fSRuslan Bukin &sc->dst_dma_tag); 173*85debf7fSRuslan Bukin if (err) { 174*85debf7fSRuslan Bukin device_printf(sc->dev, 175*85debf7fSRuslan Bukin "%s: Can't create bus_dma tag.\n", __func__); 176*85debf7fSRuslan Bukin return (-1); 177*85debf7fSRuslan Bukin } 178*85debf7fSRuslan Bukin 179*85debf7fSRuslan Bukin err = bus_dmamem_alloc(sc->dst_dma_tag, (void **)&sc->dst, 180*85debf7fSRuslan Bukin BUS_DMA_WAITOK | BUS_DMA_COHERENT, &sc->dst_dma_map); 181*85debf7fSRuslan Bukin if (err) { 182*85debf7fSRuslan Bukin device_printf(sc->dev, 183*85debf7fSRuslan Bukin "%s: Can't allocate memory.\n", __func__); 184*85debf7fSRuslan Bukin return (-1); 185*85debf7fSRuslan Bukin } 186*85debf7fSRuslan Bukin 187*85debf7fSRuslan Bukin err = bus_dmamap_load(sc->dst_dma_tag, sc->dst_dma_map, sc->dst, 188*85debf7fSRuslan Bukin sc->len, xdmatest_dmamap_cb, &sc->dst_phys, BUS_DMA_WAITOK); 189*85debf7fSRuslan Bukin if (err) { 190*85debf7fSRuslan Bukin device_printf(sc->dev, 191*85debf7fSRuslan Bukin "%s: Can't load DMA map.\n", __func__); 192*85debf7fSRuslan Bukin return (-1); 193*85debf7fSRuslan Bukin } 194*85debf7fSRuslan Bukin 195*85debf7fSRuslan Bukin return (0); 196*85debf7fSRuslan Bukin } 197*85debf7fSRuslan Bukin 198*85debf7fSRuslan Bukin static int 199*85debf7fSRuslan Bukin xdmatest_test(struct xdmatest_softc *sc) 200*85debf7fSRuslan Bukin { 201*85debf7fSRuslan Bukin int err; 202*85debf7fSRuslan Bukin int i; 203*85debf7fSRuslan Bukin 204*85debf7fSRuslan Bukin /* Get xDMA controller. */ 205*85debf7fSRuslan Bukin sc->xdma = xdma_ofw_get(sc->dev, "test"); 206*85debf7fSRuslan Bukin if (sc->xdma == NULL) { 207*85debf7fSRuslan Bukin device_printf(sc->dev, "Can't find xDMA controller.\n"); 208*85debf7fSRuslan Bukin return (-1); 209*85debf7fSRuslan Bukin } 210*85debf7fSRuslan Bukin 211*85debf7fSRuslan Bukin /* Alloc xDMA virtual channel. */ 212*85debf7fSRuslan Bukin sc->xchan = xdma_channel_alloc(sc->xdma); 213*85debf7fSRuslan Bukin if (sc->xchan == NULL) { 214*85debf7fSRuslan Bukin device_printf(sc->dev, "Can't alloc virtual DMA channel.\n"); 215*85debf7fSRuslan Bukin return (-1); 216*85debf7fSRuslan Bukin } 217*85debf7fSRuslan Bukin 218*85debf7fSRuslan Bukin /* Setup callback. */ 219*85debf7fSRuslan Bukin err = xdma_setup_intr(sc->xchan, xdmatest_intr, sc, &sc->ih); 220*85debf7fSRuslan Bukin if (err) { 221*85debf7fSRuslan Bukin device_printf(sc->dev, "Can't setup xDMA interrupt handler.\n"); 222*85debf7fSRuslan Bukin return (-1); 223*85debf7fSRuslan Bukin } 224*85debf7fSRuslan Bukin 225*85debf7fSRuslan Bukin /* We are going to fill memory. */ 226*85debf7fSRuslan Bukin bus_dmamap_sync(sc->src_dma_tag, sc->src_dma_map, BUS_DMASYNC_PREWRITE); 227*85debf7fSRuslan Bukin bus_dmamap_sync(sc->dst_dma_tag, sc->dst_dma_map, BUS_DMASYNC_PREWRITE); 228*85debf7fSRuslan Bukin 229*85debf7fSRuslan Bukin /* Fill memory. */ 230*85debf7fSRuslan Bukin for (i = 0; i < sc->len; i++) { 231*85debf7fSRuslan Bukin sc->src[i] = (i & 0xff); 232*85debf7fSRuslan Bukin sc->dst[i] = 0; 233*85debf7fSRuslan Bukin } 234*85debf7fSRuslan Bukin 235*85debf7fSRuslan Bukin /* Configure channel for memcpy transfer. */ 236*85debf7fSRuslan Bukin err = xdma_prep_memcpy(sc->xchan, sc->src_phys, sc->dst_phys, sc->len); 237*85debf7fSRuslan Bukin if (err != 0) { 238*85debf7fSRuslan Bukin device_printf(sc->dev, "Can't configure virtual channel.\n"); 239*85debf7fSRuslan Bukin return (-1); 240*85debf7fSRuslan Bukin } 241*85debf7fSRuslan Bukin 242*85debf7fSRuslan Bukin /* Start operation. */ 243*85debf7fSRuslan Bukin xdma_begin(sc->xchan); 244*85debf7fSRuslan Bukin 245*85debf7fSRuslan Bukin return (0); 246*85debf7fSRuslan Bukin } 247*85debf7fSRuslan Bukin 248*85debf7fSRuslan Bukin static int 249*85debf7fSRuslan Bukin xdmatest_verify(struct xdmatest_softc *sc) 250*85debf7fSRuslan Bukin { 251*85debf7fSRuslan Bukin int err; 252*85debf7fSRuslan Bukin int i; 253*85debf7fSRuslan Bukin 254*85debf7fSRuslan Bukin /* We have memory updated by DMA controller. */ 255*85debf7fSRuslan Bukin bus_dmamap_sync(sc->src_dma_tag, sc->src_dma_map, BUS_DMASYNC_POSTREAD); 256*85debf7fSRuslan Bukin bus_dmamap_sync(sc->dst_dma_tag, sc->dst_dma_map, BUS_DMASYNC_POSTWRITE); 257*85debf7fSRuslan Bukin 258*85debf7fSRuslan Bukin for (i = 0; i < sc->len; i++) { 259*85debf7fSRuslan Bukin if (sc->dst[i] != sc->src[i]) { 260*85debf7fSRuslan Bukin device_printf(sc->dev, 261*85debf7fSRuslan Bukin "%s: Test failed: iter %d\n", __func__, i); 262*85debf7fSRuslan Bukin return (-1); 263*85debf7fSRuslan Bukin } 264*85debf7fSRuslan Bukin } 265*85debf7fSRuslan Bukin 266*85debf7fSRuslan Bukin err = xdma_channel_free(sc->xchan); 267*85debf7fSRuslan Bukin if (err != 0) { 268*85debf7fSRuslan Bukin device_printf(sc->dev, 269*85debf7fSRuslan Bukin "%s: Test failed: can't deallocate channel.\n", __func__); 270*85debf7fSRuslan Bukin return (-1); 271*85debf7fSRuslan Bukin } 272*85debf7fSRuslan Bukin 273*85debf7fSRuslan Bukin err = xdma_put(sc->xdma); 274*85debf7fSRuslan Bukin if (err != 0) { 275*85debf7fSRuslan Bukin device_printf(sc->dev, 276*85debf7fSRuslan Bukin "%s: Test failed: can't deallocate xDMA.\n", __func__); 277*85debf7fSRuslan Bukin return (-1); 278*85debf7fSRuslan Bukin } 279*85debf7fSRuslan Bukin 280*85debf7fSRuslan Bukin return (0); 281*85debf7fSRuslan Bukin } 282*85debf7fSRuslan Bukin 283*85debf7fSRuslan Bukin static void 284*85debf7fSRuslan Bukin xdmatest_worker(void *arg) 285*85debf7fSRuslan Bukin { 286*85debf7fSRuslan Bukin struct xdmatest_softc *sc; 287*85debf7fSRuslan Bukin int timeout; 288*85debf7fSRuslan Bukin int err; 289*85debf7fSRuslan Bukin 290*85debf7fSRuslan Bukin sc = arg; 291*85debf7fSRuslan Bukin 292*85debf7fSRuslan Bukin device_printf(sc->dev, "Worker %d started.\n", 293*85debf7fSRuslan Bukin device_get_unit(sc->dev)); 294*85debf7fSRuslan Bukin 295*85debf7fSRuslan Bukin while (1) { 296*85debf7fSRuslan Bukin sc->done = 0; 297*85debf7fSRuslan Bukin 298*85debf7fSRuslan Bukin mtx_lock(&sc->mtx); 299*85debf7fSRuslan Bukin 300*85debf7fSRuslan Bukin xdmatest_test(sc); 301*85debf7fSRuslan Bukin 302*85debf7fSRuslan Bukin timeout = 100; 303*85debf7fSRuslan Bukin 304*85debf7fSRuslan Bukin do { 305*85debf7fSRuslan Bukin mtx_sleep(sc, &sc->mtx, 0, "xdmatest_wait", hz); 306*85debf7fSRuslan Bukin } while (timeout-- && sc->done == 0); 307*85debf7fSRuslan Bukin 308*85debf7fSRuslan Bukin if (timeout != 0) { 309*85debf7fSRuslan Bukin err = xdmatest_verify(sc); 310*85debf7fSRuslan Bukin if (err == 0) { 311*85debf7fSRuslan Bukin /* Test succeeded. */ 312*85debf7fSRuslan Bukin mtx_unlock(&sc->mtx); 313*85debf7fSRuslan Bukin continue; 314*85debf7fSRuslan Bukin } 315*85debf7fSRuslan Bukin } 316*85debf7fSRuslan Bukin 317*85debf7fSRuslan Bukin mtx_unlock(&sc->mtx); 318*85debf7fSRuslan Bukin device_printf(sc->dev, 319*85debf7fSRuslan Bukin "%s: Test failed.\n", __func__); 320*85debf7fSRuslan Bukin break; 321*85debf7fSRuslan Bukin } 322*85debf7fSRuslan Bukin } 323*85debf7fSRuslan Bukin 324*85debf7fSRuslan Bukin static void 325*85debf7fSRuslan Bukin xdmatest_delayed_attach(void *arg) 326*85debf7fSRuslan Bukin { 327*85debf7fSRuslan Bukin struct xdmatest_softc *sc; 328*85debf7fSRuslan Bukin 329*85debf7fSRuslan Bukin sc = arg; 330*85debf7fSRuslan Bukin 331*85debf7fSRuslan Bukin if (kproc_create(xdmatest_worker, (void *)sc, &sc->newp, 0, 0, 332*85debf7fSRuslan Bukin "xdmatest_worker") != 0) { 333*85debf7fSRuslan Bukin device_printf(sc->dev, 334*85debf7fSRuslan Bukin "%s: Failed to create worker thread.\n", __func__); 335*85debf7fSRuslan Bukin } 336*85debf7fSRuslan Bukin 337*85debf7fSRuslan Bukin config_intrhook_disestablish(&sc->config_intrhook); 338*85debf7fSRuslan Bukin } 339*85debf7fSRuslan Bukin 340*85debf7fSRuslan Bukin static int 341*85debf7fSRuslan Bukin xdmatest_probe(device_t dev) 342*85debf7fSRuslan Bukin { 343*85debf7fSRuslan Bukin 344*85debf7fSRuslan Bukin if (!ofw_bus_status_okay(dev)) 345*85debf7fSRuslan Bukin return (ENXIO); 346*85debf7fSRuslan Bukin 347*85debf7fSRuslan Bukin if (!ofw_bus_is_compatible(dev, "freebsd,xdma-test")) 348*85debf7fSRuslan Bukin return (ENXIO); 349*85debf7fSRuslan Bukin 350*85debf7fSRuslan Bukin device_set_desc(dev, "xDMA test driver"); 351*85debf7fSRuslan Bukin 352*85debf7fSRuslan Bukin return (BUS_PROBE_DEFAULT); 353*85debf7fSRuslan Bukin } 354*85debf7fSRuslan Bukin 355*85debf7fSRuslan Bukin static int 356*85debf7fSRuslan Bukin xdmatest_attach(device_t dev) 357*85debf7fSRuslan Bukin { 358*85debf7fSRuslan Bukin struct xdmatest_softc *sc; 359*85debf7fSRuslan Bukin int err; 360*85debf7fSRuslan Bukin 361*85debf7fSRuslan Bukin sc = device_get_softc(dev); 362*85debf7fSRuslan Bukin sc->dev = dev; 363*85debf7fSRuslan Bukin 364*85debf7fSRuslan Bukin mtx_init(&sc->mtx, device_get_nameunit(dev), "xdmatest", MTX_DEF); 365*85debf7fSRuslan Bukin 366*85debf7fSRuslan Bukin /* Allocate test memory */ 367*85debf7fSRuslan Bukin err = xdmatest_alloc_test_memory(sc); 368*85debf7fSRuslan Bukin if (err != 0) { 369*85debf7fSRuslan Bukin device_printf(sc->dev, "Can't allocate test memory.\n"); 370*85debf7fSRuslan Bukin return (-1); 371*85debf7fSRuslan Bukin } 372*85debf7fSRuslan Bukin 373*85debf7fSRuslan Bukin /* We'll run test later, but before / mount. */ 374*85debf7fSRuslan Bukin sc->config_intrhook.ich_func = xdmatest_delayed_attach; 375*85debf7fSRuslan Bukin sc->config_intrhook.ich_arg = sc; 376*85debf7fSRuslan Bukin if (config_intrhook_establish(&sc->config_intrhook) != 0) 377*85debf7fSRuslan Bukin device_printf(dev, "config_intrhook_establish failed\n"); 378*85debf7fSRuslan Bukin 379*85debf7fSRuslan Bukin return (0); 380*85debf7fSRuslan Bukin } 381*85debf7fSRuslan Bukin 382*85debf7fSRuslan Bukin static int 383*85debf7fSRuslan Bukin xdmatest_detach(device_t dev) 384*85debf7fSRuslan Bukin { 385*85debf7fSRuslan Bukin struct xdmatest_softc *sc; 386*85debf7fSRuslan Bukin 387*85debf7fSRuslan Bukin sc = device_get_softc(dev); 388*85debf7fSRuslan Bukin 389*85debf7fSRuslan Bukin bus_dmamap_unload(sc->src_dma_tag, sc->src_dma_map); 390*85debf7fSRuslan Bukin bus_dmamem_free(sc->src_dma_tag, sc->src, sc->src_dma_map); 391*85debf7fSRuslan Bukin bus_dma_tag_destroy(sc->src_dma_tag); 392*85debf7fSRuslan Bukin 393*85debf7fSRuslan Bukin bus_dmamap_unload(sc->dst_dma_tag, sc->dst_dma_map); 394*85debf7fSRuslan Bukin bus_dmamem_free(sc->dst_dma_tag, sc->dst, sc->dst_dma_map); 395*85debf7fSRuslan Bukin bus_dma_tag_destroy(sc->dst_dma_tag); 396*85debf7fSRuslan Bukin 397*85debf7fSRuslan Bukin return (0); 398*85debf7fSRuslan Bukin } 399*85debf7fSRuslan Bukin 400*85debf7fSRuslan Bukin static device_method_t xdmatest_methods[] = { 401*85debf7fSRuslan Bukin /* Device interface */ 402*85debf7fSRuslan Bukin DEVMETHOD(device_probe, xdmatest_probe), 403*85debf7fSRuslan Bukin DEVMETHOD(device_attach, xdmatest_attach), 404*85debf7fSRuslan Bukin DEVMETHOD(device_detach, xdmatest_detach), 405*85debf7fSRuslan Bukin 406*85debf7fSRuslan Bukin DEVMETHOD_END 407*85debf7fSRuslan Bukin }; 408*85debf7fSRuslan Bukin 409*85debf7fSRuslan Bukin static driver_t xdmatest_driver = { 410*85debf7fSRuslan Bukin "xdmatest", 411*85debf7fSRuslan Bukin xdmatest_methods, 412*85debf7fSRuslan Bukin sizeof(struct xdmatest_softc), 413*85debf7fSRuslan Bukin }; 414*85debf7fSRuslan Bukin 415*85debf7fSRuslan Bukin static devclass_t xdmatest_devclass; 416*85debf7fSRuslan Bukin 417*85debf7fSRuslan Bukin DRIVER_MODULE(xdmatest, simplebus, xdmatest_driver, xdmatest_devclass, 0, 0); 418