[MLX4] 1) added support for sending large multi-parameter messages to System Event...
[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, p_fdo->pci_dev.location);\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         struct ib_device_attr props;\r
434         struct ib_device *p_ibdev;\r
435 \r
436         MLX4_ENTER(MLX4_DBG_DRV);\r
437 \r
438         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("PreviousState 0x%x\n", PreviousState));\r
439 \r
440         // start card (needed after Hibernetion)\r
441         if (PreviousState > WdfPowerDeviceD0)\r
442                 status = __start_card( Device, p_fdo );\r
443         if ( !NT_SUCCESS( status ) ) \r
444                 goto err;\r
445         mdev = pdev->dev;\r
446 \r
447         // create child device\r
448         status = __do_static_enumeration(Device);\r
449                 if (!NT_SUCCESS(status)) {\r
450                         MLX4_PRINT_EV(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, ("__do_static_enumeration failed with 0x%x\n", status));\r
451                         goto err;\r
452                 }\r
453 \r
454         // Log Success Message\r
455         MLX4_PRINT(TRACE_LEVEL_INFORMATION ,MLX4_DBG_DRV ,\r
456                 ("Ven %x Dev %d Fw %d.%d.%d, IsBurnDevice %s\n", \r
457                 (unsigned)pdev->ven_id, (unsigned)pdev->dev_id,\r
458                 (int) (mdev->caps.fw_ver >> 32),\r
459                 (int) (mdev->caps.fw_ver >> 16) & 0xffff, \r
460                 (int) (mdev->caps.fw_ver & 0xffff),\r
461                 mlx4_is_livefish(mdev) ? "Y" : "N"\r
462                 ));\r
463         if (!mlx4_is_livefish(mdev)) {\r
464                 memset ( &props, 0, sizeof( props) );\r
465                 p_ibdev = pdev->ib_dev;\r
466                 (p_ibdev->query_device)( p_ibdev, &props );\r
467                 WriteEventLogEntryData( pdev->p_self_do, (ULONG)EVENT_MLX4_INFO_DEV_STARTED, 0, 0, 11,\r
468                         L"%04x", (ULONG)pdev->ven_id, \r
469                         L"%04x", (ULONG)pdev->dev_id,\r
470                         L"%04x", (ULONG)pdev->sub_vendor_id,\r
471                         L"%04x", (ULONG)pdev->sub_system_id,\r
472                         L"%02x", (ULONG)pdev->revision_id,\r
473                         L"%d", (int) (mdev->caps.fw_ver >> 32),\r
474                         L"%d", (int) (mdev->caps.fw_ver >> 16) & 0xffff, \r
475                         L"%d", (int) (mdev->caps.fw_ver & 0xffff),\r
476                         L"%08x", *(PULONG)((PUCHAR)&p_ibdev->node_guid + 0), \r
477                         L"%08x", *(PULONG)((PUCHAR)&p_ibdev->node_guid + 4), \r
478                         L"%s", pdev->location\r
479                         ); \r
480         }\r
481 \r
482 err:\r
483         MLX4_EXIT( MLX4_DBG_DRV );\r
484         return status;\r
485 }\r
486 \r
487 NTSTATUS\r
488 EvtDeviceD0Exit(\r
489         IN WDFDEVICE  Device,\r
490         IN WDF_POWER_DEVICE_STATE  TargetState\r
491         )\r
492 {\r
493         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
494         \r
495         MLX4_ENTER(MLX4_DBG_DRV);\r
496         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("TargetState 0x%x\n", TargetState));\r
497 \r
498         if (TargetState > WdfPowerDeviceD0)\r
499                 __stop_card( p_fdo );\r
500 \r
501         MLX4_EXIT( MLX4_DBG_DRV );\r
502         return STATUS_SUCCESS;\r
503 }\r
504 \r
505 \r
506 \r
507 /* Forwards the request to the HCA's PDO. */\r
508 static \r
509 void\r
510 __put_bus_ifc(\r
511                 IN      BUS_INTERFACE_STANDARD          *pBusIfc )\r
512 {\r
513         MLX4_ENTER(MLX4_DBG_DRV);\r
514         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("pBusIfc=0x%p\n", pBusIfc));\r
515         pBusIfc->InterfaceDereference( pBusIfc->Context );\r
516         MLX4_EXIT( MLX4_DBG_DRV );\r
517 }\r
518 \r
519 static \r
520 NTSTATUS\r
521 __get_bus_ifc(\r
522         IN                              PFDO_DEVICE_DATA const  p_fdo,\r
523         IN              const   GUID* const                             pGuid,\r
524         OUT                     BUS_INTERFACE_STANDARD  *pBusIfc )\r
525 {\r
526         NTSTATUS status;\r
527         WDFDEVICE  FdoDevice = p_fdo->FdoDevice;\r
528         MLX4_ENTER(MLX4_DBG_DRV);\r
529         \r
530         status = WdfFdoQueryForInterface( FdoDevice, pGuid, (PINTERFACE)pBusIfc,\r
531                 sizeof(BUS_INTERFACE_STANDARD), 1, NULL );\r
532         MLX4_EXIT( MLX4_DBG_DRV );\r
533         return status;\r
534 }\r
535 \r
536 static\r
537 void\r
538 __put_dma_adapter(\r
539         IN PFDO_DEVICE_DATA p_fdo,\r
540         IN PDMA_ADAPTER         p_dma )\r
541 {\r
542         UNUSED_PARAM(p_fdo);\r
543         UNUSED_PARAM(p_dma);\r
544         MLX4_ENTER(MLX4_DBG_DRV);\r
545         MLX4_EXIT( MLX4_DBG_DRV );\r
546 }\r
547 \r
548 \r
549 // this routine releases the resources, taken in __get_resources\r
550 static\r
551 void \r
552 __put_resources(\r
553         IN PFDO_DEVICE_DATA p_fdo\r
554         )\r
555 {\r
556         struct pci_dev *pdev = &p_fdo->pci_dev;\r
557 \r
558         MLX4_ENTER(MLX4_DBG_DRV);\r
559 \r
560         if (pdev->msix_info.valid) \r
561                 pci_free_msix_info_resources(&pdev->msix_info);\r
562 \r
563         if (p_fdo->dma_adapter_taken) {\r
564                 p_fdo->dma_adapter_taken = FALSE;\r
565                 __put_dma_adapter( p_fdo, pdev->p_dma_adapter );\r
566         }\r
567 \r
568         if (p_fdo->pci_bus_ifc_taken) {\r
569                 p_fdo->pci_bus_ifc_taken = FALSE;\r
570                 __put_bus_ifc(&pdev->bus_pci_ifc);\r
571         }\r
572 \r
573         if (pdev->p_msix_map)\r
574                 kfree(pdev->p_msix_map);\r
575 \r
576         \r
577         MLX4_EXIT( MLX4_DBG_DRV );\r
578 }\r
579 \r
580 static\r
581 NTSTATUS \r
582 __get_dma_adapter(\r
583         IN PFDO_DEVICE_DATA p_fdo,\r
584         OUT PDMA_ADAPTER *      pp_dma )\r
585 {\r
586         NTSTATUS status;\r
587         WDF_DMA_ENABLER_CONFIG  dmaConfig;\r
588         \r
589         MLX4_ENTER(MLX4_DBG_DRV);\r
590 \r
591         WDF_DMA_ENABLER_CONFIG_INIT( &dmaConfig,\r
592                 WdfDmaProfileScatterGather64, 0x80000000 - 1 );\r
593 \r
594         status = WdfDmaEnablerCreate( p_fdo->FdoDevice,\r
595                 &dmaConfig, WDF_NO_OBJECT_ATTRIBUTES, &p_fdo->dma_enabler );\r
596         if (!NT_SUCCESS (status)) {\r
597                 return status;\r
598         }\r
599         \r
600         *pp_dma = WdfDmaEnablerWdmGetDmaAdapter( \r
601                 p_fdo->dma_enabler, WdfDmaDirectionReadFromDevice );\r
602 \r
603         MLX4_EXIT( MLX4_DBG_DRV );\r
604         return status;\r
605 }\r
606 \r
607 // this routine fills pci_dev structure, containing all HW \r
608 // and some other necessary common resources\r
609 static\r
610 NTSTATUS \r
611 __get_resources(\r
612         IN PFDO_DEVICE_DATA p_fdo,\r
613         IN WDFCMRESLIST  ResourcesRaw,\r
614         IN WDFCMRESLIST  ResourcesTranslated\r
615         )\r
616 {\r
617         NTSTATUS status;\r
618         ULONG i, k=0;\r
619         PCM_PARTIAL_RESOURCE_DESCRIPTOR  desc;\r
620         PCM_PARTIAL_RESOURCE_DESCRIPTOR  desc_raw;\r
621         BUS_INTERFACE_STANDARD  bus_pci_ifc;\r
622         struct pci_dev *pdev = &p_fdo->pci_dev;\r
623 \r
624         MLX4_ENTER(MLX4_DBG_DRV);\r
625 \r
626         //\r
627         // Get PCI BUS interface\r
628         // \r
629         status = __get_bus_ifc( p_fdo, &GUID_BUS_INTERFACE_STANDARD, &bus_pci_ifc );\r
630         if( !NT_SUCCESS( status ) ) {\r
631                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
632                         ("failed: status=0x%x\n", status));\r
633                 return status;\r
634         }\r
635         RtlCopyMemory( &pdev->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );\r
636         p_fdo->pci_bus_ifc_taken = TRUE;\r
637 \r
638         // \r
639         // get HW resources\r
640         //\r
641         for (i = 0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) {\r
642 \r
643                 desc = WdfCmResourceListGetDescriptor( ResourcesTranslated, i );\r
644                 desc_raw = WdfCmResourceListGetDescriptor( ResourcesRaw, i );\r
645 \r
646                 switch (desc->Type) {\r
647 \r
648                         case CmResourceTypeMemory:\r
649                                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV,\r
650                                         ("EvtPrepareHardware(Raw): Desc %d: Memory: Start %#I64x, Length %#x\n", \r
651                                         i, desc_raw->u.Memory.Start.QuadPart, desc_raw->u.Memory.Length ));\r
652                                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV,\r
653                                         ("EvtPrepareHardware: Desc %d: Memory: Start %#I64x, Length %#x\n", \r
654                                         i, desc->u.Memory.Start.QuadPart, desc->u.Memory.Length ));\r
655 \r
656                                 if (k < N_BARS) {\r
657                                         pdev->bar[k].phys = desc->u.Memory.Start.QuadPart;\r
658                                         pdev->bar[k].size = (SIZE_T)desc->u.Memory.Length;\r
659                                 }\r
660                                 k++;\r
661                                 break;\r
662 \r
663 #ifdef USE_WDM_INTERRUPTS\r
664                         case CmResourceTypeInterrupt:\r
665                                 if (!pdev->n_msi_vectors_alloc)\r
666                                         pdev->int_info = *desc;\r
667                                 if (desc->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {\r
668                                         pdev->n_msi_vectors_alloc = (u8)(pdev->n_msi_vectors_alloc+desc_raw->u.MessageInterrupt.Raw.MessageCount);\r
669                                         MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV,\r
670                                                 ("EvtPrepareHardware: Desc %d: MsiInterrupt: Share %d, Flags %#x, Level %d, Vector %#x, Affinity %#x\n", \r
671                                                 i, desc->ShareDisposition, desc->Flags,\r
672                                                 desc->u.MessageInterrupt.Translated.Level, \r
673                                                 desc->u.MessageInterrupt.Translated.Vector, \r
674                                                 (u32)desc->u.MessageInterrupt.Translated.Affinity ));\r
675                                         MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV,\r
676                                                 ("EvtPrepareHardware: Desc %d: RawMsiInterrupt: Share %d, Flags %#x, MessageCount %#hx, Vector %#x, Affinity %#x\n", \r
677                                                 i, desc_raw->ShareDisposition, desc_raw->Flags,\r
678                                                 desc_raw->u.MessageInterrupt.Raw.MessageCount, \r
679                                                 desc_raw->u.MessageInterrupt.Raw.Vector,\r
680                                                 (u32)desc_raw->u.MessageInterrupt.Raw.Affinity ));\r
681                                 }\r
682                                 else { // line-based interrupt\r
683                                         MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV,\r
684                                                 ("EvtPrepareHardware: Desc %d: LineInterrupt: Share %d, Flags %#x, Level %d, Vector %#x, Affinity %#x\n", \r
685                                                 i, desc->ShareDisposition, desc->Flags,\r
686                                                 desc->u.Interrupt.Level, desc->u.Interrupt.Vector, \r
687                                                 (u32)desc->u.Interrupt.Affinity ));\r
688                                 }\r
689                                 break;\r
690 #endif\r
691 \r
692                         default:\r
693                                 //\r
694                                 // Ignore all other descriptors.\r
695                                 //\r
696                                 break;\r
697                 }\r
698         }\r
699         if (i ==0) {\r
700                 // This means that no resources are found\r
701                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, ("WdfCmResourceListGetCount: returned 0, quiting\n"));\r
702                 return STATUS_INSUFFICIENT_RESOURCES;\r
703         }\r
704 \r
705         //\r
706         // get uplink info. \r
707         //\r
708         status = pci_save_config( &pdev->bus_pci_ifc, \r
709                 &pdev->pci_cfg_space );\r
710         if( !NT_SUCCESS( status ) )\r
711         {\r
712                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
713                         ("Failed to save HCA config: status=0x%x\n", status));\r
714                 goto err;\r
715         }\r
716         pci_get_uplink_info( &pdev->pci_cfg_space, &pdev->uplink_info );\r
717 \r
718         //\r
719         // allocate DMA adapter\r
720         //\r
721         status = __get_dma_adapter( p_fdo, &pdev->p_dma_adapter );\r
722         if( !NT_SUCCESS( status ) )\r
723         {\r
724                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
725                         ("Failed to get DMA adapter: status=0x%x\n", status));\r
726                 goto err;\r
727         }\r
728         p_fdo->dma_adapter_taken = TRUE;\r
729 \r
730         //\r
731         // allocate MSI-X vector map table\r
732         //\r
733         if ( pdev->n_msi_vectors_alloc )\r
734         {\r
735                 pdev->p_msix_map = kzalloc(sizeof(struct msix_map) * pdev->n_msi_vectors_alloc, GFP_KERNEL);\r
736                 if ( !pdev->p_msix_map )\r
737                 {\r
738                         MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
739                                 ("Failed to allocate MSI-X vector map table\n"));\r
740                         goto err;\r
741                 }\r
742         }\r
743         \r
744         //\r
745         // fill more fields in pci_dev\r
746         //\r
747         pdev->ven_id = pdev->pci_cfg_space.VendorID;\r
748         pdev->dev_id = pdev->pci_cfg_space.DeviceID;\r
749         pdev->sub_vendor_id = pdev->pci_cfg_space.u.type0.SubVendorID;\r
750         pdev->sub_system_id = pdev->pci_cfg_space.u.type0.SubSystemID;\r
751         pdev->revision_id = pdev->pci_cfg_space.RevisionID;\r
752         pdev->p_self_do = WdfDeviceWdmGetDeviceObject(p_fdo->FdoDevice);\r
753         pdev->pdo = WdfDeviceWdmGetPhysicalDevice(p_fdo->FdoDevice);\r
754         \r
755         MLX4_EXIT( MLX4_DBG_DRV );\r
756         return STATUS_SUCCESS;\r
757 err:\r
758         __put_resources(p_fdo);\r
759         MLX4_EXIT( MLX4_DBG_DRV );\r
760         return status;\r
761 }\r
762 \r
763 NTSTATUS\r
764 EvtPrepareHardware(\r
765         IN WDFDEVICE  Device,\r
766         IN WDFCMRESLIST  ResourcesRaw,\r
767         IN WDFCMRESLIST  ResourcesTranslated\r
768         )\r
769 {\r
770         NTSTATUS status;\r
771         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
772         struct pci_dev *pdev = &p_fdo->pci_dev;\r
773         struct mlx4_dev *mdev;\r
774         WDFMEMORY  memory;\r
775         WDF_OBJECT_ATTRIBUTES  attributes;\r
776 \r
777         MLX4_ENTER(MLX4_DBG_DRV);\r
778 \r
779         // get resources\r
780         status = __get_resources( p_fdo, ResourcesRaw, ResourcesTranslated );\r
781         if( !NT_SUCCESS( status ) ) {\r
782                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, ("__get_resources failed: status=0x%x\n", status));\r
783                 goto err;\r
784         }\r
785 \r
786         // start the card\r
787         status = __start_card(Device, p_fdo );\r
788         if( !NT_SUCCESS( status ) ) \r
789                 goto err;\r
790         mdev = pdev->dev;\r
791 \r
792         // get VPD \r
793         status = pci_get_vpd( &pdev->bus_pci_ifc, \r
794                 &pdev->pci_cfg_space, &pdev->vpd, &pdev->vpd_size );\r
795         if( !NT_SUCCESS( status ) )\r
796         {\r
797                 MLX4_PRINT_EV(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
798                         ("pci_get_vpd failed,  status=0x%x\n", status));\r
799                 goto err;\r
800         }\r
801 \r
802         // get card location\r
803         WDF_OBJECT_ATTRIBUTES_INIT(&attributes);\r
804         attributes.ParentObject = Device;\r
805         status = WdfDeviceAllocAndQueryProperty( Device,\r
806                 DevicePropertyLocationInformation, NonPagedPool,\r
807                 &attributes, &memory );\r
808         if( NT_SUCCESS( status ) ) {\r
809                 UCHAR *ptr;\r
810 \r
811                 // get location\r
812                 ptr = WdfMemoryGetBuffer(memory, NULL);\r
813                 status = RtlStringCbCopyW( (LPWSTR)p_fdo->pci_dev.location, \r
814                         sizeof(p_fdo->pci_dev.location), (LPCWSTR)ptr );\r
815                 WdfObjectDelete(memory);\r
816                 if( !NT_SUCCESS( status ) ) {\r
817                         MLX4_PRINT_EV(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
818                                 ("Failed to move location string '%S',  status=0x%x\n", ptr, status));\r
819                 }\r
820         }\r
821         else {\r
822                 MLX4_PRINT_EV(TRACE_LEVEL_ERROR, MLX4_DBG_DRV, \r
823                         ("WdfDeviceAllocAndQueryProperty failed,  status=0x%x\n", status));\r
824         }\r
825         \r
826 err:\r
827         MLX4_EXIT( MLX4_DBG_DRV );\r
828         return status;\r
829 }\r
830 \r
831 void fix_bus_ifc(struct pci_dev *pdev)\r
832 {\r
833         PFDO_DEVICE_DATA p_fdo;\r
834 \r
835         p_fdo =  CONTAINING_RECORD(pdev, FDO_DEVICE_DATA, pci_dev);\r
836         p_fdo->bus_ib_ifc.p_ibdev = p_fdo->pci_dev.ib_dev;\r
837         p_fdo->bus_ib_ifc.pmlx4_dev = to_mdev(p_fdo->pci_dev.ib_dev)->dev;\r
838         p_fdo->bus_ib_ifc.is_livefish = mlx4_is_livefish(p_fdo->pci_dev.dev);\r
839 }\r
840 \r
841 NTSTATUS\r
842 EvtReleaseHardware(\r
843         IN WDFDEVICE  Device,\r
844         IN WDFCMRESLIST  ResourcesTranslated\r
845         )\r
846 {\r
847         PFDO_DEVICE_DATA p_fdo  = FdoGetData(Device);\r
848         struct pci_dev *pdev = &p_fdo->pci_dev;\r
849         int i;\r
850 \r
851         UNUSED_PARAM(ResourcesTranslated);\r
852 \r
853         MLX4_ENTER(MLX4_DBG_DRV);\r
854 \r
855         if ( pdev->vpd ) {\r
856                 kfree( pdev->vpd );\r
857                 pdev->vpd = NULL;\r
858                 pdev->vpd_size = 0;\r
859         }\r
860         __stop_card( p_fdo );\r
861         __put_resources( p_fdo );\r
862         for (i=0; i<MAX_HCA_CARDS; ++i) {\r
863                 if ( g.p_fdo[i] == p_fdo) {\r
864                         g.p_fdo[i] = NULL;\r
865                         break;\r
866                 }\r
867         }\r
868 \r
869         MLX4_EXIT( MLX4_DBG_DRV );\r
870         return STATUS_SUCCESS;\r
871 }\r
872 \r
873 #ifndef USE_WDM_INTERRUPTS\r
874 \r
875 static\r
876 NTSTATUS \r
877 __create_interrupt(\r
878         IN WDFDEVICE                            device,\r
879         IN int                                          int_num,\r
880         IN PFN_WDF_INTERRUPT_ISR        isr,\r
881         IN PFN_WDF_INTERRUPT_DPC        dpc,\r
882         IN PFDO_DEVICE_DATA                     p_fdo,\r
883         OUT WDFINTERRUPT                *       p_int_obj\r
884         )\r
885 {\r
886         NTSTATUS Status;\r
887 \r
888         WDF_INTERRUPT_CONFIG  interruptConfig;\r
889         WDF_OBJECT_ATTRIBUTES  interruptAttributes;\r
890         PINTERRUPT_DATA p_isr_ctx;\r
891 \r
892         MLX4_ENTER(MLX4_DBG_DRV);\r
893 \r
894         WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, isr, dpc );\r
895         \r
896         interruptConfig.EvtInterruptEnable = EvtEnableInterrupt;\r
897         interruptConfig.EvtInterruptDisable = EvtDisableInterrupt;\r
898         \r
899         \r
900         WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( \r
901                 &interruptAttributes, INTERRUPT_DATA );\r
902 \r
903         Status = WdfInterruptCreate( device,\r
904                 &interruptConfig, &interruptAttributes, p_int_obj );\r
905 \r
906         p_isr_ctx = WdfObjectGetTypedContext( *p_int_obj, INTERRUPT_DATA );\r
907         p_isr_ctx->int_num = int_num;\r
908         p_isr_ctx->p_fdo = p_fdo;\r
909         p_isr_ctx->eq = NULL;\r
910 \r
911         // one can call WdfInterruptSetPolicy() to set the policy, affinity etc\r
912 \r
913         MLX4_EXIT( MLX4_DBG_DRV );\r
914         return Status;\r
915 }\r
916 \r
917 #endif\r
918 \r
919 inline void InitBusIsr(\r
920      struct VipBusIfc* pVipBusIfc\r
921     )\r
922 {\r
923     memset(pVipBusIfc, 0, sizeof(struct VipBusIfc));\r
924     KeInitializeEvent(&pVipBusIfc->NicData.ConfigChangeEvent, SynchronizationEvent, TRUE);\r
925 }\r
926 \r
927 NTSTATUS\r
928 EvtDriverDeviceAdd(\r
929         IN WDFDRIVER        Driver,\r
930         IN PWDFDEVICE_INIT  DeviceInit\r
931         )\r
932 /*++\r
933 Routine Description:\r
934 \r
935         EvtDriverDeviceAdd is called by the framework in response to AddDevice\r
936         call from the PnP manager. We create and initialize a device object to\r
937         represent a new instance of mxe bus.\r
938 \r
939 Arguments:\r
940 \r
941         Driver - Handle to a framework driver object created in DriverEntry\r
942 \r
943         DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.\r
944 \r
945 Return Value:\r
946 \r
947         NTSTATUS\r
948 \r
949 --*/\r
950 {\r
951 #ifndef USE_WDM_INTERRUPTS\r
952         int i;\r
953 #endif\r
954         WDF_OBJECT_ATTRIBUTES                   attributes;\r
955         NTSTATUS                                                status;\r
956         WDFDEVICE                                               device;\r
957         PFDO_DEVICE_DATA                                p_fdo;\r
958         PNP_BUS_INFORMATION                             busInfo;\r
959         WDF_PNPPOWER_EVENT_CALLBACKS    Callbacks;\r
960         int i;\r
961 \r
962         UNREFERENCED_PARAMETER(Driver);\r
963 \r
964         PAGED_CODE ();\r
965         MLX4_ENTER(MLX4_DBG_DRV);\r
966 \r
967         //\r
968         // register PnP & Power stuff\r
969         //\r
970         WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);\r
971         Callbacks.EvtDevicePrepareHardware = EvtPrepareHardware;\r
972         Callbacks.EvtDeviceReleaseHardware = EvtReleaseHardware;\r
973         Callbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;\r
974         Callbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;\r
975 \r
976         WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &Callbacks );\r
977         \r
978         //\r
979         // Initialize all the properties specific to the device.\r
980         // Framework has default values for the one that are not\r
981         // set explicitly here. So please read the doc and make sure\r
982         // you are okay with the defaults.\r
983         //\r
984         WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);\r
985         WdfDeviceInitSetExclusive(DeviceInit, TRUE);\r
986 \r
987         //\r
988         // Initialize attributes structure to specify size and accessor function\r
989         // for storing device context.\r
990         //\r
991         WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_DEVICE_DATA);\r
992 \r
993         //\r
994         // Create a framework device object. In response to this call, framework\r
995         // creates a WDM deviceobject.\r
996         //\r
997         status = WdfDeviceCreate(&DeviceInit, &attributes, &device);\r
998         if (!NT_SUCCESS(status)) {\r
999                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, \r
1000                         ("WdfDeviceCreate failed with 0x%x\n", status));\r
1001                 goto end;\r
1002         }\r
1003 \r
1004         //\r
1005         // Get the device context.\r
1006         //\r
1007         p_fdo = FdoGetData(device);\r
1008         RtlZeroMemory(p_fdo, sizeof(FDO_DEVICE_DATA));\r
1009         p_fdo->FdoDevice = device; \r
1010         for (i=0; i<MAX_HCA_CARDS; ++i) {\r
1011                 if (!g.p_fdo[i]) {\r
1012                         g.p_fdo[i] = p_fdo;\r
1013                         break;\r
1014                 }\r
1015         }\r
1016 \r
1017         //\r
1018         // Init the BusIsr data\r
1019         //\r
1020         InitBusIsr(&p_fdo->mtnic_Ifc);\r
1021 \r
1022         //\r
1023         // Purpose of this lock is documented in PlugInDevice routine below.\r
1024         //\r
1025         WDF_OBJECT_ATTRIBUTES_INIT(&attributes);\r
1026         attributes.ParentObject = device;\r
1027         status = WdfWaitLockCreate(&attributes, &p_fdo->ChildLock);\r
1028         if (!NT_SUCCESS(status)) {\r
1029                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, \r
1030                         ("WdfWaitLockCreate failed with 0x%x\n", status));\r
1031                 goto end;\r
1032         }\r
1033 \r
1034         //\r
1035         // This value is used in responding to the IRP_MN_QUERY_BUS_INFORMATION\r
1036         // for the child devices. This is an optional information provided to\r
1037         // uniquely identify the bus the device is connected.\r
1038         //\r
1039         busInfo.BusTypeGuid = MLX4_BUS_TYPE_GUID;\r
1040         busInfo.LegacyBusType = PNPBus;\r
1041         busInfo.BusNumber = 0;\r
1042 \r
1043         WdfDeviceSetBusInformationForChildren(device, &busInfo);\r
1044 \r
1045         //\r
1046         // WMI\r
1047         //\r
1048         status = WmiRegistration(device);\r
1049         if (!NT_SUCCESS(status)) {\r
1050                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, \r
1051                         ("WmiRegistration failed with 0x%x\n", status));\r
1052                 goto end;\r
1053         }\r
1054 \r
1055 #ifndef USE_WDM_INTERRUPTS\r
1056 \r
1057         //\r
1058         // create interrupt objects\r
1059         //\r
1060         for ( i = 0; i < MLX4_MAX_INTERRUPTS; ++i ) {\r
1061                 status = __create_interrupt( p_fdo->FdoDevice, i, EvtInterruptIsr,\r
1062                         NULL, p_fdo, &p_fdo->interrupt[i].WdfInterrupt );\r
1063                 if (NT_SUCCESS(status)) \r
1064                         p_fdo->interrupt[i].valid = TRUE;\r
1065                 else {\r
1066                         MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_DRV,\r
1067                                 ("WdfInterruptCreate failed %#x\n", status ));\r
1068                         goto end;\r
1069                 }\r
1070         }\r
1071 \r
1072 #endif\r
1073 \r
1074         status = STATUS_SUCCESS;\r
1075 \r
1076 end:    \r
1077         MLX4_EXIT( MLX4_DBG_DRV );\r
1078         return status;\r
1079 }\r
1080 \r
1081 \r
1082 \r
1083 void\r
1084 EvtDriverUnload(\r
1085         IN              WDFDRIVER  Driver\r
1086         )\r
1087 {\r
1088         MLX4_ENTER( MLX4_DBG_DRV );\r
1089 \r
1090         UNUSED_PARAM( Driver );\r
1091 \r
1092         mlx4_ib_cleanup();\r
1093         core_cleanup();\r
1094 \r
1095         MLX4_EXIT( MLX4_DBG_DRV );\r
1096 #if defined(EVENT_TRACING)\r
1097         WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver));\r
1098 #endif\r
1099 \r
1100 }\r
1101 \r
1102 static\r
1103 NTSTATUS\r
1104 __read_registry(WDFDRIVER *hDriver)\r
1105 {\r
1106         DECLARE_CONST_UNICODE_STRING(debugLevel, L"DebugLevel");\r
1107         DECLARE_CONST_UNICODE_STRING(debugFlags, L"DebugFlags");\r
1108 \r
1109         // "log maximum number of QPs per HCA"\r
1110         DECLARE_CONST_UNICODE_STRING(numQp, L"LogNumQp");\r
1111 \r
1112         // "log number of RDMARC buffers per QP"\r
1113         DECLARE_CONST_UNICODE_STRING(numRdmaRc, L"LogNumRdmaRc");\r
1114 \r
1115         // "log maximum number of SRQs per HCA"\r
1116         DECLARE_CONST_UNICODE_STRING(numSrq, L"LogNumSrq");\r
1117 \r
1118         // "log maximum number of CQs per HCA"\r
1119         DECLARE_CONST_UNICODE_STRING(numCq, L"LogNumCq");\r
1120 \r
1121         // "log maximum number of multicast groups per HCA"\r
1122         DECLARE_CONST_UNICODE_STRING(numMcg, L"LogNumMcg");\r
1123 \r
1124         // "log maximum number of memory protection table entries per HCA"\r
1125         DECLARE_CONST_UNICODE_STRING(numMpt, L"LogNumMpt");\r
1126 \r
1127         // "log maximum number of memory translation table segments per HCA"\r
1128         DECLARE_CONST_UNICODE_STRING(numMtt, L"LogNumMtt");     \r
1129 \r
1130         // "Maximum number of MACs per ETH port (1-127, default 1"\r
1131         DECLARE_CONST_UNICODE_STRING(numMac, L"NumMac");        \r
1132 \r
1133         // "Maximum number of VLANs per ETH port (0-126, default 0)"\r
1134         DECLARE_CONST_UNICODE_STRING(numVlan, L"NumVlan");      \r
1135 \r
1136         // "Enable steering by VLAN priority on ETH ports (0/1, default 0)"\r
1137         DECLARE_CONST_UNICODE_STRING(usePrio, L"UsePrio");      \r
1138 \r
1139         // "Enable Quality of Service support in the HCA if > 0, (default 1)"\r
1140         DECLARE_CONST_UNICODE_STRING(enableQoS, L"EnableQoS");  \r
1141 \r
1142         // "Block multicast loopback packets if > 0 (default 1)"\r
1143         DECLARE_CONST_UNICODE_STRING(BlockMcastLB, L"BlockMcastLoopBack");      \r
1144 \r
1145         // "Measure the interrupt from the first packet (default 1)"\r
1146         DECLARE_CONST_UNICODE_STRING(InterruptFromFirstPacket, L"InterruptFromFirstPacket");    \r
1147 \r
1148         // "ProcessorAffinity"\r
1149         DECLARE_CONST_UNICODE_STRING(ProcessorAffinity, L"ProcessorAffinity");\r
1150 \r
1151         ULONG value;\r
1152         WDFKEY hKey = NULL;\r
1153         NTSTATUS status = STATUS_SUCCESS;\r
1154         \r
1155         status = WdfDriverOpenParametersRegistryKey( *hDriver,\r
1156                 STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &hKey );\r
1157 \r
1158         if (NT_SUCCESS (status)) {\r
1159 \r
1160                 //\r
1161                 // Read general values\r
1162                 //\r
1163                 status = WdfRegistryQueryULong(hKey, &debugLevel, &value);\r
1164                 if (NT_SUCCESS (status)) \r
1165                         g_mlx4_dbg_level = g.bwsd.DebugPrintLevel = value;\r
1166                 \r
1167                 status = WdfRegistryQueryULong(hKey, &debugFlags, &value);\r
1168                 if (NT_SUCCESS (status)) \r
1169                         g_mlx4_dbg_flags = g.bwsd.DebugPrintFlags = value;\r
1170 \r
1171                 status = WdfRegistryQueryULong(hKey, &numQp, &value);\r
1172                 if (NT_SUCCESS (status)) \r
1173                         g.mod_num_qp = value;\r
1174 \r
1175                 status = WdfRegistryQueryULong(hKey, &numRdmaRc, &value);\r
1176                 if (NT_SUCCESS (status)) \r
1177                         g.mod_rdmarc_per_qp = value;\r
1178 \r
1179                 status = WdfRegistryQueryULong(hKey, &numSrq, &value);\r
1180                 if (NT_SUCCESS (status)) \r
1181                         g.mod_num_srq = value;\r
1182 \r
1183                 status = WdfRegistryQueryULong(hKey, &numCq, &value);\r
1184                 if (NT_SUCCESS (status)) \r
1185                         g.mod_num_cq = value;\r
1186 \r
1187                 status = WdfRegistryQueryULong(hKey, &numMcg, &value);\r
1188                 if (NT_SUCCESS (status)) \r
1189                         g.mod_num_mcg = value;\r
1190 \r
1191                 status = WdfRegistryQueryULong(hKey, &numMpt, &value);\r
1192                 if (NT_SUCCESS (status)) \r
1193                         g.mod_num_mpt = value;\r
1194                 \r
1195                 status = WdfRegistryQueryULong(hKey, &numMtt, &value);\r
1196                 if (NT_SUCCESS (status)) \r
1197                         g.mod_num_mtt = value;\r
1198 \r
1199                 status = WdfRegistryQueryULong(hKey, &numMac, &value);\r
1200                 if (NT_SUCCESS (status)) \r
1201                         g.mod_num_mac = value;\r
1202                 else\r
1203                         g.mod_num_mac = 1;\r
1204 \r
1205                 status = WdfRegistryQueryULong(hKey, &numVlan, &value);\r
1206                 if (NT_SUCCESS (status)) \r
1207                         g.mod_num_vlan= value;\r
1208                 else\r
1209                         g.mod_num_vlan = 0;\r
1210 \r
1211                 status = WdfRegistryQueryULong(hKey, &usePrio, &value);\r
1212                 if (NT_SUCCESS (status)) \r
1213                         g.mod_use_prio= value;\r
1214                 else\r
1215                         g.mod_use_prio = 0;\r
1216 \r
1217                 status = WdfRegistryQueryULong(hKey, &enableQoS, &value);\r
1218                 if (NT_SUCCESS (status)) \r
1219                         g.mod_enable_qos = value;\r
1220                 else\r
1221                         g.mod_enable_qos = 0;\r
1222 \r
1223 \r
1224                 status = WdfRegistryQueryULong(hKey, &BlockMcastLB, &value);\r
1225                 if (NT_SUCCESS (status)) \r
1226                         g.mod_mlx4_blck_lb = value;\r
1227                 else\r
1228                         g.mod_mlx4_blck_lb = 1;\r
1229 \r
1230                 status = WdfRegistryQueryULong(hKey, &InterruptFromFirstPacket, &value);\r
1231                 if (NT_SUCCESS (status)) \r
1232                         g.mod_interrupt_from_first = value;\r
1233                 else\r
1234                         g.mod_interrupt_from_first = 1;\r
1235 \r
1236 \r
1237                 status = WdfRegistryQueryULong(hKey, &ProcessorAffinity, &value);\r
1238                 if (NT_SUCCESS (status)) \r
1239                         g.mod_affinity = value;\r
1240                 else\r
1241                         g.mod_affinity = 0;\r
1242                 \r
1243 \r
1244                 WdfRegistryClose(hKey);\r
1245                 status = STATUS_SUCCESS;\r
1246         }\r
1247 \r
1248         return status;\r
1249 }\r
1250 \r
1251 NTSTATUS\r
1252 DriverEntry(\r
1253         IN PDRIVER_OBJECT DriverObject,\r
1254         IN PUNICODE_STRING RegistryPath\r
1255         )\r
1256 /*++\r
1257 Routine Description:\r
1258 \r
1259         Initialize the call backs structure of Driver Framework.\r
1260 \r
1261 Arguments:\r
1262 \r
1263         DriverObject - pointer to the driver object\r
1264 \r
1265         RegistryPath - pointer to a unicode string representing the path,\r
1266                                 to driver-specific key in the registry.\r
1267 \r
1268 Return Value:\r
1269 \r
1270   NT Status Code\r
1271 \r
1272 --*/\r
1273 {\r
1274         int err;\r
1275         WDF_DRIVER_CONFIG   config;\r
1276         NTSTATUS            status;\r
1277         WDFDRIVER hDriver;\r
1278 \r
1279 #if defined(EVENT_TRACING)\r
1280         WPP_INIT_TRACING(DriverObject, RegistryPath);\r
1281 #endif\r
1282 \r
1283 \r
1284         // global initializations\r
1285         RtlZeroMemory( &g, sizeof(g) );\r
1286         g_mlx4_dbg_level = g.bwsd.DebugPrintLevel = TRACE_LEVEL_VERBOSE;\r
1287         g_mlx4_dbg_flags = g.bwsd.DebugPrintFlags = 0xffff;\r
1288 \r
1289         MLX4_ENTER(MLX4_DBG_DRV);\r
1290         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, \r
1291                 ("Built %s %s, Version %s, RelDate %s\n", \r
1292                 __DATE__, __TIME__, DRV_VERSION, DRV_RELDATE));\r
1293 \r
1294         mlx4_net_init();\r
1295         err = core_init();\r
1296         if (err) {\r
1297                 status = errno_to_ntstatus(err);\r
1298                 goto end;\r
1299         }\r
1300         err = mlx4_ib_init();\r
1301         if (err) {\r
1302                 status = errno_to_ntstatus(err);\r
1303                 goto end;\r
1304         }\r
1305 \r
1306         //\r
1307         // Initiialize driver config to control the attributes that\r
1308         // are global to the driver. Note that framework by default\r
1309         // provides a driver unload routine. If you create any resources\r
1310         // in the DriverEntry and want to be cleaned in driver unload,\r
1311         // you can override that by specifing one in the Config structure.\r
1312         //\r
1313 \r
1314         WDF_DRIVER_CONFIG_INIT(\r
1315                 &config, EvtDriverDeviceAdd );\r
1316         config.EvtDriverUnload = EvtDriverUnload;\r
1317 \r
1318         //\r
1319         // Create a framework driver object to represent our driver.\r
1320         //\r
1321         status = WdfDriverCreate(DriverObject,\r
1322                 RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,\r
1323                 &config, &hDriver);\r
1324 \r
1325         if (!NT_SUCCESS(status)) {\r
1326                 MLX4_PRINT(TRACE_LEVEL_VERBOSE, MLX4_DBG_DRV, ("WdfDriverCreate failed with status 0x%x\n", status));\r
1327                 goto end;\r
1328         }\r
1329 \r
1330         //\r
1331         // read registry parameters\r
1332         //\r
1333         status = __read_registry(&hDriver);\r
1334 \r
1335         // we don't matter the failure in the work with Registry\r
1336         status = STATUS_SUCCESS;\r
1337         \r
1338 end:\r
1339         MLX4_EXIT( MLX4_DBG_DRV );\r
1340         return status;\r
1341 \r
1342 }\r
1343 \r
1344 \r
1345 \r
1346 \r