[VNIC] Initial checkin of VNIC code. Not yet fully functional.
[mirror/winof/.git] / ulp / inic / kernel / vnic_adapter.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 #include <iba/ib_al.h>\r
33 #include <iba/ioc_ifc.h>\r
34 #include <complib/cl_bus_ifc.h>\r
35 #include "vnic_adapter.h"\r
36 \r
37 //#include "vnic_driver.h"\r
38 \r
39 extern struct _vnic_globals     g_vnic;\r
40 \r
41 NDIS_STATUS\r
42 vnic_get_adapter_params(\r
43         IN                              NDIS_HANDLE                             h_handle,\r
44         OUT                             vnic_params_t* const    p_params );\r
45 \r
46 NDIS_STATUS\r
47 vnic_get_adapter_interface(\r
48         IN                              NDIS_HANDLE                     h_handle,\r
49         IN                              vnic_adapter_t          *p_adapter);\r
50 \r
51 static ib_api_status_t\r
52 __path_record_add(\r
53         IN                              vnic_adapter_t          *p_adapter,\r
54         IN                              ib_path_rec_t           *p_path_rec );\r
55 \r
56 static ib_api_status_t\r
57 __path_record_remove(\r
58         IN                              vnic_adapter_t          *p_adapter,\r
59         IN                              ib_path_rec_t           *p_path_rec );\r
60 \r
61 static BOOLEAN\r
62 __path_records_match(\r
63         IN                              ib_path_rec_t           *p_path1,\r
64         IN                              ib_path_rec_t           *p_path2 );\r
65 \r
66 static void\r
67 __path_records_cleanup(\r
68         IN         vnic_adapter_t       *p_adapter );\r
69 \r
70 static ib_api_status_t\r
71 _vnic_get_ca_info(\r
72                         IN              vnic_adapter_t          *p_adapter );\r
73 \r
74 static inline uint8_t\r
75 _get_ioc_num_from_iocguid(\r
76                         IN              ib_net64_t              *p_iocguid );\r
77 \r
78 static BOOLEAN\r
79 __sid_valid(\r
80                 IN              vnic_adapter_t          *p_adapter,\r
81                 IN              ib_net64_t                      sid );\r
82 \r
83 static void\r
84 _vnic_viport_free(\r
85                 IN       vnic_adapter_t* const          p_adapter );\r
86 \r
87 ib_api_status_t\r
88 vnic_create_adapter(\r
89         IN              NDIS_HANDLE                     h_handle,\r
90         OUT             vnic_adapter_t**        const pp_adapter)\r
91 {\r
92         NDIS_STATUS                     status;\r
93         ib_api_status_t         ib_status;\r
94         vnic_adapter_t          *p_adapter;\r
95         KIRQL                           irql;\r
96 \r
97         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
98 \r
99         status = NdisAllocateMemoryWithTag( &p_adapter, sizeof(vnic_adapter_t), 'pada');\r
100 \r
101         if ( status != NDIS_STATUS_SUCCESS )\r
102         {\r
103                 VNIC_TRACE_EXIT(VNIC_DBG_ERROR,("Failed to allocate adapter\n"));\r
104                 return IB_INSUFFICIENT_MEMORY;\r
105         }\r
106 \r
107         NdisZeroMemory( p_adapter, sizeof(vnic_adapter_t) );\r
108 \r
109         NdisAllocateSpinLock( &p_adapter->lock );\r
110 \r
111         status = vnic_get_adapter_params( h_handle, &p_adapter->params );\r
112 \r
113         if ( status != NDIS_STATUS_SUCCESS )\r
114         {\r
115                 VNIC_TRACE( VNIC_DBG_ERROR,\r
116                         (" vnic_get_adapter_params failed with status %d\n", status));\r
117                 NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
118                 return IB_INVALID_PARAMETER;\r
119         }\r
120 \r
121         status = vnic_get_adapter_interface( h_handle, p_adapter );\r
122         if ( status != NDIS_STATUS_SUCCESS )\r
123         {\r
124                 VNIC_TRACE( VNIC_DBG_ERROR,\r
125                         ("failed status %x\n", status ) );\r
126                 NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
127                 return IB_INVALID_PARAMETER;\r
128         }\r
129 \r
130         /*Open AL */\r
131         ib_status = p_adapter->ifc.open_al( &p_adapter->h_al );\r
132         if ( ib_status != IB_SUCCESS )\r
133         {\r
134                 VNIC_TRACE( VNIC_DBG_ERROR,\r
135                         ("ib_open_al returned %s\n", p_adapter->ifc.get_err_str( ib_status )) );\r
136                 NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
137                 return ib_status;\r
138         }\r
139 \r
140         /* ca is opened here */\r
141         ib_status = _vnic_get_ca_info( p_adapter );\r
142         if( ib_status != IB_SUCCESS )\r
143         {\r
144                 VNIC_TRACE ( VNIC_DBG_ERROR,\r
145                         ("_get_ca_info return status %s\n", p_adapter->ifc.get_err_str( ib_status )) );\r
146                 NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
147                 return ib_status;\r
148         }\r
149 \r
150         KeAcquireSpinLock( &g_vnic.lock, &irql );\r
151         InsertTailList( &g_vnic.adapter_list, &p_adapter->list_entry );\r
152         InterlockedIncrement( &g_vnic.adapters );\r
153         KeReleaseSpinLock( &g_vnic.lock, irql );\r
154 \r
155         p_adapter->h_handle = h_handle;\r
156         *pp_adapter = p_adapter;\r
157 \r
158         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
159         return IB_SUCCESS;\r
160 }\r
161 \r
162 \r
163 void\r
164 vnic_destroy_adapter(\r
165          IN      vnic_adapter_t         *p_adapter)\r
166 {\r
167         ib_api_status_t ib_status = IB_SUCCESS;\r
168         KIRQL                   irql;\r
169 \r
170         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
171 \r
172         ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
173 \r
174         KeAcquireSpinLock( &g_vnic.lock, &irql );\r
175         RemoveEntryList( &p_adapter->list_entry );\r
176         InterlockedDecrement( &g_vnic.adapters );\r
177         KeReleaseSpinLock( &g_vnic.lock, irql );\r
178 \r
179         if( p_adapter->h_pnp )\r
180         {\r
181                 ib_status =\r
182                         p_adapter->ifc.dereg_pnp( p_adapter->h_pnp, ib_sync_destroy );\r
183         }\r
184 \r
185         vnic_viport_cleanup( p_adapter );\r
186 \r
187         if ( p_adapter->ca.region.h_mr )\r
188         {\r
189                 ib_status = p_adapter->ifc.dereg_mr(p_adapter->ca.region.h_mr );\r
190                 ASSERT( ib_status == IB_SUCCESS );\r
191         }\r
192 \r
193         if( p_adapter->ca.hPd )\r
194         {\r
195                 ib_status = p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL );\r
196                 ASSERT( ib_status == IB_SUCCESS );\r
197         }\r
198 \r
199         if ( p_adapter->h_ca )\r
200         {\r
201                 ib_status = p_adapter->ifc.close_ca( p_adapter->h_ca, NULL );\r
202                 ASSERT( ib_status == IB_SUCCESS );\r
203         }\r
204 \r
205         if ( p_adapter->h_al )\r
206         {\r
207                 ib_status = p_adapter->ifc.close_al( p_adapter->h_al );\r
208                 ASSERT( ib_status == IB_SUCCESS );\r
209         }\r
210 \r
211         if ( p_adapter->p_svc_entries )\r
212                 cl_free ( p_adapter->p_svc_entries );\r
213 \r
214         NdisFreeSpinLock( &p_adapter->lock );\r
215         NdisFreeMemory( p_adapter, sizeof(vnic_adapter_t), 0 );\r
216 \r
217         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
218 }\r
219 \r
220 \r
221 static ib_api_status_t\r
222 _vnic_get_ca_info(\r
223                         IN                      vnic_adapter_t          *p_adapter )\r
224 {\r
225         ib_api_status_t         ib_status = IB_SUCCESS;\r
226         ib_al_ifc_t                     *p_ifc  = &p_adapter->ifc;\r
227         uint32_t                        attr_size;\r
228         ib_ca_attr_t            *p_ca_attrs;\r
229         uint32_t                        num;\r
230         uint64_t        start_addr      = 0;\r
231 \r
232         ib_status = p_ifc->open_ca( p_adapter->h_al,\r
233                                                                 p_adapter->ifc_data.ca_guid,\r
234                                                                 ib_asyncEvent,\r
235                                                                 p_adapter,\r
236                                                                 &p_adapter->h_ca );\r
237 \r
238         if ( ib_status != IB_SUCCESS )\r
239         {\r
240                 VNIC_TRACE( VNIC_DBG_ERROR,\r
241                         ("Failed to open hca\n") );\r
242                 return IB_INSUFFICIENT_RESOURCES;\r
243         }\r
244 \r
245         ib_status = p_ifc->query_ca( p_adapter->h_ca, NULL , &attr_size );\r
246         if( ib_status != IB_INSUFFICIENT_MEMORY )\r
247         {\r
248                 VNIC_TRACE( VNIC_DBG_ERROR,\r
249                         ("ib_query_ca failed status %s\n",\r
250                         p_ifc->get_err_str( ib_status )) );\r
251                 return IB_INSUFFICIENT_RESOURCES;\r
252         }\r
253 \r
254         ASSERT( attr_size );\r
255 \r
256         p_ca_attrs = cl_zalloc( attr_size );\r
257         if ( p_ca_attrs == NULL )\r
258         {\r
259                 VNIC_TRACE( VNIC_DBG_ERROR,\r
260                         ("Allocate %d bytes failed for Channel adapter\n", attr_size ));\r
261                 return IB_INSUFFICIENT_MEMORY;\r
262         }\r
263 \r
264         ib_status = p_ifc->query_ca( p_adapter->h_ca, p_ca_attrs , &attr_size );\r
265         if ( ib_status != IB_SUCCESS )\r
266         {\r
267                 VNIC_TRACE( VNIC_DBG_ERROR,\r
268                         ("Query failed for channel adapter\n") );\r
269                 cl_free ( p_ca_attrs );\r
270                 return  ib_status;\r
271         }\r
272 \r
273         p_adapter->ca.numPorts = p_ca_attrs->num_ports;\r
274         if( p_adapter->ca.numPorts > VNIC_CA_MAX_PORTS )\r
275                 p_adapter->ca.numPorts = VNIC_CA_MAX_PORTS;\r
276 \r
277         for( num = 0; num < p_adapter->ca.numPorts; num++ )\r
278                 p_adapter->ca.portGuids[num] = p_ca_attrs->p_port_attr[num].port_guid;\r
279 \r
280         p_adapter->ca.caGuid = p_adapter->ifc_data.ca_guid;\r
281 \r
282         cl_free ( p_ca_attrs );\r
283 \r
284         ib_status = p_adapter->ifc.alloc_pd( p_adapter->h_ca,\r
285                 IB_PDT_NORMAL, p_adapter, &p_adapter->ca.hPd );\r
286         if ( ib_status != IB_SUCCESS )\r
287         {\r
288                 VNIC_TRACE_EXIT ( VNIC_DBG_ERROR,\r
289                         ("alloc PD failed status %s(%d)\n",\r
290                         p_adapter->ifc.get_err_str(ib_status), ib_status ));\r
291                 return ib_status;\r
292         }\r
293 \r
294         if ( ( ib_status = ibregion_physInit( p_adapter,\r
295                                                          &p_adapter->ca.region,\r
296                                                          p_adapter->ca.hPd,\r
297                                                          &start_addr,\r
298                                                          MAX_PHYS_MEMORY ) ) != IB_SUCCESS )\r
299         {\r
300                 VNIC_TRACE_EXIT ( VNIC_DBG_ERROR,\r
301                         ("phys region init failed status %s(%d)\n",\r
302                         p_adapter->ifc.get_err_str(ib_status), ib_status ));\r
303 \r
304                 p_adapter->ifc.dealloc_pd( p_adapter->ca.hPd, NULL );\r
305         }\r
306 \r
307         return ib_status;\r
308 }\r
309 \r
310 static BOOLEAN\r
311 _vnic_params_sanity_check(vnic_params_t *p_params)\r
312 {\r
313         DEFAULT_PARAM( p_params->MaxAddressEntries, MAX_ADDRESS_ENTRIES );\r
314         DEFAULT_PARAM( p_params->MinAddressEntries, MIN_ADDRESS_ENTRIES );\r
315      \r
316                 DEFAULT_PARAM( p_params->ViportStatsInterval, VIPORT_STATS_INTERVAL );\r
317         DEFAULT_PARAM( p_params->ViportHbInterval, VIPORT_HEARTBEAT_INTERVAL );\r
318         DEFAULT_PARAM( p_params->ViportHbTimeout, VIPORT_HEARTBEAT_TIMEOUT );\r
319        \r
320                 DEFAULT_PARAM( p_params->ControlRspTimeout, CONTROL_RSP_TIMEOUT );\r
321         DEFAULT_PARAM( p_params->ControlReqRetryCount, CONTROL_REQ_RETRY_COUNT );\r
322        \r
323                 DEFAULT_PARAM( p_params->RetryCount, RETRY_COUNT );\r
324         DEFAULT_PARAM( p_params->MinRnrTimer, MIN_RNR_TIMER );\r
325        \r
326                 DEFAULT_PARAM( p_params->MaxViportsPerNetpath, MAX_VIPORTS_PER_NETPATH );\r
327         DEFAULT_PARAM( p_params->DefaultViportsPerNetpath, DEFAULT_VIPORTS_PER_NETPATH );\r
328 \r
329                 DEFAULT_PARAM( p_params->DefaultPkey, DEFAULT_PKEY );\r
330         DEFAULT_PARAM( p_params->NotifyBundleSz, NOTIFY_BUNDLE_SZ );\r
331                 DEFAULT_PARAM( p_params->DefaultNoPathTimeout, DEFAULT_NO_PATH_TIMEOUT );\r
332         DEFAULT_PARAM( p_params->DefaultPrimaryConnectTimeout, DEFAULT_PRI_CON_TIMEOUT );\r
333         DEFAULT_PARAM( p_params->DefaultPrimaryReconnectTimeout, DEFAULT_PRI_RECON_TIMEOUT );\r
334         DEFAULT_PARAM( p_params->DefaultPrimarySwitchTimeout, DEFAULT_PRI_SWITCH_TIMEOUT );\r
335                 DEFAULT_PARAM( p_params->DefaultPreferPrimary, DEFAULT_PREFER_PRIMARY );\r
336 \r
337         U32_RANGE( p_params->MaxAddressEntries );\r
338         U32_RANGE( p_params->MinAddressEntries );\r
339                 RANGE_CHECK( p_params->MinMtu, MIN_MTU, MAX_MTU );\r
340         RANGE_CHECK( p_params->MaxMtu, MIN_MTU, MAX_MTU );\r
341         U32_RANGE( p_params->HostRecvPoolEntries );\r
342         U32_RANGE( p_params->MinHostPoolSz );\r
343         U32_RANGE( p_params->MinEiocPoolSz );\r
344         U32_RANGE( p_params->MaxEiocPoolSz );\r
345         U32_ZERO_RANGE( p_params->MinHostKickTimeout );\r
346         U32_ZERO_RANGE( p_params->MaxHostKickTimeout );\r
347         U32_ZERO_RANGE( p_params->MinHostKickEntries );\r
348         U32_ZERO_RANGE( p_params->MaxHostKickEntries );\r
349         U32_ZERO_RANGE( p_params->MinHostKickBytes );\r
350         U32_ZERO_RANGE( p_params->MaxHostKickBytes );\r
351         U32_RANGE( p_params->MinHostUpdateSz );\r
352         U32_RANGE( p_params->MaxHostUpdateSz );\r
353         U32_RANGE( p_params->MinEiocUpdateSz );\r
354         U32_RANGE( p_params->MaxEiocUpdateSz );\r
355         U8_RANGE( p_params->NotifyBundleSz );\r
356         U32_ZERO_RANGE( p_params->ViportStatsInterval );\r
357         U32_ZERO_RANGE( p_params->ViportHbInterval );\r
358         U32_ZERO_RANGE( p_params->ViportHbTimeout );\r
359         U32_RANGE( p_params->ControlRspTimeout );\r
360         U8_RANGE( p_params->ControlReqRetryCount );\r
361         ZERO_RANGE_CHECK( p_params->RetryCount, 0, 7 );\r
362         ZERO_RANGE_CHECK( p_params->MinRnrTimer, 0, 31 );\r
363         U32_RANGE( p_params->DefaultViportsPerNetpath );\r
364         U8_RANGE( p_params->MaxViportsPerNetpath );\r
365         U16_ZERO_RANGE( p_params->DefaultPkey );\r
366         U32_RANGE( p_params->DefaultNoPathTimeout );\r
367         U32_RANGE( p_params->DefaultPrimaryConnectTimeout );\r
368         U32_RANGE( p_params->DefaultPrimaryReconnectTimeout );\r
369         U32_RANGE( p_params->DefaultPrimarySwitchTimeout );\r
370         BOOLEAN_RANGE( p_params->DefaultPreferPrimary );\r
371         BOOLEAN_RANGE( p_params->UseRxCsum );\r
372         BOOLEAN_RANGE( p_params->UseTxCsum );\r
373 \r
374         LESS_THAN_OR_EQUAL( p_params->MinAddressEntries, p_params->MaxAddressEntries );\r
375         LESS_THAN_OR_EQUAL( p_params->MinMtu, p_params->MaxMtu );\r
376         LESS_THAN_OR_EQUAL( p_params->MinHostPoolSz, p_params->HostRecvPoolEntries );\r
377         POWER_OF_2( p_params->HostRecvPoolEntries );\r
378         POWER_OF_2( p_params->MinHostPoolSz );\r
379         POWER_OF_2( p_params->NotifyBundleSz );\r
380         LESS_THAN( p_params->NotifyBundleSz, p_params->MinEiocPoolSz );\r
381         LESS_THAN_OR_EQUAL( p_params->MinEiocPoolSz, p_params->MaxEiocPoolSz );\r
382         POWER_OF_2( p_params->MinEiocPoolSz );\r
383         POWER_OF_2( p_params->MaxEiocPoolSz );\r
384         LESS_THAN_OR_EQUAL( p_params->MinHostKickTimeout, p_params->MaxHostKickTimeout );\r
385         LESS_THAN_OR_EQUAL( p_params->MinHostKickEntries, p_params->MaxHostKickEntries );\r
386         LESS_THAN_OR_EQUAL( p_params->MinHostKickBytes, p_params->MaxHostKickBytes );\r
387         LESS_THAN_OR_EQUAL( p_params->MinHostUpdateSz, p_params->MaxHostUpdateSz );\r
388         POWER_OF_2( p_params->MinHostUpdateSz );\r
389         POWER_OF_2( p_params->MaxHostUpdateSz );\r
390         LESS_THAN( p_params->MinHostUpdateSz, p_params->MinHostPoolSz );\r
391         LESS_THAN( p_params->MaxHostUpdateSz, p_params->HostRecvPoolEntries );\r
392         LESS_THAN_OR_EQUAL( p_params->MinEiocUpdateSz, p_params->MaxEiocUpdateSz );\r
393         POWER_OF_2( p_params->MinEiocUpdateSz );\r
394         POWER_OF_2( p_params->MaxEiocUpdateSz );\r
395         LESS_THAN( p_params->MinEiocUpdateSz, p_params->MinEiocPoolSz );\r
396         LESS_THAN( p_params->MaxEiocUpdateSz, p_params->MaxEiocPoolSz );\r
397         LESS_THAN_OR_EQUAL( p_params->DefaultViportsPerNetpath, p_params->MaxViportsPerNetpath );\r
398 \r
399         return TRUE;\r
400 \r
401 }\r
402 NDIS_STATUS\r
403 vnic_get_adapter_params(\r
404         IN                      NDIS_HANDLE                             h_handle,\r
405         OUT                     vnic_params_t* const    p_params )\r
406 {\r
407         NDIS_STATUS                                             status;\r
408         NDIS_HANDLE                                             h_config;\r
409         NDIS_CONFIGURATION_PARAMETER    *p_reg_prm;\r
410         //NDIS_STRING                                           keyword;\r
411 \r
412         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
413 \r
414         CL_ASSERT(p_params );\r
415 \r
416         /* prepare params for default initialization */\r
417         cl_memset( p_params, 0xff, sizeof (vnic_params_t) );\r
418 \r
419         NdisOpenConfiguration( &status, &h_config, h_handle );\r
420         if( status != NDIS_STATUS_SUCCESS )\r
421         {\r
422                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
423                         ("NdisOpenConfiguration returned 0x%.8x\n", status) );\r
424                 return status;\r
425         }\r
426 \r
427         status = NDIS_STATUS_FAILURE;\r
428         p_reg_prm = NULL;\r
429 \r
430         //RtlInitUnicodeString( &keyword, L"DebugFlags" );\r
431 \r
432         //NdisReadConfiguration(\r
433         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
434         //if( status == NDIS_STATUS_SUCCESS )\r
435         //              g_vnic_dbg_lvl = p_reg_prm->ParameterData.IntegerData;\r
436 \r
437         //RtlInitUnicodeString( &keyword, L"MinMtu" );\r
438         //NdisReadConfiguration(\r
439         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
440 \r
441         p_params->MinMtu = ( status != NDIS_STATUS_SUCCESS ) ? MIN_MTU:\r
442                                                 p_reg_prm->ParameterData.IntegerData;\r
443 \r
444         //RtlInitUnicodeString( &keyword, L"MaxMtu" );\r
445         //NdisReadConfiguration(\r
446         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
447 \r
448         p_params->MaxMtu =( status != NDIS_STATUS_SUCCESS )? MAX_MTU:\r
449                                                 p_reg_prm->ParameterData.IntegerData;\r
450 \r
451         //RtlInitUnicodeString( &keyword, L"UseRxCsum" );\r
452         //NdisReadConfiguration(\r
453         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
454 \r
455         p_params->UseRxCsum = ( status != NDIS_STATUS_SUCCESS ) ?\r
456                 TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE;\r
457 \r
458         //RtlInitUnicodeString( &keyword, L"UseTxCsum" );\r
459         //NdisReadConfiguration(\r
460         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
461 \r
462         /* turn it on by default, if not present */\r
463         p_params->UseTxCsum = ( status != NDIS_STATUS_SUCCESS ) ?\r
464                 TRUE : ( p_reg_prm->ParameterData.IntegerData )? TRUE : FALSE;\r
465 \r
466         //RtlInitUnicodeString( &keyword, L"MinEiocUpdateSz" );\r
467         //NdisReadConfiguration(\r
468         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
469 \r
470         p_params->MinEiocUpdateSz = ( status != NDIS_STATUS_SUCCESS ) ?\r
471                         MIN_EIOC_UPDATE_SZ : p_reg_prm->ParameterData.IntegerData;\r
472 \r
473         //RtlInitUnicodeString( &keyword, L"MaxEiocUpdateSz" );\r
474         //NdisReadConfiguration(\r
475         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
476 \r
477         p_params->MaxEiocUpdateSz = ( status != NDIS_STATUS_SUCCESS ) ?\r
478                         MAX_EIOC_UPDATE_SZ : p_reg_prm->ParameterData.IntegerData;\r
479 \r
480         //RtlInitUnicodeString( &keyword, L"MinHostUpdateSz" );\r
481         //NdisReadConfiguration(\r
482         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
483 \r
484         p_params->MinHostUpdateSz = ( status != NDIS_STATUS_SUCCESS ) ?\r
485                         MIN_HOST_UPDATE_SZ : p_reg_prm->ParameterData.IntegerData;\r
486 \r
487         //RtlInitUnicodeString( &keyword, L"MaxHostUpdateSz" );\r
488         //NdisReadConfiguration(\r
489         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
490 \r
491         p_params->MaxHostUpdateSz = ( status != NDIS_STATUS_SUCCESS ) ?\r
492                         MAX_HOST_UPDATE_SZ : p_reg_prm->ParameterData.IntegerData;\r
493 \r
494         //RtlInitUnicodeString( &keyword, L"MinHostKickBytes" );\r
495         //NdisReadConfiguration(\r
496         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
497 \r
498         p_params->MinHostKickBytes = ( status != NDIS_STATUS_SUCCESS ) ?\r
499                         MIN_HOST_KICK_BYTES : p_reg_prm->ParameterData.IntegerData;\r
500 \r
501         //RtlInitUnicodeString( &keyword, L"MaxHostKickBytes" );\r
502         //NdisReadConfiguration(\r
503         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
504 \r
505         p_params->MaxHostKickBytes = ( status != NDIS_STATUS_SUCCESS ) ?\r
506                         MAX_HOST_KICK_BYTES : p_reg_prm->ParameterData.IntegerData;\r
507 \r
508         //RtlInitUnicodeString( &keyword, L"MinHostKickEntries" );\r
509         //NdisReadConfiguration(\r
510         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
511 \r
512         p_params->MinHostKickEntries =  ( status != NDIS_STATUS_SUCCESS ) ?\r
513                         MIN_HOST_KICK_ENTRIES : p_reg_prm->ParameterData.IntegerData;\r
514 \r
515         //RtlInitUnicodeString( &keyword, L"MaxHostKickEntries" );\r
516         //NdisReadConfiguration(\r
517         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
518 \r
519         p_params->MaxHostKickEntries =  ( status != NDIS_STATUS_SUCCESS ) ?\r
520                         MAX_HOST_KICK_ENTRIES : p_reg_prm->ParameterData.IntegerData;\r
521 \r
522         //RtlInitUnicodeString( &keyword, L"MinHostKickTimeout" );\r
523         //NdisReadConfiguration(\r
524         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
525 \r
526         p_params->MinHostKickTimeout =  ( status != NDIS_STATUS_SUCCESS ) ?\r
527                         MIN_HOST_KICK_TIMEOUT : p_reg_prm->ParameterData.IntegerData;\r
528 \r
529         //RtlInitUnicodeString( &keyword, L"MaxHostKickTimeout" );\r
530         //NdisReadConfiguration(\r
531         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
532 \r
533         p_params->MaxHostKickTimeout =  ( status != NDIS_STATUS_SUCCESS ) ?\r
534                         MAX_HOST_KICK_TIMEOUT : p_reg_prm->ParameterData.IntegerData;\r
535 \r
536         //RtlInitUnicodeString( &keyword, L"MinEiocPoolSz" );\r
537         //NdisReadConfiguration(\r
538         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
539 \r
540         p_params->MinEiocPoolSz =  ( status != NDIS_STATUS_SUCCESS ) ?\r
541                         MIN_EIOC_POOL_SZ : p_reg_prm->ParameterData.IntegerData;\r
542 \r
543         //RtlInitUnicodeString( &keyword, L"MaxEiocPoolSz" );\r
544         //NdisReadConfiguration(\r
545         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
546 \r
547         p_params->MaxEiocPoolSz =  ( status != NDIS_STATUS_SUCCESS ) ?\r
548                         MAX_EIOC_POOL_SZ : p_reg_prm->ParameterData.IntegerData;\r
549 \r
550         //RtlInitUnicodeString( &keyword, L"MinHostPoolSz" );\r
551         //NdisReadConfiguration(\r
552         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
553 \r
554         p_params->MinHostPoolSz =  ( status != NDIS_STATUS_SUCCESS ) ?\r
555                         MIN_HOST_POOL_SZ : p_reg_prm->ParameterData.IntegerData;\r
556 \r
557         //RtlInitUnicodeString( &keyword, L"HostRecvPoolEntries" );\r
558         //NdisReadConfiguration(\r
559         //      &status, &p_reg_prm, h_config, &keyword, NdisParameterInteger );\r
560 \r
561         p_params->HostRecvPoolEntries =  ( status != NDIS_STATUS_SUCCESS ) ?\r
562                         HOST_RECV_POOL_ENTRIES : p_reg_prm->ParameterData.IntegerData;\r
563 \r
564         NdisCloseConfiguration( h_config );\r
565 \r
566         status = ( _vnic_params_sanity_check(p_params)?\r
567                                 NDIS_STATUS_SUCCESS: NDIS_STATUS_FAILURE );\r
568 \r
569         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
570         return status;\r
571 }\r
572 \r
573 ib_api_status_t\r
574 vnic_viport_allocate(\r
575         IN                      vnic_adapter_t* const           p_adapter,\r
576         IN OUT          viport_t**              const           pp_viport )\r
577 {\r
578         viport_t        *p_viport;\r
579         NDIS_STATUS      status;\r
580         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
581 \r
582         NdisAcquireSpinLock( &p_adapter->lock );\r
583         status = NdisAllocateMemoryWithTag( &p_viport, sizeof(viport_t), 'trop' );\r
584 \r
585         if( status != NDIS_STATUS_SUCCESS )\r
586         {\r
587                 NdisReleaseSpinLock( &p_adapter->lock );\r
588                 VNIC_TRACE_EXIT(VNIC_DBG_ERROR,\r
589                                 ( "Failed allocating Viport structure\n" ));\r
590                 return IB_ERROR;\r
591         }\r
592 \r
593         NdisZeroMemory( p_viport, sizeof(viport_t) );\r
594 \r
595         KeInitializeSpinLock( &p_viport->lock );\r
596         InitializeListHead( &p_viport->listPtrs );\r
597         cl_qlist_init( &p_viport->send_pending_list );\r
598 \r
599         KeInitializeEvent( &p_viport->conn_event, SynchronizationEvent, FALSE );\r
600 \r
601         p_viport->p_adapter = p_adapter;\r
602 \r
603         viport_get_adapter_name( p_viport );\r
604 \r
605         viport_config_defaults ( p_viport );\r
606         VNIC_TRACE( VNIC_DBG_PNP, ("Configure Viport default values\n") );\r
607 \r
608         control_construct( &p_viport->control, p_viport );\r
609         data_construct( &p_viport->data, p_viport );\r
610 \r
611         *pp_viport = p_viport;\r
612 \r
613         NdisReleaseSpinLock( &p_adapter->lock );\r
614         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
615         return IB_SUCCESS;\r
616 }\r
617 static void\r
618 _vnic_viport_free(\r
619         IN       vnic_adapter_t* const          p_adapter )\r
620 {\r
621         viport_t        *p_viport = p_adapter->p_viport;\r
622         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
623 \r
624         if ( p_viport )\r
625         {\r
626                 p_adapter->p_viport = NULL;\r
627                 NdisFreeMemory( p_viport, sizeof(viport_t), 0 );\r
628         }\r
629         p_adapter->state = INIC_UNINITIALIZED;\r
630 \r
631         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
632 }\r
633 \r
634 \r
635 NDIS_STATUS\r
636 vnic_set_mcast(\r
637         IN                              vnic_adapter_t* const           p_adapter,\r
638         IN                              mac_addr_t* const                       p_mac_array,\r
639         IN              const   uint8_t                                         mc_count )\r
640 {\r
641         NDIS_STATUS     status;\r
642 \r
643         VNIC_ENTER( VNIC_DBG_MCAST );\r
644 \r
645         /* Copy the MC address list into the adapter. */\r
646         if( mc_count )\r
647         {\r
648                 RtlCopyMemory(\r
649                         p_adapter->mcast_array, p_mac_array, mc_count * MAC_ADDR_LEN );\r
650         }\r
651         p_adapter->mc_count = mc_count;\r
652 \r
653         if( !p_adapter->p_currentPath->pViport )\r
654                 return NDIS_STATUS_SUCCESS;\r
655 \r
656         p_adapter->pending_set = TRUE;\r
657         status = viport_setMulticast( p_adapter->p_currentPath->pViport );\r
658         if( status != NDIS_STATUS_PENDING )\r
659         {\r
660                 p_adapter->pending_set = FALSE;\r
661         }\r
662 \r
663         VNIC_EXIT( VNIC_DBG_MCAST );\r
664         return status;\r
665 }\r
666 \r
667 \r
668 static BOOLEAN\r
669 __path_records_match(\r
670         IN                      ib_path_rec_t           *p_path1,\r
671         IN                      ib_path_rec_t           *p_path2 )\r
672 {\r
673         if ( p_path1->dgid.unicast.prefix != p_path2->dgid.unicast.prefix )\r
674                 return FALSE;\r
675         if ( p_path1->dgid.unicast.interface_id != p_path2->dgid.unicast.interface_id )\r
676                 return FALSE;\r
677         if ( p_path1->dlid != p_path2->dlid )\r
678                 return FALSE;\r
679         if ( p_path1->pkey != p_path2->pkey )\r
680                 return FALSE;\r
681         if ( p_path1->rate != p_path2->rate )\r
682                 return FALSE;\r
683 \r
684         return TRUE;\r
685 }\r
686 \r
687 static BOOLEAN\r
688 __sid_valid(\r
689                 IN              vnic_adapter_t          *p_adapter,\r
690                 IN              ib_net64_t                      sid )\r
691 {\r
692         vnic_sid_t      svc_id;\r
693         svc_id.as_uint64 = sid;\r
694         if( ( svc_id.s.base_id & 0x10 ) != 0x10 )\r
695                 return FALSE;\r
696         if( svc_id.s.oui[0] != 0x00 &&\r
697                 svc_id.s.oui[1] != 0x06 &&\r
698                 svc_id.s.oui[2] != 0x6a )\r
699                 return FALSE;\r
700         if ( svc_id.s.type != CONTROL_SID &&\r
701                  svc_id.s.type != DATA_SID )\r
702                  return FALSE;\r
703         if ( svc_id.s.ioc_num   != _get_ioc_num_from_iocguid( &p_adapter->ifc_data.guid ) )\r
704                 return FALSE;\r
705         return TRUE;\r
706 }\r
707 static inline uint8_t\r
708 _get_ioc_num_from_iocguid(\r
709                   IN ib_net64_t         *p_iocguid )\r
710 {\r
711         return ( (vnic_ioc_guid_t *)p_iocguid)->s.ioc_num;\r
712 }\r
713 \r
714 static ib_api_status_t\r
715 __path_record_add(\r
716         IN                              vnic_adapter_t          *p_adapter,\r
717         IN                              ib_path_rec_t           *p_path_rec )\r
718 {\r
719 \r
720         NdisAcquireSpinLock( &p_adapter->lock );\r
721 \r
722         if ( !__path_records_match( &p_adapter->path_record.path_rec, p_path_rec ) )\r
723         {\r
724                         p_adapter->path_record.path_rec = *p_path_rec;\r
725                         p_adapter->path_record.num_entries++;\r
726         }\r
727 \r
728         NdisReleaseSpinLock( &p_adapter->lock );\r
729         return IB_SUCCESS;\r
730 }\r
731 \r
732 static ib_api_status_t\r
733 __path_record_remove(\r
734                 IN                      vnic_adapter_t          *p_adapter,\r
735                 IN                      ib_path_rec_t           *p_path_rec )\r
736 {\r
737 \r
738         NdisAcquireSpinLock( &p_adapter->lock );\r
739 \r
740         if ( __path_records_match( &p_adapter->path_record.path_rec, p_path_rec ) )\r
741         {\r
742                 --p_adapter->path_record.num_entries;\r
743                 cl_memclr( &p_adapter->path_record.path_rec, sizeof( ib_path_rec_t ));\r
744         }\r
745 \r
746         NdisReleaseSpinLock( &p_adapter->lock );\r
747         return IB_SUCCESS;\r
748 }\r
749 \r
750 static void\r
751 __path_records_cleanup(\r
752                    vnic_adapter_t       *p_adapter )\r
753 {\r
754 \r
755         NdisAcquireSpinLock( &p_adapter->lock );\r
756 \r
757         cl_memclr( &p_adapter->path_record.path_rec, sizeof( ib_path_rec_t ));\r
758         p_adapter->path_record.num_entries = 0;\r
759 \r
760         NdisReleaseSpinLock( &p_adapter->lock );\r
761         return;\r
762 }\r
763 ib_api_status_t\r
764 __vnic_pnp_cb(\r
765         IN              ib_pnp_rec_t                *p_pnp_rec )\r
766 {\r
767         ib_api_status_t                 ib_status = IB_SUCCESS;\r
768         ib_pnp_ioc_rec_t                *p_ioc_rec;\r
769         ib_pnp_ioc_path_rec_t   *p_ioc_path;\r
770 \r
771         vnic_adapter_t * __ptr64 p_adapter = (vnic_adapter_t * __ptr64)p_pnp_rec->pnp_context;\r
772         \r
773         VNIC_ENTER( VNIC_DBG_PNP );\r
774 \r
775         CL_ASSERT( p_adapter );\r
776 \r
777         switch( p_pnp_rec->pnp_event )\r
778         {\r
779                 case IB_PNP_IOC_ADD:\r
780                         p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
781 \r
782                         VNIC_TRACE( VNIC_DBG_PNP, ("IB_PNP_IOC_ADD for %s.\n", p_ioc_rec->info.profile.id_string) );\r
783 \r
784                         if( p_adapter->ifc_data.ca_guid != p_ioc_rec->ca_guid )\r
785                         {\r
786                                 VNIC_TRACE_EXIT( VNIC_DBG_WARN, ("Invalid CA GUID.\n") );\r
787                                 ib_status = IB_INVALID_GUID;\r
788                                 break;\r
789                         }\r
790                         if( p_adapter->ifc_data.guid != p_ioc_rec->info.profile.ioc_guid )\r
791                         {\r
792                                 VNIC_TRACE_EXIT( VNIC_DBG_WARN, ("Invalid IOC GUID.\n") );\r
793                                 ib_status = IB_INVALID_GUID;\r
794                                 break;\r
795                         }\r
796                         /* get ioc profile data */\r
797                         NdisAcquireSpinLock( &p_adapter->lock );\r
798                 \r
799                         InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_ADD );\r
800                 \r
801                         p_adapter->ioc_info = p_ioc_rec->info;\r
802                         p_adapter->num_svc_entries = p_ioc_rec->info.profile.num_svc_entries;\r
803                 \r
804                         CL_ASSERT(p_adapter->num_svc_entries >= 2 );\r
805 \r
806                         if( !__sid_valid( p_adapter, p_ioc_rec->svc_entry_array[0].id ) )\r
807                         {\r
808                                 NdisReleaseSpinLock( &p_adapter->lock );\r
809 \r
810                                 VNIC_TRACE_EXIT( VNIC_DBG_WARN,\r
811                                         ("Invalid Service ID %#I64x\n",p_ioc_rec->svc_entry_array[0].id ) );\r
812 \r
813                                 ib_status = IB_INVALID_GUID; // should it be set INVALID_SERVICE_TYPE ?\r
814                                 break;\r
815                         }\r
816 \r
817                         p_adapter->p_svc_entries =\r
818                                         cl_zalloc( sizeof(ib_svc_entry_t) *\r
819                                         p_adapter->ioc_info.profile.num_svc_entries );\r
820 \r
821                         if( p_adapter->p_svc_entries == NULL )\r
822                         {\r
823                                 NdisReleaseSpinLock( &p_adapter->lock );\r
824 \r
825                                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("Insufficient Memory.\n") );\r
826                                 ib_status = IB_INSUFFICIENT_MEMORY;\r
827                                 break;\r
828                         }\r
829 \r
830                         cl_memcpy( p_adapter->p_svc_entries,\r
831                                                 p_ioc_rec->svc_entry_array,\r
832                                                 sizeof(ib_svc_entry_t) * p_adapter->ioc_info.profile.num_svc_entries);\r
833 \r
834                         VNIC_TRACE( VNIC_DBG_PNP,\r
835                                 ("Found %d Service Entries.\n", p_adapter->ioc_info.profile.num_svc_entries));\r
836                         NdisReleaseSpinLock( &p_adapter->lock );\r
837                         break;\r
838 \r
839                 case IB_PNP_IOC_REMOVE:\r
840                         CL_ASSERT( p_pnp_rec->guid == p_adapter->ifc_data.guid );\r
841                 \r
842                         p_ioc_rec = (ib_pnp_ioc_rec_t*)p_pnp_rec;\r
843 \r
844                         InterlockedExchange( (volatile LONG*)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE );\r
845                 \r
846                         VNIC_TRACE( VNIC_DBG_PNP, ("IB_PNP_IOC_REMOVE for %s.\n",\r
847                                                         p_adapter->ioc_info.profile.id_string) );\r
848                 \r
849                         NdisMIndicateStatus( p_adapter->h_handle,\r
850                                         NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );\r
851                                 NdisMIndicateStatusComplete( p_adapter->h_handle );\r
852                         vnic_viport_cleanup( p_adapter );\r
853                         break;\r
854 \r
855                 case IB_PNP_IOC_PATH_ADD:\r
856                         /* path for our IOC ? */\r
857                         if ( p_pnp_rec->guid != p_adapter->ifc_data.guid )\r
858                         {\r
859                                 VNIC_TRACE( VNIC_DBG_PNP,\r
860                                         ("Getting path for wrong IOC\n") );\r
861                                 ib_status = IB_INVALID_GUID;\r
862                                 break;\r
863                         }\r
864                         p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
865 \r
866                         if( p_adapter->state != INIC_UNINITIALIZED )\r
867                                 break;\r
868 \r
869                         ib_status = __path_record_add( p_adapter, &p_ioc_path->path );\r
870                         if ( ib_status != IB_SUCCESS )\r
871                         {\r
872                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
873                                         ("Failed to add path record\n") );\r
874                                 break;\r
875                         }\r
876 \r
877                         netpath_init( &p_adapter->primaryPath, p_adapter );\r
878                         p_adapter->p_currentPath = &p_adapter->primaryPath;\r
879 \r
880                         ib_status = vnic_viport_allocate( p_adapter, &p_adapter->p_viport );\r
881 \r
882                         if( ib_status != IB_SUCCESS )\r
883                         {\r
884                                 VNIC_TRACE ( VNIC_DBG_ERROR,\r
885                                                         ("Failed status %s\n", p_adapter->ifc.get_err_str( ib_status )) );\r
886                                 _vnic_viport_free( p_adapter );\r
887                                 return ib_status;\r
888                         }\r
889                 \r
890                         netpath_addPath( p_adapter->p_currentPath, p_adapter->p_viport );\r
891                         viport_setPath( p_adapter->p_viport,\r
892                                                         &p_adapter->path_record.path_rec,\r
893                                                         &p_adapter->ioc_info.profile.ioc_guid );\r
894                 \r
895                         ib_status = viport_control_connect( p_adapter->p_viport );\r
896                         if( ib_status != IB_SUCCESS )\r
897                         {\r
898                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
899                                                 ("Control path connect failed status s%\n",\r
900                                                                                 p_adapter->ifc.get_err_str( ib_status )) );\r
901                                 vnic_viport_cleanup( p_adapter );\r
902                                 break;\r
903                         }\r
904 \r
905                         ib_status = viport_data_connect( p_adapter->p_viport );\r
906                         if( ib_status != IB_SUCCESS )\r
907                         {\r
908                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
909                                         ("Data path connect failed status %s\n",\r
910                                         p_adapter->ifc.get_err_str( ib_status )) );\r
911                                 vnic_viport_cleanup( p_adapter );\r
912                                 break;\r
913                         }\r
914 \r
915                         p_adapter->state = INIC_REGISTERED;\r
916                         break;\r
917 \r
918                 case IB_PNP_IOC_PATH_REMOVE:\r
919                         p_ioc_path = (ib_pnp_ioc_path_rec_t*)p_pnp_rec;\r
920 \r
921                         VNIC_TRACE( VNIC_DBG_PNP,\r
922                                 ("IB_PNP_IOC_PATH_REMOVE (slid:%d dlid:%d) for %s.\n",\r
923                                 ntoh16( p_ioc_path->path.slid ),\r
924                                 ntoh16( p_ioc_path->path.dlid ),\r
925                                 p_adapter->ioc_info.profile.id_string));\r
926 \r
927                         ib_status = __path_record_remove( p_adapter, &p_ioc_path->path );\r
928                 \r
929                         if ( ib_status != IB_SUCCESS )\r
930                         {\r
931                                 VNIC_TRACE( VNIC_DBG_ERROR,\r
932                                         ("Failed to remove path record\n") );\r
933                         }\r
934                         break;\r
935 \r
936                 default:\r
937                         VNIC_TRACE( VNIC_DBG_PNP,\r
938                                 (" Received unhandled PnP event %#x\n", p_pnp_rec->pnp_event ) );\r
939                         break;\r
940         }\r
941 \r
942         VNIC_EXIT( VNIC_DBG_PNP );\r
943         return ib_status;\r
944 }\r
945 \r
946 \r
947 NDIS_STATUS\r
948 vnic_get_adapter_interface(\r
949         IN      NDIS_HANDLE                     h_handle,\r
950         IN      vnic_adapter_t          *p_adapter)\r
951 {\r
952 \r
953         NTSTATUS                        status;\r
954         ib_al_ifc_data_t        data;\r
955         IO_STACK_LOCATION       io_stack;\r
956         DEVICE_OBJECT           *p_pdo;\r
957 \r
958         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
959 \r
960         NdisMGetDeviceProperty( h_handle, &p_pdo, NULL, NULL, NULL, NULL );\r
961 \r
962         data.size = sizeof(ioc_ifc_data_t);\r
963         data.type = &GUID_IOC_INTERFACE_DATA;\r
964         data.version = IOC_INTERFACE_DATA_VERSION;\r
965         data.p_data = &p_adapter->ifc_data;\r
966 \r
967         io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
968         io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
969         io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
970         io_stack.Parameters.QueryInterface.Interface = (INTERFACE*)&p_adapter->ifc;\r
971         io_stack.Parameters.QueryInterface.InterfaceSpecificData = &data;\r
972         io_stack.Parameters.QueryInterface.InterfaceType = &GUID_IB_AL_INTERFACE;\r
973 \r
974         status = cl_fwd_query_ifc( p_pdo, &io_stack );\r
975 \r
976         if( !NT_SUCCESS( status ) )\r
977         {\r
978                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
979                         ("Query interface for VNIC interface returned %08x.\n", status) );\r
980                 return status;\r
981         }\r
982         /*\r
983          * Dereference the interface now so that the bus driver doesn't fail a\r
984          * query remove IRP.  We will always get unloaded before the bus driver\r
985          * since we're a child device.\r
986          */\r
987         p_adapter->ifc.wdm.InterfaceDereference(\r
988                 p_adapter->ifc.wdm.Context );\r
989 \r
990         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
991 \r
992         return NDIS_STATUS_SUCCESS;\r
993 }\r
994 \r
995 \r
996 void\r
997 vnic_viport_cleanup(\r
998                 IN      vnic_adapter_t          *p_adapter )\r
999 {\r
1000         VNIC_ENTER( VNIC_DBG_ADAPTER );\r
1001 \r
1002         if ( p_adapter->p_viport )\r
1003                 viport_cleanup(p_adapter->p_viport );\r
1004         p_adapter->p_viport = NULL;\r
1005 \r
1006         VNIC_EXIT( VNIC_DBG_ADAPTER );\r
1007 }\r