1*4f027abdSMarcel Moolenaar /*- 2*4f027abdSMarcel Moolenaar * Copyright (c) 2015 Marcel Moolenaar 3*4f027abdSMarcel Moolenaar * All rights reserved. 4*4f027abdSMarcel Moolenaar * 5*4f027abdSMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 6*4f027abdSMarcel Moolenaar * modification, are permitted provided that the following conditions 7*4f027abdSMarcel Moolenaar * are met: 8*4f027abdSMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 9*4f027abdSMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 10*4f027abdSMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 11*4f027abdSMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 12*4f027abdSMarcel Moolenaar * documentation and/or other materials provided with the distribution. 13*4f027abdSMarcel Moolenaar * 14*4f027abdSMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15*4f027abdSMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16*4f027abdSMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17*4f027abdSMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18*4f027abdSMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19*4f027abdSMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20*4f027abdSMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21*4f027abdSMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*4f027abdSMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23*4f027abdSMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*4f027abdSMarcel Moolenaar */ 25*4f027abdSMarcel Moolenaar 26*4f027abdSMarcel Moolenaar #include <sys/cdefs.h> 27*4f027abdSMarcel Moolenaar __FBSDID("$FreeBSD$"); 28*4f027abdSMarcel Moolenaar 29*4f027abdSMarcel Moolenaar #include <sys/param.h> 30*4f027abdSMarcel Moolenaar #include <sys/systm.h> 31*4f027abdSMarcel Moolenaar #include <machine/bus.h> 32*4f027abdSMarcel Moolenaar #include <machine/bus_dma.h> 33*4f027abdSMarcel Moolenaar #include <machine/resource.h> 34*4f027abdSMarcel Moolenaar #include <sys/bus.h> 35*4f027abdSMarcel Moolenaar #include <sys/conf.h> 36*4f027abdSMarcel Moolenaar #include <sys/kernel.h> 37*4f027abdSMarcel Moolenaar #include <sys/malloc.h> 38*4f027abdSMarcel Moolenaar #include <sys/module.h> 39*4f027abdSMarcel Moolenaar #include <sys/queue.h> 40*4f027abdSMarcel Moolenaar #include <sys/rman.h> 41*4f027abdSMarcel Moolenaar #include <sys/sbuf.h> 42*4f027abdSMarcel Moolenaar 43*4f027abdSMarcel Moolenaar #include <dev/proto/proto.h> 44*4f027abdSMarcel Moolenaar #include <dev/proto/proto_dev.h> 45*4f027abdSMarcel Moolenaar #include <dev/proto/proto_busdma.h> 46*4f027abdSMarcel Moolenaar 47*4f027abdSMarcel Moolenaar MALLOC_DEFINE(M_PROTO_BUSDMA, "proto_busdma", "DMA management data"); 48*4f027abdSMarcel Moolenaar 49*4f027abdSMarcel Moolenaar static int 50*4f027abdSMarcel Moolenaar proto_busdma_tag_create(struct proto_ioc_busdma *ioc, 51*4f027abdSMarcel Moolenaar struct proto_tag **tag_io, bus_dma_tag_t *busdma_tag_io) 52*4f027abdSMarcel Moolenaar { 53*4f027abdSMarcel Moolenaar struct proto_tag *tag; 54*4f027abdSMarcel Moolenaar int error; 55*4f027abdSMarcel Moolenaar 56*4f027abdSMarcel Moolenaar error = bus_dma_tag_create(*busdma_tag_io, ioc->u.tag.align, 57*4f027abdSMarcel Moolenaar ioc->u.tag.bndry, ioc->u.tag.maxaddr, BUS_SPACE_MAXADDR, 58*4f027abdSMarcel Moolenaar NULL, NULL, ioc->u.tag.maxsz, ioc->u.tag.nsegs, 59*4f027abdSMarcel Moolenaar ioc->u.tag.maxsegsz, ioc->u.tag.flags, NULL, NULL, 60*4f027abdSMarcel Moolenaar busdma_tag_io); 61*4f027abdSMarcel Moolenaar if (error) 62*4f027abdSMarcel Moolenaar return (error); 63*4f027abdSMarcel Moolenaar 64*4f027abdSMarcel Moolenaar tag = malloc(sizeof(*tag), M_PROTO_BUSDMA, M_WAITOK | M_ZERO); 65*4f027abdSMarcel Moolenaar tag->parent = *tag_io; 66*4f027abdSMarcel Moolenaar tag->busdma_tag = *busdma_tag_io; 67*4f027abdSMarcel Moolenaar *tag_io = tag; 68*4f027abdSMarcel Moolenaar return (0); 69*4f027abdSMarcel Moolenaar } 70*4f027abdSMarcel Moolenaar 71*4f027abdSMarcel Moolenaar static void 72*4f027abdSMarcel Moolenaar proto_busdma_tag_destroy(struct proto_tag *tag) 73*4f027abdSMarcel Moolenaar { 74*4f027abdSMarcel Moolenaar 75*4f027abdSMarcel Moolenaar bus_dma_tag_destroy(tag->busdma_tag); 76*4f027abdSMarcel Moolenaar free(tag, M_PROTO_BUSDMA); 77*4f027abdSMarcel Moolenaar } 78*4f027abdSMarcel Moolenaar 79*4f027abdSMarcel Moolenaar static struct proto_tag * 80*4f027abdSMarcel Moolenaar proto_busdma_tag_lookup(struct proto_busdma *busdma, u_long key) 81*4f027abdSMarcel Moolenaar { 82*4f027abdSMarcel Moolenaar struct proto_tag *tag; 83*4f027abdSMarcel Moolenaar 84*4f027abdSMarcel Moolenaar LIST_FOREACH(tag, &busdma->tags, link) { 85*4f027abdSMarcel Moolenaar if ((void *)tag == (void *)key) 86*4f027abdSMarcel Moolenaar return (tag); 87*4f027abdSMarcel Moolenaar } 88*4f027abdSMarcel Moolenaar return (NULL); 89*4f027abdSMarcel Moolenaar } 90*4f027abdSMarcel Moolenaar 91*4f027abdSMarcel Moolenaar struct proto_busdma * 92*4f027abdSMarcel Moolenaar proto_busdma_attach(struct proto_softc *sc) 93*4f027abdSMarcel Moolenaar { 94*4f027abdSMarcel Moolenaar struct proto_busdma *busdma; 95*4f027abdSMarcel Moolenaar 96*4f027abdSMarcel Moolenaar busdma = malloc(sizeof(*busdma), M_PROTO_BUSDMA, M_WAITOK | M_ZERO); 97*4f027abdSMarcel Moolenaar return (busdma); 98*4f027abdSMarcel Moolenaar } 99*4f027abdSMarcel Moolenaar 100*4f027abdSMarcel Moolenaar int 101*4f027abdSMarcel Moolenaar proto_busdma_detach(struct proto_softc *sc, struct proto_busdma *busdma) 102*4f027abdSMarcel Moolenaar { 103*4f027abdSMarcel Moolenaar 104*4f027abdSMarcel Moolenaar proto_busdma_cleanup(sc, busdma); 105*4f027abdSMarcel Moolenaar free(busdma, M_PROTO_BUSDMA); 106*4f027abdSMarcel Moolenaar return (0); 107*4f027abdSMarcel Moolenaar } 108*4f027abdSMarcel Moolenaar 109*4f027abdSMarcel Moolenaar int 110*4f027abdSMarcel Moolenaar proto_busdma_cleanup(struct proto_softc *sc, struct proto_busdma *busdma) 111*4f027abdSMarcel Moolenaar { 112*4f027abdSMarcel Moolenaar struct proto_tag *tag, *tag1; 113*4f027abdSMarcel Moolenaar 114*4f027abdSMarcel Moolenaar LIST_FOREACH_SAFE(tag, &busdma->tags, link, tag1) { 115*4f027abdSMarcel Moolenaar LIST_REMOVE(tag, link); 116*4f027abdSMarcel Moolenaar proto_busdma_tag_destroy(tag); 117*4f027abdSMarcel Moolenaar } 118*4f027abdSMarcel Moolenaar return (0); 119*4f027abdSMarcel Moolenaar } 120*4f027abdSMarcel Moolenaar 121*4f027abdSMarcel Moolenaar int 122*4f027abdSMarcel Moolenaar proto_busdma_ioctl(struct proto_softc *sc, struct proto_busdma *busdma, 123*4f027abdSMarcel Moolenaar struct proto_ioc_busdma *ioc) 124*4f027abdSMarcel Moolenaar { 125*4f027abdSMarcel Moolenaar struct proto_tag *tag; 126*4f027abdSMarcel Moolenaar bus_dma_tag_t busdma_tag; 127*4f027abdSMarcel Moolenaar int error; 128*4f027abdSMarcel Moolenaar 129*4f027abdSMarcel Moolenaar error = 0; 130*4f027abdSMarcel Moolenaar switch (ioc->request) { 131*4f027abdSMarcel Moolenaar case PROTO_IOC_BUSDMA_TAG_CREATE: 132*4f027abdSMarcel Moolenaar busdma_tag = bus_get_dma_tag(sc->sc_dev); 133*4f027abdSMarcel Moolenaar tag = NULL; 134*4f027abdSMarcel Moolenaar error = proto_busdma_tag_create(ioc, &tag, &busdma_tag); 135*4f027abdSMarcel Moolenaar if (error) 136*4f027abdSMarcel Moolenaar break; 137*4f027abdSMarcel Moolenaar LIST_INSERT_HEAD(&busdma->tags, tag, link); 138*4f027abdSMarcel Moolenaar ioc->key = (uintptr_t)(void *)tag; 139*4f027abdSMarcel Moolenaar break; 140*4f027abdSMarcel Moolenaar case PROTO_IOC_BUSDMA_TAG_DERIVE: 141*4f027abdSMarcel Moolenaar tag = proto_busdma_tag_lookup(busdma, ioc->key); 142*4f027abdSMarcel Moolenaar if (tag == NULL) { 143*4f027abdSMarcel Moolenaar error = EINVAL; 144*4f027abdSMarcel Moolenaar break; 145*4f027abdSMarcel Moolenaar } 146*4f027abdSMarcel Moolenaar busdma_tag = tag->busdma_tag; 147*4f027abdSMarcel Moolenaar error = proto_busdma_tag_create(ioc, &tag, &busdma_tag); 148*4f027abdSMarcel Moolenaar if (error) 149*4f027abdSMarcel Moolenaar break; 150*4f027abdSMarcel Moolenaar LIST_INSERT_HEAD(&busdma->tags, tag, link); 151*4f027abdSMarcel Moolenaar ioc->key = (uintptr_t)(void *)tag; 152*4f027abdSMarcel Moolenaar break; 153*4f027abdSMarcel Moolenaar case PROTO_IOC_BUSDMA_TAG_DESTROY: 154*4f027abdSMarcel Moolenaar tag = proto_busdma_tag_lookup(busdma, ioc->key); 155*4f027abdSMarcel Moolenaar if (tag == NULL) { 156*4f027abdSMarcel Moolenaar error = EINVAL; 157*4f027abdSMarcel Moolenaar break; 158*4f027abdSMarcel Moolenaar } 159*4f027abdSMarcel Moolenaar LIST_REMOVE(tag, link); 160*4f027abdSMarcel Moolenaar proto_busdma_tag_destroy(tag); 161*4f027abdSMarcel Moolenaar break; 162*4f027abdSMarcel Moolenaar default: 163*4f027abdSMarcel Moolenaar error = EINVAL; 164*4f027abdSMarcel Moolenaar break; 165*4f027abdSMarcel Moolenaar } 166*4f027abdSMarcel Moolenaar return (error); 167*4f027abdSMarcel Moolenaar } 168