Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / 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
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <string.h>
23 #include <ipxe/interface.h>
24
25 /** @file
26  *
27  * Object interfaces
28  *
29  */
30
31 /*****************************************************************************
32  *
33  * The null interface
34  *
35  */
36
37 /**
38  * Close null interface
39  *
40  * @v intf              Null interface
41  * @v rc                Reason for close
42  */
43 static void null_intf_close ( struct interface *intf __unused,
44                               int rc __unused ) {
45
46         /* Do nothing.  In particular, do not call intf_restart(),
47          * since that would result in an infinite loop.
48          */
49 }
50
51 /** Null interface operations */
52 static struct interface_operation null_intf_op[] = {
53         INTF_OP ( intf_close, struct interface *, null_intf_close ),
54 };
55
56 /** Null interface descriptor */
57 struct interface_descriptor null_intf_desc =
58         INTF_DESC_PURE ( null_intf_op );
59
60 /** The null interface */
61 struct interface null_intf = INTF_INIT ( null_intf_desc );
62
63 /*****************************************************************************
64  *
65  * Object interface plumbing
66  *
67  */
68
69 /**
70  * Plug an object interface into a new destination object interface
71  *
72  * @v intf              Object interface
73  * @v dest              New destination object interface
74  *
75  * The reference to the existing destination interface is dropped, a
76  * reference to the new destination interface is obtained, and the
77  * interface is updated to point to the new destination interface.
78  *
79  * Note that there is no "unplug" call; instead you must plug the
80  * interface into a null interface.
81  */
82 void intf_plug ( struct interface *intf, struct interface *dest ) {
83         DBGC ( INTF_COL ( intf ),
84                "INTF " INTF_INTF_FMT " replug to " INTF_FMT "\n",
85                INTF_INTF_DBG ( intf, intf->dest ), INTF_DBG ( dest ) );
86         intf_get ( dest );
87         intf_put ( intf->dest );
88         intf->dest = dest;
89 }
90
91 /**
92  * Plug two object interfaces together
93  *
94  * @v a                 Object interface A
95  * @v b                 Object interface B
96  *
97  * Plugs interface A into interface B, and interface B into interface
98  * A.  (The basic plug() function is unidirectional; this function is
99  * merely a shorthand for two calls to plug(), hence the name.)
100  */
101 void intf_plug_plug ( struct interface *a, struct interface *b ) {
102         intf_plug ( a, b );
103         intf_plug ( b, a );
104 }
105
106 /**
107  * Unplug an object interface
108  *
109  * @v intf              Object interface
110  */
111 void intf_unplug ( struct interface *intf ) {
112         intf_plug ( intf, &null_intf );
113 }
114
115 /**
116  * Ignore all further operations on an object interface
117  *
118  * @v intf              Object interface
119  */
120 void intf_nullify ( struct interface *intf ) {
121         intf->desc = &null_intf_desc;
122 }
123
124 /**
125  * Increment reference count on an object interface
126  *
127  * @v intf              Object interface
128  * @ret intf            Object interface
129  */
130 struct interface * intf_get ( struct interface *intf ) {
131         ref_get ( intf->refcnt );
132         return intf;
133 }
134
135 /**
136  * Decrement reference count on an object interface
137  *
138  * @v intf              Object interface
139  */
140 void intf_put ( struct interface *intf ) {
141         ref_put ( intf->refcnt );
142 }
143
144 /**
145  * Get pointer to object containing object interface
146  *
147  * @v intf              Object interface
148  * @ret object          Containing object
149  */
150 void * intf_object ( struct interface *intf ) {
151         return ( ( ( void * ) intf ) - intf->desc->offset );
152 }
153
154 /**
155  * Get pass-through interface
156  *
157  * @v intf              Object interface
158  * @ret passthru        Pass-through interface, or NULL
159  */
160 static struct interface * intf_get_passthru ( struct interface *intf ) {
161         struct interface_descriptor *desc = intf->desc;
162
163         if ( desc->passthru_offset ) {
164                 return ( ( ( void * ) intf ) + desc->passthru_offset );
165         } else {
166                 return NULL;
167         }
168 }
169
170 /**
171  * Get object interface destination and operation method (without pass-through)
172  *
173  * @v intf              Object interface
174  * @v type              Operation type
175  * @ret dest            Destination interface
176  * @ret func            Implementing method, or NULL
177  */
178 void * intf_get_dest_op_no_passthru_untyped ( struct interface *intf,
179                                               void *type,
180                                               struct interface **dest ) {
181         struct interface_descriptor *desc;
182         struct interface_operation *op;
183         unsigned int i;
184
185         *dest = intf_get ( intf->dest );
186         desc = (*dest)->desc;
187         for ( i = desc->num_op, op = desc->op ; i ; i--, op++ ) {
188                 if ( op->type == type )
189                         return op->func;
190         }
191
192         return NULL;
193 }
194
195 /**
196  * Get object interface destination and operation method
197  *
198  * @v intf              Object interface
199  * @v type              Operation type
200  * @ret dest            Destination interface
201  * @ret func            Implementing method, or NULL
202  */
203 void * intf_get_dest_op_untyped ( struct interface *intf, void *type,
204                                   struct interface **dest ) {
205         void *func;
206
207         while ( 1 ) {
208
209                 /* Search for an implementing method provided by the
210                  * current destination interface.
211                  */
212                 func = intf_get_dest_op_no_passthru_untyped( intf, type, dest );
213                 if ( func )
214                         return func;
215
216                 /* Pass through to the underlying interface, if applicable */
217                 if ( ! ( intf = intf_get_passthru ( *dest ) ) )
218                         return NULL;
219                 intf_put ( *dest );
220         }
221 }
222
223 /*****************************************************************************
224  *
225  * Generic interface operations
226  *
227  */
228
229 /**
230  * Close an object interface
231  *
232  * @v intf              Object interface
233  * @v rc                Reason for close
234  *
235  * Note that this function merely informs the destination object that
236  * the interface is about to be closed; it doesn't actually disconnect
237  * the interface.  In most cases, you probably want to use
238  * intf_shutdown() or intf_restart() instead.
239  */
240 void intf_close ( struct interface *intf, int rc ) {
241         struct interface *dest;
242         intf_close_TYPE ( void * ) *op =
243                 intf_get_dest_op ( intf, intf_close, &dest );
244         void *object = intf_object ( dest );
245
246         DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " close (%s)\n",
247                INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
248
249         if ( op ) {
250                 op ( object, rc );
251         } else {
252                 /* Default is to restart the interface */
253                 intf_restart ( dest, rc );
254         }
255
256         intf_put ( dest );
257 }
258
259 /**
260  * Shut down an object interface
261  *
262  * @v intf              Object interface
263  * @v rc                Reason for close
264  *
265  * Blocks further operations from being received via the interface,
266  * executes a close operation on the destination interface, and
267  * unplugs the interface.
268  */
269 void intf_shutdown ( struct interface *intf, int rc ) {
270
271         DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " shutting down (%s)\n",
272                INTF_DBG ( intf ), strerror ( rc ) );
273
274         /* Block further operations */
275         intf_nullify ( intf );
276
277         /* Notify destination of close */
278         intf_close ( intf, rc );
279
280         /* Unplug interface */
281         intf_unplug ( intf );
282 }
283
284 /**
285  * Shut down and restart an object interface
286  *
287  * @v intf              Object interface
288  * @v rc                Reason for close
289  *
290  * Shuts down the interface, then unblocks operations that were
291  * blocked during shutdown.
292  */
293 void intf_restart ( struct interface *intf, int rc ) {
294         struct interface_descriptor *desc = intf->desc;
295
296         /* Shut down the interface */
297         intf_shutdown ( intf, rc );
298
299         DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " restarting\n",
300                INTF_DBG ( intf ) );
301
302         /* Restore the interface descriptor.  Must be done after
303          * shutdown (rather than inhibiting intf_shutdown() from
304          * nullifying the descriptor) in order to avoid a potential
305          * infinite loop as the intf_close() operations on each side
306          * of the link call each other recursively.
307          */
308         intf->desc = desc;
309 }