2
* Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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
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.
24
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
27
#include <ipxe/interface.h>
35
/*****************************************************************************
42
* Close null interface
44
* @v intf Null interface
45
* @v rc Reason for close
47
static void null_intf_close ( struct interface *intf __unused,
50
/* Do nothing. In particular, do not call intf_restart(),
51
* since that would result in an infinite loop.
55
/** Null interface operations */
56
static struct interface_operation null_intf_op[] = {
57
INTF_OP ( intf_close, struct interface *, null_intf_close ),
60
/** Null interface descriptor */
61
struct interface_descriptor null_intf_desc =
62
INTF_DESC_PURE ( null_intf_op );
64
/** The null interface */
65
struct interface null_intf = INTF_INIT ( null_intf_desc );
67
/*****************************************************************************
69
* Object interface plumbing
74
* Plug an object interface into a new destination object interface
76
* @v intf Object interface
77
* @v dest New destination object interface
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.
83
* Note that there is no "unplug" call; instead you must plug the
84
* interface into a null interface.
86
void intf_plug ( struct interface *intf, struct interface *dest ) {
87
DBGC ( INTF_COL ( intf ),
88
"INTF " INTF_INTF_FMT " replug to " INTF_FMT "\n",
89
INTF_INTF_DBG ( intf, intf->dest ), INTF_DBG ( dest ) );
91
intf_put ( intf->dest );
96
* Plug two object interfaces together
98
* @v a Object interface A
99
* @v b Object interface B
101
* Plugs interface A into interface B, and interface B into interface
102
* A. (The basic plug() function is unidirectional; this function is
103
* merely a shorthand for two calls to plug(), hence the name.)
105
void intf_plug_plug ( struct interface *a, struct interface *b ) {
111
* Unplug an object interface
113
* @v intf Object interface
115
void intf_unplug ( struct interface *intf ) {
116
intf_plug ( intf, &null_intf );
120
* Ignore all further operations on an object interface
122
* @v intf Object interface
124
void intf_nullify ( struct interface *intf ) {
125
intf->desc = &null_intf_desc;
129
* Increment reference count on an object interface
131
* @v intf Object interface
132
* @ret intf Object interface
134
struct interface * intf_get ( struct interface *intf ) {
135
ref_get ( intf->refcnt );
140
* Decrement reference count on an object interface
142
* @v intf Object interface
144
void intf_put ( struct interface *intf ) {
145
ref_put ( intf->refcnt );
149
* Get pointer to object containing object interface
151
* @v intf Object interface
152
* @ret object Containing object
154
void * intf_object ( struct interface *intf ) {
155
return ( ( ( void * ) intf ) - intf->desc->offset );
159
* Get pass-through interface
161
* @v intf Object interface
162
* @ret passthru Pass-through interface, or NULL
164
static struct interface * intf_get_passthru ( struct interface *intf ) {
165
struct interface_descriptor *desc = intf->desc;
167
if ( desc->passthru_offset ) {
168
return ( ( ( void * ) intf ) + desc->passthru_offset );
175
* Get object interface destination and operation method (without pass-through)
177
* @v intf Object interface
178
* @v type Operation type
179
* @ret dest Destination interface
180
* @ret func Implementing method, or NULL
182
void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf,
184
struct interface **dest ) {
185
struct interface_descriptor *desc;
186
struct interface_operation *op;
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 )
200
* Get object interface destination and operation method
202
* @v intf Object interface
203
* @v type Operation type
204
* @ret dest Destination interface
205
* @ret func Implementing method, or NULL
207
void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
208
struct interface **dest ) {
213
/* Search for an implementing method provided by the
214
* current destination interface.
216
func = intf_get_dest_op_no_passthru_untyped( intf, type, dest );
220
/* Pass through to the underlying interface, if applicable */
221
if ( ! ( intf = intf_get_passthru ( *dest ) ) )
227
/*****************************************************************************
229
* Generic interface operations
234
* Close an object interface
236
* @v intf Object interface
237
* @v rc Reason for close
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.
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 );
250
DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " close (%s)\n",
251
INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
256
/* Default is to restart the interface */
257
intf_restart ( dest, rc );
264
* Shut down an object interface
266
* @v intf Object interface
267
* @v rc Reason for close
269
* Blocks further operations from being received via the interface,
270
* executes a close operation on the destination interface, and
271
* unplugs the interface.
273
void intf_shutdown ( struct interface *intf, int rc ) {
275
DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " shutting down (%s)\n",
276
INTF_DBG ( intf ), strerror ( rc ) );
278
/* Block further operations */
279
intf_nullify ( intf );
281
/* Notify destination of close */
282
intf_close ( intf, rc );
284
/* Unplug interface */
285
intf_unplug ( intf );
289
* Shut down and restart an object interface
291
* @v intf Object interface
292
* @v rc Reason for close
294
* Shuts down the interface, then unblocks operations that were
295
* blocked during shutdown.
297
void intf_restart ( struct interface *intf, int rc ) {
298
struct interface_descriptor *desc = intf->desc;
300
/* Shut down the interface */
301
intf_shutdown ( intf, rc );
303
DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " restarting\n",
306
/* Restore the interface descriptor. Must be done after
307
* shutdown (rather than inhibiting intf_shutdown() from
308
* nullifying the descriptor) in order to avoid a potential
309
* infinite loop as the intf_close() operations on each side
310
* of the link call each other recursively.
316
* Poke an object interface
318
* @v intf Object interface
319
* @v type Operation type
321
* This is a helper function to implement methods which take no
322
* parameters and return nothing.
324
void intf_poke ( struct interface *intf,
325
void ( type ) ( struct interface *intf ) ) {
326
struct interface *dest;
327
intf_poke_TYPE ( void * ) *op =
328
intf_get_dest_op_untyped ( intf, type, &dest );
329
void *object = intf_object ( dest );
334
/* Default is to do nothing */