1 /*******************************************************************************
2 * Copyright (C) 2018 Cadence Design Systems, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to use this Software with Cadence processor cores only and
7 * not with any other processors and platforms, subject to
8 * the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included
11 * in all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 ******************************************************************************/
22 
23 /*******************************************************************************
24  * xf-io.h
25  *
26  * Input/output data ports
27  *
28  *******************************************************************************/
29 
30 #ifndef __XF_H
31 #error "xf-io.h mustn't be included directly"
32 #endif
33 
34 /*******************************************************************************
35  * Types definitions
36  ******************************************************************************/
37 
38 /* ...input port with interim buffer */
39 typedef struct xf_input_port
40 {
41     /* ...message queue */
42     xf_msg_queue_t          queue;
43 
44     /* ...internal contiguous buffer to store incoming data */
45     void                   *buffer;
46 
47     /* ...size of internal buffer */
48     u32                     length;
49 
50     /* ...current writing position in the buffer */
51     u32                     filled;
52 
53     /* ...interim pointer to input message buffer */
54     void                   *access;
55 
56     /* ...remaining length of current input message */
57     u32                     remaining;
58 
59     /* ...execution flags */
60     u32                     flags;
61 
62 }   xf_input_port_t;
63 
64 /*******************************************************************************
65  * Input port flags
66  ******************************************************************************/
67 
68 /* ...data enabled */
69 #define XF_INPUT_FLAG_CREATED           (1 << 0)
70 
71 /* ...data enabled */
72 #define XF_INPUT_FLAG_ENABLED           (1 << 1)
73 
74 /* ...end-of-stream condition */
75 #define XF_INPUT_FLAG_EOS               (1 << 2)
76 
77 /* ...stream completed */
78 #define XF_INPUT_FLAG_DONE              (1 << 3)
79 
80 /* ...stream purging sequence */
81 #define XF_INPUT_FLAG_PURGING           (1 << 4)
82 
83 /* ...base input port flags mask */
84 #define __XF_INPUT_FLAGS(flags)         ((flags) & ((1 << 5) - 1))
85 
86 /* ...custom input port flag */
87 #define __XF_INPUT_FLAG(f)              ((f) << 5)
88 
89 /*******************************************************************************
90  * Helpers
91  ******************************************************************************/
92 
93 /* ...test if input port is created */
xf_input_port_created(xf_input_port_t * port)94 static inline int xf_input_port_created(xf_input_port_t *port)
95 {
96     return (port->flags & XF_INPUT_FLAG_CREATED);
97 }
98 
99 /* ...check if input port is ready (has pending message) */
xf_input_port_ready(xf_input_port_t * port)100 static inline int xf_input_port_ready(xf_input_port_t *port)
101 {
102     return (xf_msg_queue_head(&port->queue) != NULL);
103 }
104 
105 /* ...test if input port entered end-of-stream condition */
xf_input_port_done(xf_input_port_t * port)106 static inline int xf_input_port_done(xf_input_port_t *port)
107 {
108     return (port->flags & XF_INPUT_FLAG_DONE);
109 }
110 
111 /* ...check if port is in bypass mode */
xf_input_port_bypass(xf_input_port_t * port)112 static inline int xf_input_port_bypass(xf_input_port_t *port)
113 {
114     return port->buffer == NULL;
115 }
116 
117 /* ...bypass port only: check if there is a data available */
xf_input_port_data(xf_input_port_t * port)118 static inline void * xf_input_port_data(xf_input_port_t *port)
119 {
120     return port->access;
121 }
122 
123 /* ...bypass port only: get remaining length of current message */
xf_input_port_length(xf_input_port_t * port)124 static inline u32 xf_input_port_length(xf_input_port_t *port)
125 {
126     return port->remaining;
127 }
128 
129 /* ...non-bypass port only: get current fill level */
xf_input_port_level(xf_input_port_t * port)130 static inline u32 xf_input_port_level(xf_input_port_t *port)
131 {
132     return port->filled;
133 }
134 
135 /*******************************************************************************
136  * Output port data
137  ******************************************************************************/
138 
139 typedef struct xf_output_port
140 {
141     /* ...pending message queue */
142     xf_msg_queue_t          queue;
143 
144     /* ...message pool */
145     xf_msg_pool_t           pool;
146 
147     /* ...saved port unrouting message */
148     xf_message_t           *unroute;
149 
150     /* ...length of output buffer */
151     u32                     length;
152 
153     /* ...output port flags */
154     u32                     flags;
155 
156 }   xf_output_port_t;
157 
158 /*******************************************************************************
159  * Output port flags
160  ******************************************************************************/
161 
162 /* ...port is created */
163 #define XF_OUTPUT_FLAG_CREATED          (1 << 0)
164 
165 /* ...port is routed */
166 #define XF_OUTPUT_FLAG_ROUTED           (1 << 1)
167 
168 /* ...data enabled */
169 #define XF_OUTPUT_FLAG_ENABLED          (1 << 2)
170 
171 /* ...stream completed */
172 #define XF_OUTPUT_FLAG_DONE             (1 << 3)
173 
174 /* ...flushing sequence is on-going */
175 #define XF_OUTPUT_FLAG_FLUSHING         (1 << 4)
176 
177 /* ...port is idle - no outstanding messages */
178 #define XF_OUTPUT_FLAG_IDLE             (1 << 5)
179 
180 /* ...port is being unrouted */
181 #define XF_OUTPUT_FLAG_UNROUTING        (1 << 6)
182 
183 /* ...base output port flags accessor */
184 #define __XF_OUTPUT_FLAGS(flags)        ((flags) & ((1 << 7) - 1))
185 
186 /* ...custom output port flag */
187 #define __XF_OUTPUT_FLAG(f)             ((f) << 7)
188 
189 /*******************************************************************************
190  * Helpers
191  ******************************************************************************/
192 
193 /* ...test if input port is created */
xf_output_port_created(xf_output_port_t * port)194 static inline int xf_output_port_created(xf_output_port_t *port)
195 {
196     return (port->flags & XF_OUTPUT_FLAG_CREATED);
197 }
198 
199 /* ...check if port is routed */
xf_output_port_routed(xf_output_port_t * port)200 static inline int xf_output_port_routed(xf_output_port_t *port)
201 {
202     return ((port->flags & XF_OUTPUT_FLAG_ROUTED) != 0);
203 }
204 
205 /* ...check if port unrouting sequence is ongoing */
xf_output_port_unrouting(xf_output_port_t * port)206 static inline int xf_output_port_unrouting(xf_output_port_t *port)
207 {
208     return ((port->flags & XF_OUTPUT_FLAG_UNROUTING) != 0);
209 }
210 
211 /* ...check if port is idle (owns all data buffers) */
xf_output_port_idle(xf_output_port_t * port)212 static inline int xf_output_port_idle(xf_output_port_t *port)
213 {
214     return ((port->flags & XF_OUTPUT_FLAG_IDLE) != 0);
215 }
216 
217 /* ...check if port is ready (has output buffers - better use flags - tbd) */
xf_output_port_ready(xf_output_port_t * port)218 static inline int xf_output_port_ready(xf_output_port_t *port)
219 {
220     return (xf_msg_queue_head(&port->queue) != NULL && !xf_output_port_unrouting(port));
221 }
222 
223 /* ...output port flow-control message accessor */
xf_output_port_control_msg(xf_output_port_t * port)224 static inline xf_message_t * xf_output_port_control_msg(xf_output_port_t *port)
225 {
226     return xf_msg_pool_item(&port->pool, 0);
227 }
228 
229 /*******************************************************************************
230  * Input port API
231  ******************************************************************************/
232 
233 /* ...initialize input port structure */
234 extern int  xf_input_port_init(xf_input_port_t *port, u32 size, u32 align, u32 core);
235 
236 /* ...put message into input port queue */
237 extern int  xf_input_port_put(xf_input_port_t *port, xf_message_t *m);
238 
239 /* ...fill-in required amount of data into input port buffer */
240 extern int  xf_input_port_fill(xf_input_port_t *port);
241 
242 /* ...pad input buffer with given value */
243 extern void xf_input_port_pad(xf_input_port_t *port, u8 pad);
244 
245 /* ...consume bytes from input buffer */
246 extern void xf_input_port_consume(xf_input_port_t *port, u32 n);
247 
248 /* ...purge input port queue */
249 extern void xf_input_port_purge(xf_input_port_t *port);
250 
251 /* ...save flow-control message for propagated input port purging sequence */
252 extern void xf_input_port_control_save(xf_input_port_t *port, xf_message_t *m);
253 
254 /* ...complete input port purging sequence */
255 extern void xf_input_port_purge_done(xf_input_port_t *port);
256 
257 /* ...destroy input port data */
258 extern void xf_input_port_destroy(xf_input_port_t *port, u32 core);
259 
260 /*******************************************************************************
261  * Output port API
262  ******************************************************************************/
263 
264 /* ...initialize output port structure */
265 extern int  xf_output_port_init(xf_output_port_t *port, u32 size);
266 
267 /* ...put next message to the output port */
268 extern int  xf_output_port_put(xf_output_port_t *port, xf_message_t *m);
269 
270 /* ...get data buffer of output message */
271 extern void * xf_output_port_data(xf_output_port_t *port);
272 
273 /* ...route output port */
274 extern int xf_output_port_route(xf_output_port_t *port, u32 id, u32 n, u32 length, u32 align);
275 
276 /* ...unroute output port */
277 extern void xf_output_port_unroute(xf_output_port_t *port);
278 
279 /* ...start output port unrouting sequence */
280 extern void xf_output_port_unroute_start(xf_output_port_t *port, xf_message_t *m);
281 
282 /* ...complete port unrouting sequence */
283 extern void xf_output_port_unroute_done(xf_output_port_t *port);
284 
285 /* ...produce output message marking amount of bytes produced */
286 extern int  xf_output_port_produce(xf_output_port_t *port, u32 n);
287 
288 /* ...purge output port */
289 extern void xf_output_port_purge(xf_output_port_t *port);
290 
291 /* ...flush output port and return non-zero result if sequence is over */
292 extern int xf_output_port_flush(xf_output_port_t *port, u32 opcode);
293 
294 /* ...complete flushing sequence */
295 extern void xf_output_port_flush_done(xf_output_port_t *port);
296 
297 /* ...destroy output port data */
298 extern void xf_output_port_destroy(xf_output_port_t *port, u32 core);
299