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 
85  if ( intf == &null_intf )
86  return;
87 
88  DBGC ( INTF_COL ( intf ),
89  "INTF " INTF_INTF_FMT " replug to " INTF_FMT "\n",
90  INTF_INTF_DBG ( intf, intf->dest ), INTF_DBG ( dest ) );
91 
92  intf_get ( dest );
93  intf_put ( intf->dest );
94  intf->dest = dest;
95 }
96 
97 /**
98  * Plug two object interfaces together
99  *
100  * @v a Object interface A
101  * @v b Object interface B
102  *
103  * Plugs interface A into interface B, and interface B into interface
104  * A. (The basic plug() function is unidirectional; this function is
105  * merely a shorthand for two calls to plug(), hence the name.)
106  */
107 void intf_plug_plug ( struct interface *a, struct interface *b ) {
108  intf_plug ( a, b );
109  intf_plug ( b, a );
110 }
111 
112 /**
113  * Unplug an object interface
114  *
115  * @v intf Object interface
116  */
117 void intf_unplug ( struct interface *intf ) {
118  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " unplug\n",
119  INTF_INTF_DBG ( intf, intf->dest ) );
120  intf_put ( intf->dest );
121  intf->dest = &null_intf;
122 }
123 
124 /**
125  * Ignore all further operations on an object interface
126  *
127  * @v intf Object interface
128  */
129 void intf_nullify ( struct interface *intf ) {
131 }
132 
133 /**
134  * Increment reference count on an object interface
135  *
136  * @v intf Object interface
137  * @ret intf Object interface
138  */
139 struct interface * intf_get ( struct interface *intf ) {
140  ref_get ( intf->refcnt );
141  return intf;
142 }
143 
144 /**
145  * Decrement reference count on an object interface
146  *
147  * @v intf Object interface
148  */
149 void intf_put ( struct interface *intf ) {
150  ref_put ( intf->refcnt );
151 }
152 
153 /**
154  * Get pointer to object containing object interface
155  *
156  * @v intf Object interface
157  * @ret object Containing object
158  */
159 void * intf_object ( struct interface *intf ) {
160  return ( ( ( void * ) intf ) - intf->desc->offset );
161 }
162 
163 /**
164  * Get pass-through interface
165  *
166  * @v intf Object interface
167  * @ret passthru Pass-through interface, or NULL
168  */
169 static struct interface * intf_get_passthru ( struct interface *intf ) {
170  struct interface_descriptor *desc = intf->desc;
171 
172  if ( desc->passthru_offset ) {
173  return ( ( ( void * ) intf ) + desc->passthru_offset );
174  } else {
175  return NULL;
176  }
177 }
178 
179 /**
180  * Get object interface destination and operation method (without pass-through)
181  *
182  * @v intf Object interface
183  * @v type Operation type
184  * @ret dest Destination interface
185  * @ret func Implementing method, or NULL
186  */
188  void *type,
189  struct interface **dest ) {
190  struct interface_descriptor *desc;
191  struct interface_operation *op;
192  unsigned int i;
193 
194  *dest = intf_get ( intf->dest );
195  desc = (*dest)->desc;
196  for ( i = desc->num_op, op = desc->op ; i ; i--, op++ ) {
197  if ( op->type == type )
198  return op->func;
199  }
200 
201  return NULL;
202 }
203 
204 /**
205  * Get object interface destination and operation method
206  *
207  * @v intf Object interface
208  * @v type Operation type
209  * @ret dest Destination interface
210  * @ret func Implementing method, or NULL
211  */
212 void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
213  struct interface **dest ) {
214  void *func;
215 
216  while ( 1 ) {
217 
218  /* Search for an implementing method provided by the
219  * current destination interface.
220  */
222  if ( func )
223  return func;
224 
225  /* Pass through to the underlying interface, if applicable */
226  if ( ! ( intf = intf_get_passthru ( *dest ) ) )
227  return NULL;
228  intf_put ( *dest );
229  }
230 }
231 
232 /*****************************************************************************
233  *
234  * Generic interface operations
235  *
236  */
237 
238 /**
239  * Close an object interface
240  *
241  * @v intf Object interface
242  * @v rc Reason for close
243  *
244  * Note that this function merely informs the destination object that
245  * the interface is about to be closed; it doesn't actually disconnect
246  * the interface. In most cases, you probably want to use
247  * intf_shutdown() or intf_restart() instead.
248  */
249 void intf_close ( struct interface *intf, int rc ) {
250  struct interface *dest;
251  intf_close_TYPE ( void * ) *op =
253  void *object = intf_object ( dest );
254 
255  DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " close (%s)\n",
256  INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
257 
258  if ( op ) {
259  op ( object, rc );
260  } else {
261  /* Default is to restart the interface */
262  intf_restart ( dest, rc );
263  }
264 
265  intf_put ( dest );
266 }
267 
268 /**
269  * Shut down an object interface
270  *
271  * @v intf Object interface
272  * @v rc Reason for close
273  *
274  * Blocks further operations from being received via the interface,
275  * executes a close operation on the destination interface, and
276  * unplugs the interface.
277  */
278 void intf_shutdown ( struct interface *intf, int rc ) {
279  struct interface tmp;
280 
281  DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " shutting down (%s)\n",
282  INTF_DBG ( intf ), strerror ( rc ) );
283 
284  /* Block further operations */
285  intf_nullify ( intf );
286 
287  /* Transfer destination to temporary interface */
288  intf_temp_init ( &tmp, intf );
289  tmp.dest = intf->dest;
290  intf->dest = &null_intf;
291 
292  /* Notify destination of close via temporary interface */
293  intf_close ( &tmp, rc );
294 
295  /* Unplug temporary interface */
296  intf_unplug ( &tmp );
297 }
298 
299 /**
300  * Shut down multiple object interfaces
301  *
302  * @v intfs Object interfaces
303  * @v rc Reason for close
304  */
305 void intfs_vshutdown ( va_list intfs, int rc ) {
306  struct interface *intf;
307  va_list tmp;
308 
309  /* Nullify all interfaces to avoid potential loops */
310  va_copy ( tmp, intfs );
311  while ( ( intf = va_arg ( tmp, struct interface * ) ) )
312  intf_nullify ( intf );
313  va_end ( tmp );
314 
315  /* Shut down all interfaces */
316  while ( ( intf = va_arg ( intfs, struct interface * ) ) )
317  intf_shutdown ( intf, rc );
318 }
319 
320 /**
321  * Shut down multiple object interfaces
322  *
323  * @v rc Reason for close
324  * @v ... Object interfaces
325  */
326 void intfs_shutdown ( int rc, ... ) {
327  va_list intfs;
328 
329  va_start ( intfs, rc );
330  intfs_vshutdown ( intfs, rc );
331  va_end ( intfs );
332 }
333 
334 /**
335  * Shut down and restart an object interface
336  *
337  * @v intf Object interface
338  * @v rc Reason for close
339  *
340  * Shuts down the interface, then unblocks operations that were
341  * blocked during shutdown.
342  */
343 void intf_restart ( struct interface *intf, int rc ) {
344 
345  /* Shut down the interface */
346  intf_shutdown ( intf, rc );
347 
348  DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " restarting\n",
349  INTF_DBG ( intf ) );
350 
351  /* Restore the interface descriptor. Must be done after
352  * shutdown (rather than inhibiting intf_shutdown() from
353  * nullifying the descriptor) in order to avoid a potential
354  * infinite loop as the intf_close() operations on each side
355  * of the link call each other recursively.
356  */
357  intf_reinit ( intf );
358 }
359 
360 /**
361  * Shut down and restart multiple object interfaces
362  *
363  * @v intfs Object interfaces
364  * @v rc Reason for close
365  */
366 void intfs_vrestart ( va_list intfs, int rc ) {
367  struct interface *intf;
368  va_list tmp;
369 
370  /* Shut down all interfaces */
371  va_copy ( tmp, intfs );
372  intfs_vshutdown ( tmp, rc );
373  va_end ( tmp );
374 
375  /* Reinitialise all interfaces */
376  while ( ( intf = va_arg ( intfs, struct interface * ) ) )
377  intf_reinit ( intf );
378 }
379 
380 /**
381  * Shut down and restart multiple object interfaces
382  *
383  * @v rc Reason for close
384  * @v ... Object interfaces
385  */
386 void intfs_restart ( int rc, ... ) {
387  va_list intfs;
388 
389  va_start ( intfs, rc );
390  intfs_vrestart ( intfs, rc );
391  va_end ( intfs );
392 }
393 
394 /**
395  * Insert a filter interface
396  *
397  * @v intf Object interface
398  * @v upper Upper end of filter
399  * @v lower Lower end of filter
400  */
401 void intf_insert ( struct interface *intf, struct interface *upper,
402  struct interface *lower ) {
403  struct interface *dest = intf->dest;
404 
405  intf_get ( dest );
406  intf_plug_plug ( intf, upper );
407  intf_plug_plug ( lower, dest );
408  intf_put ( dest );
409 }
410 
411 /**
412  * Poke an object interface
413  *
414  * @v intf Object interface
415  * @v type Operation type
416  *
417  * This is a helper function to implement methods which take no
418  * parameters and return nothing.
419  */
420 void intf_poke ( struct interface *intf,
421  void ( type ) ( struct interface *intf ) ) {
422  struct interface *dest;
423  intf_poke_TYPE ( void * ) *op =
425  void *object = intf_object ( dest );
426 
427  if ( op ) {
428  op ( object );
429  } else {
430  /* Default is to do nothing */
431  }
432 
433  intf_put ( dest );
434 }
static struct interface * intf_get_passthru(struct interface *intf)
Get pass-through interface.
Definition: interface.c:169
struct interface * intf_get(struct interface *intf)
Increment reference count on an object interface.
Definition: interface.c:139
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:212
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:249
#define INTF_INTF_FMT
printf() format string for INTF_INTF_DBG()
Definition: interface.h:297
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:343
#define va_end(ap)
Definition: stdarg.h:9
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
#define INTF_DBG(intf)
printf() arguments for representing an object interface
Definition: interface.h:292
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:306
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:217
uint32_t type
Operating system type.
Definition: ena.h:12
#define INTF_COL(intf)
Find debugging colourisation for an object interface.
Definition: interface.h:281
uint64_t desc
Microcode descriptor list physical address.
Definition: ucode.h:12
#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
size_t offset
Offset of interface within containing object.
Definition: interface.h:57
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:107
#define INTF_DESC_PURE(operations)
Define an object interface descriptor for a pure-interface object.
Definition: interface.h:115
#define va_copy(dest, src)
Definition: stdarg.h:10
void intfs_shutdown(int rc,...)
Shut down multiple object interfaces.
Definition: interface.c:326
void intfs_restart(int rc,...)
Shut down and restart multiple object interfaces.
Definition: interface.c:386
void * intf_object(struct interface *intf)
Get pointer to object containing object interface.
Definition: interface.c:159
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
void * func
Implementing method.
Definition: interface.h:21
struct interface * intf
Original interface.
Definition: interface.h:158
struct interface * dest
Destination object interface.
Definition: interface.h:133
unsigned long tmp
Definition: linux_pci.h:63
#define va_arg(ap, type)
Definition: stdarg.h:8
An object interface.
Definition: interface.h:124
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
Object interfaces.
void intf_unplug(struct interface *intf)
Unplug an object interface.
Definition: interface.c:117
An object interface descriptor.
Definition: interface.h:55
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
#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:190
static uint16_t struct vmbus_xfer_pages_operations * op
Definition: netvsc.h:327
void intf_insert(struct interface *intf, struct interface *upper, struct interface *lower)
Insert a filter interface.
Definition: interface.c:401
void intf_nullify(struct interface *intf)
Ignore all further operations on an object interface.
Definition: interface.c:129
__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:305
void intf_put(struct interface *intf)
Decrement reference count on an object interface.
Definition: interface.c:149
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:150
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:187
struct interface_descriptor * desc
Interface descriptor.
Definition: interface.h:145
struct refcnt * refcnt
Reference counter.
Definition: interface.h:139
#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:366
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
void intf_poke(struct interface *intf, void(type)(struct interface *intf))
Poke an object interface.
Definition: interface.c:420
String functions.
static void intf_temp_init(struct interface *intf, struct interface *original)
Initialise a temporary outbound-only object interface.
Definition: interface.h:232
#define intf_get_dest_op(intf, type, dest)
Get object interface destination and operation method.
Definition: interface.h:269
#define intf_close_TYPE(object_type)
Definition: interface.h:176
#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:284
static void intf_reinit(struct interface *intf)
Reinitialise an object interface.
Definition: interface.h:313