xref: /netbsd-src/sys/rump/net/lib/libshmif/shmif_busops.c (revision 50fa67ff5f493fc9711b7a255ad8ff6e4be7c0fe)
1 /*	$NetBSD: shmif_busops.c,v 1.4 2010/08/15 18:55:03 pooka Exp $	*/
2 
3 /*
4  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
5  *
6  * Development of this software was supported by The Nokia Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: shmif_busops.c,v 1.4 2010/08/15 18:55:03 pooka Exp $");
32 
33 #include <sys/param.h>
34 #include <sys/atomic.h>
35 
36 #include "shmifvar.h"
37 
38 #ifndef _KERNEL
39 #include <assert.h>
40 #define KASSERT(a) assert(a)
41 #else
42 #include <rump/rumpuser.h>
43 #endif
44 
45 uint32_t
46 shmif_advance(uint32_t oldoff, uint32_t delta)
47 {
48 	uint32_t newoff;
49 
50 	newoff = oldoff + delta;
51 	if (newoff >= BUSMEM_DATASIZE)
52 		newoff -= (BUSMEM_DATASIZE);
53 	return newoff;
54 
55 }
56 
57 uint32_t
58 shmif_busread(struct shmif_mem *busmem, void *dest, uint32_t off, size_t len,
59 	bool *wrap)
60 {
61 	size_t chunk;
62 
63 	KASSERT(len < (BUSMEM_DATASIZE) && off <= BUSMEM_DATASIZE);
64 	chunk = MIN(len, BUSMEM_DATASIZE - off);
65 	memcpy(dest, busmem->shm_data + off, chunk);
66 	len -= chunk;
67 
68 	if (len == 0)
69 		return off + chunk;
70 
71 	/* else, wraps around */
72 	off = 0;
73 	*wrap = true;
74 
75 	/* finish reading */
76 	memcpy((uint8_t *)dest + chunk, busmem->shm_data + off, len);
77 	return off + len;
78 }
79 
80 void
81 shmif_advancefirst(struct shmif_mem *busmem, uint32_t off, size_t len)
82 {
83 
84 	while (off <= busmem->shm_first + sizeof(struct shmif_pkthdr)
85 	    && off+len > busmem->shm_first) {
86 		DPRINTF(("advancefirst: old offset %d, ", busmem->shm_first));
87 		busmem->shm_first = shmif_nextpktoff(busmem, busmem->shm_first);
88 		DPRINTF(("new offset: %d\n", busmem->shm_first));
89 	}
90 }
91 
92 uint32_t
93 shmif_buswrite(struct shmif_mem *busmem, uint32_t off, void *data, size_t len,
94 	bool *wrap)
95 {
96 	size_t chunk;
97 
98 	KASSERT(len < (BUSMEM_DATASIZE) && off <= BUSMEM_DATASIZE);
99 
100 	chunk = MIN(len, BUSMEM_DATASIZE - off);
101 	len -= chunk;
102 
103 	shmif_advancefirst(busmem, off, chunk + (len ? 1 : 0));
104 
105 	memcpy(busmem->shm_data + off, data, chunk);
106 
107 	DPRINTF(("buswrite: wrote %d bytes to %d", chunk, off));
108 
109 	if (len == 0) {
110 		DPRINTF(("\n"));
111 		return off + chunk;
112 	}
113 
114 	DPRINTF((", wrapped bytes %d to 0\n", len));
115 
116 	/* else, wraps around */
117 	off = 0;
118 	*wrap = true;
119 
120 	shmif_advancefirst(busmem, off, len);
121 
122 	/* finish writing */
123 	memcpy(busmem->shm_data + off, (uint8_t *)data + chunk, len);
124 	return off + len;
125 }
126 
127 uint32_t
128 shmif_nextpktoff(struct shmif_mem *busmem, uint32_t oldoff)
129 {
130 	struct shmif_pkthdr sp;
131 	bool dummy;
132 
133 	shmif_busread(busmem, &sp, oldoff, sizeof(sp), &dummy);
134 	KASSERT(sp.sp_len < BUSMEM_DATASIZE);
135 
136 	return shmif_advance(oldoff, sizeof(sp) + sp.sp_len);
137 }
138