345205ec50df7c717f73085f6cbeca185a0485a6
[mirror/winof/.git] / hw / mlx4 / kernel / bus / drv / drv.c
1 /*++\r
2 \r
3 Copyright (c) 2003  Microsoft Corporation All Rights Reserved\r
4 \r
5 Module Name:\r
6 \r
7     BUSENUM.C\r
8 \r
9 Abstract:\r
10 \r
11     This module contains routines to handle the function driver\r
12     aspect of the bus driver. This sample is functionally\r
13     equivalent to the WDM mxe bus driver.\r
14 \r
15 Environment:\r
16 \r
17     kernel mode only\r
18 \r
19 --*/\r
20 \r
21 #include "precomp.h"\r
22 #include <initguid.h>\r
23 #include <wdmguid.h>\r
24 \r
25 #if defined (EVENT_TRACING)\r
26 #ifdef offsetof\r
27 #undef offsetof\r
28 #endif\r
29 #include "drv.tmh"\r
30 #endif \r
31 \r
32 #ifdef ALLOC_PRAGMA\r
33 #pragma alloc_text (INIT, DriverEntry)\r
34 #pragma alloc_text (PAGE, EvtDeviceAdd)\r
35 #pragma alloc_text (PAGE, EvtDriverUnload)\r
36 #pragma alloc_text (PAGE, EvtDeviceD0Entry)\r
37 #pragma alloc_text (PAGE, EvtDeviceD0Exit)\r
38 #pragma alloc_text (PAGE, EvtPrepareHardware)\r
39 #pragma alloc_text (PAGE, EvtReleaseHardware)\r
40 #endif\r
41 \r
42 #define DRV_VERSION     "1.0"\r
43 #define DRV_RELDATE     "02/01/2008"\r
44 \r
45 GLOBALS g = {0};\r
46 uint32_t g_mlx4_dbg_flags = 0xffff;\r
47 uint32_t g_mlx4_dbg_level = TRACE_LEVEL_INFORMATION;\r
48 WCHAR g_wlog_buf[ MAX_LOG_BUF_LEN ];\r
49 UCHAR g_slog_buf[ MAX_LOG_BUF_LEN ];\r
50 \r
51 #ifndef USE_WDM_INTERRUPTS\r
52 \r
53 typedef struct {\r
54         int                                     int_num;\r
55         PFDO_DEVICE_DATA        p_fdo;\r
56         struct mlx4_eq *        eq;\r
57 } INTERRUPT_DATA, *PINTERRUPT_DATA;\r
58 \r
59 WDF_DECLARE_CONTEXT_TYPE(INTERRUPT_DATA);\r
60 \r
61 NTSTATUS    \r
62 EvtEnableInterrupt(     \r
63         IN WDFINTERRUPT  Interrupt,\r
64         IN WDFDEVICE  AssociatedDevice\r
65         )\r
66 {\r
67         UNUSED_PARAM(Interrupt);\r
68         UNUSED_PARAM(AssociatedDevice);\r
69         MLX4_ENTER(MLX4_DBG_DRV);\r
70         MLX4_EXIT( MLX4_DBG_DRV );\r
71         return STATUS_SUCCESS;\r
72 }\r
73 \r
74 NTSTATUS\r
75 EvtDisableInterrupt (\r
76         IN WDFINTERRUPT  Interrupt,\r
77         IN WDFDEVICE  AssociatedDevice\r
78         )\r
79 {\r
80         UNUSED_PARAM(Interrupt);\r
81         UNUSED_PARAM(AssociatedDevice);\r
82         MLX4_ENTER(MLX4_DBG_DRV);\r
83         MLX4_EXIT( MLX4_DBG_DRV );\r
84         return STATUS_SUCCESS;\r
85 }\r
86 \r
87 BOOLEAN\r
88 EvtInterruptIsr(\r
89         IN WDFINTERRUPT  Interrupt,\r
90         IN ULONG  MessageID\r
91         )\r
92 {\r
93         BOOLEAN isr_handled = FALSE;\r
94         PINTERRUPT_DATA p_isr_ctx = WdfObjectGetTypedContext( Interrupt, INTERRUPT_DATA );\r
95 \r
96         UNUSED_PARAM(MessageID);\r
97 \r
98 //      MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, ("Fdo %p\n", p_isr_ctx->p_fdo));\r
99         if (p_isr_ctx->eq && p_isr_ctx->eq->isr)\r
100                 isr_handled = p_isr_ctx->eq->isr( p_isr_ctx->eq->eq_ix, p_isr_ctx->eq->ctx );\r
101         \r
102         return isr_handled;\r
103 }\r
104 \r
105 #endif\r
106 \r
107 static \r
108 NTSTATUS\r
109 __create_child(\r
110         __in WDFDEVICE  Device,\r
111         __in PWCHAR     HardwareIds,\r
112         __in PWCHAR     DeviceDescription,\r
113         __in ULONG      SerialNo\r
114         )\r
115 \r
116 /*++\r
117 \r
118 Routine Description:\r
119 \r
120         The user application has told us that a new device on the bus has arrived.\r
121 \r
122         We therefore need to create a new PDO, initialize it, add it to the list\r
123         of PDOs for this FDO bus, and then tell Plug and Play that all of this\r
124         happened so that it will start sending prodding IRPs.\r
125 \r
126 --*/\r
127 \r
128 {\r
129         NTSTATUS                        status = STATUS_SUCCESS;\r
130         BOOLEAN                         unique = TRUE;\r
131         WDFDEVICE                       hChild;\r
132         PPDO_DEVICE_DATA        p_pdo;\r
133         PFDO_DEVICE_DATA        p_fdo;\r
134 \r
135         PAGED_CODE ();\r
136         MLX4_ENTER(MLX4_DBG_DRV);\r
137 \r
138         //\r
139         // First make sure that we don't already have another device with the\r
140         // same serial number.\r
141         // Framework creates a collection of all the child devices we have\r
142         // created so far. So acquire the handle to the collection and lock\r
143         // it before walking the item.\r
144         //\r
145         p_fdo = FdoGetData(Device);\r
146         hChild = NULL;\r
147 \r
148         //\r
149         // We need an additional lock to synchronize addition because\r
150         // WdfFdoLockStaticChildListForIteration locks against anyone immediately\r
151         // updating the static child list (the changes are put on a queue until the\r
152         // list has been unlocked).  This type of lock does not enforce our concept\r
153         // of unique IDs on the bus (ie SerialNo).\r
154         //\r
155         // Without our additional lock, 2 threads could execute this function, both\r
156         // find that the requested SerialNo is not in the list and attempt to add\r
157         // it.  If that were to occur, 2 PDOs would have the same unique SerialNo,\r
158         // which is incorrect.\r
159         //\r
160         // We must use a passive level lock because you can only call WdfDeviceCreate\r
161         // at PASSIVE_LEVEL.\r
162         //\r
163         WdfWaitLockAcquire(p_fdo->ChildLock, NULL);\r
164         WdfFdoLockStaticChildListForIteration(Device);\r
165 \r
166         while ((hChild = WdfFdoRetrieveNextStaticChild(Device,\r
167                 hChild, WdfRetrieveAddedChildren)) != NULL) {\r
168                 //\r
169                 // WdfFdoRetrieveNextStaticChild returns reported and to be reported\r
170                 // children (ie children who have been added but not yet reported to PNP).\r
171                 //\r
172                 // A surprise removed child will not be returned in this list.\r
173                 //\r
174                 p_pdo = PdoGetData(hChild);\r
175                 p_pdo->PdoDevice = hChild;\r
176                 p_pdo->p_fdo = p_fdo;\r
177 \r
178                 //\r
179                 // It's okay to plug in another device with the same serial number\r
180                 // as long as the previous one is in a surprise-removed state. The\r
181                 // previous one would be in that state after the device has been\r
182                 // physically removed, if somebody has an handle open to it.\r
183                 //\r
184                 if (SerialNo == p_pdo->SerialNo) {\r
185                 unique = FALSE;\r
186                 status = STATUS_INVALID_PARAMETER;\r
187                 break;\r
188                 }\r
189         }\r
190 \r
191         if (unique) {\r
192                 //\r
193                 // Create a new child device.  It is OK to create and add a child while\r
194                 // the list locked for enumeration.  The enumeration lock applies only\r
195                 // to enumeration, not addition or removal.\r
196                 //\r
197                 status = create_pdo(Device, HardwareIds, DeviceDescription, SerialNo);\r
198         }\r
199 \r
200         WdfFdoUnlockStaticChildListFromIteration(Device);\r
201         WdfWaitLockRelease(p_fdo->ChildLock);\r
202 \r
203         MLX4_EXIT( MLX4_DBG_DRV );\r
204         return status;\r
205 }\r
206 \r
207 static \r
208 NTSTATUS\r
209 __do_static_enumeration(\r
210         IN WDFDEVICE Device\r
211         )\r
212 /*++\r
213 Routine Description:\r
214 \r
215         The routine enables you to statically enumerate child devices\r
216         during start instead of running the enum.exe/notify.exe to\r
217         enumerate mxe devices.\r
218 \r
219         In order to statically enumerate, user must specify the number\r
220         of mxes in the Mxe Bus driver's device registry. The\r
221         default value is 2.\r
222 \r
223         You can also configure this value in the Mxe Bus Inf file.\r
224 \r
225 --*/\r
226 \r
227 {\r
228         NTSTATUS status = STATUS_SUCCESS;\r
229         int i;\r
230         int number_of_ib_ports;\r
231         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
232         struct mlx4_dev *mdev   = p_fdo->pci_dev.dev;\r
233 \r
234         MLX4_ENTER(MLX4_DBG_DRV);\r
235 \r
236         if ( p_fdo->children_created )\r
237                 goto end;\r
238         \r
239         // eventually we'll have all information about children in Registry\r
240         // DriverEntry will read it into a Global storage and\r
241         // this routine will create all the children on base on this info\r
242         number_of_ib_ports = mlx4_count_ib_ports(mdev);\r
243         ASSERT(number_of_ib_ports >=0 && number_of_ib_ports <=2);\r
244         \r
245         if(number_of_ib_ports > 0) {\r
246                 status = __create_child(Device, BUS_HARDWARE_IDS, BUS_HARDWARE_DESCRIPTION, 0 );\r
247                 if (!NT_SUCCESS(status)) {\r
248                          MLX4_PRINT_EV(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, ("__create_child (ib)failed with 0x%x\n", status));\r
249                 }\r
250         }\r
251 \r
252         // Create ethernet ports if needed\r
253         for (i = 0; i < MLX4_MAX_PORTS; i++) {\r
254                 if(mlx4_is_eth_port(mdev, i)) {\r
255                         status = __create_child(Device, ETH_HARDWARE_IDS, ETH_HARDWARE_DESCRIPTION, i+1 );\r
256                         if (!NT_SUCCESS(status)) {\r
257                                  MLX4_PRINT_EV(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, ("__create_child (eth) failed with 0x%x\n", status));\r
258                         }\r
259                 }\r
260         }\r
261 \r
262         p_fdo->children_created = TRUE;\r
263         \r
264 end:\r
265         MLX4_EXIT( MLX4_DBG_DRV );\r
266         return status;\r
267 }\r
268 \r
269 static \r
270 NTSTATUS\r
271 __start_card( \r
272         IN PFDO_DEVICE_DATA p_fdo \r
273         )\r
274 {\r
275 #ifndef USE_WDM_INTERRUPTS\r
276                 int i;\r
277 #endif\r
278         int err;\r
279         NTSTATUS status = STATUS_SUCCESS;\r
280         struct pci_dev *pdev = &p_fdo->pci_dev;\r
281 \r
282         MLX4_ENTER(MLX4_DBG_DRV);\r
283 \r
284         if ( p_fdo->card_started )\r
285                 goto err; \r
286                 \r
287         // enable the card\r
288         status = pci_hca_enable( &pdev->bus_pci_ifc, &pdev->pci_cfg_space );\r
289         if( !NT_SUCCESS( status ) ) \r
290                 goto err;\r
291 \r
292         //\r
293         // init the card\r
294         //\r
295 \r
296 #ifndef USE_WDM_INTERRUPTS\r
297         // enable interrupts for start up\r
298         for ( i = 0; i < MLX4_MAX_INTERRUPTS; ++i ) \r
299                 WdfInterruptEnable(p_fdo->interrupt[i].WdfInterrupt);\r
300 #endif  \r
301 \r
302         // NET library\r
303         err = mlx4_init_one( &p_fdo->pci_dev );\r
304         if (err) {\r
305                 status = errno_to_ntstatus(err);\r
306                 goto err;\r
307         }\r
308 \r
309 #ifndef USE_WDM_INTERRUPTS\r
310         //\r
311         // complete filling interrupt context (for more efficiency)\r
312         //\r
313         for ( i = 0; i < MLX4_MAX_INTERRUPTS; ++i ) {\r
314                 struct mlx4_priv *priv = mlx4_priv( p_fdo->pci_dev.dev );\r
315                 PINTERRUPT_DATA p_isr_ctx = WdfObjectGetTypedContext( \r
316                         p_fdo->interrupt[i].WdfInterrupt, INTERRUPT_DATA );\r
317 \r
318                 p_isr_ctx->eq = &priv->eq_table.eq[i];\r
319         }\r
320 #endif\r
321 \r
322         //\r
323         // prepare MLX4 IB interface\r
324         //\r
325 \r
326         // fill the header\r
327         p_fdo->bus_ib_ifc.i.Size = sizeof(MLX4_BUS_IB_INTERFACE);\r
328         p_fdo->bus_ib_ifc.i.Version = MLX4_BUS_IB_INTERFACE_VERSION;\r
329         // Let the framework handle reference counting.\r
330         p_fdo->bus_ib_ifc.i.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;\r
331         p_fdo->bus_ib_ifc.i.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;\r
332 \r
333         p_fdo->bus_ib_ifc.pdev = &p_fdo->pci_dev;\r
334         p_fdo->bus_ib_ifc.p_ibdev = p_fdo->pci_dev.ib_dev;\r
335         p_fdo->bus_ib_ifc.pmlx4_dev = to_mdev(p_fdo->pci_dev.ib_dev)->dev;\r
336         p_fdo->bus_ib_ifc.is_livefish = mlx4_is_livefish(p_fdo->pci_dev.dev);\r
337 \r
338         p_fdo->card_started = TRUE;\r
339 \r
340 err:\r
341         MLX4_EXIT( MLX4_DBG_DRV );\r
342         return status;\r
343 }\r
344 \r
345 static\r
346 void\r
347 __stop_card(\r
348         IN PFDO_DEVICE_DATA p_fdo\r
349         )\r
350 {\r
351         if ( p_fdo->card_started ) {\r
352                 p_fdo->card_started = FALSE;\r
353                 mlx4_remove_one( &p_fdo->pci_dev );\r
354         }\r
355 }\r
356 \r
357 \r
358 NTSTATUS\r
359 EvtDeviceD0Entry(\r
360         IN WDFDEVICE  Device,\r
361         IN WDF_POWER_DEVICE_STATE  PreviousState\r
362         )\r
363 {\r
364         NTSTATUS status = STATUS_SUCCESS;\r
365         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
366         struct pci_dev *pdev    = &p_fdo->pci_dev;\r
367         struct mlx4_dev *mdev;\r
368 \r
369         MLX4_ENTER(MLX4_DBG_DRV);\r
370 \r
371         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("PreviousState 0x%x\n", PreviousState));\r
372 \r
373         // start card (needed after Hibernetion)\r
374         if (PreviousState > WdfPowerDeviceD0)\r
375                 __start_card( p_fdo );\r
376         mdev = pdev->dev;\r
377 \r
378         // create child device\r
379         status = __do_static_enumeration(Device);\r
380                 if (!NT_SUCCESS(status)) {\r
381                         MLX4_PRINT_EV(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, ("__do_static_enumeration failed with 0x%x\n", status));\r
382                         goto err;\r
383                 }\r
384 \r
385         // Log Success Message\r
386         MLX4_PRINT_EV(TRACE_LEVEL_INFORMATION ,MLX4_DBG_DRV ,\r
387                 ("Ven %x Dev %d Fw %d.%d.%d, IsBurnDevice %s\n", \r
388                 (unsigned)pdev->ven_id, (unsigned)pdev->dev_id,\r
389                 (int) (mdev->caps.fw_ver >> 32),\r
390                 (int) (mdev->caps.fw_ver >> 16) & 0xffff, \r
391                 (int) (mdev->caps.fw_ver & 0xffff),\r
392                 mlx4_is_livefish(mdev) ? "Y" : "N"\r
393                 ));\r
394 \r
395 err:\r
396         MLX4_EXIT( MLX4_DBG_DRV );\r
397         return status;\r
398 }\r
399 \r
400 NTSTATUS\r
401 EvtDeviceD0Exit(\r
402         IN WDFDEVICE  Device,\r
403         IN WDF_POWER_DEVICE_STATE  TargetState\r
404         )\r
405 {\r
406         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
407         \r
408         MLX4_ENTER(MLX4_DBG_DRV);\r
409         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("TargetState 0x%x\n", TargetState));\r
410 \r
411         if (TargetState > WdfPowerDeviceD0)\r
412                 __stop_card( p_fdo );\r
413 \r
414         MLX4_EXIT( MLX4_DBG_DRV );\r
415         return STATUS_SUCCESS;\r
416 }\r
417 \r
418 \r
419 \r
420 /* Forwards the request to the HCA's PDO. */\r
421 static \r
422 void\r
423 __put_bus_ifc(\r
424                 IN      BUS_INTERFACE_STANDARD          *pBusIfc )\r
425 {\r
426         MLX4_ENTER(MLX4_DBG_DRV);\r
427         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("pBusIfc=0x%p\n", pBusIfc));\r
428         pBusIfc->InterfaceDereference( pBusIfc->Context );\r
429         MLX4_EXIT( MLX4_DBG_DRV );\r
430 }\r
431 \r
432 static \r
433 NTSTATUS\r
434 __get_bus_ifc(\r
435         IN                              PFDO_DEVICE_DATA const  p_fdo,\r
436         IN              const   GUID* const                             pGuid,\r
437         OUT                     BUS_INTERFACE_STANDARD  *pBusIfc )\r
438 {\r
439         NTSTATUS status;\r
440         WDFDEVICE  FdoDevice = p_fdo->FdoDevice;\r
441         MLX4_ENTER(MLX4_DBG_DRV);\r
442         \r
443         status = WdfFdoQueryForInterface( FdoDevice, pGuid, (PINTERFACE)pBusIfc,\r
444                 sizeof(BUS_INTERFACE_STANDARD), 1, NULL );\r
445         MLX4_EXIT( MLX4_DBG_DRV );\r
446         return status;\r
447 }\r
448 \r
449 static\r
450 void\r
451 __put_dma_adapter(\r
452         IN PFDO_DEVICE_DATA p_fdo,\r
453         IN PDMA_ADAPTER         p_dma )\r
454 {\r
455         UNUSED_PARAM(p_fdo);\r
456         UNUSED_PARAM(p_dma);\r
457         MLX4_ENTER(MLX4_DBG_DRV);\r
458         MLX4_EXIT( MLX4_DBG_DRV );\r
459 }\r
460 \r
461 \r
462 // this routine releases the resources, taken in __get_resources\r
463 static\r
464 void \r
465 __put_resources(\r
466         IN PFDO_DEVICE_DATA p_fdo\r
467         )\r
468 {\r
469         struct pci_dev *pdev = &p_fdo->pci_dev;\r
470         MLX4_ENTER(MLX4_DBG_DRV);\r
471 \r
472         if (p_fdo->dma_adapter_taken) {\r
473                 p_fdo->dma_adapter_taken = FALSE;\r
474                 __put_dma_adapter( p_fdo, pdev->p_dma_adapter );\r
475         }\r
476 \r
477         if (p_fdo->pci_bus_ifc_taken) {\r
478                 p_fdo->pci_bus_ifc_taken = FALSE;\r
479                 __put_bus_ifc(&pdev->bus_pci_ifc);\r
480         }\r
481         MLX4_EXIT( MLX4_DBG_DRV );\r
482 }\r
483 \r
484 static\r
485 NTSTATUS \r
486 __get_dma_adapter(\r
487         IN PFDO_DEVICE_DATA p_fdo,\r
488         OUT PDMA_ADAPTER *      pp_dma )\r
489 {\r
490         NTSTATUS status;\r
491         WDF_DMA_ENABLER_CONFIG  dmaConfig;\r
492         \r
493         MLX4_ENTER(MLX4_DBG_DRV);\r
494 \r
495         WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,\r
496                 WdfDmaProfileScatterGather64, 0x80000000 - 1 );\r
497 \r
498         status = WdfDmaEnablerCreate( p_fdo->FdoDevice,\r
499                 &dmaConfig, WDF_NO_OBJECT_ATTRIBUTES, &p_fdo->dma_enabler );\r
500         if (!NT_SUCCESS (status)) {\r
501                 return status;\r
502         }\r
503         \r
504         *pp_dma = WdfDmaEnablerWdmGetDmaAdapter( \r
505                 p_fdo->dma_enabler, WdfDmaDirectionReadFromDevice );\r
506 \r
507         MLX4_EXIT( MLX4_DBG_DRV );\r
508         return status;\r
509 }\r
510 \r
511 // this routine fills pci_dev structure, containing all HW \r
512 // and some other necessary common resources\r
513 static\r
514 NTSTATUS \r
515 __get_resources(\r
516         IN PFDO_DEVICE_DATA p_fdo,\r
517         IN WDFCMRESLIST  ResourcesRaw,\r
518         IN WDFCMRESLIST  ResourcesTranslated\r
519         )\r
520 {\r
521         NTSTATUS status;\r
522         ULONG i, k=0;\r
523         PCM_PARTIAL_RESOURCE_DESCRIPTOR  desc;\r
524         PCM_PARTIAL_RESOURCE_DESCRIPTOR  desc_raw;\r
525         BUS_INTERFACE_STANDARD  bus_pci_ifc;\r
526         struct pci_dev *pdev = &p_fdo->pci_dev;\r
527 \r
528         MLX4_ENTER(MLX4_DBG_DRV);\r
529 \r
530         //\r
531         // Get PCI BUS interface\r
532         // \r
533         status = __get_bus_ifc( p_fdo, &GUID_BUS_INTERFACE_STANDARD, &bus_pci_ifc );\r
534         if( !NT_SUCCESS( status ) ) {\r
535                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
536                         ("failed: status=0x%x\n", status));\r
537                 return status;\r
538         }\r
539         RtlCopyMemory( &pdev->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );\r
540         p_fdo->pci_bus_ifc_taken = TRUE;\r
541 \r
542         // \r
543         // get HW resources\r
544         //\r
545         for (i = 0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {\r
546 \r
547                 desc = WdfCmResourceListGetDescriptor( ResourcesTranslated, i );\r
548                 desc_raw = WdfCmResourceListGetDescriptor( ResourcesRaw, i );\r
549 \r
550                 switch (desc->Type) {\r
551 \r
552                         case CmResourceTypeMemory:\r
553                                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV,\r
554                                         ("EvtPrepareHardware(Raw): Desc %d: Memory: Start %#I64x, Length %#x\n", \r
555                                         i, desc_raw->u.Memory.Start.QuadPart, desc_raw->u.Memory.Length ));\r
556                                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV,\r
557                                         ("EvtPrepareHardware: Desc %d: Memory: Start %#I64x, Length %#x\n", \r
558                                         i, desc->u.Memory.Start.QuadPart, desc->u.Memory.Length ));\r
559 \r
560                                 if (k < N_BARS) {\r
561                                         pdev->bar[k].phys = desc->u.Memory.Start.QuadPart;\r
562                                         pdev->bar[k].size = (SIZE_T)desc->u.Memory.Length;\r
563                                 }\r
564                                 k++;\r
565                                 break;\r
566 \r
567 #ifdef USE_WDM_INTERRUPTS\r
568                         case CmResourceTypeInterrupt:\r
569                                 pdev->int_info = *desc;\r
570                                 if (desc->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {\r
571                                         MLX4_PRINT(TRACE_LEVEL_WARNING, MLX4_DBG_DRV,\r
572                                                 ("EvtPrepareHardware: Desc %d: MsiInterrupt: Share %d, Flags %#x, Level %d, Vector %#x, Affinity %#x\n", \r
573                                                 i, desc->ShareDisposition, desc->Flags,\r
574                                                 desc->u.MessageInterrupt.Translated.Level, \r
575                                                 desc->u.MessageInterrupt.Translated.Vector, \r
576                                                 (u32)desc->u.MessageInterrupt.Translated.Affinity ));\r
577                                         MLX4_PRINT(TRACE_LEVEL_WARNING, MLX4_DBG_DRV,\r
578                                                 ("EvtPrepareHardware: Desc %d: RawMsiInterrupt: Share %d, Flags %#x, MessageCount %#hx, Vector %#x, Affinity %#x\n", \r
579                                                 i, desc_raw->ShareDisposition, desc_raw->Flags,\r
580                                                 desc_raw->u.MessageInterrupt.Raw.MessageCount, \r
581                                                 desc_raw->u.MessageInterrupt.Raw.Vector,\r
582                                                 (u32)desc_raw->u.MessageInterrupt.Raw.Affinity ));\r
583                                 }\r
584                                 else { // line-based interrupt\r
585                                         MLX4_PRINT(TRACE_LEVEL_WARNING, MLX4_DBG_DRV,\r
586                                                 ("EvtPrepareHardware: Desc %d: LineInterrupt: Share %d, Flags %#x, Level %d, Vector %#x, Affinity %#x\n", \r
587                                                 i, desc->ShareDisposition, desc->Flags,\r
588                                                 desc->u.Interrupt.Level, desc->u.Interrupt.Vector, \r
589                                                 (u32)desc->u.Interrupt.Affinity ));\r
590                                 }\r
591                                 break;\r
592 #endif\r
593 \r
594                         default:\r
595                                 //\r
596                                 // Ignore all other descriptors.\r
597                                 //\r
598                                 break;\r
599                 }\r
600         }\r
601         if (i ==0) {\r
602                 // This means that no resources are found\r
603                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, ("WdfCmResourceListGetCount: returned 0, quiting\n"));\r
604                 return STATUS_INSUFFICIENT_RESOURCES;\r
605         }\r
606 \r
607         //\r
608         // get uplink info. \r
609         //\r
610         status = pci_save_config( &pdev->bus_pci_ifc, &pdev->pci_cfg_space);\r
611         if( !NT_SUCCESS( status ) )\r
612         {\r
613                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
614                         ("Failed to save HCA config: status=0x%x\n", status));\r
615                 goto err;\r
616         }\r
617         pci_get_uplink_info( &pdev->pci_cfg_space, &pdev->uplink_info );\r
618 \r
619         //\r
620         // allocate DMA adapter\r
621         //\r
622         status = __get_dma_adapter( p_fdo, &pdev->p_dma_adapter );\r
623         if( !NT_SUCCESS( status ) )\r
624         {\r
625                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
626                         ("Failed to get DMA adapter: status=0x%x\n", status));\r
627                 goto err;\r
628         }\r
629         p_fdo->dma_adapter_taken = TRUE;\r
630         \r
631         //\r
632         // fill more fields in pci_dev\r
633         //\r
634         pdev->ven_id = pdev->pci_cfg_space.VendorID;\r
635         pdev->dev_id = pdev->pci_cfg_space.DeviceID;\r
636         pdev->p_self_do = WdfDeviceWdmGetDeviceObject(p_fdo->FdoDevice);\r
637         \r
638         MLX4_EXIT( MLX4_DBG_DRV );\r
639         return STATUS_SUCCESS;\r
640 err:\r
641         __put_resources(p_fdo);\r
642         MLX4_EXIT( MLX4_DBG_DRV );\r
643         return status;\r
644 }\r
645 \r
646 NTSTATUS\r
647 EvtPrepareHardware(\r
648         IN WDFDEVICE  Device,\r
649         IN WDFCMRESLIST  ResourcesRaw,\r
650         IN WDFCMRESLIST  ResourcesTranslated\r
651         )\r
652 {\r
653         NTSTATUS status;\r
654         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
655 \r
656         MLX4_ENTER(MLX4_DBG_DRV);\r
657 \r
658         // get resources\r
659         status = __get_resources( p_fdo, ResourcesRaw, ResourcesTranslated );\r
660         if( !NT_SUCCESS( status ) ) {\r
661                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, ("__get_resources failed: status=0x%x\n", status));\r
662                 goto err;\r
663         }\r
664 \r
665         // start the card\r
666         status = __start_card( p_fdo );\r
667         \r
668 err:\r
669         MLX4_EXIT( MLX4_DBG_DRV );\r
670         return status;\r
671 }\r
672 \r
673 void fix_bus_ifc(struct pci_dev *pdev)\r
674 {\r
675         PFDO_DEVICE_DATA p_fdo;\r
676 \r
677         p_fdo =  CONTAINING_RECORD(pdev, FDO_DEVICE_DATA, pci_dev);\r
678         p_fdo->bus_ib_ifc.p_ibdev = p_fdo->pci_dev.ib_dev;\r
679         p_fdo->bus_ib_ifc.pmlx4_dev = to_mdev(p_fdo->pci_dev.ib_dev)->dev;\r
680         p_fdo->bus_ib_ifc.is_livefish = mlx4_is_livefish(p_fdo->pci_dev.dev);\r
681 }\r
682 \r
683 NTSTATUS\r
684 EvtReleaseHardware(\r
685         IN WDFDEVICE  Device,\r
686         IN WDFCMRESLIST  ResourcesTranslated\r
687         )\r
688 {\r
689         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
690 \r
691         UNUSED_PARAM(ResourcesTranslated);\r
692 \r
693         MLX4_ENTER(MLX4_DBG_DRV);\r
694 \r
695         __stop_card( p_fdo );\r
696         __put_resources( p_fdo );\r
697 \r
698         MLX4_EXIT( MLX4_DBG_DRV );\r
699         return STATUS_SUCCESS;\r
700 }\r
701 \r
702 #ifndef USE_WDM_INTERRUPTS\r
703 \r
704 static\r
705 NTSTATUS \r
706 __create_interrupt(\r
707         IN WDFDEVICE                            device,\r
708         IN int                                          int_num,\r
709         IN PFN_WDF_INTERRUPT_ISR        isr,\r
710         IN PFN_WDF_INTERRUPT_DPC        dpc,\r
711         IN PFDO_DEVICE_DATA                     p_fdo,\r
712         OUT WDFINTERRUPT                *       p_int_obj\r
713         )\r
714 {\r
715         NTSTATUS Status;\r
716 \r
717         WDF_INTERRUPT_CONFIG  interruptConfig;\r
718         WDF_OBJECT_ATTRIBUTES  interruptAttributes;\r
719         PINTERRUPT_DATA p_isr_ctx;\r
720 \r
721         MLX4_ENTER(MLX4_DBG_DRV);\r
722 \r
723         WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, isr, dpc );\r
724         \r
725         interruptConfig.EvtInterruptEnable = EvtEnableInterrupt;\r
726         interruptConfig.EvtInterruptDisable = EvtDisableInterrupt;\r
727         \r
728         \r
729         WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( \r
730                 &interruptAttributes, INTERRUPT_DATA );\r
731 \r
732         Status = WdfInterruptCreate( device,\r
733                 &interruptConfig, &interruptAttributes, p_int_obj );\r
734 \r
735         p_isr_ctx = WdfObjectGetTypedContext( *p_int_obj, INTERRUPT_DATA );\r
736         p_isr_ctx->int_num = int_num;\r
737         p_isr_ctx->p_fdo = p_fdo;\r
738         p_isr_ctx->eq = NULL;\r
739 \r
740         // one can call WdfInterruptSetPolicy() to set the policy, affinity etc\r
741 \r
742         MLX4_EXIT( MLX4_DBG_DRV );\r
743         return Status;\r
744 }\r
745 \r
746 #endif\r
747 \r
748 inline void InitBusIsr(\r
749      struct VipBusIfc* pVipBusIfc\r
750     )\r
751 {\r
752     memset(pVipBusIfc, 0, sizeof(struct VipBusIfc));\r
753     KeInitializeEvent(&pVipBusIfc->NicData.ConfigChangeEvent, SynchronizationEvent, TRUE);\r
754 }\r
755 \r
756 NTSTATUS\r
757 EvtDeviceAdd(\r
758         IN WDFDRIVER        Driver,\r
759         IN PWDFDEVICE_INIT  DeviceInit\r
760         )\r
761 /*++\r
762 Routine Description:\r
763 \r
764         EvtDeviceAdd is called by the framework in response to AddDevice\r
765         call from the PnP manager. We create and initialize a device object to\r
766         represent a new instance of mxe bus.\r
767 \r
768 Arguments:\r
769 \r
770         Driver - Handle to a framework driver object created in DriverEntry\r
771 \r
772         DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.\r
773 \r
774 Return Value:\r
775 \r
776         NTSTATUS\r
777 \r
778 --*/\r
779 {\r
780 #ifndef USE_WDM_INTERRUPTS\r
781         int i;\r
782 #endif\r
783         WDF_OBJECT_ATTRIBUTES                   attributes;\r
784         NTSTATUS                                                status;\r
785         WDFDEVICE                                               device;\r
786         PFDO_DEVICE_DATA                                p_fdo;\r
787         PNP_BUS_INFORMATION                             busInfo;\r
788         WDF_PNPPOWER_EVENT_CALLBACKS    Callbacks;\r
789 \r
790         UNREFERENCED_PARAMETER(Driver);\r
791 \r
792         PAGED_CODE ();\r
793         MLX4_ENTER(MLX4_DBG_DRV);\r
794 \r
795         //\r
796         // register PnP & Power stuff\r
797         //\r
798         WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);\r
799         Callbacks.EvtDevicePrepareHardware = EvtPrepareHardware;\r
800         Callbacks.EvtDeviceReleaseHardware = EvtReleaseHardware;\r
801         Callbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;\r
802         Callbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;\r
803 \r
804         WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &Callbacks );\r
805         \r
806         //\r
807         // Initialize all the properties specific to the device.\r
808         // Framework has default values for the one that are not\r
809         // set explicitly here. So please read the doc and make sure\r
810         // you are okay with the defaults.\r
811         //\r
812         WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);\r
813         WdfDeviceInitSetExclusive(DeviceInit, TRUE);\r
814 \r
815         //\r
816         // Initialize attributes structure to specify size and accessor function\r
817         // for storing device context.\r
818         //\r
819         WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_DEVICE_DATA);\r
820 \r
821         //\r
822         // Create a framework device object. In response to this call, framework\r
823         // creates a WDM deviceobject.\r
824         //\r
825         status = WdfDeviceCreate(&DeviceInit, &attributes, &device);\r
826         if (!NT_SUCCESS(status)) {\r
827                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, \r
828                         ("WdfDeviceCreate failed with 0x%x\n", status));\r
829                 goto end;\r
830         }\r
831 \r
832         //\r
833         // Get the device context.\r
834         //\r
835         p_fdo = FdoGetData(device);\r
836         RtlZeroMemory(p_fdo, sizeof(FDO_DEVICE_DATA));\r
837         p_fdo->FdoDevice = device;\r
838 \r
839     //\r
840     // Init the BusIsr data\r
841     //\r
842     InitBusIsr(&p_fdo->mtnic_Ifc);\r
843 \r
844         //\r
845         // Init the BusIsr data\r
846         //\r
847         InitBusIsr(&p_fdo->mtnic_Ifc);\r
848 \r
849         //\r
850         // Purpose of this lock is documented in PlugInDevice routine below.\r
851         //\r
852         WDF_OBJECT_ATTRIBUTES_INIT(&attributes);\r
853         attributes.ParentObject = device;\r
854         status = WdfWaitLockCreate(&attributes, &p_fdo->ChildLock);\r
855         if (!NT_SUCCESS(status)) {\r
856                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, \r
857                         ("WdfWaitLockCreate failed with 0x%x\n", status));\r
858                 goto end;\r
859         }\r
860 \r
861         //\r
862         // This value is used in responding to the IRP_MN_QUERY_BUS_INFORMATION\r
863         // for the child devices. This is an optional information provided to\r
864         // uniquely identify the bus the device is connected.\r
865         //\r
866         busInfo.BusTypeGuid = MLX4_BUS_TYPE_GUID;\r
867         busInfo.LegacyBusType = PNPBus;\r
868         busInfo.BusNumber = 0;\r
869 \r
870         WdfDeviceSetBusInformationForChildren(device, &busInfo);\r
871 \r
872         //\r
873         // WMI\r
874         //\r
875         status = WmiRegistration(device);\r
876         if (!NT_SUCCESS(status)) {\r
877                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, \r
878                         ("WmiRegistration failed with 0x%x\n", status));\r
879                 goto end;\r
880         }\r
881 \r
882 #ifndef USE_WDM_INTERRUPTS\r
883 \r
884         //\r
885         // create interrupt objects\r
886         //\r
887         for ( i = 0; i < MLX4_MAX_INTERRUPTS; ++i ) {\r
888                 status = __create_interrupt( p_fdo->FdoDevice, i, EvtInterruptIsr,\r
889                         NULL, p_fdo, &p_fdo->interrupt[i].WdfInterrupt );\r
890                 if (NT_SUCCESS(status)) \r
891                         p_fdo->interrupt[i].valid = TRUE;\r
892                 else {\r
893                         MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV,\r
894                                 ("WdfInterruptCreate failed %#x\n", status ));\r
895                         goto end;\r
896                 }\r
897         }\r
898 \r
899 #endif\r
900 \r
901         status = STATUS_SUCCESS;\r
902 \r
903 end:    \r
904         MLX4_EXIT( MLX4_DBG_DRV );\r
905         return status;\r
906 }\r
907 \r
908 \r
909 \r
910 void\r
911 EvtDriverUnload(\r
912         IN              WDFDRIVER  Driver\r
913         )\r
914 {\r
915         MLX4_ENTER( MLX4_DBG_DRV );\r
916 \r
917         UNUSED_PARAM( Driver );\r
918 \r
919         mlx4_ib_cleanup();\r
920         core_cleanup();\r
921 \r
922         MLX4_EXIT( MLX4_DBG_DRV );\r
923 #if defined(EVENT_TRACING)\r
924         WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver));\r
925 #endif\r
926 \r
927 }\r
928 \r
929 static\r
930 NTSTATUS\r
931 __read_registry(WDFDRIVER *hDriver)\r
932 {\r
933         DECLARE_CONST_UNICODE_STRING(debugLevel, L"DebugLevel");\r
934         DECLARE_CONST_UNICODE_STRING(debugFlags, L"DebugFlags");\r
935 \r
936         // "log maximum number of QPs per HCA"\r
937         DECLARE_CONST_UNICODE_STRING(numQp, L"LogNumQp");\r
938 \r
939         // "log number of RDMARC buffers per QP"\r
940         DECLARE_CONST_UNICODE_STRING(numRdmaRc, L"LogNumRdmaRc");\r
941 \r
942         // "log maximum number of SRQs per HCA"\r
943         DECLARE_CONST_UNICODE_STRING(numSrq, L"LogNumSrq");\r
944 \r
945         // "log maximum number of CQs per HCA"\r
946         DECLARE_CONST_UNICODE_STRING(numCq, L"LogNumCq");\r
947 \r
948         // "log maximum number of multicast groups per HCA"\r
949         DECLARE_CONST_UNICODE_STRING(numMcg, L"LogNumMcg");\r
950 \r
951         // "log maximum number of memory protection table entries per HCA"\r
952         DECLARE_CONST_UNICODE_STRING(numMpt, L"LogNumMpt");\r
953 \r
954         // "log maximum number of memory translation table segments per HCA"\r
955         DECLARE_CONST_UNICODE_STRING(numMtt, L"LogNumMtt");     \r
956 \r
957         // "Maximum number of MACs per ETH port (1-127, default 1"\r
958         DECLARE_CONST_UNICODE_STRING(numMac, L"NumMac");        \r
959 \r
960         // "Maximum number of VLANs per ETH port (0-126, default 0)"\r
961         DECLARE_CONST_UNICODE_STRING(numVlan, L"NumVlan");      \r
962 \r
963         // "Enable steering by VLAN priority on ETH ports (0/1, default 0)"\r
964         DECLARE_CONST_UNICODE_STRING(usePrio, L"UsePrio");      \r
965 \r
966         // "Enable Quality of Service support in the HCA if > 0, (default 1)"\r
967         DECLARE_CONST_UNICODE_STRING(enableQoS, L"EnableQoS");  \r
968 \r
969         // "Block multicast loopback packets if > 0 (default 1)"\r
970         DECLARE_CONST_UNICODE_STRING(BlockMcastLB, L"BlockMcastLoopBack");      \r
971 \r
972         // "Measure the interrupt from the first packet (default 1)"\r
973         DECLARE_CONST_UNICODE_STRING(InterruptFromFirstPacket, L"InterruptFromFirstPacket");    \r
974 \r
975         // "Ports L2 type (ib/eth/auto, entry per port, comma seperated, default ib for all)"\r
976         DECLARE_CONST_UNICODE_STRING(PortType, L"PortType");\r
977 \r
978         // "MSI is supported"\r
979         DECLARE_CONST_UNICODE_STRING(MsiEnable, L"MsiEnable");\r
980 \r
981         // "max number of interrupt vectors, supported"\r
982         DECLARE_CONST_UNICODE_STRING(MsiNumVector, L"MsiNumVector");\r
983         \r
984         ULONG value;\r
985         WDFKEY hKey = NULL;\r
986         NTSTATUS status = STATUS_SUCCESS;\r
987 \r
988         UNICODE_STRING uvalue;\r
989 #define  MAX_UVALUE 100\r
990         WCHAR uvalue_data[MAX_UVALUE];\r
991         \r
992         status = WdfDriverOpenParametersRegistryKey( *hDriver,\r
993                 STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &hKey );\r
994 \r
995         if (NT_SUCCESS (status)) {\r
996 \r
997                 //\r
998                 // Read general values\r
999                 //\r
1000                 status = WdfRegistryQueryULong(hKey, &debugLevel, &value);\r
1001                 if (NT_SUCCESS (status)) \r
1002                         g_mlx4_dbg_level = g.bwsd.DebugPrintLevel = value;\r
1003                 \r
1004                 status = WdfRegistryQueryULong(hKey, &debugFlags, &value);\r
1005                 if (NT_SUCCESS (status)) \r
1006                         g_mlx4_dbg_flags = g.bwsd.DebugPrintFlags = value;\r
1007 \r
1008                 status = WdfRegistryQueryULong(hKey, &numQp, &value);\r
1009                 if (NT_SUCCESS (status)) \r
1010                         g.mod_num_qp = value;\r
1011 \r
1012                 status = WdfRegistryQueryULong(hKey, &numRdmaRc, &value);\r
1013                 if (NT_SUCCESS (status)) \r
1014                         g.mod_rdmarc_per_qp = value;\r
1015 \r
1016                 status = WdfRegistryQueryULong(hKey, &numSrq, &value);\r
1017                 if (NT_SUCCESS (status)) \r
1018                         g.mod_num_srq = value;\r
1019 \r
1020                 status = WdfRegistryQueryULong(hKey, &numCq, &value);\r
1021                 if (NT_SUCCESS (status)) \r
1022                         g.mod_num_cq = value;\r
1023 \r
1024                 status = WdfRegistryQueryULong(hKey, &numMcg, &value);\r
1025                 if (NT_SUCCESS (status)) \r
1026                         g.mod_num_mcg = value;\r
1027 \r
1028                 status = WdfRegistryQueryULong(hKey, &numMpt, &value);\r
1029                 if (NT_SUCCESS (status)) \r
1030                         g.mod_num_mpt = value;\r
1031                 \r
1032                 status = WdfRegistryQueryULong(hKey, &numMtt, &value);\r
1033                 if (NT_SUCCESS (status)) \r
1034                         g.mod_num_mtt = value;\r
1035 \r
1036                 status = WdfRegistryQueryULong(hKey, &numMac, &value);\r
1037                 if (NT_SUCCESS (status)) \r
1038                         g.mod_num_mac = value;\r
1039                 else\r
1040                         g.mod_num_mac = 1;\r
1041 \r
1042                 status = WdfRegistryQueryULong(hKey, &numVlan, &value);\r
1043                 if (NT_SUCCESS (status)) \r
1044                         g.mod_num_vlan= value;\r
1045                 else\r
1046                         g.mod_num_vlan = 0;\r
1047 \r
1048                 status = WdfRegistryQueryULong(hKey, &usePrio, &value);\r
1049                 if (NT_SUCCESS (status)) \r
1050                         g.mod_use_prio= value;\r
1051                 else\r
1052                         g.mod_use_prio = 0;\r
1053 \r
1054                 status = WdfRegistryQueryULong(hKey, &enableQoS, &value);\r
1055                 if (NT_SUCCESS (status)) \r
1056                         g.mod_enable_qos = value;\r
1057                 else\r
1058                         g.mod_enable_qos = 1;\r
1059 \r
1060 \r
1061                 status = WdfRegistryQueryULong(hKey, &BlockMcastLB, &value);\r
1062                 if (NT_SUCCESS (status)) \r
1063                         g.mod_mlx4_blck_lb = value;\r
1064                 else\r
1065                         g.mod_mlx4_blck_lb = 1;\r
1066 \r
1067                 status = WdfRegistryQueryULong(hKey, &InterruptFromFirstPacket, &value);\r
1068                 if (NT_SUCCESS (status)) \r
1069                         g.mod_interrupt_from_first = value;\r
1070                 else\r
1071                         g.mod_interrupt_from_first = 1;\r
1072 \r
1073 \r
1074                 status = WdfRegistryQueryULong(hKey, &MsiEnable, &value);\r
1075                 if (NT_SUCCESS (status)) \r
1076                         g.mod_msi_enable = value;\r
1077                 else\r
1078                         g.mod_msi_enable = 0;\r
1079                 \r
1080                 status = WdfRegistryQueryULong(hKey, &MsiNumVector, &value);\r
1081                 if (NT_SUCCESS (status)) \r
1082                         g.mod_msi_num_vector = value;\r
1083                 else\r
1084                         g.mod_msi_num_vector = 8;\r
1085 \r
1086                 uvalue.Buffer = uvalue_data;\r
1087                 uvalue.MaximumLength = MAX_UVALUE;\r
1088                 uvalue.Length = 0;\r
1089 \r
1090                 status = WdfRegistryQueryUnicodeString(hKey, &PortType, NULL, &uvalue);\r
1091                 if (NT_SUCCESS (status)) {\r
1092                         if (!wcscmp(uvalue_data, L"ib,ib")) {\r
1093                                 g.mod_port_type [0] = MLX4_PORT_TYPE_IB;\r
1094                                 g.mod_port_type [1] = MLX4_PORT_TYPE_IB;\r
1095                         } else\r
1096                         if (!wcscmp(uvalue_data, L"ib,eth")) {\r
1097                                 g.mod_port_type [0] = MLX4_PORT_TYPE_IB;\r
1098                                 g.mod_port_type [1] = MLX4_PORT_TYPE_ETH;\r
1099                         } else\r
1100                         if (!wcscmp(uvalue_data, L"eth,ib")) {\r
1101                                 g.mod_port_type [0] = MLX4_PORT_TYPE_ETH;\r
1102                                 g.mod_port_type [1] = MLX4_PORT_TYPE_IB;\r
1103                         } else\r
1104                         if (!wcscmp(uvalue_data, L"eth,eth")) {\r
1105                                 g.mod_port_type [0] = MLX4_PORT_TYPE_ETH;\r
1106                                 g.mod_port_type [1] = MLX4_PORT_TYPE_ETH;\r
1107                         }\r
1108                 }\r
1109                 else {\r
1110                         g.mod_port_type [0] = MLX4_PORT_TYPE_IB;\r
1111                         g.mod_port_type [1] = MLX4_PORT_TYPE_IB;\r
1112                 }\r
1113 \r
1114 \r
1115                 WdfRegistryClose(hKey);\r
1116                 status = STATUS_SUCCESS;\r
1117         }\r
1118 \r
1119         return status;\r
1120 }\r
1121 \r
1122 NTSTATUS\r
1123 DriverEntry(\r
1124         IN PDRIVER_OBJECT DriverObject,\r
1125         IN PUNICODE_STRING RegistryPath\r
1126         )\r
1127 /*++\r
1128 Routine Description:\r
1129 \r
1130         Initialize the call backs structure of Driver Framework.\r
1131 \r
1132 Arguments:\r
1133 \r
1134         DriverObject - pointer to the driver object\r
1135 \r
1136         RegistryPath - pointer to a unicode string representing the path,\r
1137                                 to driver-specific key in the registry.\r
1138 \r
1139 Return Value:\r
1140 \r
1141   NT Status Code\r
1142 \r
1143 --*/\r
1144 {\r
1145         int err;\r
1146         WDF_DRIVER_CONFIG   config;\r
1147         NTSTATUS            status;\r
1148         WDFDRIVER hDriver;\r
1149 \r
1150 #if defined(EVENT_TRACING)\r
1151         WPP_INIT_TRACING(DriverObject, RegistryPath);\r
1152 #endif\r
1153 \r
1154 \r
1155         // global initializations\r
1156         RtlZeroMemory( &g, sizeof(g) );\r
1157         g_mlx4_dbg_level = g.bwsd.DebugPrintLevel = TRACE_LEVEL_VERBOSE;\r
1158         g_mlx4_dbg_flags = g.bwsd.DebugPrintFlags = 0xffff;\r
1159 \r
1160         MLX4_ENTER(MLX4_DBG_DRV);\r
1161         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, \r
1162                 ("Built %s %s, Version %s, RelDate %s\n", \r
1163                 __DATE__, __TIME__, DRV_VERSION, DRV_RELDATE));\r
1164 \r
1165         mlx4_net_init();\r
1166         err = core_init();\r
1167         if (err) {\r
1168                 status = errno_to_ntstatus(err);\r
1169                 goto end;\r
1170         }\r
1171         err = mlx4_ib_init();\r
1172         if (err) {\r
1173                 status = errno_to_ntstatus(err);\r
1174                 goto end;\r
1175         }\r
1176 \r
1177         //\r
1178         // Initiialize driver config to control the attributes that\r
1179         // are global to the driver. Note that framework by default\r
1180         // provides a driver unload routine. If you create any resources\r
1181         // in the DriverEntry and want to be cleaned in driver unload,\r
1182         // you can override that by specifing one in the Config structure.\r
1183         //\r
1184 \r
1185         WDF_DRIVER_CONFIG_INIT(\r
1186                 &config, EvtDeviceAdd );\r
1187         config.EvtDriverUnload = EvtDriverUnload;\r
1188 \r
1189         //\r
1190         // Create a framework driver object to represent our driver.\r
1191         //\r
1192         status = WdfDriverCreate(DriverObject,\r
1193                 RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,\r
1194                 &config, &hDriver);\r
1195 \r
1196         if (!NT_SUCCESS(status)) {\r
1197                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, ("WdfDriverCreate failed with status 0x%x\n", status));\r
1198                 goto end;\r
1199         }\r
1200 \r
1201         //\r
1202         // read registry parameters\r
1203         //\r
1204         status = __read_registry(&hDriver);\r
1205 \r
1206         // we don't matter the failure in the work with Registry\r
1207         status = STATUS_SUCCESS;\r
1208         \r
1209 end:\r
1210         MLX4_EXIT( MLX4_DBG_DRV );\r
1211         return status;\r
1212 \r
1213 }\r
1214 \r
1215 \r
1216 \r