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