[process] Include process name in debug messages
[ipxe.git] / src / core / interface.c
1 /*
2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <string.h>
27 #include <ipxe/interface.h>
28
29 /** @file
30 *
31 * Object interfaces
32 *
33 */
34
35 /*****************************************************************************
36 *
37 * The null interface
38 *
39 */
40
41 /**
42 * Close null interface
43 *
44 * @v intf Null interface
45 * @v rc Reason for close
46 */
47 static void null_intf_close ( struct interface *intf __unused,
48 int rc __unused ) {
49
50 /* Do nothing. In particular, do not call intf_restart(),
51 * since that would result in an infinite loop.
52 */
53 }
54
55 /** Null interface operations */
56 static struct interface_operation null_intf_op[] = {
57 INTF_OP ( intf_close, struct interface *, null_intf_close ),
58 };
59
60 /** Null interface descriptor */
61 struct interface_descriptor null_intf_desc =
62 INTF_DESC_PURE ( null_intf_op );
63
64 /** The null interface */
65 struct interface null_intf = INTF_INIT ( null_intf_desc );
66
67 /*****************************************************************************
68 *
69 * Object interface plumbing
70 *
71 */
72
73 /**
74 * Plug an object interface into a new destination object interface
75 *
76 * @v intf Object interface
77 * @v dest New destination object interface
78 *
79 * The reference to the existing destination interface is dropped, a
80 * reference to the new destination interface is obtained, and the
81 * interface is updated to point to the new destination interface.
82 */
83 void intf_plug ( struct interface *intf, struct interface *dest ) {
84 DBGC ( INTF_COL ( intf ),
85 "INTF " INTF_INTF_FMT " replug to " INTF_FMT "\n",
86 INTF_INTF_DBG ( intf, intf->dest ), INTF_DBG ( dest ) );
87 intf_get ( dest );
88 intf_put ( intf->dest );
89 intf->dest = dest;
90 }
91
92 /**
93 * Plug two object interfaces together
94 *
95 * @v a Object interface A
96 * @v b Object interface B
97 *
98 * Plugs interface A into interface B, and interface B into interface
99 * A. (The basic plug() function is unidirectional; this function is
100 * merely a shorthand for two calls to plug(), hence the name.)
101 */
102 void intf_plug_plug ( struct interface *a, struct interface *b ) {
103 intf_plug ( a, b );
104 intf_plug ( b, a );
105 }
106
107 /**
108 * Unplug an object interface
109 *
110 * @v intf Object interface
111 */
112 void intf_unplug ( struct interface *intf ) {
113 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " unplug\n",
114 INTF_INTF_DBG ( intf, intf->dest ) );
115 intf_put ( intf->dest );
116 intf->dest = &null_intf;
117 }
118
119 /**
120 * Ignore all further operations on an object interface
121 *
122 * @v intf Object interface
123 */
124 void intf_nullify ( struct interface *intf ) {
125 intf->desc = &null_intf_desc;
126 }
127
128 /**
129 * Increment reference count on an object interface
130 *
131 * @v intf Object interface
132 * @ret intf Object interface
133 */
134 struct interface * intf_get ( struct interface *intf ) {
135 ref_get ( intf->refcnt );
136 return intf;
137 }
138
139 /**
140 * Decrement reference count on an object interface
141 *
142 * @v intf Object interface
143 */
144 void intf_put ( struct interface *intf ) {
145 ref_put ( intf->refcnt );
146 }
147
148 /**
149 * Get pointer to object containing object interface
150 *
151 * @v intf Object interface
152 * @ret object Containing object
153 */
154 void * intf_object ( struct interface *intf ) {
155 return ( ( ( void * ) intf ) - intf->desc->offset );
156 }
157
158 /**
159 * Get pass-through interface
160 *
161 * @v intf Object interface
162 * @ret passthru Pass-through interface, or NULL
163 */
164 static struct interface * intf_get_passthru ( struct interface *intf ) {
165 struct interface_descriptor *desc = intf->desc;
166
167 if ( desc->passthru_offset ) {
168 return ( ( ( void * ) intf ) + desc->passthru_offset );
169 } else {
170 return NULL;
171 }
172 }
173
174 /**
175 * Get object interface destination and operation method (without pass-through)
176 *
177 * @v intf Object interface
178 * @v type Operation type
179 * @ret dest Destination interface
180 * @ret func Implementing method, or NULL
181 */
182 void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf,
183 void *type,
184 struct interface **dest ) {
185 struct interface_descriptor *desc;
186 struct interface_operation *op;
187 unsigned int i;
188
189 *dest = intf_get ( intf->dest );
190 desc = (*dest)->desc;
191 for ( i = desc->num_op, op = desc->op ; i ; i--, op++ ) {
192 if ( op->type == type )
193 return op->func;
194 }
195
196 return NULL;
197 }
198
199 /**
200 * Get object interface destination and operation method
201 *
202 * @v intf Object interface
203 * @v type Operation type
204 * @ret dest Destination interface
205 * @ret func Implementing method, or NULL
206 */
207 void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
208 struct interface **dest ) {
209 void *func;
210
211 while ( 1 ) {
212
213 /* Search for an implementing method provided by the
214 * current destination interface.
215 */
216 func = intf_get_dest_op_no_passthru_untyped( intf, type, dest );
217 if ( func )
218 return func;
219
220 /* Pass through to the underlying interface, if applicable */
221 if ( ! ( intf = intf_get_passthru ( *dest ) ) )
222 return NULL;
223 intf_put ( *dest );
224 }
225 }
226
227 /*****************************************************************************
228 *
229 * Generic interface operations
230 *
231 */
232
233 /**
234 * Close an object interface
235 *
236 * @v intf Object interface
237 * @v rc Reason for close
238 *
239 * Note that this function merely informs the destination object that
240 * the interface is about to be closed; it doesn't actually disconnect
241 * the interface. In most cases, you probably want to use
242 * intf_shutdown() or intf_restart() instead.
243 */
244 void intf_close ( struct interface *intf, int rc ) {
245 struct interface *dest;
246 intf_close_TYPE ( void * ) *op =
247 intf_get_dest_op ( intf, intf_close, &dest );
248 void *object = intf_object ( dest );
249
250 DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " close (%s)\n",
251 INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
252
253 if ( op ) {
254 op ( object, rc );
255 } else {
256 /* Default is to restart the interface */
257 intf_restart ( dest, rc );
258 }
259
260 intf_put ( dest );
261 }
262
263 /**
264 * Shut down an object interface
265 *
266 * @v intf Object interface
267 * @v rc Reason for close
268 *
269 * Blocks further operations from being received via the interface,
270 * executes a close operation on the destination interface, and
271 * unplugs the interface.
272 */
273 void intf_shutdown ( struct interface *intf, int rc ) {
274 struct interface tmp;
275
276 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " shutting down (%s)\n",
277 INTF_DBG ( intf ), strerror ( rc ) );
278
279 /* Block further operations */
280 intf_nullify ( intf );
281
282 /* Transfer destination to temporary interface */
283 tmp.dest = intf->dest;
284 intf->dest = &null_intf;
285
286 /* Notify destination of close via temporary interface */
287 intf_close ( &tmp, rc );
288
289 /* Unplug temporary interface */
290 intf_unplug ( &tmp );
291 }
292
293 /**
294 * Shut down multiple object interfaces
295 *
296 * @v intfs Object interfaces
297 * @v rc Reason for close
298 */
299 void intfs_vshutdown ( va_list intfs, int rc ) {
300 struct interface *intf;
301 va_list tmp;
302
303 /* Nullify all interfaces to avoid potential loops */
304 va_copy ( tmp, intfs );
305 while ( ( intf = va_arg ( tmp, struct interface * ) ) )
306 intf_nullify ( intf );
307 va_end ( tmp );
308
309 /* Shut down all interfaces */
310 while ( ( intf = va_arg ( intfs, struct interface * ) ) )
311 intf_shutdown ( intf, rc );
312 }
313
314 /**
315 * Shut down multiple object interfaces
316 *
317 * @v rc Reason for close
318 * @v ... Object interfaces
319 */
320 void intfs_shutdown ( int rc, ... ) {
321 va_list intfs;
322
323 va_start ( intfs, rc );
324 intfs_vshutdown ( intfs, rc );
325 va_end ( intfs );
326 }
327
328 /**
329 * Shut down and restart an object interface
330 *
331 * @v intf Object interface
332 * @v rc Reason for close
333 *
334 * Shuts down the interface, then unblocks operations that were
335 * blocked during shutdown.
336 */
337 void intf_restart ( struct interface *intf, int rc ) {
338
339 /* Shut down the interface */
340 intf_shutdown ( intf, rc );
341
342 DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " restarting\n",
343 INTF_DBG ( intf ) );
344
345 /* Restore the interface descriptor. Must be done after
346 * shutdown (rather than inhibiting intf_shutdown() from
347 * nullifying the descriptor) in order to avoid a potential
348 * infinite loop as the intf_close() operations on each side
349 * of the link call each other recursively.
350 */
351 intf_reinit ( intf );
352 }
353
354 /**
355 * Shut down and restart multiple object interfaces
356 *
357 * @v intfs Object interfaces
358 * @v rc Reason for close
359 */
360 void intfs_vrestart ( va_list intfs, int rc ) {
361 struct interface *intf;
362 va_list tmp;
363
364 /* Shut down all interfaces */
365 va_copy ( tmp, intfs );
366 intfs_vshutdown ( tmp, rc );
367 va_end ( tmp );
368
369 /* Reinitialise all interfaces */
370 while ( ( intf = va_arg ( intfs, struct interface * ) ) )
371 intf_reinit ( intf );
372 }
373
374 /**
375 * Shut down and restart multiple object interfaces
376 *
377 * @v rc Reason for close
378 * @v ... Object interfaces
379 */
380 void intfs_restart ( int rc, ... ) {
381 va_list intfs;
382
383 va_start ( intfs, rc );
384 intfs_vrestart ( intfs, rc );
385 va_end ( intfs );
386 }
387
388 /**
389 * Poke an object interface
390 *
391 * @v intf Object interface
392 * @v type Operation type
393 *
394 * This is a helper function to implement methods which take no
395 * parameters and return nothing.
396 */
397 void intf_poke ( struct interface *intf,
398 void ( type ) ( struct interface *intf ) ) {
399 struct interface *dest;
400 intf_poke_TYPE ( void * ) *op =
401 intf_get_dest_op_untyped ( intf, type, &dest );
402 void *object = intf_object ( dest );
403
404 if ( op ) {
405 op ( object );
406 } else {
407 /* Default is to do nothing */
408 }
409
410 intf_put ( dest );
411 }