xref: /freebsd/sys/dev/proto/proto_busdma.c (revision 4f027abddb02c5b6df045e359a96728b3cd7a09e)
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