2 * Copyright (c) 2015 Marcel Moolenaar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <machine/bus.h>
32 #include <machine/bus_dma.h>
33 #include <machine/resource.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/queue.h>
43 #include <dev/proto/proto.h>
44 #include <dev/proto/proto_dev.h>
45 #include <dev/proto/proto_busdma.h>
47 MALLOC_DEFINE(M_PROTO_BUSDMA, "proto_busdma", "DMA management data");
50 proto_busdma_tag_create(struct proto_ioc_busdma *ioc,
51 struct proto_tag **tag_io, bus_dma_tag_t *busdma_tag_io)
53 struct proto_tag *tag;
56 error = bus_dma_tag_create(*busdma_tag_io, ioc->u.tag.align,
57 ioc->u.tag.bndry, ioc->u.tag.maxaddr, BUS_SPACE_MAXADDR,
58 NULL, NULL, ioc->u.tag.maxsz, ioc->u.tag.nsegs,
59 ioc->u.tag.maxsegsz, ioc->u.tag.flags, NULL, NULL,
64 tag = malloc(sizeof(*tag), M_PROTO_BUSDMA, M_WAITOK | M_ZERO);
65 tag->parent = *tag_io;
66 tag->busdma_tag = *busdma_tag_io;
72 proto_busdma_tag_destroy(struct proto_tag *tag)
75 bus_dma_tag_destroy(tag->busdma_tag);
76 free(tag, M_PROTO_BUSDMA);
79 static struct proto_tag *
80 proto_busdma_tag_lookup(struct proto_busdma *busdma, u_long key)
82 struct proto_tag *tag;
84 LIST_FOREACH(tag, &busdma->tags, link) {
85 if ((void *)tag == (void *)key)
92 proto_busdma_attach(struct proto_softc *sc)
94 struct proto_busdma *busdma;
96 busdma = malloc(sizeof(*busdma), M_PROTO_BUSDMA, M_WAITOK | M_ZERO);
101 proto_busdma_detach(struct proto_softc *sc, struct proto_busdma *busdma)
104 proto_busdma_cleanup(sc, busdma);
105 free(busdma, M_PROTO_BUSDMA);
110 proto_busdma_cleanup(struct proto_softc *sc, struct proto_busdma *busdma)
112 struct proto_tag *tag, *tag1;
114 LIST_FOREACH_SAFE(tag, &busdma->tags, link, tag1) {
115 LIST_REMOVE(tag, link);
116 proto_busdma_tag_destroy(tag);
122 proto_busdma_ioctl(struct proto_softc *sc, struct proto_busdma *busdma,
123 struct proto_ioc_busdma *ioc)
125 struct proto_tag *tag;
126 bus_dma_tag_t busdma_tag;
130 switch (ioc->request) {
131 case PROTO_IOC_BUSDMA_TAG_CREATE:
132 busdma_tag = bus_get_dma_tag(sc->sc_dev);
134 error = proto_busdma_tag_create(ioc, &tag, &busdma_tag);
137 LIST_INSERT_HEAD(&busdma->tags, tag, link);
138 ioc->key = (uintptr_t)(void *)tag;
140 case PROTO_IOC_BUSDMA_TAG_DERIVE:
141 tag = proto_busdma_tag_lookup(busdma, ioc->key);
146 busdma_tag = tag->busdma_tag;
147 error = proto_busdma_tag_create(ioc, &tag, &busdma_tag);
150 LIST_INSERT_HEAD(&busdma->tags, tag, link);
151 ioc->key = (uintptr_t)(void *)tag;
153 case PROTO_IOC_BUSDMA_TAG_DESTROY:
154 tag = proto_busdma_tag_lookup(busdma, ioc->key);
159 LIST_REMOVE(tag, link);
160 proto_busdma_tag_destroy(tag);