1 /*
2 * Copyright (c) 2013, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33 /** ============================================================================
34 * @file VirtQueue.xdc
35 *
36 * @brief Virtio Queue interface for BIOS
37 *
38 * Differences between BIOS version and Linux kernel (include/linux/virtio.h):
39 * - Renamed module from virtio.h to VirtQueue.h to match the API prefixes;
40 * - BIOS (XDC) types and CamelCasing used;
41 * - virtio_device concept removed (i.e, assumes no containing device);
42 * - removed scatterlist;
43 * - VirtQueues are created statically here, so just added a VirtQueue_init()
44 * fxn to take the place of the Virtio vring_new_virtqueue() API;
45 * - The notify function is implicit in the implementation, and not provided
46 * by the client, as it is in Linux virtio.
47 * - Broke into APIs to add/get used and avail buffers, as the API is
48 * assymmetric.
49 *
50 * Usage:
51 * This IPC only works between one processor designated as the Host (Linux)
52 * and one or more Slave processors (BIOS).
53 *
54 * For any Host/Slave pair, there are 2 VirtQueues (aka Vrings);
55 * Only the Host adds new buffers to the avail list of a vring;
56 * Available buffers can be empty or full, depending on direction;
57 * Used buffer means "processed" (emptied or filled);
58 *
59 * Host:
60 * - To send buffer to the slave processor:
61 * add_avail_buf(slave_virtqueue);
62 * kick(slave_virtqueue);
63 * get_used_buf(slave_virtqueue);
64 * - To receive buffer from slave processor:
65 * add_avail_buf(host_virtqueue);
66 * kick(host_virtqueue);
67 * get_used_buf(host_virtqueue);
68 *
69 * Slave:
70 * - To send buffer to the host:
71 * get_avail_buf(host_virtqueue);
72 * add_used_buf(host_virtqueue);
73 * kick(host_virtqueue);
74 * - To receive buffer from the host:
75 * get_avail_buf(slave_virtqueue);
76 * add_used_buf(slave_virtqueue);
77 * kick(slave_virtqueue);
78 *
79 * All VirtQueue operations can be called in any context.
80 *
81 * The virtio header should be included in an application as follows:
82 * @code
83 * #include <ti/ipc/rpmsg/VirtQueue.h>
84 * @endcode
85 *
86 * ============================================================================
87 */
89 import ti.sysbios.knl.Swi;
90 import ti.sdo.utils.MultiProc;
92 /*!
93 * ======== VirtQueue ========
94 *
95 */
98 module VirtQueue
99 {
100 // -------- Module Constants --------
102 // -------- Module Types --------
105 /*!
106 * ======== BasicView ========
107 * @_nodoc
108 */
109 metaonly struct BasicView {
111 };
113 /*!
114 * ======== ModuleView ========
115 * @_nodoc
116 */
117 metaonly struct ModuleView {
119 };
121 /*!
122 * ======== rovViewInfo ========
123 * @_nodoc
124 */
125 /* @Facet
126 metaonly config ViewInfo.Instance rovViewInfo =
127 xdc.rov.ViewInfo.create({
128 viewMap: [
129 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic', structName: 'BasicView'}],
130 ['Module', {type: ViewInfo.MODULE, viewInitFxn: 'viewInitModule', structName: 'ModuleView'}]
131 ]
132 });
133 */
134 // -------- Module Proxies --------
136 // -------- Module Parameters --------
138 /* Predefined device addresses */
139 config UInt32 CORE0_MEM_VRING0 = 0xA0000000;
140 config UInt32 CORE0_MEM_VRING1 = 0xA0004000;
141 config UInt32 VRING_OFFSET = 0x00080000;
143 /*
144 * Sizes of the virtqueues (expressed in number of buffers supported,
145 * and must be power of two)
146 */
147 config UInt VQ0_SIZE = 256;
148 config UInt VQ1_SIZE = 256;
150 /* See VirtQueue.c also for other constants: */
151 config UInt RP_MSG_NUM_BUFS = VQ0_SIZE; /* must be power of two */
152 config UInt RP_MSG_BUF_SIZE = 512;
155 config UInt PAGE_SIZE = 4096;
157 /*
158 * The alignment to use between consumer and producer parts of vring.
159 * Note: this is part of the "wire" protocol. If you change this, you need
160 * to update your BIOS image as well
161 */
162 config UInt RP_MSG_VRING_ALIGN = 4096;
164 /*!
165 * ======== startup ========
166 *
167 * Plug interrupts, and if host, initialize vring memory and send
168 * startup sequence events to slave.
169 */
170 Void startup(UInt16 remoteProcId, Bool isHost);
172 instance:
174 /*!
175 * @brief Initialize at runtime the VirtQueue
176 *
177 * Maps to Instance_init function
178 *
179 * @param[in] remoteProcId Remote processor ID associated with this VirtQueue.
180 *
181 * @Returns Returns a handle to a new initialized VirtQueue.
182 */
183 @DirectCall
184 create(UInt16 remoteProcId);
186 /*!
187 * @brief Notify other processor of new buffers in the queue.
188 *
189 * After one or more add_buf calls, invoke this to kick the other side.
190 *
191 * @param[in] vq the VirtQueue.
192 *
193 * @sa VirtQueue_addBuf
194 */
195 @DirectCall
196 Void kick();
198 /*!
199 * @brief VirtQueue instance returns slave status
200 *
201 * Returns if this VirtQueue instance belongs to a slave
202 *
203 * @param[in] vq the VirtQueue.
204 *
205 */
206 @DirectCall
207 Bool isSlave();
209 /*!
210 * @brief VirtQueue instance returns host status
211 *
212 * Returns if this VirtQueue instance belongs to a host
213 *
214 * @param[in] vq the VirtQueue.
215 *
216 */
217 @DirectCall
218 Bool isHost();
220 /*!
221 * @brief VirtQueue instance returns queue ID
222 *
223 * Returns VirtQueue instance's queue ID.
224 *
225 * @param[in] vq the VirtQueue.
226 *
227 */
228 @DirectCall
229 UInt16 getId();
231 /*!
232 * @brief VirtQueue instance returns Swi handle
233 *
234 * Returns VirtQueue instance Swi handle
235 *
236 * @param[in] vq the VirtQueue.
237 *
238 */
239 @DirectCall
240 Swi.Handle getSwiHandle();
242 /*
243 * ========================================================================
244 * Host Only Functions:
245 * ========================================================================
246 */
248 /*!
249 * @brief Add available buffer to virtqueue's available buffer list.
250 * Only used by Host.
251 *
252 * @param[in] vq the VirtQueue.
253 * @param[in] buf the buffer to be processed by the slave.
254 *
255 * @return Remaining capacity of queue or a negative error.
256 *
257 * @sa VirtQueue_getUsedBuf
258 */
259 @DirectCall
260 Int addAvailBuf(Void *buf);
262 /*!
263 * @brief Get the next used buffer.
264 * Only used by Host.
265 *
266 * @param[in] vq the VirtQueue.
267 *
268 * @return Returns NULL or the processed buffer.
269 *
270 * @sa VirtQueue_addAvailBuf
271 */
272 @DirectCall
273 Void *getUsedBuf();
275 /*
276 * ========================================================================
277 * Slave Only Functions:
278 * ========================================================================
279 */
281 /*!
282 * @brief Get the next available buffer.
283 * Only used by Slave.
284 *
285 * @param[in] vq the VirtQueue.
286 * @param[out] buf Pointer to location of available buffer;
287 *
288 * @return Returns a token used to identify the available buffer, to be
289 * passed back into VirtQueue_addUsedBuf();
290 * token is negative if failure to find an available buffer.
291 *
292 * @sa VirtQueue_addUsedBuf
293 */
294 @DirectCall
295 Int16 getAvailBuf(Void **buf);
297 /*!
298 * @brief Add used buffer to virtqueue's used buffer list.
299 * Only used by Slave.
300 *
301 * @param[in] vq the VirtQueue.
302 * @param[in] token token of the buffer to be added to vring used list.
303 *
304 * @return Remaining capacity of queue or a negative error.
305 *
306 * @sa VirtQueue_getAvailBuf
307 */
308 @DirectCall
309 Int addUsedBuf(Int16 head);
311 // -------- Handle Parameters --------
313 config Bool host = false;
315 config Fxn callback = null;
317 config Swi.Handle swiHandle = null;
319 config UInt intVectorId = ~1u;
321 // -------- Handle Functions --------
323 internal: /* not for client use */
325 void init();
327 /*!
328 * ======== hostIsr ========
329 */
330 Void hostIsr(UArg msg);
332 /*!
333 * ======== slaveIsr ========
334 */
335 Void slaveIsr(UArg msg);
337 /*!
338 * ======== Module_State ========
339 * @_nodoc
340 */
341 struct Module_State
342 {
343 UInt16 numQueues;
344 UInt16 hostSlaveSynced;
345 UInt16 virtQueueInitialized;
346 UInt32 *queueRegistry;
347 Ptr traceBufPtr;
348 }
350 /*!
351 * ======== Instance_State ========
352 * @_nodoc
353 */
354 struct Instance_State {
355 Bool hostSlaveSynced;
356 UInt16 id;
357 Fxn callback;
358 Swi.Handle swiHandle;
359 Void *vringPtr;
360 UInt16 num_free;
361 UInt16 last_avail_idx;
362 UInt16 last_used_idx;
363 UInt16 procId;
364 };
365 }