iPXE
interface.c
Go to the documentation of this file.
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[] = {
58 };
59 
60 /** Null interface descriptor */
63 
64 /** The null interface */
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  */
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  */
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 }
static struct interface * intf_get_passthru(struct interface *intf)
Get pass-through interface.
Definition: interface.c:164
struct interface * intf_get(struct interface *intf)
Increment reference count on an object interface.
Definition: interface.c:134
An object interface operation.
Definition: interface.h:17
void * intf_get_dest_op_untyped(struct interface *intf, void *type, struct interface **dest)
Get object interface destination and operation method.
Definition: interface.c:207
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:244
#define INTF_INTF_FMT
printf() format string for INTF_INTF_DBG()
Definition: interface.h:240
struct interface null_intf
The null interface.
Definition: interface.c:65
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:337
#define va_end(ap)
Definition: stdarg.h:9
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:273
#define INTF_DBG(intf)
printf() arguments for representing an object interface
Definition: interface.h:237
struct interface_descriptor null_intf_desc
Null interface descriptor.
Definition: interface.c:61
#define INTF_INTF_DBG(intf, dest)
printf() arguments for representing an object interface pair
Definition: interface.h:249
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:187
uint8_t type
Type.
Definition: ena.h:16
#define INTF_COL(intf)
Find debugging colourisation for an object interface.
Definition: interface.h:226
#define DBGC(...)
Definition: compiler.h:505
static void null_intf_close(struct interface *intf __unused, int rc __unused)
Close null interface.
Definition: interface.c:47
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:102
#define INTF_DESC_PURE(operations)
Define an object interface descriptor for a pure-interface object.
Definition: interface.h:100
#define va_copy(dest, src)
Definition: stdarg.h:10
void intfs_shutdown(int rc,...)
Shut down multiple object interfaces.
Definition: interface.c:320
void intfs_restart(int rc,...)
Shut down and restart multiple object interfaces.
Definition: interface.c:380
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:154
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void * func
Implementing method.
Definition: interface.h:21
unsigned int num_op
Number of interface operations.
Definition: interface.h:44
struct interface * dest
Destination object interface.
Definition: interface.h:118
struct interface_operation * op
Object interface operations.
Definition: interface.h:46
#define va_arg(ap, type)
Definition: stdarg.h:8
An object interface.
Definition: interface.h:109
ssize_t passthru_offset
Offset to pass-through interface, if present.
Definition: interface.h:48
Object interfaces.
static void * dest
Definition: strings.h:176
void intf_unplug(struct interface *intf)
Unplug an object interface.
Definition: interface.c:112
An object interface descriptor.
Definition: interface.h:40
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define ref_get(refcnt)
Get additional reference to object.
Definition: refcnt.h:92
uint8_t * tmp
Definition: entropy.h:156
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
#define intf_poke_TYPE(object_type)
Definition: interface.h:160
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
void intf_nullify(struct interface *intf)
Ignore all further operations on an object interface.
Definition: interface.c:124
__builtin_va_list va_list
Definition: stdarg.h:6
static struct interface_operation null_intf_op[]
Null interface operations.
Definition: interface.c:56
void intfs_vshutdown(va_list intfs, int rc)
Shut down multiple object interfaces.
Definition: interface.c:299
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:144
void * intf_get_dest_op_no_passthru_untyped(struct interface *intf, void *type, struct interface **dest)
Get object interface destination and operation method (without pass-through)
Definition: interface.c:182
struct interface_descriptor * desc
Interface descriptor.
Definition: interface.h:126
struct refcnt * refcnt
Reference counter.
Definition: interface.h:124
#define va_start(ap, last)
Definition: stdarg.h:7
void intfs_vrestart(va_list intfs, int rc)
Shut down and restart multiple object interfaces.
Definition: interface.c:360
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
void intf_poke(struct interface *intf, void(type)(struct interface *intf))
Poke an object interface.
Definition: interface.c:397
String functions.
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:214
#define intf_close_TYPE(object_type)
Definition: interface.h:148
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
void intf_plug(struct interface *intf, struct interface *dest)
Plug an object interface into a new destination object interface.
Definition: interface.c:83
#define INTF_FMT
printf() format string for INTF_DBG()
Definition: interface.h:229
static void intf_reinit(struct interface *intf)
Reinitialise an object interface.
Definition: interface.h:256