xref: /freebsd/tools/bus_space/busdma.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
19c2cdb1aSMarcel Moolenaar /*-
29c2cdb1aSMarcel Moolenaar  * Copyright (c) 2015 Marcel Moolenaar
39c2cdb1aSMarcel Moolenaar  * All rights reserved.
49c2cdb1aSMarcel Moolenaar  *
59c2cdb1aSMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
69c2cdb1aSMarcel Moolenaar  * modification, are permitted provided that the following conditions
79c2cdb1aSMarcel Moolenaar  * are met:
89c2cdb1aSMarcel Moolenaar  *
99c2cdb1aSMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
109c2cdb1aSMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
119c2cdb1aSMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
129c2cdb1aSMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
139c2cdb1aSMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
149c2cdb1aSMarcel Moolenaar  *
159c2cdb1aSMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
169c2cdb1aSMarcel Moolenaar  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
179c2cdb1aSMarcel Moolenaar  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
189c2cdb1aSMarcel Moolenaar  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
199c2cdb1aSMarcel Moolenaar  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
209c2cdb1aSMarcel Moolenaar  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
219c2cdb1aSMarcel Moolenaar  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
229c2cdb1aSMarcel Moolenaar  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
239c2cdb1aSMarcel Moolenaar  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
249c2cdb1aSMarcel Moolenaar  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
259c2cdb1aSMarcel Moolenaar  */
269c2cdb1aSMarcel Moolenaar 
279c2cdb1aSMarcel Moolenaar #include <sys/cdefs.h>
289c2cdb1aSMarcel Moolenaar #include <sys/ioctl.h>
299c2cdb1aSMarcel Moolenaar #include <sys/mman.h>
30cc606478SMarcel Moolenaar #include <assert.h>
319c2cdb1aSMarcel Moolenaar #include <errno.h>
329c2cdb1aSMarcel Moolenaar #include <fcntl.h>
339c2cdb1aSMarcel Moolenaar #include <limits.h>
3471d80fbaSMarcel Moolenaar #include <stdio.h>
359c2cdb1aSMarcel Moolenaar #include <stdlib.h>
369c2cdb1aSMarcel Moolenaar #include <string.h>
379c2cdb1aSMarcel Moolenaar #include <unistd.h>
389c2cdb1aSMarcel Moolenaar 
399c2cdb1aSMarcel Moolenaar #include "busdma.h"
409c2cdb1aSMarcel Moolenaar 
419c2cdb1aSMarcel Moolenaar #include "../../sys/dev/proto/proto_dev.h"
429c2cdb1aSMarcel Moolenaar 
436f769b73SMarcel Moolenaar struct obj {
446f769b73SMarcel Moolenaar 	int	oid;
456f769b73SMarcel Moolenaar 	u_int	type;
466f769b73SMarcel Moolenaar #define	OBJ_TYPE_NONE	0
476f769b73SMarcel Moolenaar #define	OBJ_TYPE_TAG	1
486f769b73SMarcel Moolenaar #define	OBJ_TYPE_MD	2
49cc606478SMarcel Moolenaar #define	OBJ_TYPE_SEG	3
509c2cdb1aSMarcel Moolenaar 	u_int	refcnt;
519c2cdb1aSMarcel Moolenaar 	int	fd;
526f769b73SMarcel Moolenaar 	struct obj *parent;
539c2cdb1aSMarcel Moolenaar 	u_long	key;
546f769b73SMarcel Moolenaar 	union {
556f769b73SMarcel Moolenaar 		struct {
566f769b73SMarcel Moolenaar 			unsigned long	align;
576f769b73SMarcel Moolenaar 			unsigned long	bndry;
586f769b73SMarcel Moolenaar 			unsigned long	maxaddr;
596f769b73SMarcel Moolenaar 			unsigned long	maxsz;
606f769b73SMarcel Moolenaar 			unsigned long	maxsegsz;
616f769b73SMarcel Moolenaar 			unsigned long	nsegs;
626f769b73SMarcel Moolenaar 			unsigned long	datarate;
636f769b73SMarcel Moolenaar 		} tag;
646f769b73SMarcel Moolenaar 		struct {
65cc606478SMarcel Moolenaar 			struct obj	*seg[3];
66cc606478SMarcel Moolenaar 			int		nsegs[3];
67cc606478SMarcel Moolenaar #define	BUSDMA_MD_BUS	0
68cc606478SMarcel Moolenaar #define	BUSDMA_MD_PHYS	1
69cc606478SMarcel Moolenaar #define	BUSDMA_MD_VIRT	2
70cc606478SMarcel Moolenaar 		} md;
71cc606478SMarcel Moolenaar 		struct {
72cc606478SMarcel Moolenaar 			struct obj	*next;
73cc606478SMarcel Moolenaar 			unsigned long	address;
74cc606478SMarcel Moolenaar 			unsigned long	size;
75cc606478SMarcel Moolenaar 		} seg;
766f769b73SMarcel Moolenaar 	} u;
779c2cdb1aSMarcel Moolenaar };
789c2cdb1aSMarcel Moolenaar 
796f769b73SMarcel Moolenaar static struct obj **oidtbl = NULL;
806f769b73SMarcel Moolenaar static int noids = 0;
819c2cdb1aSMarcel Moolenaar 
826f769b73SMarcel Moolenaar static struct obj *
obj_alloc(u_int type)836f769b73SMarcel Moolenaar obj_alloc(u_int type)
849c2cdb1aSMarcel Moolenaar {
856f769b73SMarcel Moolenaar 	struct obj **newtbl, *obj;
866f769b73SMarcel Moolenaar 	int oid;
879c2cdb1aSMarcel Moolenaar 
88cc606478SMarcel Moolenaar 	obj = calloc(1, sizeof(struct obj));
896f769b73SMarcel Moolenaar 	obj->type = type;
909c2cdb1aSMarcel Moolenaar 
916f769b73SMarcel Moolenaar 	for (oid = 0; oid < noids; oid++) {
926f769b73SMarcel Moolenaar 		if (oidtbl[oid] == 0)
939c2cdb1aSMarcel Moolenaar 			break;
949c2cdb1aSMarcel Moolenaar 	}
956f769b73SMarcel Moolenaar 	if (oid == noids) {
966f769b73SMarcel Moolenaar 		newtbl = realloc(oidtbl, sizeof(struct obj *) * (noids + 1));
979c2cdb1aSMarcel Moolenaar 		if (newtbl == NULL) {
986f769b73SMarcel Moolenaar 			free(obj);
999c2cdb1aSMarcel Moolenaar 			return (NULL);
1009c2cdb1aSMarcel Moolenaar 		}
1016f769b73SMarcel Moolenaar 		oidtbl = newtbl;
1026f769b73SMarcel Moolenaar 		noids++;
1039c2cdb1aSMarcel Moolenaar 	}
1046f769b73SMarcel Moolenaar 	oidtbl[oid] = obj;
1056f769b73SMarcel Moolenaar 	obj->oid = oid;
1066f769b73SMarcel Moolenaar 	return (obj);
1079c2cdb1aSMarcel Moolenaar }
1089c2cdb1aSMarcel Moolenaar 
1099c2cdb1aSMarcel Moolenaar static int
obj_free(struct obj * obj)1106f769b73SMarcel Moolenaar obj_free(struct obj *obj)
1119c2cdb1aSMarcel Moolenaar {
1129c2cdb1aSMarcel Moolenaar 
1136f769b73SMarcel Moolenaar 	oidtbl[obj->oid] = NULL;
1146f769b73SMarcel Moolenaar 	free(obj);
1159c2cdb1aSMarcel Moolenaar 	return (0);
1169c2cdb1aSMarcel Moolenaar }
1179c2cdb1aSMarcel Moolenaar 
1186f769b73SMarcel Moolenaar static struct obj *
obj_lookup(int oid,u_int type)1196f769b73SMarcel Moolenaar obj_lookup(int oid, u_int type)
1209c2cdb1aSMarcel Moolenaar {
1216f769b73SMarcel Moolenaar 	struct obj *obj;
1229c2cdb1aSMarcel Moolenaar 
1236f769b73SMarcel Moolenaar 	if (oid < 0 || oid >= noids) {
1249c2cdb1aSMarcel Moolenaar 		errno = EINVAL;
1259c2cdb1aSMarcel Moolenaar 		return (NULL);
1269c2cdb1aSMarcel Moolenaar 	}
1276f769b73SMarcel Moolenaar 	obj = oidtbl[oid];
1286f769b73SMarcel Moolenaar 	if (obj->refcnt == 0) {
1299c2cdb1aSMarcel Moolenaar 		errno = ENXIO;
1309c2cdb1aSMarcel Moolenaar 		return (NULL);
1319c2cdb1aSMarcel Moolenaar 	}
1326f769b73SMarcel Moolenaar 	if (type != OBJ_TYPE_NONE && obj->type != type) {
1336f769b73SMarcel Moolenaar 		errno = ENODEV;
1346f769b73SMarcel Moolenaar 		return (NULL);
1356f769b73SMarcel Moolenaar 	}
1366f769b73SMarcel Moolenaar 	return (obj);
1379c2cdb1aSMarcel Moolenaar }
1389c2cdb1aSMarcel Moolenaar 
13922900685SMarcel Moolenaar static struct obj *
bd_tag_new(struct obj * ptag,int fd,u_long align,u_long bndry,u_long maxaddr,u_long maxsz,u_int nsegs,u_long maxsegsz,u_int datarate,u_int flags)1406f769b73SMarcel Moolenaar bd_tag_new(struct obj *ptag, int fd, u_long align, u_long bndry,
1419c2cdb1aSMarcel Moolenaar     u_long maxaddr, u_long maxsz, u_int nsegs, u_long maxsegsz,
1429c2cdb1aSMarcel Moolenaar     u_int datarate, u_int flags)
1439c2cdb1aSMarcel Moolenaar {
1449c2cdb1aSMarcel Moolenaar 	struct proto_ioc_busdma ioc;
1456f769b73SMarcel Moolenaar 	struct obj *tag;
1469c2cdb1aSMarcel Moolenaar 
1476f769b73SMarcel Moolenaar 	tag = obj_alloc(OBJ_TYPE_TAG);
1489c2cdb1aSMarcel Moolenaar 	if (tag == NULL)
1499c2cdb1aSMarcel Moolenaar 		return (NULL);
1509c2cdb1aSMarcel Moolenaar 
1519c2cdb1aSMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
1529c2cdb1aSMarcel Moolenaar 	ioc.request = (ptag != NULL) ? PROTO_IOC_BUSDMA_TAG_DERIVE :
1539c2cdb1aSMarcel Moolenaar 	    PROTO_IOC_BUSDMA_TAG_CREATE;
1549c2cdb1aSMarcel Moolenaar 	ioc.key = (ptag != NULL) ? ptag->key : 0;
1559c2cdb1aSMarcel Moolenaar 	ioc.u.tag.align = align;
1569c2cdb1aSMarcel Moolenaar 	ioc.u.tag.bndry = bndry;
1579c2cdb1aSMarcel Moolenaar 	ioc.u.tag.maxaddr = maxaddr;
1589c2cdb1aSMarcel Moolenaar 	ioc.u.tag.maxsz = maxsz;
1599c2cdb1aSMarcel Moolenaar 	ioc.u.tag.nsegs = nsegs;
1609c2cdb1aSMarcel Moolenaar 	ioc.u.tag.maxsegsz = maxsegsz;
1619c2cdb1aSMarcel Moolenaar 	ioc.u.tag.datarate = datarate;
1629c2cdb1aSMarcel Moolenaar 	ioc.u.tag.flags = flags;
1639c2cdb1aSMarcel Moolenaar 	if (ioctl(fd, PROTO_IOC_BUSDMA, &ioc) == -1) {
1646f769b73SMarcel Moolenaar 		obj_free(tag);
1659c2cdb1aSMarcel Moolenaar 		return (NULL);
1669c2cdb1aSMarcel Moolenaar 	}
1679c2cdb1aSMarcel Moolenaar 	tag->refcnt = 1;
1689c2cdb1aSMarcel Moolenaar 	tag->fd = fd;
1696f769b73SMarcel Moolenaar 	tag->parent = ptag;
1706f769b73SMarcel Moolenaar 	tag->key = ioc.result;
1716f769b73SMarcel Moolenaar 	tag->u.tag.align = ioc.u.tag.align;
1726f769b73SMarcel Moolenaar 	tag->u.tag.bndry = ioc.u.tag.bndry;
1736f769b73SMarcel Moolenaar 	tag->u.tag.maxaddr = ioc.u.tag.maxaddr;
1746f769b73SMarcel Moolenaar 	tag->u.tag.maxsz = ioc.u.tag.maxsz;
1756f769b73SMarcel Moolenaar 	tag->u.tag.maxsegsz = ioc.u.tag.maxsegsz;
1766f769b73SMarcel Moolenaar 	tag->u.tag.nsegs = ioc.u.tag.nsegs;
1776f769b73SMarcel Moolenaar 	tag->u.tag.datarate = ioc.u.tag.datarate;
1789c2cdb1aSMarcel Moolenaar 	return (tag);
1799c2cdb1aSMarcel Moolenaar }
1809c2cdb1aSMarcel Moolenaar 
1819c2cdb1aSMarcel Moolenaar int
bd_tag_create(const char * dev,u_long align,u_long bndry,u_long maxaddr,u_long maxsz,u_int nsegs,u_long maxsegsz,u_int datarate,u_int flags)1829c2cdb1aSMarcel Moolenaar bd_tag_create(const char *dev, u_long align, u_long bndry, u_long maxaddr,
1839c2cdb1aSMarcel Moolenaar     u_long maxsz, u_int nsegs, u_long maxsegsz, u_int datarate, u_int flags)
1849c2cdb1aSMarcel Moolenaar {
18571d80fbaSMarcel Moolenaar 	char path[PATH_MAX];
1866f769b73SMarcel Moolenaar 	struct obj *tag;
18771d80fbaSMarcel Moolenaar 	int fd, len;
1889c2cdb1aSMarcel Moolenaar 
18971d80fbaSMarcel Moolenaar 	len = snprintf(path, PATH_MAX, "/dev/proto/%s/busdma", dev);
19071d80fbaSMarcel Moolenaar 	if (len >= PATH_MAX) {
19171d80fbaSMarcel Moolenaar 		errno = EINVAL;
19271d80fbaSMarcel Moolenaar 		return (-1);
19371d80fbaSMarcel Moolenaar 	}
19471d80fbaSMarcel Moolenaar 	fd = open(path, O_RDWR);
1959c2cdb1aSMarcel Moolenaar 	if (fd == -1)
1969c2cdb1aSMarcel Moolenaar 		return (-1);
1979c2cdb1aSMarcel Moolenaar 
1989c2cdb1aSMarcel Moolenaar 	tag = bd_tag_new(NULL, fd, align, bndry, maxaddr, maxsz, nsegs,
1999c2cdb1aSMarcel Moolenaar 	    maxsegsz, datarate, flags);
2009c2cdb1aSMarcel Moolenaar 	if (tag == NULL) {
2019c2cdb1aSMarcel Moolenaar 		close(fd);
2029c2cdb1aSMarcel Moolenaar 		return (-1);
2039c2cdb1aSMarcel Moolenaar 	}
2046f769b73SMarcel Moolenaar 	return (tag->oid);
2059c2cdb1aSMarcel Moolenaar }
2069c2cdb1aSMarcel Moolenaar 
2079c2cdb1aSMarcel Moolenaar int
bd_tag_derive(int ptid,u_long align,u_long bndry,u_long maxaddr,u_long maxsz,u_int nsegs,u_long maxsegsz,u_int datarate,u_int flags)2089c2cdb1aSMarcel Moolenaar bd_tag_derive(int ptid, u_long align, u_long bndry, u_long maxaddr,
2099c2cdb1aSMarcel Moolenaar     u_long maxsz, u_int nsegs, u_long maxsegsz, u_int datarate, u_int flags)
2109c2cdb1aSMarcel Moolenaar {
2116f769b73SMarcel Moolenaar 	struct obj *ptag, *tag;
2129c2cdb1aSMarcel Moolenaar 
2136f769b73SMarcel Moolenaar 	ptag = obj_lookup(ptid, OBJ_TYPE_TAG);
2149c2cdb1aSMarcel Moolenaar 	if (ptag == NULL)
2159c2cdb1aSMarcel Moolenaar 		return (-1);
2169c2cdb1aSMarcel Moolenaar 
2179c2cdb1aSMarcel Moolenaar 	tag = bd_tag_new(ptag, ptag->fd, align, bndry, maxaddr, maxsz, nsegs,
2189c2cdb1aSMarcel Moolenaar 	    maxsegsz, datarate, flags);
2199c2cdb1aSMarcel Moolenaar 	if (tag == NULL)
2209c2cdb1aSMarcel Moolenaar 		return (-1);
2219c2cdb1aSMarcel Moolenaar 	ptag->refcnt++;
2226f769b73SMarcel Moolenaar 	return (tag->oid);
2239c2cdb1aSMarcel Moolenaar }
2249c2cdb1aSMarcel Moolenaar 
2259c2cdb1aSMarcel Moolenaar int
bd_tag_destroy(int tid)2269c2cdb1aSMarcel Moolenaar bd_tag_destroy(int tid)
2279c2cdb1aSMarcel Moolenaar {
2289c2cdb1aSMarcel Moolenaar 	struct proto_ioc_busdma ioc;
2296f769b73SMarcel Moolenaar 	struct obj *ptag, *tag;
2309c2cdb1aSMarcel Moolenaar 
2316f769b73SMarcel Moolenaar 	tag = obj_lookup(tid, OBJ_TYPE_TAG);
2329c2cdb1aSMarcel Moolenaar 	if (tag == NULL)
2339c2cdb1aSMarcel Moolenaar 		return (errno);
2349c2cdb1aSMarcel Moolenaar 	if (tag->refcnt > 1)
2359c2cdb1aSMarcel Moolenaar 		return (EBUSY);
2369c2cdb1aSMarcel Moolenaar 
2379c2cdb1aSMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
2389c2cdb1aSMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_TAG_DESTROY;
2399c2cdb1aSMarcel Moolenaar 	ioc.key = tag->key;
2409c2cdb1aSMarcel Moolenaar 	if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
2419c2cdb1aSMarcel Moolenaar 		return (errno);
2429c2cdb1aSMarcel Moolenaar 
2436f769b73SMarcel Moolenaar 	if (tag->parent != NULL)
2446f769b73SMarcel Moolenaar 		tag->parent->refcnt--;
2456f769b73SMarcel Moolenaar 	else
2469c2cdb1aSMarcel Moolenaar 		close(tag->fd);
2476f769b73SMarcel Moolenaar 	obj_free(tag);
2486f769b73SMarcel Moolenaar 	return (0);
2499c2cdb1aSMarcel Moolenaar }
2506f769b73SMarcel Moolenaar 
25122900685SMarcel Moolenaar static int
bd_md_add_seg(struct obj * md,int type,u_long addr,u_long size)25222900685SMarcel Moolenaar bd_md_add_seg(struct obj *md, int type, u_long addr, u_long size)
25322900685SMarcel Moolenaar {
25422900685SMarcel Moolenaar 	struct obj *seg;
25522900685SMarcel Moolenaar 
25622900685SMarcel Moolenaar 	seg = obj_alloc(OBJ_TYPE_SEG);
25722900685SMarcel Moolenaar 	if (seg == NULL)
25822900685SMarcel Moolenaar 		return (errno);
25922900685SMarcel Moolenaar 	seg->refcnt = 1;
26022900685SMarcel Moolenaar 	seg->parent = md;
26122900685SMarcel Moolenaar 	seg->u.seg.address = addr;
26222900685SMarcel Moolenaar 	seg->u.seg.size = size;
26322900685SMarcel Moolenaar 
26422900685SMarcel Moolenaar 	md->u.md.seg[type] = seg;
26522900685SMarcel Moolenaar 	md->u.md.nsegs[type] = 1;
26622900685SMarcel Moolenaar 	return (0);
26722900685SMarcel Moolenaar }
26822900685SMarcel Moolenaar 
2694af242aaSMarcel Moolenaar static int
bd_md_del_segs(struct obj * md,int type,int unmap)2704af242aaSMarcel Moolenaar bd_md_del_segs(struct obj *md, int type, int unmap)
2714af242aaSMarcel Moolenaar {
2724af242aaSMarcel Moolenaar 	struct obj *seg, *seg0;
2734af242aaSMarcel Moolenaar 
2744af242aaSMarcel Moolenaar 	for (seg = md->u.md.seg[type]; seg != NULL; seg = seg0) {
2754af242aaSMarcel Moolenaar 		if (unmap)
2764af242aaSMarcel Moolenaar 			munmap((void *)seg->u.seg.address, seg->u.seg.size);
2774af242aaSMarcel Moolenaar 		seg0 = seg->u.seg.next;
2784af242aaSMarcel Moolenaar 		obj_free(seg);
2794af242aaSMarcel Moolenaar 	}
2804af242aaSMarcel Moolenaar 	return (0);
2814af242aaSMarcel Moolenaar }
2824af242aaSMarcel Moolenaar 
28322900685SMarcel Moolenaar int
bd_md_create(int tid,u_int flags)28422900685SMarcel Moolenaar bd_md_create(int tid, u_int flags)
28522900685SMarcel Moolenaar {
28622900685SMarcel Moolenaar 	struct proto_ioc_busdma ioc;
28722900685SMarcel Moolenaar 	struct obj *md, *tag;
28822900685SMarcel Moolenaar 
28922900685SMarcel Moolenaar 	tag = obj_lookup(tid, OBJ_TYPE_TAG);
29022900685SMarcel Moolenaar 	if (tag == NULL)
29122900685SMarcel Moolenaar 		return (-1);
29222900685SMarcel Moolenaar 
29322900685SMarcel Moolenaar 	md = obj_alloc(OBJ_TYPE_MD);
29422900685SMarcel Moolenaar 	if (md == NULL)
29522900685SMarcel Moolenaar 		return (-1);
29622900685SMarcel Moolenaar 
29722900685SMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
29822900685SMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_MD_CREATE;
29922900685SMarcel Moolenaar 	ioc.u.md.tag = tag->key;
30022900685SMarcel Moolenaar 	ioc.u.md.flags = flags;
30122900685SMarcel Moolenaar 	if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1) {
30222900685SMarcel Moolenaar 		obj_free(md);
30322900685SMarcel Moolenaar 		return (-1);
30422900685SMarcel Moolenaar 	}
30522900685SMarcel Moolenaar 
30622900685SMarcel Moolenaar 	md->refcnt = 1;
30722900685SMarcel Moolenaar 	md->fd = tag->fd;
30822900685SMarcel Moolenaar 	md->parent = tag;
30922900685SMarcel Moolenaar 	tag->refcnt++;
31022900685SMarcel Moolenaar 	md->key = ioc.result;
31122900685SMarcel Moolenaar 	return (md->oid);
31222900685SMarcel Moolenaar }
31322900685SMarcel Moolenaar 
31422900685SMarcel Moolenaar int
bd_md_destroy(int mdid)31522900685SMarcel Moolenaar bd_md_destroy(int mdid)
31622900685SMarcel Moolenaar {
31722900685SMarcel Moolenaar 	struct proto_ioc_busdma ioc;
31822900685SMarcel Moolenaar 	struct obj *md;
31922900685SMarcel Moolenaar 
32022900685SMarcel Moolenaar 	md = obj_lookup(mdid, OBJ_TYPE_MD);
32122900685SMarcel Moolenaar 	if (md == NULL)
32222900685SMarcel Moolenaar 		return (errno);
32322900685SMarcel Moolenaar 
32422900685SMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
32522900685SMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_MD_DESTROY;
32622900685SMarcel Moolenaar 	ioc.key = md->key;
32722900685SMarcel Moolenaar 	if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
32822900685SMarcel Moolenaar 		return (errno);
32922900685SMarcel Moolenaar 
33022900685SMarcel Moolenaar 	md->parent->refcnt--;
33122900685SMarcel Moolenaar 	obj_free(md);
33222900685SMarcel Moolenaar 	return (0);
33322900685SMarcel Moolenaar }
33422900685SMarcel Moolenaar 
33522900685SMarcel Moolenaar int
bd_md_load(int mdid,void * buf,u_long len,u_int flags)33622900685SMarcel Moolenaar bd_md_load(int mdid, void *buf, u_long len, u_int flags)
33722900685SMarcel Moolenaar {
33822900685SMarcel Moolenaar 	struct proto_ioc_busdma ioc;
33922900685SMarcel Moolenaar 	struct obj *md;
34022900685SMarcel Moolenaar 	int error;
34122900685SMarcel Moolenaar 
34222900685SMarcel Moolenaar 	md = obj_lookup(mdid, OBJ_TYPE_MD);
34322900685SMarcel Moolenaar 	if (md == NULL)
34422900685SMarcel Moolenaar 		return (errno);
34522900685SMarcel Moolenaar 
34622900685SMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
34722900685SMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_MD_LOAD;
34822900685SMarcel Moolenaar 	ioc.key = md->key;
34922900685SMarcel Moolenaar 	ioc.u.md.flags = flags;
35022900685SMarcel Moolenaar 	ioc.u.md.virt_addr = (uintptr_t)buf;
35122900685SMarcel Moolenaar 	ioc.u.md.virt_size = len;
35222900685SMarcel Moolenaar 	if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
35322900685SMarcel Moolenaar 		return (errno);
35422900685SMarcel Moolenaar 
35522900685SMarcel Moolenaar 	error = bd_md_add_seg(md, BUSDMA_MD_VIRT, ioc.u.md.virt_addr, len);
35622900685SMarcel Moolenaar 	error = bd_md_add_seg(md, BUSDMA_MD_PHYS, ioc.u.md.phys_addr, len);
35722900685SMarcel Moolenaar 	error = bd_md_add_seg(md, BUSDMA_MD_BUS, ioc.u.md.bus_addr, len);
35822900685SMarcel Moolenaar 	return (error);
35922900685SMarcel Moolenaar }
36022900685SMarcel Moolenaar 
3616f769b73SMarcel Moolenaar int
bd_md_unload(int mdid)3624af242aaSMarcel Moolenaar bd_md_unload(int mdid)
3634af242aaSMarcel Moolenaar {
3644af242aaSMarcel Moolenaar 	struct proto_ioc_busdma ioc;
3654af242aaSMarcel Moolenaar 	struct obj *md;
3664af242aaSMarcel Moolenaar 	int error;
3674af242aaSMarcel Moolenaar 
3684af242aaSMarcel Moolenaar 	md = obj_lookup(mdid, OBJ_TYPE_MD);
3694af242aaSMarcel Moolenaar 	if (md == NULL)
3704af242aaSMarcel Moolenaar 		return (errno);
3714af242aaSMarcel Moolenaar 
3724af242aaSMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
3734af242aaSMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_MD_UNLOAD;
3744af242aaSMarcel Moolenaar 	ioc.key = md->key;
3754af242aaSMarcel Moolenaar 	if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
3764af242aaSMarcel Moolenaar 		return (errno);
3774af242aaSMarcel Moolenaar 
3784af242aaSMarcel Moolenaar 	bd_md_del_segs(md, BUSDMA_MD_VIRT, 0);
3794af242aaSMarcel Moolenaar 	bd_md_del_segs(md, BUSDMA_MD_PHYS, 0);
3804af242aaSMarcel Moolenaar 	bd_md_del_segs(md, BUSDMA_MD_BUS, 0);
3814af242aaSMarcel Moolenaar 	return (0);
3824af242aaSMarcel Moolenaar }
3834af242aaSMarcel Moolenaar 
3844af242aaSMarcel Moolenaar int
bd_mem_alloc(int tid,u_int flags)3856f769b73SMarcel Moolenaar bd_mem_alloc(int tid, u_int flags)
3866f769b73SMarcel Moolenaar {
3876f769b73SMarcel Moolenaar 	struct proto_ioc_busdma ioc;
3886f769b73SMarcel Moolenaar 	struct obj *md, *tag;
38922900685SMarcel Moolenaar 	uintptr_t addr;
39022900685SMarcel Moolenaar 	int error;
3916f769b73SMarcel Moolenaar 
3926f769b73SMarcel Moolenaar 	tag = obj_lookup(tid, OBJ_TYPE_TAG);
3936f769b73SMarcel Moolenaar 	if (tag == NULL)
3946f769b73SMarcel Moolenaar 		return (-1);
3956f769b73SMarcel Moolenaar 
3966f769b73SMarcel Moolenaar 	md = obj_alloc(OBJ_TYPE_MD);
3976f769b73SMarcel Moolenaar 	if (md == NULL)
3986f769b73SMarcel Moolenaar 		return (-1);
3996f769b73SMarcel Moolenaar 
4006f769b73SMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
4016f769b73SMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_MEM_ALLOC;
40222900685SMarcel Moolenaar 	ioc.u.md.tag = tag->key;
40322900685SMarcel Moolenaar 	ioc.u.md.flags = flags;
4046f769b73SMarcel Moolenaar 	if (ioctl(tag->fd, PROTO_IOC_BUSDMA, &ioc) == -1) {
4056f769b73SMarcel Moolenaar 		obj_free(md);
4066f769b73SMarcel Moolenaar 		return (-1);
4076f769b73SMarcel Moolenaar 	}
4086f769b73SMarcel Moolenaar 
4096f769b73SMarcel Moolenaar 	md->refcnt = 1;
4106f769b73SMarcel Moolenaar 	md->fd = tag->fd;
4116f769b73SMarcel Moolenaar 	md->parent = tag;
4126f769b73SMarcel Moolenaar 	tag->refcnt++;
4136f769b73SMarcel Moolenaar 	md->key = ioc.result;
414cc606478SMarcel Moolenaar 
415d11f2a4cSMarcel Moolenaar 	/* XXX we need to support multiple segments */
41622900685SMarcel Moolenaar 	assert(ioc.u.md.phys_nsegs == 1);
41722900685SMarcel Moolenaar 	assert(ioc.u.md.bus_nsegs == 1);
41822900685SMarcel Moolenaar 	error = bd_md_add_seg(md, BUSDMA_MD_PHYS, ioc.u.md.phys_addr,
41922900685SMarcel Moolenaar 	    tag->u.tag.maxsz);
42022900685SMarcel Moolenaar 	error = bd_md_add_seg(md, BUSDMA_MD_BUS, ioc.u.md.bus_addr,
42122900685SMarcel Moolenaar 	    tag->u.tag.maxsz);
422d11f2a4cSMarcel Moolenaar 
42322900685SMarcel Moolenaar 	addr = (uintptr_t)mmap(NULL, tag->u.tag.maxsz, PROT_READ | PROT_WRITE,
42422900685SMarcel Moolenaar 	    MAP_NOCORE | MAP_SHARED, md->fd, ioc.u.md.phys_addr);
42522900685SMarcel Moolenaar 	if (addr == (uintptr_t)MAP_FAILED)
426d11f2a4cSMarcel Moolenaar 		goto fail;
42722900685SMarcel Moolenaar 	error = bd_md_add_seg(md, BUSDMA_MD_VIRT, addr, tag->u.tag.maxsz);
428cc606478SMarcel Moolenaar 
4296f769b73SMarcel Moolenaar 	return (md->oid);
430d11f2a4cSMarcel Moolenaar 
431d11f2a4cSMarcel Moolenaar  fail:
432d11f2a4cSMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
433d11f2a4cSMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_MEM_FREE;
434d11f2a4cSMarcel Moolenaar 	ioc.key = md->key;
435d11f2a4cSMarcel Moolenaar 	ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc);
436d11f2a4cSMarcel Moolenaar 	md->parent->refcnt--;
437d11f2a4cSMarcel Moolenaar 	obj_free(md);
438d11f2a4cSMarcel Moolenaar 	return (-1);
4396f769b73SMarcel Moolenaar }
4406f769b73SMarcel Moolenaar 
4416f769b73SMarcel Moolenaar int
bd_mem_free(int mdid)4426f769b73SMarcel Moolenaar bd_mem_free(int mdid)
4436f769b73SMarcel Moolenaar {
4446f769b73SMarcel Moolenaar 	struct proto_ioc_busdma ioc;
4454af242aaSMarcel Moolenaar 	struct obj *md;
4466f769b73SMarcel Moolenaar 
4476f769b73SMarcel Moolenaar 	md = obj_lookup(mdid, OBJ_TYPE_MD);
4486f769b73SMarcel Moolenaar 	if (md == NULL)
4496f769b73SMarcel Moolenaar 		return (errno);
4506f769b73SMarcel Moolenaar 
4516f769b73SMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
4526f769b73SMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_MEM_FREE;
4536f769b73SMarcel Moolenaar 	ioc.key = md->key;
4546f769b73SMarcel Moolenaar 	if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
4556f769b73SMarcel Moolenaar 		return (errno);
4566f769b73SMarcel Moolenaar 
4574af242aaSMarcel Moolenaar 	bd_md_del_segs(md, BUSDMA_MD_VIRT, 1);
4584af242aaSMarcel Moolenaar 	bd_md_del_segs(md, BUSDMA_MD_PHYS, 0);
4594af242aaSMarcel Moolenaar 	bd_md_del_segs(md, BUSDMA_MD_BUS, 0);
4606f769b73SMarcel Moolenaar 	md->parent->refcnt--;
4616f769b73SMarcel Moolenaar 	obj_free(md);
4629c2cdb1aSMarcel Moolenaar 	return (0);
4639c2cdb1aSMarcel Moolenaar }
464cc606478SMarcel Moolenaar 
465cc606478SMarcel Moolenaar int
bd_md_first_seg(int mdid,int space)466cc606478SMarcel Moolenaar bd_md_first_seg(int mdid, int space)
467cc606478SMarcel Moolenaar {
468cc606478SMarcel Moolenaar 	struct obj *md, *seg;
469cc606478SMarcel Moolenaar 
470cc606478SMarcel Moolenaar 	md = obj_lookup(mdid, OBJ_TYPE_MD);
471cc606478SMarcel Moolenaar 	if (md == NULL)
472cc606478SMarcel Moolenaar 		return (-1);
473cc606478SMarcel Moolenaar 
474cc606478SMarcel Moolenaar 	if (space != BUSDMA_MD_BUS && space != BUSDMA_MD_PHYS &&
475cc606478SMarcel Moolenaar 	    space != BUSDMA_MD_VIRT) {
476cc606478SMarcel Moolenaar 		errno = EINVAL;
477cc606478SMarcel Moolenaar 		return (-1);
478cc606478SMarcel Moolenaar 	}
479cc606478SMarcel Moolenaar 	seg = md->u.md.seg[space];
480cc606478SMarcel Moolenaar 	if (seg == NULL) {
481cc606478SMarcel Moolenaar 		errno = ENXIO;
482cc606478SMarcel Moolenaar 		return (-1);
483cc606478SMarcel Moolenaar 	}
484cc606478SMarcel Moolenaar 	return (seg->oid);
485cc606478SMarcel Moolenaar }
486cc606478SMarcel Moolenaar 
487cc606478SMarcel Moolenaar int
bd_md_next_seg(int mdid,int sid)488cc606478SMarcel Moolenaar bd_md_next_seg(int mdid, int sid)
489cc606478SMarcel Moolenaar {
490cc606478SMarcel Moolenaar 	struct obj *seg;
491cc606478SMarcel Moolenaar 
492cc606478SMarcel Moolenaar 	seg = obj_lookup(sid, OBJ_TYPE_SEG);
493cc606478SMarcel Moolenaar 	if (seg == NULL)
494cc606478SMarcel Moolenaar 		return (-1);
495cc606478SMarcel Moolenaar 
496cc606478SMarcel Moolenaar 	seg = seg->u.seg.next;
497cc606478SMarcel Moolenaar 	if (seg == NULL) {
498cc606478SMarcel Moolenaar 		errno = ENXIO;
499cc606478SMarcel Moolenaar 		return (-1);
500cc606478SMarcel Moolenaar 	}
501cc606478SMarcel Moolenaar 	return (seg->oid);
502cc606478SMarcel Moolenaar }
503cc606478SMarcel Moolenaar 
504cc606478SMarcel Moolenaar int
bd_seg_get_addr(int sid,u_long * addr_p)505cc606478SMarcel Moolenaar bd_seg_get_addr(int sid, u_long *addr_p)
506cc606478SMarcel Moolenaar {
507cc606478SMarcel Moolenaar 	struct obj *seg;
508cc606478SMarcel Moolenaar 
509cc606478SMarcel Moolenaar 	if (addr_p == NULL)
510cc606478SMarcel Moolenaar 		return (EINVAL);
511cc606478SMarcel Moolenaar 
512cc606478SMarcel Moolenaar 	seg = obj_lookup(sid, OBJ_TYPE_SEG);
513cc606478SMarcel Moolenaar 	if (seg == NULL)
514cc606478SMarcel Moolenaar 		return (errno);
515cc606478SMarcel Moolenaar 
516cc606478SMarcel Moolenaar 	*addr_p = seg->u.seg.address;
517cc606478SMarcel Moolenaar 	return (0);
518cc606478SMarcel Moolenaar }
519cc606478SMarcel Moolenaar 
520cc606478SMarcel Moolenaar int
bd_seg_get_size(int sid,u_long * size_p)521cc606478SMarcel Moolenaar bd_seg_get_size(int sid, u_long *size_p)
522cc606478SMarcel Moolenaar {
523cc606478SMarcel Moolenaar 	struct obj *seg;
524cc606478SMarcel Moolenaar 
525cc606478SMarcel Moolenaar 	if (size_p == NULL)
526cc606478SMarcel Moolenaar 		return (EINVAL);
527cc606478SMarcel Moolenaar 
528cc606478SMarcel Moolenaar 	seg = obj_lookup(sid, OBJ_TYPE_SEG);
529cc606478SMarcel Moolenaar 	if (seg == NULL)
530cc606478SMarcel Moolenaar 		return (errno);
531cc606478SMarcel Moolenaar 
532cc606478SMarcel Moolenaar 	*size_p = seg->u.seg.size;
533cc606478SMarcel Moolenaar 	return (0);
534cc606478SMarcel Moolenaar }
5354af242aaSMarcel Moolenaar 
5364af242aaSMarcel Moolenaar int
bd_sync(int mdid,u_int op,u_long ofs,u_long len)537*015b8583SMarcel Moolenaar bd_sync(int mdid, u_int op, u_long ofs, u_long len)
5384af242aaSMarcel Moolenaar {
5394af242aaSMarcel Moolenaar 	struct proto_ioc_busdma ioc;
5404af242aaSMarcel Moolenaar 	struct obj *md;
5414af242aaSMarcel Moolenaar 
5424af242aaSMarcel Moolenaar 	md = obj_lookup(mdid, OBJ_TYPE_MD);
5434af242aaSMarcel Moolenaar 	if (md == NULL)
5444af242aaSMarcel Moolenaar 		return (errno);
5454af242aaSMarcel Moolenaar 
5464af242aaSMarcel Moolenaar 	memset(&ioc, 0, sizeof(ioc));
5474af242aaSMarcel Moolenaar 	ioc.request = PROTO_IOC_BUSDMA_SYNC;
5484af242aaSMarcel Moolenaar 	ioc.key = md->key;
5494af242aaSMarcel Moolenaar 	ioc.u.sync.op = op;
550*015b8583SMarcel Moolenaar 	ioc.u.sync.base = ofs;
551*015b8583SMarcel Moolenaar 	ioc.u.sync.size = len;
5524af242aaSMarcel Moolenaar 	if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
5534af242aaSMarcel Moolenaar 		return (errno);
5544af242aaSMarcel Moolenaar 
5554af242aaSMarcel Moolenaar 	return (0);
5564af242aaSMarcel Moolenaar }
557