1 #ifndef _IPXE_INTERFACE_H
2 #define _IPXE_INTERFACE_H
3
4 /** @file
5 *
6 * Object interfaces
7 *
8 */
9
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
12 #include <stddef.h>
13 #include <stdarg.h>
14 #include <ipxe/refcnt.h>
15
16 /** An object interface operation */
17 struct interface_operation {
18 /** Operation type */
19 void *type;
20 /** Implementing method */
21 void *func;
22 };
23
24 /**
25 * Define an object interface operation
26 *
27 * @v op_type Operation type
28 * @v object_type Implementing method's expected object type
29 * @v op_func Implementing method
30 * @ret op Object interface operation
31 */
32 #define INTF_OP( op_type, object_type, op_func ) { \
33 .type = op_type, \
34 .func = ( ( ( ( typeof ( op_func ) * ) NULL ) == \
35 ( ( op_type ## _TYPE ( object_type ) * ) NULL ) ) \
36 ? op_func : op_func ), \
37 }
38
39 /**
40 * Define an unused object interface operation
41 *
42 * @v op_type Operation type
43 * @v object_type Implementing method's expected object type
44 * @v op_func Implementing method
45 * @ret op Object interface operation
46 */
47 #define UNUSED_INTF_OP( op_type, object_type, op_func ) { \
48 .type = NULL, \
49 .func = ( ( ( ( typeof ( op_func ) * ) NULL ) == \
50 ( ( op_type ## _TYPE ( object_type ) * ) NULL ) ) \
51 ? NULL : NULL ), \
52 }
53
54 /** An object interface descriptor */
55 struct interface_descriptor {
56 /** Offset of interface within containing object */
57 size_t offset;
58 /** Number of interface operations */
59 unsigned int num_op;
60 /** Object interface operations */
61 struct interface_operation *op;
62 /** Offset to pass-through interface, if present */
63 ssize_t passthru_offset;
64 };
65
66 #define intf_offset( object_type, intf ) \
67 ( ( ( ( typeof ( ( ( object_type * ) NULL )->intf ) * ) NULL ) \
68 == ( ( struct interface * ) NULL ) ) \
69 ? offsetof ( object_type, intf ) \
70 : offsetof ( object_type, intf ) )
71
72 /**
73 * Define an object interface descriptor
74 *
75 * @v object_type Containing object data type
76 * @v intf Interface name (i.e. field within object data type)
77 * @v operations Object interface operations array
78 * @ret desc Object interface descriptor
79 */
80 #define INTF_DESC( object_type, intf, operations ) { \
81 .offset = intf_offset ( object_type, intf ), \
82 .op = operations, \
83 .num_op = ( sizeof ( operations ) / \
84 sizeof ( operations[0] ) ), \
85 .passthru_offset = 0, \
86 }
87
88 /**
89 * Define an object interface descriptor with pass-through interface
90 *
91 * @v object_type Containing object data type
92 * @v intf Interface name (i.e. field within object data type)
93 * @v operations Object interface operations array
94 * @v passthru Pass-through interface name
95 * @ret desc Object interface descriptor
96 */
97 #define INTF_DESC_PASSTHRU( object_type, intf, operations, passthru ) { \
98 .offset = offsetof ( object_type, intf ), \
99 .op = operations, \
100 .num_op = ( sizeof ( operations ) / \
101 sizeof ( operations[0] ) ), \
102 .passthru_offset = ( intf_offset ( object_type, passthru ) - \
103 intf_offset ( object_type, intf ) ), \
104 }
105
106 /**
107 * Define an object interface descriptor for a pure-interface object
108 *
109 * @v operations Object interface operations array
110 * @ret desc Object interface descriptor
111 *
112 * A pure-interface object is an object that consists solely of a
113 * single interface.
114 */
115 #define INTF_DESC_PURE( operations ) { \
116 .offset = 0, \
117 .op = operations, \
118 .num_op = ( sizeof ( operations ) / \
119 sizeof ( operations[0] ) ), \
120 .passthru_offset = 0, \
121 }
122
123 /** An object interface */
124 struct interface {
125 /** Destination object interface
126 *
127 * When the containing object invokes an operation on this
128 * interface, it will be executed by the destination object.
129 *
130 * This pointer may never be NULL. When the interface is
131 * unplugged, it should point to the null interface.
132 */
133 struct interface *dest;
134 /** Reference counter
135 *
136 * If this interface is not part of a reference-counted
137 * object, this field may be NULL.
138 */
139 struct refcnt *refcnt;
140 /** Interface descriptor */
141 struct interface_descriptor *desc;
142 /** Original interface descriptor
143 *
144 * Used by intf_reinit().
145 */
146 struct interface_descriptor *original;
147 };
148
149 extern void intf_plug ( struct interface *intf, struct interface *dest );
150 extern void intf_plug_plug ( struct interface *a, struct interface *b );
151 extern void intf_unplug ( struct interface *intf );
152 extern void intf_nullify ( struct interface *intf );
153 extern struct interface * intf_get ( struct interface *intf );
154 extern void intf_put ( struct interface *intf );
155 extern void * __attribute__ (( pure )) intf_object ( struct interface *intf );
156 extern void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf,
157 void *type,
158 struct interface **dest );
159 extern void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
160 struct interface **dest );
161
162 extern void intf_close ( struct interface *intf, int rc );
163 #define intf_close_TYPE( object_type ) \
164 typeof ( void ( object_type, int rc ) )
165
166 extern void intf_shutdown ( struct interface *intf, int rc );
167 extern void intfs_vshutdown ( va_list intfs, int rc );
168 extern void intfs_shutdown ( int rc, ... ) __attribute__ (( sentinel ));
169 extern void intf_restart ( struct interface *intf, int rc );
170 extern void intfs_vrestart ( va_list intfs, int rc );
171 extern void intfs_restart ( int rc, ... ) __attribute__ (( sentinel ));
172 extern void intf_insert ( struct interface *intf, struct interface *upper,
173 struct interface *lower );
174
175 extern void intf_poke ( struct interface *intf,
176 void ( type ) ( struct interface *intf ) );
177 #define intf_poke_TYPE( object_type ) \
178 typeof ( void ( object_type ) )
179
180 extern struct interface_descriptor null_intf_desc;
181 extern struct interface null_intf;
182
183 /**
184 * Initialise an object interface
185 *
186 * @v intf Object interface
187 * @v desc Object interface descriptor
188 * @v refcnt Containing object reference counter, or NULL
189 */
intf_init(struct interface * intf,struct interface_descriptor * desc,struct refcnt * refcnt)190 static inline void intf_init ( struct interface *intf,
191 struct interface_descriptor *desc,
192 struct refcnt *refcnt ) {
193 intf->dest = &null_intf;
194 intf->refcnt = refcnt;
195 intf->desc = desc;
196 intf->original = desc;
197 }
198
199 /**
200 * Initialise a static object interface
201 *
202 * @v descriptor Object interface descriptor
203 */
204 #define INTF_INIT( descriptor ) { \
205 .dest = &null_intf, \
206 .refcnt = NULL, \
207 .desc = &(descriptor), \
208 .original = &(descriptor), \
209 }
210
211 /**
212 * Get object interface destination and operation method (without pass-through)
213 *
214 * @v intf Object interface
215 * @v type Operation type
216 * @ret dest Destination interface
217 * @ret func Implementing method, or NULL
218 */
219 #define intf_get_dest_op_no_passthru( intf, type, dest ) \
220 ( ( type ## _TYPE ( void * ) * ) \
221 intf_get_dest_op_no_passthru_untyped ( intf, type, dest ) )
222
223 /**
224 * Get object interface destination and operation method
225 *
226 * @v intf Object interface
227 * @v type Operation type
228 * @ret dest Destination interface
229 * @ret func Implementing method, or NULL
230 */
231 #define intf_get_dest_op( intf, type, dest ) \
232 ( ( type ## _TYPE ( void * ) * ) \
233 intf_get_dest_op_untyped ( intf, type, dest ) )
234
235 /**
236 * Find debugging colourisation for an object interface
237 *
238 * @v intf Object interface
239 * @ret col Debugging colourisation
240 *
241 * Use as the first argument to DBGC() or equivalent macro.
242 */
243 #define INTF_COL( intf ) intf_object ( intf )
244
245 /** printf() format string for INTF_DBG() */
246 #define INTF_FMT "%p+%zx"
247
248 /**
249 * printf() arguments for representing an object interface
250 *
251 * @v intf Object interface
252 * @ret args printf() argument list corresponding to INTF_FMT
253 */
254 #define INTF_DBG( intf ) intf_object ( intf ), (intf)->desc->offset
255
256 /** printf() format string for INTF_INTF_DBG() */
257 #define INTF_INTF_FMT INTF_FMT "->" INTF_FMT
258
259 /**
260 * printf() arguments for representing an object interface pair
261 *
262 * @v intf Object interface
263 * @v dest Destination object interface
264 * @ret args printf() argument list corresponding to INTF_INTF_FMT
265 */
266 #define INTF_INTF_DBG( intf, dest ) INTF_DBG ( intf ), INTF_DBG ( dest )
267
268 /**
269 * Reinitialise an object interface
270 *
271 * @v intf Object interface
272 */
intf_reinit(struct interface * intf)273 static inline void intf_reinit ( struct interface *intf ) {
274
275 /* Restore original interface descriptor */
276 intf->desc = intf->original;
277 }
278
279 #endif /* _IPXE_INTERFACE_H */
280