[VNIC] Initial checkin of VNIC code. Not yet fully functional.
[mirror/winof/.git] / ulp / inic / kernel / vnic_driver.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 \r
33 \r
34 #include <complib/cl_init.h>\r
35 #include "vnic_driver.h"\r
36 \r
37 \r
38 vnic_globals_t  g_vnic;\r
39 \r
40 #define DEFAULT_HOST_NAME "VNIC Host"\r
41 \r
42 //uint32_t g_vnic_dbg_lvl = VNIC_DBG_ERROR | VNIC_DBG_INIT | VNIC_DBG_IB | VNIC_DBG_INFO;\r
43 uint32_t g_vnic_dbg_lvl = VNIC_DEBUG_FLAGS;\r
44 \r
45 static void\r
46 _vnic_complete_query(\r
47         IN                              vnic_adapter_t* const           p_adapter,\r
48         IN                              pending_oid_t* const            p_oid_info,\r
49         IN              const   NDIS_STATUS                                     status,\r
50         IN              const   void* const                                     p_buf,\r
51         IN              const   ULONG                                           buf_len );\r
52 \r
53 static NDIS_STATUS\r
54 __vnic_get_tcp_task_offload(\r
55         IN                              vnic_adapter_t*                 p_adapter,\r
56         IN                              pending_oid_t* const            p_oid_info );\r
57 \r
58 static NDIS_STATUS\r
59 __vnic_set_tcp_task_offload(\r
60         IN                              vnic_adapter_t*                 p_adapter,\r
61         IN                              void* const                             p_info_buf,\r
62         IN                              ULONG* const                    p_info_len );\r
63 \r
64 static NDIS_STATUS\r
65 _vnic_process_packet_filter(\r
66                 IN      vnic_adapter_t* const   p_adapter,\r
67                 IN      ULONG                                   pkt_filter );\r
68 \r
69 static void\r
70 __vnic_read_machine_name( void );\r
71 \r
72 static NDIS_STATUS\r
73 __vnic_set_machine_name(\r
74                 IN              VOID    *p_uni_array,\r
75                 IN              USHORT  buf_size );\r
76 \r
77 /*\r
78 p_drv_obj\r
79         Pointer to Driver Object for this device driver\r
80 p_registry_path\r
81         Pointer to unicode string containing path to this driver's registry area\r
82 return\r
83         STATUS_SUCCESS, NDIS_STATUS_BAD_CHARACTERISTICS, NDIS_STATUS_BAD_VERSION,\r
84         NDIS_STATUS_RESOURCES, or NDIS_STATUS_FAILURE\r
85 IRQL = PASSIVE_LEVEL\r
86 */\r
87 NTSTATUS\r
88 DriverEntry(\r
89         IN                              PDRIVER_OBJECT                          p_drv_obj,\r
90         IN                              PUNICODE_STRING                         p_registry_path )\r
91 {\r
92         NDIS_STATUS                                             status;\r
93         NDIS_MINIPORT_CHARACTERISTICS   characteristics;\r
94 \r
95         VNIC_ENTER( VNIC_DBG_INIT );\r
96 \r
97 #ifdef _DEBUG_\r
98         PAGED_CODE();\r
99 #endif\r
100 \r
101         status = CL_INIT;\r
102 \r
103         if( !NT_SUCCESS( status ) )\r
104         {\r
105                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
106                         ("cl_init failed.\n") );\r
107                 return status;\r
108         }\r
109 \r
110         status          = NDIS_STATUS_SUCCESS;\r
111 \r
112         KeInitializeSpinLock( &g_vnic.lock );\r
113         InitializeListHead( &g_vnic.adapter_list );\r
114 \r
115         g_vnic.adapters = 0;\r
116         g_vnic.ndis_handle = NULL;\r
117 \r
118         NdisMInitializeWrapper( &g_vnic.ndis_handle, p_drv_obj, p_registry_path, NULL );\r
119 \r
120         if ( g_vnic.ndis_handle == NULL )\r
121         {\r
122                 VNIC_TRACE( VNIC_DBG_ERROR,\r
123                         ("NdisMInitializeWrapper failed\n"));\r
124                 CL_DEINIT;\r
125                 return NDIS_STATUS_FAILURE;\r
126         }\r
127 \r
128         cl_memclr( &characteristics, sizeof(characteristics) );\r
129 \r
130         characteristics.MajorNdisVersion                = MAJOR_NDIS_VERSION;\r
131         characteristics.MinorNdisVersion                = MINOR_NDIS_VERSION;\r
132         characteristics.CheckForHangHandler             = vnic_check_for_hang;\r
133         characteristics.HaltHandler                             = vnic_halt;\r
134         characteristics.InitializeHandler               = vnic_initialize;\r
135         characteristics.QueryInformationHandler = vnic_oid_query_info;\r
136         characteristics.ResetHandler                    = vnic_reset;\r
137         characteristics.SetInformationHandler   = vnic_oid_set_info;\r
138         characteristics.ReturnPacketHandler             = vnic_return_packet;\r
139         characteristics.SendPacketsHandler              = vnic_send_packets;\r
140 \r
141 #ifdef NDIS51_MINIPORT\r
142         characteristics.PnPEventNotifyHandler   = vnic_pnp_notify;\r
143         characteristics.AdapterShutdownHandler  = vnic_shutdown;\r
144 #endif\r
145 \r
146         status = NdisMRegisterMiniport(\r
147                 g_vnic.ndis_handle, &characteristics, sizeof(characteristics) );\r
148 \r
149         if( status != NDIS_STATUS_SUCCESS )\r
150         {\r
151                 VNIC_TRACE( VNIC_DBG_ERROR,\r
152                         ("NdisMRegisterMiniport failed with status of %d\n", status) );\r
153                 NdisTerminateWrapper( g_vnic.ndis_handle, NULL );\r
154                 CL_DEINIT;\r
155         }\r
156         else\r
157         {\r
158                 NdisMRegisterUnloadHandler( g_vnic.ndis_handle, vnic_unload );\r
159         \r
160                 __vnic_read_machine_name();\r
161         }\r
162 \r
163         VNIC_EXIT( VNIC_DBG_INIT );\r
164         return status;\r
165 }\r
166 \r
167 \r
168 VOID\r
169 vnic_unload(\r
170         IN                              PDRIVER_OBJECT                          p_drv_obj )\r
171 {\r
172         VNIC_ENTER( VNIC_DBG_INIT );\r
173 \r
174         UNREFERENCED_PARAMETER( p_drv_obj );\r
175         CL_DEINIT;\r
176 \r
177         VNIC_EXIT( VNIC_DBG_INIT );\r
178 }\r
179 \r
180 \r
181 //! Initialization function called for each IOC discovered\r
182 /*  The MiniportInitialize function is a required function that sets up a\r
183 NIC (or virtual NIC) for network I/O operations, claims all hardware\r
184 resources necessary to the NIC in the registry, and allocates resources\r
185 the driver needs to carry out network I/O operations.\r
186 IRQL = PASSIVE_LEVEL\r
187 \r
188 @param p_open_status Pointer to a status field set if this function returns NDIS_STATUS_OPEN_ERROR\r
189 @param p_selected_medium_index Pointer to unsigned integer noting index into medium_array for this NIC\r
190 @param medium_array Array of mediums for this NIC\r
191 @param medium_array_size Number of elements in medium_array\r
192 @param h_handle Handle assigned by NDIS for this NIC\r
193 @param wrapper_config_context Handle used for Ndis initialization functions\r
194 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_UNSUPPORTED_MEDIA, NDIS_STATUS_RESOURCES,\r
195 NDIS_STATUS_NOT_SUPPORTED\r
196 */\r
197 NDIS_STATUS\r
198 vnic_initialize(\r
199                 OUT                     PNDIS_STATUS                            p_open_status,\r
200                 OUT                     PUINT                                           p_selected_medium_index,\r
201         IN                              PNDIS_MEDIUM                            medium_array,\r
202         IN                              UINT                                            medium_array_size,\r
203         IN                              NDIS_HANDLE                                     h_handle,\r
204         IN                              NDIS_HANDLE                                     wrapper_config_context )\r
205 {\r
206         NDIS_STATUS                     status = NDIS_STATUS_SUCCESS;\r
207         ib_api_status_t         ib_status;\r
208         ib_pnp_req_t            pnp_req;\r
209         UINT                            medium_index;\r
210         vnic_adapter_t          *p_adapter;\r
211         ULONG                           buffer_size;\r
212 \r
213         VNIC_ENTER( VNIC_DBG_INIT );\r
214 \r
215 #ifdef _DEBUG_\r
216         PAGED_CODE();\r
217 #endif\r
218 \r
219         UNUSED_PARAM( p_open_status );\r
220         UNUSED_PARAM( wrapper_config_context );\r
221 \r
222         /* Search for our medium */\r
223         for( medium_index = 0; medium_index < medium_array_size; ++medium_index )\r
224         {\r
225                 /* Check to see if we found our medium */\r
226                 if( medium_array[medium_index] == NdisMedium802_3 )\r
227                         break;\r
228         }\r
229 \r
230         if( medium_index == medium_array_size ) /* Never found it */\r
231         {\r
232                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR, ("No supported media.\n") );\r
233                 return NDIS_STATUS_UNSUPPORTED_MEDIA;\r
234         }\r
235 \r
236         *p_selected_medium_index = medium_index;\r
237 \r
238                 /* Create the adapter */\r
239         ib_status = vnic_create_adapter( h_handle, &p_adapter );\r
240         if( ib_status != IB_SUCCESS )\r
241         {\r
242                 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,\r
243                         ("returned status %x\n", ib_status ) );\r
244                 return NDIS_STATUS_FAILURE;\r
245         }\r
246 \r
247         /* set NDIS features we support */\r
248         NdisMSetAttributesEx( h_handle,\r
249                                                 p_adapter,\r
250                                                 5,                                              /*check for hung t-out */\r
251                                                 NDIS_ATTRIBUTE_BUS_MASTER |\r
252                                                 NDIS_ATTRIBUTE_DESERIALIZE |\r
253                                                 NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK |\r
254                                                 NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS,\r
255                                                 NdisInterfacePNPBus );\r
256 \r
257         buffer_size = sizeof(ViportTrailer_t) +\r
258                 ROUNDUPP2(p_adapter->params.MaxMtu + sizeof(eth_hdr_t),VIPORT_TRAILER_ALIGNMENT );\r
259 \r
260         status = NdisMInitializeScatterGatherDma( h_handle, TRUE, buffer_size );\r
261         if ( status != NDIS_STATUS_SUCCESS )\r
262         {\r
263                 VNIC_TRACE( VNIC_DBG_ERROR,\r
264                         ("Init ScatterGatherDma failed status %#x\n", status ) );\r
265                 goto failure;\r
266         }\r
267 \r
268         /* Register for IOC events */\r
269         pnp_req.pfn_pnp_cb = __vnic_pnp_cb;\r
270         pnp_req.pnp_class = IB_PNP_IOC | IB_PNP_FLAG_REG_SYNC;\r
271         pnp_req.pnp_context = p_adapter;\r
272 \r
273         ib_status = p_adapter->ifc.reg_pnp( p_adapter->h_al, &pnp_req, &p_adapter->h_pnp );\r
274 \r
275         if( ib_status != IB_SUCCESS )\r
276         {\r
277                 VNIC_TRACE( VNIC_DBG_ERROR,\r
278                         ("ib_reg_pnp returned %s\n", p_adapter->ifc.get_err_str( ib_status )) );\r
279                 status = NDIS_STATUS_FAILURE;\r
280                 goto failure;\r
281         }\r
282 \r
283         if( p_adapter->state == INIC_UNINITIALIZED )\r
284         {\r
285                 status = NDIS_STATUS_FAILURE;\r
286 failure:\r
287                 vnic_destroy_adapter( p_adapter );\r
288                 return status;\r
289         }\r
290 \r
291         VNIC_EXIT( VNIC_DBG_INIT );\r
292         return status;\r
293 \r
294 }\r
295 \r
296 \r
297 //! Deallocates resources when the NIC is removed and halts the NIC..\r
298 /*  IRQL = DISPATCH_LEVEL\r
299 \r
300 @param adapter_context The adapter context allocated at start\r
301 */\r
302 void\r
303 vnic_halt(\r
304         IN                      NDIS_HANDLE                     adapter_context )\r
305 {\r
306         vnic_adapter_t  *p_adapter;\r
307 \r
308         VNIC_ENTER( VNIC_DBG_INIT );\r
309         CL_ASSERT( adapter_context );\r
310 \r
311         p_adapter = (vnic_adapter_t*)adapter_context;\r
312 \r
313         vnic_destroy_adapter( p_adapter );\r
314 \r
315         VNIC_EXIT( VNIC_DBG_INIT );\r
316 }\r
317 \r
318 \r
319 //! Reports the state of the NIC, or monitors the responsiveness of an underlying device driver.\r
320 /*  IRQL = DISPATCH_LEVEL\r
321 \r
322 @param adapter_context The adapter context allocated at start\r
323 @return TRUE if the driver determines that its NIC is not operating\r
324 */\r
325 BOOLEAN\r
326 vnic_check_for_hang(\r
327         IN                              NDIS_HANDLE                                     adapter_context )\r
328 {\r
329         vnic_adapter_t  *p_adapter;\r
330 \r
331         CL_ASSERT( adapter_context );\r
332         p_adapter = (vnic_adapter_t*)adapter_context;\r
333 \r
334         if( p_adapter->p_viport )\r
335         {\r
336                 p_adapter->hung =\r
337                         (BOOLEAN)( p_adapter->p_viport->errored != 0 );\r
338         }\r
339         if( p_adapter->hung )\r
340         {\r
341                 VNIC_TRACE( VNIC_DBG_WARN, ("Adapter Hung\n"));\r
342                 p_adapter->hung = FALSE;\r
343                 return TRUE;\r
344         }\r
345         return FALSE;\r
346 }\r
347 \r
348 \r
349 //! Returns information about the capabilities and status of the driver and/or its NIC.\r
350 /*  IRQL = DISPATCH_LEVEL\r
351 \r
352 @param adapter_context The adapter context allocated at start\r
353 @param oid Object ID representing the query operation to be carried out\r
354 @param info_buf Buffer containing any input for this query and location for output\r
355 @param info_buf_len Number of bytes available in info_buf\r
356 @param p_bytes_written Pointer to number of bytes written into info_buf\r
357 @param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
358 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
359 NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_NOT_ACCEPTED, NDIS_STATUS_NOT_SUPPORTED,\r
360 NDIS_STATUS_RESOURCES\r
361 */\r
362 NDIS_STATUS\r
363 vnic_oid_query_info(\r
364         IN                              NDIS_HANDLE                                     adapter_context,\r
365         IN                              NDIS_OID                                        oid,\r
366         IN                              PVOID                                           info_buf,\r
367         IN                              ULONG                                           info_buf_len,\r
368                 OUT                     PULONG                                          p_bytes_written,\r
369                 OUT                     PULONG                                          p_bytes_needed )\r
370 {\r
371         vnic_adapter_t          *p_adapter;\r
372         NDIS_STATUS                     status;\r
373         USHORT                          version;\r
374         uint32_t                        info32;\r
375         uint64_t                        info64;\r
376         PVOID                           src_buf;\r
377         ULONG                           buf_len;\r
378         pending_oid_t           oid_info;\r
379 \r
380         VNIC_ENTER( VNIC_DBG_OID );\r
381 \r
382         oid_info.oid = oid;\r
383         oid_info.p_buf = info_buf;\r
384         oid_info.buf_len = info_buf_len;\r
385         oid_info.p_bytes_used = p_bytes_written;\r
386         oid_info.p_bytes_needed = p_bytes_needed;\r
387 \r
388         CL_ASSERT( adapter_context );\r
389         p_adapter = (vnic_adapter_t *)adapter_context;\r
390 \r
391         CL_ASSERT( p_bytes_written );\r
392         CL_ASSERT( p_bytes_needed );\r
393 \r
394         status = NDIS_STATUS_SUCCESS;\r
395         src_buf = &info32;\r
396         buf_len = sizeof(info32);\r
397 \r
398         switch( oid )\r
399         {\r
400         /* Required General */\r
401         case OID_GEN_SUPPORTED_LIST:\r
402                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
403                         ("received query for OID_GEN_SUPPORTED_LIST\n") );\r
404                 src_buf = (PVOID)SUPPORTED_OIDS;\r
405                 buf_len = sizeof(SUPPORTED_OIDS);\r
406                 break;\r
407 \r
408         case OID_GEN_HARDWARE_STATUS:\r
409                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
410                         ("received query for OID_GEN_HARDWARE_STATUS\n") );\r
411 \r
412                 if( p_adapter->p_currentPath->carrier )\r
413                 {\r
414                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
415                                 ("returning NdisHardwareStatusReady\n") );\r
416                         info32 = NdisHardwareStatusReady;\r
417                 }\r
418                 else\r
419                 {\r
420                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
421                                 ("returning NdisHardwareStatusInitializing\n") );\r
422                         info32 = NdisHardwareStatusNotReady;\r
423                 }\r
424                 break;\r
425 \r
426         case OID_GEN_MEDIA_SUPPORTED:\r
427         case OID_GEN_MEDIA_IN_USE:\r
428                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
429                         ("received query for OID_GEN_MEDIA_SUPPORTED "\r
430                         "or OID_GEN_MEDIA_IN_USE\n") );\r
431                 info32 = NdisMedium802_3;\r
432                 break;\r
433 \r
434         case OID_GEN_MAXIMUM_FRAME_SIZE:\r
435                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
436                         ("received query for OID_GEN_MAXIMUM_FRAME_SIZE\n") );\r
437                 if( !p_adapter->p_currentPath->carrier )\r
438                 {\r
439                         info32 = p_adapter->params.MinMtu;\r
440                 }\r
441                 else\r
442                 {\r
443                         info32 = p_adapter->p_currentPath->pViport->mtu;\r
444                         /*TODO: add VLAN tag size if support request */\r
445                 }\r
446                 break;\r
447 \r
448         case OID_GEN_LINK_SPEED:\r
449                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
450                                 ("received query for OID_GEN_LINK_SPEED\n") );\r
451 \r
452                 if( p_adapter->p_currentPath->carrier )\r
453                 {\r
454                         info32 = DEFAULT_LINK_SPEED_x100BPS;  /*  x 100bps units */\r
455                 }\r
456                 else\r
457                 {\r
458                         status = NDIS_STATUS_NOT_ACCEPTED;\r
459                 }\r
460                 break;\r
461 \r
462         case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
463                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
464                         ("received query for OID_GEN_TRANSMIT_BUFFER_SPACE\n") );\r
465                 if ( !p_adapter->p_currentPath->carrier )\r
466                 {\r
467                         p_adapter->pending_query = TRUE;\r
468                         p_adapter->query_oid = oid_info;\r
469 \r
470                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
471                                 ("returning NDIS_STATUS_PENDING\n") );\r
472                         status = NDIS_STATUS_PENDING;\r
473                 }\r
474                 else\r
475                 {\r
476                         info32 = p_adapter->p_viport->data.xmitPool.bufferSz *\r
477                                 p_adapter->p_viport->data.xmitPool.poolSz;\r
478                 }\r
479                 break;\r
480 \r
481         case OID_GEN_RECEIVE_BUFFER_SPACE:\r
482                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
483                         ("received query for OID_GEN_RECEIVE_BUFFER_SPACE "\r
484                         "or OID_GEN_RECEIVE_BUFFER_SPACE\n") );\r
485                 if ( !p_adapter->p_currentPath->carrier )\r
486                 {\r
487                         p_adapter->pending_query = TRUE;\r
488                         p_adapter->query_oid = oid_info;\r
489 \r
490                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
491                                 ("returning NDIS_STATUS_PENDING\n") );\r
492                         status = NDIS_STATUS_PENDING;\r
493                 }\r
494                 else\r
495                 {\r
496                         info32 = p_adapter->p_viport->data.recvPool.bufferSz *\r
497                                 p_adapter->p_viport->data.recvPool.poolSz;\r
498                 }\r
499                 break;\r
500         case OID_GEN_MAXIMUM_LOOKAHEAD:\r
501         case OID_GEN_CURRENT_LOOKAHEAD:\r
502         case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
503         case OID_GEN_RECEIVE_BLOCK_SIZE:\r
504         case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
505                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
506                         ("received query for OID_GEN_MAXIMUM_LOOKAHEAD "\r
507                         "or OID_GEN_CURRENT_LOOKAHEAD or "\r
508                         "OID_GEN_TRANSMIT_BLOCK_SIZE or "\r
509                         "OID_GEN_RECEIVE_BLOCK_SIZE or "\r
510                         "OID_GEN_MAXIMUM_TOTAL_SIZE\n") );\r
511                 if( !p_adapter->p_currentPath->carrier )\r
512                 {\r
513                         info32 = p_adapter->params.MinMtu;\r
514                 }\r
515                 else\r
516                 {\r
517                         info32 = p_adapter->p_currentPath->pViport->mtu;\r
518                 }\r
519                 /*TODO: add VLAN tag size if support requested */\r
520                 info32 += sizeof(eth_hdr_t);\r
521                 break;\r
522 \r
523         case OID_GEN_VENDOR_ID:\r
524                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
525                         ("received query for OID_GEN_VENDOR_ID\n") );\r
526 \r
527                 src_buf = (void*)VENDOR_ID;\r
528                 buf_len = sizeof(VENDOR_ID);\r
529                 break;\r
530 \r
531         case OID_GEN_VENDOR_DESCRIPTION:\r
532                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
533                         ("received query for OID_GEN_VENDOR_DESCRIPTION\n") );\r
534                 src_buf = VENDOR_DESCRIPTION;\r
535                 buf_len = sizeof(VENDOR_DESCRIPTION);\r
536                 break;\r
537 \r
538         case OID_GEN_VENDOR_DRIVER_VERSION:\r
539                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
540                         ("  received query for OID_GEN_VENDOR_DRIVER_VERSION\n" ) );\r
541                 src_buf = &version;\r
542                 buf_len = sizeof(version);\r
543                 //TODO: Figure out what the right version is.\r
544                 version = INIC_MAJORVERSION << 8 | INIC_MINORVERSION;\r
545                 break;\r
546 \r
547         case OID_GEN_PHYSICAL_MEDIUM:\r
548                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
549                         ("  received query for OID_GEN_PHYSICAL_MEDIUM\n" ) );\r
550                 info32 = NdisPhysicalMediumUnspecified;\r
551                 break;\r
552 \r
553         case OID_GEN_CURRENT_PACKET_FILTER:\r
554                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
555                         ("  received query for OID_GEN_CURRENT_PACKET_FILTER\n" ) );\r
556                 info32 = p_adapter->packet_filter;\r
557                 break;\r
558 \r
559         case OID_GEN_DRIVER_VERSION:\r
560                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
561                         ("  received query for OID_GEN_DRIVER_VERSION\n" ) );\r
562                 src_buf = &version;\r
563                 buf_len = sizeof(version);\r
564                 version = MAJOR_NDIS_VERSION << 8 | MINOR_NDIS_VERSION;\r
565                 break;\r
566 \r
567         case OID_GEN_MAC_OPTIONS:\r
568                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
569                         ("  received query for OID_GEN_MAC_OPTIONS\n" ) );\r
570                 info32 = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |\r
571                                 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |\r
572                                 NDIS_MAC_OPTION_NO_LOOPBACK |\r
573                                 NDIS_MAC_OPTION_FULL_DUPLEX ;\r
574 //TODO: Figure out if we will support priority and VLANs.\r
575 //                              NDIS_MAC_OPTION_8021P_PRIORITY;\r
576 //#ifdef NDIS51_MINIPORT\r
577 //                      info |= NDIS_MAC_OPTION_8021Q_VLAN;\r
578 //#endif\r
579                 break;\r
580 \r
581         case OID_GEN_MEDIA_CONNECT_STATUS:\r
582                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
583                         ("  received query for OID_GEN_MEDIA_CONNECT_STATUS\n" ) );\r
584 \r
585                 info32 =  ( p_adapter->carrier )?\r
586                                         NdisMediaStateConnected :\r
587                                         NdisMediaStateDisconnected;\r
588                 break;\r
589 \r
590         case OID_GEN_MAXIMUM_SEND_PACKETS:\r
591                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
592                         ("  received query for OID_GEN_MAXIMUM_SEND_PACKETS\n" ) );\r
593                 info32 = MAXLONG; // NDIS ignored it anyway\r
594                 break;\r
595 \r
596         /* Required General Statistics */\r
597         case OID_GEN_XMIT_OK:\r
598                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
599                         ("  received query for OID_GEN_XMIT_OK\n" ) );\r
600                 if ( !p_adapter->p_currentPath->carrier )\r
601                 {\r
602                         info32 = 0;\r
603                 }\r
604                 else\r
605                 {\r
606                         info64  = p_adapter->p_viport->stats.ifOutOk;\r
607                         src_buf = &info64;\r
608                         buf_len = sizeof(info64);\r
609                 }\r
610                 break;\r
611 \r
612         case OID_GEN_RCV_OK:\r
613                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
614                         ("  received query for OID_GEN_RCV_OK\n" ) );\r
615                 if ( !p_adapter->p_currentPath->carrier)\r
616                 {\r
617                         info32 = 0;\r
618                         break;\r
619                 }\r
620                 if ( info_buf_len == sizeof(info32) )\r
621                 {\r
622                         info32 = (uint32_t)p_adapter->p_viport->stats.ifInOk;\r
623                 }\r
624                 else\r
625                 {\r
626                         info64  = p_adapter->p_viport->stats.ifInOk;\r
627                         src_buf = &info64;\r
628                         buf_len = sizeof(info64);\r
629                 }\r
630                 break;\r
631 \r
632         case OID_GEN_XMIT_ERROR:\r
633                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
634                         ("  received query for OID_GEN_XMIT_ERROR\n" ) );\r
635                 if ( !p_adapter->p_currentPath->carrier )\r
636                 {\r
637                         info32 = 0;\r
638                 }\r
639                 else\r
640                 {\r
641                 info64  = p_adapter->p_viport->stats.ifOutErrors;\r
642                 src_buf = &info64;\r
643                 buf_len = sizeof(info64);\r
644                 }\r
645                 break;\r
646 \r
647         case OID_GEN_RCV_ERROR:\r
648                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
649                         ("  received query for OID_GEN_RCV_ERROR\n" ) );\r
650                 if ( !p_adapter->p_currentPath->carrier )\r
651                 {\r
652                         info32 = 0;\r
653                 }\r
654                 else\r
655                 {\r
656                 info64 = p_adapter->p_viport->stats.ifInErrors;\r
657                 src_buf = &info64;\r
658                 buf_len = sizeof(info64);\r
659                 }\r
660                 break;\r
661 \r
662         case OID_GEN_RCV_NO_BUFFER:\r
663                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
664                         ("  received query for OID_GEN_RCV_NO_BUFFER\n" ) );\r
665                 info32 = 0;\r
666                 status = NDIS_STATUS_SUCCESS;\r
667                 break;\r
668 \r
669         case OID_GEN_DIRECTED_BYTES_XMIT:\r
670                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
671                         ("  received query for OID_GEN_DIRECTED_BYTES_XMIT\n" ) );\r
672                 if ( !p_adapter->p_currentPath->carrier )\r
673                 {\r
674                         info32 = 0;\r
675                 }\r
676                 else\r
677                 {\r
678                 info64 = p_adapter->p_viport->stats.ifOutUcastBytes;\r
679                 src_buf = &info64;\r
680                 buf_len = sizeof(info64);\r
681                 }\r
682                 break;\r
683 \r
684         case OID_GEN_DIRECTED_FRAMES_XMIT:\r
685                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
686                         ("  received query for OID_GEN_DIRECTED_FRAMES_XMIT\n" ) );\r
687                 if ( !p_adapter->p_currentPath->carrier )\r
688                 {\r
689                         info32 = 0;\r
690                 }\r
691                 else\r
692                 {\r
693                 info64 = p_adapter->p_viport->stats.ifOutNUcastPkts;\r
694                 src_buf = &info64;\r
695                 buf_len = sizeof(info64);\r
696                 }\r
697                 break;\r
698 \r
699         case OID_GEN_MULTICAST_BYTES_XMIT:\r
700                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
701                         ("  received query for OID_GEN_MULTICAST_BYTES_XMIT\n" ) );\r
702                 if ( !p_adapter->p_currentPath->carrier )\r
703                 {\r
704                         info32 = 0;\r
705                 }\r
706                 else\r
707                 {\r
708                 info64 = p_adapter->p_viport->stats.ifOutMulticastBytes;\r
709                 src_buf = &info64;\r
710                 buf_len = sizeof(info64);\r
711                 }\r
712                 break;\r
713 \r
714         case OID_GEN_MULTICAST_FRAMES_XMIT:\r
715                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
716                         ("  received query for OID_GEN_MULTICAST_FRAMES_XMIT\n" ) );\r
717                 if ( !p_adapter->p_currentPath->carrier )\r
718                 {\r
719                         info32 = 0;\r
720                 }\r
721                 else\r
722                 {\r
723                 info64 = p_adapter->p_viport->stats.ifOutMulticastPkts;\r
724                 src_buf = &info64;\r
725                 buf_len = sizeof(info64);\r
726                 }\r
727                 break;\r
728 \r
729         case OID_GEN_BROADCAST_BYTES_XMIT:\r
730                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
731                         ("  received query for OID_GEN_BROADCAST_BYTES_XMIT\n" ) );\r
732                 if ( !p_adapter->p_currentPath->carrier )\r
733                 {\r
734                         info32 = 0;\r
735                 }\r
736                 else\r
737                 {\r
738                         info64 = p_adapter->p_viport->stats.ifOutBroadcastBytes;\r
739                         src_buf = &info64;\r
740                         buf_len = sizeof(info64);\r
741                 }\r
742                 break;\r
743 \r
744         case OID_GEN_BROADCAST_FRAMES_XMIT:\r
745                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
746                         ("  received query for OID_GEN_BROADCAST_FRAMES_XMIT\n" ) );\r
747                 if ( !p_adapter->p_currentPath->carrier )\r
748                 {\r
749                         info32 = 0;\r
750                 }\r
751                 else\r
752                 {\r
753                 info64 = p_adapter->p_viport->stats.ifOutBroadcastPkts;\r
754                 src_buf = &info64;\r
755                 buf_len = sizeof(info64);\r
756                 }\r
757                 break;\r
758         case OID_GEN_DIRECTED_BYTES_RCV:\r
759                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
760                         ("  received query for OID_GEN_DIRECTED_BYTES_RCV\n" ) );\r
761                 if ( !p_adapter->p_currentPath->carrier )\r
762                 {\r
763                         info32 = 0;\r
764                 }\r
765                 else\r
766                 {\r
767                 info64 = p_adapter->p_viport->stats.ifInUcastBytes;\r
768                 src_buf = &info64;\r
769                 buf_len = sizeof(info64);\r
770                 }\r
771                 break;\r
772 \r
773         case OID_GEN_DIRECTED_FRAMES_RCV:\r
774                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
775                         ("  received query for OID_GEN_DIRECTED_FRAMES_RCV\n" ) );\r
776                 if ( !p_adapter->p_currentPath->carrier )\r
777                 {\r
778                         info32 = 0;\r
779                 }\r
780                 else\r
781                 {\r
782                 info64 = p_adapter->p_viport->stats.ifInNUcastPkts;\r
783                 src_buf = &info64;\r
784                 buf_len = sizeof(info64);\r
785                 }\r
786                 break;\r
787 \r
788         case OID_GEN_MULTICAST_BYTES_RCV:\r
789                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
790                         ("  received query for OID_GEN_MULTICAST_BYTES_RCV\n" ) );\r
791                 if ( !p_adapter->p_currentPath->carrier )\r
792                 {\r
793                         info32 = 0;\r
794                 }\r
795                 else\r
796                 {\r
797                 info64 = p_adapter->p_viport->stats.ifInMulticastBytes;\r
798                 src_buf = &info64;\r
799                 buf_len = sizeof(info64);\r
800                 }\r
801                 break;\r
802 \r
803         case OID_GEN_MULTICAST_FRAMES_RCV:\r
804                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
805                         ("  received query for OID_GEN_MULTICAST_FRAMES_RCV\n" ) );\r
806                 if ( !p_adapter->p_currentPath->carrier )\r
807                 {\r
808                         info32 = 0;\r
809                 }\r
810 \r
811                 else\r
812                 {\r
813                 info64 = p_adapter->p_viport->stats.ifInMulticastPkts;\r
814                 src_buf = &info64;\r
815                 buf_len = sizeof(info64);\r
816                 }\r
817                 break;\r
818 \r
819         case OID_GEN_BROADCAST_BYTES_RCV:\r
820                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
821                         ("  received query for OID_GEN_BROADCAST_BYTES_RCV\n" ) );\r
822                 if ( !p_adapter->p_currentPath->carrier )\r
823                 {\r
824                         info32 = 0;\r
825                 }\r
826                 else\r
827                 {\r
828                 info64 = p_adapter->p_viport->stats.ifInBroadcastBytes;\r
829                 src_buf = &info64;\r
830                 buf_len = sizeof(info64);\r
831                 }\r
832                 break;\r
833 \r
834         case OID_GEN_BROADCAST_FRAMES_RCV:\r
835                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
836                         ("  received query for OID_GEN_BROADCAST_FRAMES_RCV\n" ) );\r
837                 if ( !p_adapter->p_currentPath->carrier )\r
838                 {\r
839                         info32 = 0;\r
840                 }\r
841                 else\r
842                 {\r
843                 info64 = p_adapter->p_viport->stats.ifInBroadcastPkts;\r
844                 src_buf = &info64;\r
845                 buf_len = sizeof(info64);\r
846                 }\r
847                 break;\r
848 \r
849         /* Required Ethernet operational characteristics */\r
850         case OID_802_3_PERMANENT_ADDRESS:\r
851         case OID_802_3_CURRENT_ADDRESS:\r
852 #if defined( _DEBUG_ )\r
853                 if( oid == OID_802_3_PERMANENT_ADDRESS )\r
854                 {\r
855                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
856                                 ("  received query for OID_802_3_PERMANENT_ADDRESS\n" ) );\r
857                 }\r
858                 else\r
859                 {\r
860                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
861                                 ("  received query for OID_802_3_CURRENT_ADDRESS\n" ) );\r
862                 }\r
863 #endif  /* defined( _DEBUG_ )*/\r
864                 if ( !p_adapter->macSet )\r
865                 {\r
866                         p_adapter->pending_query = TRUE;\r
867                         p_adapter->query_oid = oid_info;\r
868 \r
869                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
870                                 ("returning NDIS_STATUS_PENDING\n") );\r
871                         status = NDIS_STATUS_PENDING;\r
872                 }\r
873                 else\r
874                 {\r
875                         src_buf = &p_adapter->p_viport->hwMacAddress;\r
876                         buf_len = HW_ADDR_LEN;\r
877                 }\r
878                 break;\r
879 \r
880         case OID_802_3_MULTICAST_LIST:\r
881                 VNIC_TRACE( VNIC_DBG_INFO,\r
882                         ("  received query for OID_802_3_MULTICAST_LIST\n" ) );\r
883         \r
884                 if (!p_adapter->p_currentPath->carrier &&\r
885                         !(p_adapter->p_viport->flags & INIC_FLAG_ENABLE_NIC) )\r
886                 {\r
887                         p_adapter->pending_query = TRUE;\r
888                         p_adapter->query_oid = oid_info;\r
889 \r
890                         VNIC_TRACE( VNIC_DBG_INFO,\r
891                                 ("returning NDIS_STATUS_PENDING\n") );\r
892                         status = NDIS_STATUS_PENDING;\r
893                 }\r
894                 else if ( p_adapter->mc_count > 0 )\r
895                 {\r
896                         buf_len = p_adapter->mc_count * sizeof( mac_addr_t );\r
897                         src_buf = &p_adapter->mcast_array;\r
898                 }\r
899                 else\r
900                 {\r
901                         info32 = 0;\r
902                 }\r
903                 break;\r
904 \r
905         case OID_802_3_MAXIMUM_LIST_SIZE:\r
906                 VNIC_TRACE( VNIC_DBG_INFO,\r
907                         ("  received query for OID_802_3_MAXIMUM_LIST_SIZE\n" ) );\r
908                 if ( !p_adapter->macSet )\r
909                 {\r
910                         info32 = MAX_MCAST;\r
911                 }\r
912                 else\r
913                 {\r
914                         info32 = p_adapter->p_viport->numMacAddresses - MCAST_ADDR_START;\r
915                 }\r
916                 break;\r
917         case OID_802_3_MAC_OPTIONS:\r
918                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
919                         ("  received query for OID_802_3_MAC_OPTIONS\n" ) );\r
920                 info32 = 0;\r
921                 break;\r
922 \r
923         /* Required Ethernet stats */\r
924         case OID_802_3_RCV_ERROR_ALIGNMENT:\r
925         case OID_802_3_XMIT_ONE_COLLISION:\r
926         case OID_802_3_XMIT_MORE_COLLISIONS:\r
927                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
928                         ("  received query for OID_802_3_RCV_ERROR_ALIGNMENT or "\r
929                         "OID_802_3_XMIT_ONE_COLLISION or "\r
930                         "OID_802_3_XMIT_MORE_COLLISIONS\n" ) );\r
931                 info32 = 0;\r
932                 break;\r
933 \r
934         case OID_TCP_TASK_OFFLOAD:\r
935                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
936                         ("  received query for OID_TCP_TASK_OFFLOAD\n" ) );\r
937 \r
938                 src_buf = NULL;\r
939                 status = __vnic_get_tcp_task_offload( p_adapter, &oid_info );\r
940                 break;\r
941 \r
942         /* Optional General */\r
943         case OID_GEN_SUPPORTED_GUIDS:\r
944 #ifdef NDIS51_MINIPORT\r
945         case OID_GEN_VLAN_ID:\r
946 #endif\r
947 \r
948         /* Optional General Stats */\r
949         case OID_GEN_RCV_CRC_ERROR:\r
950         case OID_GEN_TRANSMIT_QUEUE_LENGTH:\r
951 \r
952         /* Optional Ethernet Stats */\r
953         case OID_802_3_XMIT_DEFERRED:\r
954         case OID_802_3_XMIT_MAX_COLLISIONS:\r
955         case OID_802_3_RCV_OVERRUN:\r
956         case OID_802_3_XMIT_UNDERRUN:\r
957         case OID_802_3_XMIT_HEARTBEAT_FAILURE:\r
958         case OID_802_3_XMIT_TIMES_CRS_LOST:\r
959         case OID_802_3_XMIT_LATE_COLLISIONS:\r
960         case OID_PNP_CAPABILITIES:\r
961                 status = NDIS_STATUS_NOT_SUPPORTED;\r
962                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
963                         ("  received an unsupported oid of 0x%.8X!\n" , oid) );\r
964                 break;\r
965 \r
966         case OID_GEN_PROTOCOL_OPTIONS:\r
967         case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
968 #ifdef NDIS51_MINIPORT\r
969         case OID_GEN_MACHINE_NAME:\r
970         case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
971 #endif\r
972         default:\r
973                 status = NDIS_STATUS_INVALID_OID;\r
974                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
975                         ("  received an invalid oid of 0x%.8X!\n" , oid) );\r
976                 break;\r
977         }\r
978 \r
979         /*\r
980          * Complete the request as if it was handled asynchronously to maximize\r
981          * code reuse for when we really handle the requests asynchronously.\r
982          * Note that this requires the QueryInformation entry point to always\r
983          * return NDIS_STATUS_PENDING\r
984          */\r
985         if( status != NDIS_STATUS_PENDING )\r
986         {\r
987                 _vnic_complete_query(\r
988                         p_adapter, &oid_info, status, src_buf, buf_len );\r
989         }\r
990 \r
991         VNIC_EXIT( VNIC_DBG_OID );\r
992         return NDIS_STATUS_PENDING;\r
993 }\r
994 \r
995 \r
996 static void\r
997 _vnic_complete_query(\r
998         IN                              vnic_adapter_t* const           p_adapter,\r
999         IN                              pending_oid_t* const            p_oid_info,\r
1000         IN              const   NDIS_STATUS                                     status,\r
1001         IN              const   void* const                                     p_buf,\r
1002         IN              const   ULONG                                           buf_len )\r
1003 {\r
1004         NDIS_STATUS             oid_status = status;\r
1005 \r
1006         VNIC_ENTER( VNIC_DBG_OID );\r
1007 \r
1008         CL_ASSERT( status != NDIS_STATUS_PENDING );\r
1009 \r
1010         if( status == NDIS_STATUS_SUCCESS )\r
1011         {\r
1012                 if( p_oid_info->buf_len < buf_len )\r
1013                 {\r
1014                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1015                                 ("Insufficient buffer space.  "\r
1016                                 "Returning NDIS_STATUS_INVALID_LENGTH.\n") );\r
1017                         oid_status = NDIS_STATUS_INVALID_LENGTH;\r
1018                         *p_oid_info->p_bytes_needed = buf_len;\r
1019                         *p_oid_info->p_bytes_used = 0;\r
1020                 }\r
1021                 else if( p_oid_info->p_buf )\r
1022                 {\r
1023                         /* Only copy if we have a distinct source buffer. */\r
1024                         if( p_buf )\r
1025                         {\r
1026                                 NdisMoveMemory( p_oid_info->p_buf, p_buf, buf_len );\r
1027                                 *p_oid_info->p_bytes_used = buf_len;\r
1028                         }\r
1029                 }\r
1030                 else\r
1031                 {\r
1032                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1033                                 ("Returning NDIS_NOT_ACCEPTED") );\r
1034                         oid_status = NDIS_STATUS_NOT_ACCEPTED;\r
1035                 }\r
1036         }\r
1037         else\r
1038         {\r
1039                 *p_oid_info->p_bytes_used = 0;\r
1040         }\r
1041 \r
1042         p_adapter->pending_query = FALSE;\r
1043 \r
1044         NdisMQueryInformationComplete( p_adapter->h_handle, oid_status );\r
1045 \r
1046         VNIC_EXIT( VNIC_DBG_OID );\r
1047 }\r
1048 \r
1049 \r
1050 static NDIS_STATUS\r
1051 __vnic_get_tcp_task_offload(\r
1052         IN                              vnic_adapter_t*                 p_adapter,\r
1053         IN                              pending_oid_t* const            p_oid_info )\r
1054 {\r
1055         NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
1056         NDIS_TASK_OFFLOAD                       *p_offload_task;\r
1057         NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
1058         //uint8_t                                               port_num;\r
1059         ULONG                                           buf_len;\r
1060 \r
1061         buf_len = sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
1062                 sizeof(NDIS_TASK_OFFLOAD) +\r
1063                 sizeof(NDIS_TASK_TCP_IP_CHECKSUM) - 1;\r
1064 \r
1065         *(p_oid_info->p_bytes_needed) = buf_len;\r
1066 \r
1067         if( p_oid_info->buf_len < buf_len )\r
1068                 return NDIS_STATUS_INVALID_LENGTH;\r
1069 \r
1070         p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_oid_info->p_buf;\r
1071         if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
1072                 return NDIS_STATUS_INVALID_DATA;\r
1073 \r
1074         if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
1075                 IEEE_802_3_Encapsulation )\r
1076         {\r
1077                 return NDIS_STATUS_INVALID_DATA;\r
1078         }\r
1079 \r
1080         p_offload_hdr->OffsetFirstTask = sizeof(NDIS_TASK_OFFLOAD_HEADER);\r
1081         p_offload_task = (NDIS_TASK_OFFLOAD*)(p_offload_hdr + 1);\r
1082         p_offload_task->Version = NDIS_TASK_OFFLOAD_VERSION;\r
1083         p_offload_task->Size = sizeof(NDIS_TASK_OFFLOAD);\r
1084         p_offload_task->Task = TcpIpChecksumNdisTask;\r
1085         p_offload_task->OffsetNextTask = 0;\r
1086         p_offload_task->TaskBufferLength = sizeof(NDIS_TASK_TCP_IP_CHECKSUM);\r
1087         p_offload_chksum =\r
1088                 (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
1089 \r
1090         p_offload_chksum->V4Transmit.IpOptionsSupported =\r
1091                                                                 p_adapter->params.UseTxCsum;\r
1092         p_offload_chksum->V4Transmit.TcpOptionsSupported =\r
1093                                                                 p_adapter->params.UseTxCsum;\r
1094         p_offload_chksum->V4Transmit.TcpChecksum =\r
1095                                                                 p_adapter->params.UseTxCsum;\r
1096         p_offload_chksum->V4Transmit.UdpChecksum =\r
1097                                                                 p_adapter->params.UseTxCsum;\r
1098         p_offload_chksum->V4Transmit.IpChecksum =\r
1099                                                                 p_adapter->params.UseTxCsum;\r
1100 \r
1101         p_offload_chksum->V4Receive.IpOptionsSupported = TRUE;\r
1102         p_offload_chksum->V4Receive.TcpOptionsSupported = TRUE;\r
1103         p_offload_chksum->V4Receive.TcpChecksum =\r
1104                                                                 p_adapter->params.UseRxCsum;\r
1105         p_offload_chksum->V4Receive.UdpChecksum =\r
1106                                                                 p_adapter->params.UseRxCsum;\r
1107         p_offload_chksum->V4Receive.IpChecksum =\r
1108                                                                 p_adapter->params.UseRxCsum;\r
1109 \r
1110         p_offload_chksum->V6Transmit.IpOptionsSupported = FALSE;\r
1111         p_offload_chksum->V6Transmit.TcpOptionsSupported = FALSE;\r
1112         p_offload_chksum->V6Transmit.TcpChecksum = FALSE;\r
1113         p_offload_chksum->V6Transmit.UdpChecksum = FALSE;\r
1114 \r
1115         p_offload_chksum->V6Receive.IpOptionsSupported = FALSE;\r
1116         p_offload_chksum->V6Receive.TcpOptionsSupported = FALSE;\r
1117         p_offload_chksum->V6Receive.TcpChecksum = FALSE;\r
1118         p_offload_chksum->V6Receive.UdpChecksum = FALSE;\r
1119 \r
1120         *(p_oid_info->p_bytes_used) = buf_len;\r
1121 \r
1122         return NDIS_STATUS_SUCCESS;\r
1123 }\r
1124 \r
1125 static NDIS_STATUS\r
1126 __vnic_set_tcp_task_offload(\r
1127         IN                              vnic_adapter_t*                 p_adapter,\r
1128         IN                              void* const                             p_info_buf,\r
1129         IN                              ULONG* const                    p_info_len )\r
1130 {\r
1131         NDIS_TASK_OFFLOAD_HEADER        *p_offload_hdr;\r
1132         NDIS_TASK_OFFLOAD                       *p_offload_task;\r
1133         NDIS_TASK_TCP_IP_CHECKSUM       *p_offload_chksum;\r
1134 \r
1135         VNIC_ENTER( VNIC_DBG_OID );\r
1136 \r
1137         p_offload_hdr = (NDIS_TASK_OFFLOAD_HEADER*)p_info_buf;\r
1138 \r
1139         if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
1140                 return NDIS_STATUS_INVALID_LENGTH;\r
1141 \r
1142         if( p_offload_hdr->Version != NDIS_TASK_OFFLOAD_VERSION )\r
1143                 return NDIS_STATUS_INVALID_DATA;\r
1144 \r
1145         if( p_offload_hdr->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER) )\r
1146                 return NDIS_STATUS_INVALID_LENGTH;\r
1147 \r
1148         if( !p_offload_hdr->OffsetFirstTask )\r
1149                 return NDIS_STATUS_SUCCESS;\r
1150 \r
1151         if( p_offload_hdr->EncapsulationFormat.Encapsulation !=\r
1152                 IEEE_802_3_Encapsulation )\r
1153         {\r
1154                 return NDIS_STATUS_INVALID_DATA;\r
1155         }\r
1156 \r
1157         p_offload_task = (NDIS_TASK_OFFLOAD*)\r
1158                 (((UCHAR*)p_offload_hdr) + p_offload_hdr->OffsetFirstTask);\r
1159 \r
1160         if( *p_info_len < sizeof(NDIS_TASK_OFFLOAD_HEADER) +\r
1161                 offsetof( NDIS_TASK_OFFLOAD, TaskBuffer ) +\r
1162                 sizeof(NDIS_TASK_TCP_IP_CHECKSUM) )\r
1163         {\r
1164                 return NDIS_STATUS_INVALID_LENGTH;\r
1165         }\r
1166 \r
1167         if( p_offload_task->Version != NDIS_TASK_OFFLOAD_VERSION )\r
1168                 return NDIS_STATUS_INVALID_DATA;\r
1169         p_offload_chksum =\r
1170                 (NDIS_TASK_TCP_IP_CHECKSUM*)p_offload_task->TaskBuffer;\r
1171 \r
1172         if( !p_adapter->params.UseTxCsum &&\r
1173                 (p_offload_chksum->V4Transmit.IpOptionsSupported ||\r
1174                 p_offload_chksum->V4Transmit.TcpOptionsSupported ||\r
1175                 p_offload_chksum->V4Transmit.TcpChecksum ||\r
1176                 p_offload_chksum->V4Transmit.UdpChecksum ||\r
1177                 p_offload_chksum->V4Transmit.IpChecksum) )\r
1178         {\r
1179                 return NDIS_STATUS_NOT_SUPPORTED;\r
1180         }\r
1181 \r
1182         if( !p_adapter->params.UseRxCsum &&\r
1183                 (p_offload_chksum->V4Receive.IpOptionsSupported ||\r
1184                 p_offload_chksum->V4Receive.TcpOptionsSupported ||\r
1185                 p_offload_chksum->V4Receive.TcpChecksum ||\r
1186                 p_offload_chksum->V4Receive.UdpChecksum ||\r
1187                 p_offload_chksum->V4Receive.IpChecksum) )\r
1188         {\r
1189                 return NDIS_STATUS_NOT_SUPPORTED;\r
1190         }\r
1191         if( p_offload_chksum->V6Receive.IpOptionsSupported ||\r
1192                 p_offload_chksum->V6Receive.TcpOptionsSupported ||\r
1193                 p_offload_chksum->V6Receive.TcpChecksum ||\r
1194                 p_offload_chksum->V6Receive.UdpChecksum  ||\r
1195                 p_offload_chksum->V6Transmit.IpOptionsSupported ||\r
1196                 p_offload_chksum->V6Transmit.TcpOptionsSupported ||\r
1197                 p_offload_chksum->V6Transmit.TcpChecksum ||\r
1198                 p_offload_chksum->V6Transmit.UdpChecksum )\r
1199         {\r
1200                 return NDIS_STATUS_NOT_SUPPORTED;\r
1201         }\r
1202         VNIC_EXIT( VNIC_DBG_OID );\r
1203 \r
1204         return NDIS_STATUS_SUCCESS;\r
1205 }\r
1206 \r
1207 \r
1208 //! Issues a hardware reset to the NIC and/or resets the driver's software state.\r
1209 /*  Tear down the connection and start over again.  This is only called when there is a problem.\r
1210 For example, if a send, query info, or set info had a time out.  MiniportCheckForHang will\r
1211 be called first.\r
1212 IRQL = DISPATCH_LEVEL\r
1213 \r
1214 @param p_addr_resetPointer to BOOLLEAN that is set to TRUE if the NDIS\r
1215 library should call MiniportSetInformation to restore addressing information to the current values.\r
1216 @param adapter_context The adapter context allocated at start\r
1217 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_NOT_RESETTABLE,\r
1218 NDIS_STATUS_RESET_IN_PROGRESS, NDIS_STATUS_SOFT_ERRORS, NDIS_STATUS_HARD_ERRORS\r
1219 */\r
1220 NDIS_STATUS\r
1221 vnic_reset(\r
1222                 OUT                     PBOOLEAN                                        p_addr_reset,\r
1223         IN                              NDIS_HANDLE                                     adapter_context)\r
1224 {\r
1225 //      vnic_adapter_t* p_adapter;\r
1226 \r
1227         VNIC_ENTER( VNIC_DBG_INIT );\r
1228         CL_ASSERT( p_addr_reset );\r
1229         CL_ASSERT( adapter_context );\r
1230         //p_adapter = (vnic_adapter_t*)adapter_context;\r
1231         *p_addr_reset = TRUE;\r
1232 \r
1233         UNREFERENCED_PARAMETER( adapter_context );\r
1234 \r
1235         VNIC_EXIT( VNIC_DBG_INIT );\r
1236         return NDIS_STATUS_NOT_RESETTABLE;\r
1237 }\r
1238 \r
1239 \r
1240 //! Request changes in the state information that the miniport driver maintains\r
1241 /*  For example, this is used to set multicast addresses and the packet filter.\r
1242 IRQL = DISPATCH_LEVEL\r
1243 \r
1244 @param adapter_context The adapter context allocated at start\r
1245 @param oid Object ID representing the set operation to be carried out\r
1246 @param info_buf Buffer containing input for this set and location for any output\r
1247 @param info_buf_len Number of bytes available in info_buf\r
1248 @param p_bytes_read Pointer to number of bytes read from info_buf\r
1249 @param p_bytes_needed Pointer to number of bytes needed to satisfy this oid\r
1250 @return NDIS_STATUS_SUCCESS, NDIS_STATUS_PENDING, NDIS_STATUS_INVALID_OID,\r
1251 NDIS_STATUS_INVALID_LENGTH, NDIS_STATUS_INVALID_DATA, NDIS_STATUS_NOT_ACCEPTED,\r
1252 NDIS_STATUS_NOT_SUPPORTED, NDIS_STATUS_RESOURCES\r
1253 */\r
1254 NDIS_STATUS\r
1255 vnic_oid_set_info(\r
1256         IN                              NDIS_HANDLE                                     adapter_context,\r
1257         IN                              NDIS_OID                                        oid,\r
1258         IN                              PVOID                                           info_buf,\r
1259         IN                              ULONG                                           info_buf_len,\r
1260                 OUT                     PULONG                                          p_bytes_read,\r
1261                 OUT                     PULONG                                          p_bytes_needed )\r
1262 {\r
1263         vnic_adapter_t*         p_adapter;\r
1264         NDIS_STATUS                     status;\r
1265         ULONG                           buf_len;\r
1266         pending_oid_t           oid_info;\r
1267 \r
1268         VNIC_ENTER( VNIC_DBG_OID );\r
1269 \r
1270         CL_ASSERT( adapter_context );\r
1271         p_adapter = (vnic_adapter_t*)adapter_context;\r
1272 \r
1273         CL_ASSERT( p_bytes_read );\r
1274         CL_ASSERT( p_bytes_needed );\r
1275         CL_ASSERT( !p_adapter->pending_set );\r
1276 \r
1277         status = NDIS_STATUS_SUCCESS;\r
1278         *p_bytes_needed = 0;\r
1279         buf_len = sizeof(ULONG);\r
1280 \r
1281         oid_info.oid = oid;\r
1282         oid_info.p_buf = info_buf;\r
1283         oid_info.buf_len = info_buf_len;\r
1284         oid_info.p_bytes_used = p_bytes_read;\r
1285         oid_info.p_bytes_needed = p_bytes_needed;\r
1286 \r
1287         /* do not set anything until IB path initialized and NIC is enabled */\r
1288         if( !p_adapter->p_currentPath->carrier )\r
1289         {\r
1290                 *p_bytes_read = 0;\r
1291                 return NDIS_STATUS_NOT_ACCEPTED;\r
1292         }\r
1293 \r
1294         switch( oid )\r
1295         {\r
1296         /* Required General */\r
1297         case OID_GEN_CURRENT_PACKET_FILTER:\r
1298                 VNIC_TRACE( VNIC_DBG_INFO,\r
1299                         ("  received set for OID_GEN_CURRENT_PACKET_FILTER, %#x\n", *(uint32_t*)info_buf  ));\r
1300                 if ( !p_adapter->p_currentPath->carrier )\r
1301                 {\r
1302                         status = NDIS_STATUS_NOT_ACCEPTED;\r
1303                         break;\r
1304                 }\r
1305                 if( info_buf_len < sizeof( p_adapter->packet_filter ) )\r
1306                 {\r
1307                         status = NDIS_STATUS_INVALID_LENGTH;\r
1308                 }\r
1309                 else if( !info_buf )\r
1310                 {\r
1311                         status = NDIS_STATUS_INVALID_DATA;\r
1312                 }\r
1313                 else\r
1314                 {\r
1315                         p_adapter->set_oid = oid_info;\r
1316                         status = _vnic_process_packet_filter( p_adapter, *((uint32_t*)info_buf) );\r
1317                 }\r
1318                 break;\r
1319 \r
1320         case OID_GEN_CURRENT_LOOKAHEAD:\r
1321                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1322                         ("  received set for OID_GEN_CURRENT_LOOKAHEAD\n" ));\r
1323                 if( info_buf_len < buf_len )\r
1324                         status = NDIS_STATUS_INVALID_LENGTH;\r
1325                 break;\r
1326 \r
1327         case OID_GEN_PROTOCOL_OPTIONS:\r
1328                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1329                         ("  received set for OID_GEN_PROTOCOL_OPTIONS\n" ));\r
1330                 if( info_buf_len < buf_len )\r
1331                         status = NDIS_STATUS_INVALID_LENGTH;\r
1332                 break;\r
1333 \r
1334 #ifdef NDIS51_MINIPORT\r
1335         case OID_GEN_MACHINE_NAME:\r
1336                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1337                         ("  received set for OID_GEN_MACHINE_NAME\n" ) );\r
1338                 if( info_buf_len < buf_len )\r
1339                         status = NDIS_STATUS_INVALID_LENGTH;\r
1340         //      else\r
1341         //              status = __vnic_set_machine_name( info_buf,\r
1342         //                                                                               (USHORT)info_buf_len );\r
1343                 break;\r
1344 #endif\r
1345 \r
1346         /* Required Ethernet operational characteristics */\r
1347         case OID_802_3_MULTICAST_LIST:\r
1348                 if( !p_adapter->p_currentPath->carrier )\r
1349                 {\r
1350                         status = NDIS_STATUS_NOT_ACCEPTED;\r
1351                         break;\r
1352                 }\r
1353                 VNIC_TRACE( VNIC_DBG_INFO,\r
1354                         ("  received set for OID_802_3_MULTICAST_LIST\n" ) );\r
1355                 if( info_buf_len > MAX_MCAST * sizeof(mac_addr_t) )\r
1356                 {\r
1357                         VNIC_TRACE( VNIC_DBG_INFO,\r
1358                                 ("  OID_802_3_MULTICAST_LIST - Multicast list full.\n" ) );\r
1359                         status = NDIS_STATUS_MULTICAST_FULL;\r
1360                         *p_bytes_needed = MAX_MCAST * sizeof(mac_addr_t);\r
1361                 }\r
1362                 else if( info_buf_len % sizeof(mac_addr_t) )\r
1363                 {\r
1364                         VNIC_TRACE( VNIC_DBG_INFO,\r
1365                                 ("  OID_802_3_MULTICAST_LIST - Invalid input buffer length.\n" ) );\r
1366                         status = NDIS_STATUS_INVALID_DATA;\r
1367                 }\r
1368                 else if( info_buf == NULL && info_buf_len != 0 )\r
1369                 {\r
1370                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1371                                 ("  OID_802_3_MULTICAST_LIST - Invalid input buffer.\n" ) );\r
1372                         status = NDIS_STATUS_INVALID_DATA;\r
1373                 }\r
1374                 else\r
1375                 {\r
1376                         p_adapter->set_oid = oid_info;\r
1377                         status = vnic_set_mcast( p_adapter, (mac_addr_t*)info_buf,\r
1378                                                 (uint8_t)(info_buf_len / sizeof(mac_addr_t)) );\r
1379                 }\r
1380                 break;\r
1381 \r
1382         case OID_TCP_TASK_OFFLOAD:\r
1383                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1384                         ("  received set for OID_TCP_TASK_OFFLOAD\n" ) );\r
1385                 buf_len = info_buf_len;\r
1386                 status = __vnic_set_tcp_task_offload( p_adapter, info_buf, &buf_len );\r
1387                 break;\r
1388 \r
1389         /* Optional General */\r
1390         case OID_GEN_TRANSPORT_HEADER_OFFSET:\r
1391                         VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1392                                 ("Set for OID_GEN_TRANSPORT_HEADER_OFFSET\n") );\r
1393                 break;\r
1394 #ifdef NDIS51_MINIPORT\r
1395         case OID_GEN_RNDIS_CONFIG_PARAMETER:\r
1396         case OID_GEN_VLAN_ID:\r
1397 #endif\r
1398                 status = NDIS_STATUS_NOT_SUPPORTED;\r
1399                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1400                         ("  received an unsupported oid of 0x%.8X!\n" , oid));\r
1401                 break;\r
1402 \r
1403         case OID_GEN_SUPPORTED_LIST:\r
1404         case OID_GEN_HARDWARE_STATUS:\r
1405         case OID_GEN_MEDIA_SUPPORTED:\r
1406         case OID_GEN_MEDIA_IN_USE:\r
1407         case OID_GEN_MAXIMUM_FRAME_SIZE:\r
1408         case OID_GEN_LINK_SPEED:\r
1409         case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
1410         case OID_GEN_RECEIVE_BUFFER_SPACE:\r
1411         case OID_GEN_MAXIMUM_LOOKAHEAD:\r
1412         case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
1413         case OID_GEN_RECEIVE_BLOCK_SIZE:\r
1414         case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
1415         case OID_GEN_VENDOR_ID:\r
1416         case OID_GEN_VENDOR_DESCRIPTION:\r
1417         case OID_GEN_VENDOR_DRIVER_VERSION:\r
1418         case OID_GEN_DRIVER_VERSION:\r
1419         case OID_GEN_MAC_OPTIONS:\r
1420         case OID_GEN_MEDIA_CONNECT_STATUS:\r
1421         case OID_GEN_MAXIMUM_SEND_PACKETS:\r
1422         case OID_GEN_SUPPORTED_GUIDS:\r
1423         case OID_GEN_PHYSICAL_MEDIUM:\r
1424         default:\r
1425                 status = NDIS_STATUS_INVALID_OID;\r
1426                 VNIC_TRACE( VNIC_DBG_OID | VNIC_DBG_INFO,\r
1427                         ("  received an invalid oid of 0x%.8X!\n" , oid));\r
1428                 break;\r
1429         }\r
1430 \r
1431         if( status == NDIS_STATUS_SUCCESS )\r
1432         {\r
1433                 *p_bytes_read = buf_len;\r
1434         }\r
1435         else\r
1436         {\r
1437                 if( status == NDIS_STATUS_INVALID_LENGTH )\r
1438                 {\r
1439                         if ( !*p_bytes_needed )\r
1440                         {\r
1441                                 *p_bytes_needed = buf_len;\r
1442                         }\r
1443                 }\r
1444 \r
1445                 *p_bytes_read = 0;\r
1446         }\r
1447 \r
1448         VNIC_EXIT( VNIC_DBG_OID );\r
1449         return status;\r
1450 }\r
1451 \r
1452 \r
1453 //! Transfers some number of packets, specified as an array of packet pointers, over the network.\r
1454 /*  For a deserialized driver, these packets are completed asynchronously\r
1455 using NdisMSendComplete.\r
1456 IRQL <= DISPATCH_LEVEL\r
1457 \r
1458 @param adapter_context Pointer to vnic_adapter_t structure with per NIC state\r
1459 @param packet_array Array of packets to send\r
1460 @param numPackets Number of packets in the array\r
1461 */\r
1462 void\r
1463 vnic_send_packets(\r
1464         IN                              NDIS_HANDLE                                     adapter_context,\r
1465         IN                              PPNDIS_PACKET                           packet_array,\r
1466         IN                              UINT                                            num_packets )\r
1467 {\r
1468         vnic_adapter_t          *p_adapter;\r
1469         viport_t                        *p_viport;\r
1470         UINT                            packet_num;\r
1471 \r
1472         VNIC_ENTER( VNIC_DBG_SEND );\r
1473 \r
1474         CL_ASSERT( adapter_context );\r
1475 \r
1476         p_adapter = (vnic_adapter_t*)adapter_context;\r
1477         p_viport = p_adapter->p_viport;\r
1478 \r
1479         NdisAcquireSpinLock( &p_adapter->lock );\r
1480 \r
1481         if( !p_adapter->carrier )\r
1482         {\r
1483                 NdisReleaseSpinLock( &p_adapter->lock );\r
1484                 for( packet_num = 0; packet_num < num_packets; ++packet_num )\r
1485                 {\r
1486                         NdisMSendComplete( p_adapter->h_handle,\r
1487                                 packet_array[packet_num], NDIS_STATUS_ADAPTER_NOT_READY );\r
1488                 }\r
1489                 VNIC_EXIT( VNIC_DBG_SEND );\r
1490                 return;\r
1491         }\r
1492         NdisReleaseSpinLock( &p_adapter->lock );\r
1493 \r
1494         for( packet_num = 0; packet_num < num_packets; ++packet_num )\r
1495         {\r
1496                 netpath_xmitPacket( p_adapter->p_currentPath,\r
1497                                                                                         packet_array[packet_num] );\r
1498         }\r
1499         VNIC_EXIT( VNIC_DBG_SEND );\r
1500 }\r
1501 \r
1502 void\r
1503 vnic_pnp_notify(\r
1504         IN                              NDIS_HANDLE                                     adapter_context,\r
1505         IN                              NDIS_DEVICE_PNP_EVENT           pnp_event,\r
1506         IN                              PVOID                                           info_buf,\r
1507         IN                              ULONG                                           info_buf_len )\r
1508 {\r
1509         vnic_adapter_t  *p_adapter;\r
1510 \r
1511         VNIC_ENTER( VNIC_DBG_PNP );\r
1512 \r
1513         UNUSED_PARAM( info_buf );\r
1514         UNUSED_PARAM( info_buf_len );\r
1515 \r
1516         p_adapter = (vnic_adapter_t*)adapter_context;\r
1517 \r
1518         VNIC_TRACE( VNIC_DBG_PNP, ("Event %d\n", pnp_event) );\r
1519         if( pnp_event != NdisDevicePnPEventPowerProfileChanged )\r
1520         {\r
1521                 InterlockedExchange( (volatile LONG *)&p_adapter->pnp_state, IB_PNP_IOC_REMOVE );\r
1522                 vnic_resume_oids( p_adapter );\r
1523         }\r
1524 \r
1525         VNIC_EXIT( VNIC_DBG_PNP );\r
1526 }\r
1527 \r
1528 \r
1529 void\r
1530 vnic_shutdown(\r
1531         IN              PVOID           adapter_context )\r
1532 {\r
1533         VNIC_ENTER( VNIC_DBG_INIT );\r
1534 \r
1535         UNUSED_PARAM( adapter_context );\r
1536 \r
1537         VNIC_EXIT( VNIC_DBG_INIT );\r
1538 }\r
1539 \r
1540 \r
1541 void\r
1542 vnic_resume_set_oids(\r
1543         IN                              vnic_adapter_t* const           p_adapter )\r
1544 {\r
1545         NDIS_STATUS             status = NDIS_STATUS_SUCCESS;\r
1546         BOOLEAN                 pending_set;\r
1547         pending_oid_t   set_oid = {0};\r
1548 \r
1549         VNIC_ENTER( VNIC_DBG_OID );\r
1550 \r
1551         NdisAcquireSpinLock( &p_adapter->lock );\r
1552         /*\r
1553          * Set the status depending on our state.  Fail OID requests that\r
1554          * are pending while we reset the adapter.\r
1555          */\r
1556         switch( p_adapter->pnp_state )\r
1557         {\r
1558         case IB_PNP_IOC_ADD:\r
1559                 break;\r
1560 \r
1561         case IB_PNP_IOC_REMOVE:\r
1562         default:\r
1563                 status = NDIS_STATUS_NOT_ACCEPTED;\r
1564                 break;\r
1565         }\r
1566 \r
1567         pending_set = p_adapter->pending_set;\r
1568         if( pending_set )\r
1569         {\r
1570                 set_oid = p_adapter->set_oid;\r
1571                 p_adapter->pending_set = FALSE;\r
1572         }\r
1573         NdisReleaseSpinLock( &p_adapter->lock );\r
1574 \r
1575         ASSERT( KeGetCurrentIrql() == DISPATCH_LEVEL );\r
1576 \r
1577         if( pending_set )\r
1578         {\r
1579                 switch( set_oid.oid )\r
1580                 {\r
1581                 case OID_GEN_CURRENT_PACKET_FILTER:\r
1582                         /* Validation already performed in the SetInformation path. */\r
1583                         p_adapter->packet_filter = *(PULONG)set_oid.p_buf;\r
1584                         NdisMSetInformationComplete( p_adapter->h_handle, status );\r
1585                         break;\r
1586 \r
1587                 case OID_GEN_MACHINE_NAME:\r
1588                         status = __vnic_set_machine_name ( p_adapter->set_oid.p_buf, (USHORT)p_adapter->set_oid.buf_len );\r
1589                         NdisMSetInformationComplete( p_adapter->h_handle, status );\r
1590                         break;\r
1591 \r
1592                 case OID_802_3_MULTICAST_LIST:\r
1593                         NdisMSetInformationComplete( p_adapter->h_handle, status );\r
1594                         break;\r
1595 \r
1596                 default:\r
1597                         CL_ASSERT( set_oid.oid && 0 );\r
1598                         break;\r
1599                 }\r
1600         }\r
1601 \r
1602         VNIC_EXIT( VNIC_DBG_OID );\r
1603 }\r
1604 \r
1605 \r
1606 void\r
1607 vnic_resume_oids(\r
1608         IN                              vnic_adapter_t* const           p_adapter )\r
1609 {\r
1610         ULONG                   info;\r
1611         NDIS_STATUS             status = NDIS_STATUS_SUCCESS;\r
1612         BOOLEAN                 pending_query;\r
1613         pending_oid_t   query_oid = {0};\r
1614         KIRQL                   irql;\r
1615 \r
1616         uint8_t         mac[HW_ADDR_LEN];\r
1617 \r
1618         VNIC_ENTER( VNIC_DBG_OID );\r
1619 \r
1620         NdisAcquireSpinLock( &p_adapter->lock );\r
1621         /*\r
1622          * Set the status depending on our state.  Fail OID requests that\r
1623          * are pending while we reset the adapter.\r
1624          */\r
1625         switch( p_adapter->pnp_state )\r
1626         {\r
1627         case IB_PNP_IOC_ADD:\r
1628                 break;\r
1629 \r
1630         case IB_PNP_IOC_REMOVE:\r
1631         default:\r
1632                 status = NDIS_STATUS_NOT_ACCEPTED;\r
1633                 break;\r
1634         }\r
1635 \r
1636         pending_query = p_adapter->pending_query;\r
1637 \r
1638         if( pending_query )\r
1639         {\r
1640                 query_oid = p_adapter->query_oid;\r
1641                 p_adapter->pending_query = FALSE;\r
1642         }\r
1643         NdisReleaseSpinLock( &p_adapter->lock );\r
1644 \r
1645         KeRaiseIrql( DISPATCH_LEVEL, &irql );\r
1646 \r
1647         /*\r
1648          * If we had a pending OID request for OID_GEN_LINK_SPEED,\r
1649          * complete it now.  Note that we hold the object lock since\r
1650          * NdisMQueryInformationComplete is called at DISPATCH_LEVEL.\r
1651          */\r
1652         if( pending_query )\r
1653         {\r
1654                 switch( query_oid.oid )\r
1655                 {\r
1656                 case OID_802_3_CURRENT_ADDRESS:\r
1657                 case OID_802_3_PERMANENT_ADDRESS:\r
1658                         cl_memcpy( mac, p_adapter->p_viport->hwMacAddress, HW_ADDR_LEN );\r
1659                         _vnic_complete_query( p_adapter,\r
1660                                                         &query_oid,\r
1661                                                         status,\r
1662                                                         mac,\r
1663                                                         HW_ADDR_LEN );\r
1664                         break;\r
1665                 case OID_GEN_LINK_SPEED:\r
1666                         info    = DEFAULT_LINK_SPEED_x100BPS;\r
1667                         _vnic_complete_query( p_adapter,\r
1668                                                         &query_oid,\r
1669                                                         status,\r
1670                                                         &info,\r
1671                                                         sizeof( info ) );\r
1672                         break;\r
1673 \r
1674                 case OID_GEN_MEDIA_CONNECT_STATUS:\r
1675                         info = ( p_adapter->carrier )? NdisMediaStateConnected :\r
1676                                                                                  NdisMediaStateDisconnected;\r
1677                         _vnic_complete_query( p_adapter,\r
1678                                                         &query_oid,\r
1679                                                         status,\r
1680                                                         &info,\r
1681                                                         sizeof( info ) );\r
1682                         break;\r
1683                 case OID_802_3_MULTICAST_LIST:\r
1684                         ASSERT( p_adapter->p_viport );\r
1685                          _vnic_complete_query( p_adapter,\r
1686                                                         &query_oid,\r
1687                                                         status,\r
1688                                                         &p_adapter->p_viport->macAddresses[MCAST_ADDR_START],\r
1689                                                         (p_adapter->p_viport->numMacAddresses -\r
1690                                                         MCAST_ADDR_START) * sizeof( mac_addr_t ) );\r
1691                          break;\r
1692                 case OID_GEN_TRANSMIT_BUFFER_SPACE:\r
1693                                 info = p_adapter->p_viport->data.xmitPool.bufferSz *\r
1694                                                 p_adapter->p_viport->data.xmitPool.numXmitBufs;\r
1695                                 _vnic_complete_query( p_adapter,\r
1696                                                         &query_oid,\r
1697                                                         status,\r
1698                                                         &info,\r
1699                                                         sizeof( info ) );\r
1700                         break;\r
1701                 case OID_GEN_RECEIVE_BUFFER_SPACE:\r
1702                                 info = p_adapter->p_viport->data.recvPool.bufferSz *\r
1703                                                 p_adapter->p_viport->data.recvPool.poolSz;\r
1704                                 _vnic_complete_query( p_adapter,\r
1705                                                         &query_oid,\r
1706                                                         status,\r
1707                                                         &info,\r
1708                                                         sizeof( info ) );\r
1709                         break;\r
1710                 default:\r
1711                                  CL_ASSERT( query_oid.oid == OID_GEN_LINK_SPEED   ||\r
1712                                         query_oid.oid == OID_GEN_MEDIA_CONNECT_STATUS ||\r
1713                                         query_oid.oid == OID_802_3_MULTICAST_LIST     ||\r
1714                                         query_oid.oid == OID_802_3_CURRENT_ADDRESS    ||\r
1715                                         query_oid.oid == OID_802_3_PERMANENT_ADDRESS  ||\r
1716                                         query_oid.oid == OID_GEN_RECEIVE_BUFFER_SPACE ||\r
1717                                         query_oid.oid == OID_GEN_TRANSMIT_BUFFER_SPACE );\r
1718                                         break;\r
1719                 }\r
1720         }\r
1721 \r
1722         vnic_resume_set_oids( p_adapter );\r
1723 \r
1724         KeLowerIrql( irql );\r
1725 \r
1726         VNIC_EXIT( VNIC_DBG_OID );\r
1727 }\r
1728 \r
1729 static NDIS_STATUS\r
1730 __vnic_set_machine_name(\r
1731                 IN              VOID    *p_uni_array,\r
1732                 IN              USHORT  buf_size )\r
1733 {\r
1734         NDIS_STATUS             status = NDIS_STATUS_SUCCESS;\r
1735         uint8_t *p_src_buf = (uint8_t *)p_uni_array;\r
1736         int i;\r
1737 \r
1738         VNIC_ENTER( VNIC_DBG_OID );\r
1739 \r
1740         cl_memclr(g_vnic.host_name, 65 );\r
1741         for( i = 0; i < ( buf_size >1 ); i++ )\r
1742         {\r
1743                 g_vnic.host_name[i] = *(p_src_buf + i*2);\r
1744         }\r
1745 \r
1746         return status;\r
1747 }\r
1748 \r
1749 static void\r
1750 __vnic_read_machine_name( void )\r
1751 {\r
1752         /* this code is borrowed from the bus_driver */\r
1753 \r
1754         NTSTATUS                                        nt_status;\r
1755         /* Remember the terminating entry in the table below. */\r
1756         RTL_QUERY_REGISTRY_TABLE        table[2];\r
1757         UNICODE_STRING                          hostNamePath;\r
1758         UNICODE_STRING                          hostNameW;\r
1759         ANSI_STRING                                     hostName;\r
1760 \r
1761         VNIC_ENTER( VNIC_DBG_INIT );\r
1762 \r
1763         /* Get the host name. */\r
1764         RtlInitUnicodeString( &hostNamePath, L"ComputerName\\ComputerName" );\r
1765         RtlInitUnicodeString( &hostNameW, NULL );\r
1766 \r
1767         /*\r
1768          * Clear the table.  This clears all the query callback pointers,\r
1769          * and sets up the terminating table entry.\r
1770          */\r
1771         cl_memclr( table, sizeof(table) );\r
1772 \r
1773         /* Setup the table entries. */\r
1774         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
1775         table[0].Name = L"ComputerName";\r
1776         table[0].EntryContext = &hostNameW;\r
1777         table[0].DefaultType = REG_SZ;\r
1778         table[0].DefaultData = &hostNameW;\r
1779         table[0].DefaultLength = 0;\r
1780 \r
1781         /* Have at it! */\r
1782         nt_status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL,\r
1783                 hostNamePath.Buffer, table, NULL, NULL );\r
1784         if( NT_SUCCESS( nt_status ) )\r
1785         {\r
1786                 /* Convert the UNICODE host name to UTF-8 (ASCII). */\r
1787                 hostName.Length = 0;\r
1788                 hostName.MaximumLength = sizeof(g_vnic.host_name) - 1;\r
1789                 hostName.Buffer = (PCHAR)g_vnic.host_name;\r
1790                 nt_status = RtlUnicodeStringToAnsiString( &hostName, &hostNameW, FALSE );\r
1791                 RtlFreeUnicodeString( &hostNameW );\r
1792         }\r
1793         else\r
1794         {\r
1795                 VNIC_TRACE(VNIC_DBG_ERROR , ("Failed to get host name from registry\n") );\r
1796                 /* Use the default name... */\r
1797                 cl_memcpy( g_vnic.host_name,\r
1798                                         DEFAULT_HOST_NAME,\r
1799                                         min (sizeof( g_vnic.host_name), sizeof(DEFAULT_HOST_NAME) ) );\r
1800         }\r
1801 \r
1802         VNIC_EXIT( VNIC_DBG_INIT );\r
1803 }\r
1804 \r
1805 /* function: usec_timer_start\r
1806                 uses cl_timer* functionality (init/destroy/stop/start )\r
1807                 except it takes expiration time parameter in microseconds.\r
1808 */\r
1809 cl_status_t\r
1810 usec_timer_start(\r
1811         IN      cl_timer_t* const       p_timer,\r
1812         IN      const uint32_t          time_usec )\r
1813 {\r
1814         LARGE_INTEGER   due_time;\r
1815 \r
1816         CL_ASSERT( p_timer );\r
1817         CL_ASSERT( p_timer->pfn_callback );\r
1818         CL_ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL );\r
1819 \r
1820         /* Due time is in 100 ns increments.  Negative for relative time. */\r
1821         due_time.QuadPart = -(int64_t)(((uint64_t)time_usec) * 10);\r
1822 \r
1823         /* Store the timeout time in the timer object. in microseconds */\r
1824         p_timer->timeout_time = cl_get_time_stamp() + (((uint64_t)time_usec));\r
1825 \r
1826         KeSetTimer( &p_timer->timer, due_time, &p_timer->dpc );\r
1827         return( CL_SUCCESS );\r
1828 }\r
1829 \r
1830 \r
1831 static NDIS_STATUS\r
1832 _vnic_process_packet_filter(\r
1833                 IN      vnic_adapter_t* const   p_adapter,\r
1834                 IN      ULONG                                   pkt_filter )\r
1835 {\r
1836         NDIS_STATUS     status;\r
1837 \r
1838         VNIC_ENTER(VNIC_DBG_FUNC );\r
1839 \r
1840         ASSERT( p_adapter );\r
1841         ASSERT( p_adapter->p_viport );\r
1842         ASSERT( !(p_adapter->p_viport->updates & SYNC_QUERY) );\r
1843 \r
1844         InterlockedExchange((volatile LONG*)&p_adapter->packet_filter, pkt_filter );\r
1845 \r
1846         ASSERT( (p_adapter->p_viport->updates & ~MCAST_OVERFLOW) == 0 );\r
1847 \r
1848         if( pkt_filter & NDIS_PACKET_TYPE_ALL_MULTICAST )\r
1849         {\r
1850                 if( !p_adapter->p_viport->flags & INIC_FLAG_ENABLE_MCAST_ALL )\r
1851                 {\r
1852                         p_adapter->p_viport->newFlags |= INIC_FLAG_ENABLE_MCAST_ALL;\r
1853                         // TODO: Shouldn't MCAST_OVERFLOW be a flag bit, not an update bit?\r
1854                         InterlockedOr( &p_adapter->p_viport->updates,\r
1855                                 NEED_LINK_CONFIG | MCAST_OVERFLOW );\r
1856                 }\r
1857         }\r
1858         if ( pkt_filter & NDIS_PACKET_TYPE_PROMISCUOUS )\r
1859         {\r
1860                 if( !p_adapter->p_viport->flags & INIC_FLAG_ENABLE_PROMISC )\r
1861                 {\r
1862                         p_adapter->p_viport->newFlags |= INIC_FLAG_ENABLE_PROMISC;\r
1863                         InterlockedOr( &p_adapter->p_viport->updates, NEED_LINK_CONFIG );\r
1864                 }\r
1865         }\r
1866         /* BROADCAST and MULTICAST flags VEx enable by default */\r
1867         p_adapter->pending_set = TRUE;\r
1868         status = _viport_process_query( p_adapter->p_viport, FALSE );\r
1869         VNIC_TRACE( VNIC_DBG_INFO,\r
1870                                         ("LINK CONFIG status %x\n", status ));\r
1871         if( status != NDIS_STATUS_PENDING )\r
1872                 p_adapter->pending_set = FALSE;\r
1873 \r
1874         VNIC_EXIT( VNIC_DBG_FUNC );\r
1875         return status;\r
1876 }\r
1877 \r