48ec280d724ac142719455a4069e4d551237e079
[mirror/winof/.git] / hw / mlx4 / kernel / bus / drv / pdo.c
1 #include "precomp.h"\r
2 #include <initguid.h>\r
3 #include <wdmguid.h>\r
4 \r
5 #if defined (EVENT_TRACING)\r
6 #ifdef offsetof\r
7 #undef offsetof\r
8 #endif\r
9 #include "pdo.tmh"\r
10 #endif \r
11 \r
12 #define MAX_ID_LEN 80\r
13 \r
14 NTSTATUS\r
15 EvtDeviceProcessQueryInterfaceRequest(\r
16         IN WDFDEVICE  Device,\r
17         IN LPGUID  InterfaceType,\r
18         IN OUT PINTERFACE  ExposedInterface,\r
19         IN OUT PVOID  ExposedInterfaceSpecificData\r
20         )\r
21 {\r
22         PPDO_DEVICE_DATA p_pdo = PdoGetData(Device);\r
23         PFDO_DEVICE_DATA p_fdo  = p_pdo->p_fdo;\r
24         PMLX4_BUS_IB_INTERFACE p_ib_ifc = (PMLX4_BUS_IB_INTERFACE)ExposedInterface;\r
25 \r
26         UNUSED_PARAM(InterfaceType);\r
27         UNUSED_PARAM(ExposedInterfaceSpecificData);\r
28 \r
29         if (p_fdo->pci_dev.dev) {\r
30                 p_ib_ifc->p_ibdev = p_fdo->bus_ib_ifc.p_ibdev;\r
31                 p_ib_ifc->pmlx4_dev = p_fdo->bus_ib_ifc.pmlx4_dev;\r
32                 p_ib_ifc->is_livefish = p_fdo->bus_ib_ifc.is_livefish;\r
33                 return STATUS_SUCCESS;\r
34         }\r
35         else {\r
36                 p_ib_ifc->p_ibdev = NULL;\r
37                 p_ib_ifc->pmlx4_dev = NULL;\r
38                 p_ib_ifc->is_livefish = FALSE;\r
39                 return STATUS_UNSUCCESSFUL;\r
40         }\r
41 \r
42 }\r
43 \r
44 NTSTATUS\r
45 create_pdo(\r
46         __in WDFDEVICE  Device,\r
47         __in PWCHAR     HardwareIds,\r
48         __in PWCHAR     DeviceDescription,\r
49         __in ULONG      SerialNo\r
50 )\r
51 /*++\r
52 \r
53 Routine Description:\r
54 \r
55     This routine creates and initialize a PDO.\r
56 \r
57 Arguments:\r
58 \r
59 Return Value:\r
60 \r
61     NT Status code.\r
62 \r
63 --*/\r
64 {\r
65         NTSTATUS                    status;\r
66         PWDFDEVICE_INIT             pDeviceInit = NULL;\r
67         PPDO_DEVICE_DATA            p_pdo = NULL;\r
68         PFDO_DEVICE_DATA            p_fdo;\r
69         WDFDEVICE                   hChild = NULL;\r
70         WDF_OBJECT_ATTRIBUTES       pdoAttributes;\r
71         WDF_DEVICE_PNP_CAPABILITIES pnpCaps;\r
72         WDF_DEVICE_POWER_CAPABILITIES powerCaps;\r
73         UNICODE_STRING compatId;\r
74         DECLARE_CONST_UNICODE_STRING(deviceLocation, L"MLX4 Bus 0");\r
75         UNICODE_STRING deviceId;\r
76         DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);\r
77 \r
78         MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("Entered CreatePdo\n"));\r
79 \r
80         RtlInitUnicodeString(&compatId, HardwareIds);\r
81         PAGED_CODE();\r
82 \r
83         //\r
84         // Allocate a WDFDEVICE_INIT structure and set the properties\r
85         // so that we can create a device object for the child.\r
86         //\r
87         pDeviceInit = WdfPdoInitAllocate(Device);\r
88 \r
89         if (pDeviceInit == NULL) {\r
90                 status = STATUS_INSUFFICIENT_RESOURCES;\r
91                 goto Cleanup;\r
92         }\r
93 \r
94         //\r
95         // Set DeviceType\r
96         //\r
97         WdfDeviceInitSetDeviceType(pDeviceInit, FILE_DEVICE_BUS_EXTENDER);\r
98 \r
99         //\r
100         // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId\r
101         //\r
102         RtlInitUnicodeString(&deviceId,HardwareIds);\r
103 \r
104         status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId);\r
105         if (!NT_SUCCESS(status)) {\r
106                 goto Cleanup;\r
107         }\r
108 \r
109         //\r
110         // Note same string  is used to initialize hardware id too\r
111         //\r
112         status = WdfPdoInitAddHardwareID(pDeviceInit, &deviceId);\r
113         if (!NT_SUCCESS(status)) {\r
114                 goto Cleanup;\r
115         }\r
116 \r
117         status = WdfPdoInitAddCompatibleID(pDeviceInit, &compatId);\r
118         if (!NT_SUCCESS(status)) {\r
119                 goto Cleanup;\r
120         }\r
121 \r
122         status =  RtlUnicodeStringPrintf(&buffer, L"%02d", SerialNo);\r
123         if (!NT_SUCCESS(status)) {\r
124                 goto Cleanup;\r
125         }\r
126 \r
127         status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);\r
128         if (!NT_SUCCESS(status)) {\r
129                 goto Cleanup;\r
130         }\r
131 \r
132         //\r
133         // Provide a description about the device. This text is usually read from\r
134         // the device. In the case of USB device, this text comes from the string\r
135         // descriptor. This text is displayed momentarily by the PnP manager while\r
136         // it's looking for a matching INF. If it finds one, it uses the Device\r
137         // Description from the INF file or the friendly name created by\r
138         // coinstallers to display in the device manager. FriendlyName takes\r
139         // precedence over the DeviceDesc from the INF file.\r
140         //\r
141         status = RtlUnicodeStringPrintf(&buffer,DeviceDescription  , SerialNo );\r
142         \r
143         if (!NT_SUCCESS(status)) {\r
144                 goto Cleanup;\r
145         }\r
146 \r
147         //\r
148         // You can call WdfPdoInitAddDeviceText multiple times, adding device\r
149         // text for multiple locales. When the system displays the text, it\r
150         // chooses the text that matches the current locale, if available.\r
151         // Otherwise it will use the string for the default locale.\r
152         // The driver can specify the driver's default locale by calling\r
153         // WdfPdoInitSetDefaultLocale.\r
154         //\r
155         status = WdfPdoInitAddDeviceText(pDeviceInit,\r
156                 &buffer, &deviceLocation, 0x409);\r
157         if (!NT_SUCCESS(status)) {\r
158                 goto Cleanup;\r
159         }\r
160 \r
161         WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409);\r
162 \r
163         //\r
164         // Initialize the attributes to specify the size of PDO device extension.\r
165         // All the state information private to the PDO will be tracked here.\r
166         //\r
167         WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA);\r
168 \r
169         status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);\r
170         if (!NT_SUCCESS(status)) {\r
171                 goto Cleanup;\r
172         }\r
173 \r
174         //\r
175         // Once the device is created successfully, framework frees the\r
176         // DeviceInit memory and sets the pDeviceInit to NULL. So don't\r
177         // call any WdfDeviceInit functions after that.\r
178         //\r
179         // Get the device context.\r
180         //\r
181         p_pdo = PdoGetData(hChild);\r
182         p_fdo = FdoGetData(Device);\r
183 \r
184         p_pdo->p_fdo = p_fdo;\r
185         p_pdo->SerialNo = SerialNo;\r
186         p_pdo->PdoDevice = hChild;\r
187 \r
188         //\r
189         // Set PnP properties for the child device.\r
190         //\r
191         WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);\r
192         pnpCaps.Address  = SerialNo;\r
193         pnpCaps.UINumber = SerialNo;\r
194 \r
195         WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);\r
196 \r
197         //\r
198         // Set Power properties for the child device\r
199         //\r
200         WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);\r
201 \r
202         powerCaps.DeviceD1 = WdfTrue;\r
203         powerCaps.WakeFromD1 = WdfTrue;\r
204         powerCaps.DeviceWake = PowerDeviceD1;\r
205 \r
206         powerCaps.DeviceState[PowerSystemWorking]   = PowerDeviceD0;\r
207         powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;\r
208         powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD3;\r
209         powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD3;\r
210         powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
211         powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3;\r
212 \r
213         WdfDeviceSetPowerCapabilities(hChild, &powerCaps);\r
214 \r
215         //\r
216         // Set bus IB interface\r
217         //\r
218         p_fdo->bus_ib_ifc.port_id = (u8) SerialNo;\r
219         p_fdo->bus_ib_ifc.pVipBusIfc = &p_fdo->mtnic_Ifc;\r
220         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_pd_alloc = mlx4_pd_alloc;\r
221         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_pd_free = mlx4_pd_free;\r
222         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_uar_alloc = mlx4_uar_alloc;\r
223         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_uar_free = mlx4_uar_free;\r
224         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_mr_alloc = mlx4_mr_alloc;\r
225         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_mr_free = mlx4_mr_free;\r
226         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_mr_enable = mlx4_mr_enable;\r
227         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_get_region = mlx4_qp_get_region;\r
228         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_alloc_hwq_res = mlx4_alloc_hwq_res;\r
229         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_free_hwq_res = mlx4_free_hwq_res;\r
230 \r
231         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_cq_alloc = mlx4_cq_alloc;\r
232         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_cq_free = mlx4_cq_free;\r
233         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_cq_modify = mlx4_cq_modify;\r
234         \r
235         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_register_mac = mlx4_register_mac;\r
236         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_unregister_mac = mlx4_unregister_mac;\r
237         \r
238         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_srq_alloc = mlx4_srq_alloc;\r
239         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_srq_free = mlx4_srq_free;\r
240         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_srq_invalidate = mlx4_srq_invalidate;\r
241         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_srq_remove = mlx4_srq_remove;\r
242 \r
243         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_alloc = mlx4_qp_alloc;\r
244         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_free = mlx4_qp_free;\r
245         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_remove = mlx4_qp_remove;\r
246         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_modify = mlx4_qp_modify;\r
247         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_to_ready = mlx4_qp_to_ready;\r
248         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_reserve_range = mlx4_qp_reserve_range;\r
249         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_qp_release_range = mlx4_qp_release_range;\r
250 \r
251         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_alloc_cmd_mailbox = mlx4_alloc_cmd_mailbox;\r
252         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_free_cmd_mailbox = mlx4_free_cmd_mailbox;\r
253         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_cmd = imlx4_cmd;\r
254 \r
255         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_INIT_PORT = mlx4_INIT_PORT;\r
256         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_CLOSE_PORT = mlx4_CLOSE_PORT;\r
257         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_add_eq = mlx4_add_eq;\r
258         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_remove_eq = mlx4_remove_eq;\r
259         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_register_ev_cb = mlx4_reset_cb_register;\r
260         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_unregister_ev_cb = mlx4_reset_cb_unregister;\r
261         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_reset_request = mlx4_reset_request;\r
262         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_reset_execute = mlx4_reset_execute;\r
263         p_fdo->bus_ib_ifc.mlx4_interface.mlx4_reset_ready = mlx4_reset_ready;\r
264         \r
265         //\r
266         // Create a custom interface so that other drivers can\r
267         // query (IRP_MN_QUERY_INTERFACE) and use our callbacks directly.\r
268         //\r
269         p_fdo->bus_ib_ifc.i.Context = p_pdo;\r
270 \r
271         WDF_QUERY_INTERFACE_CONFIG_INIT( &p_pdo->qiMlx4Bus,\r
272                 (PINTERFACE) &p_fdo->bus_ib_ifc,\r
273                 &MLX4_BUS_IB_INTERFACE_GUID, EvtDeviceProcessQueryInterfaceRequest);\r
274 \r
275         status = WdfDeviceAddQueryInterface( hChild, &p_pdo->qiMlx4Bus );\r
276         if (!NT_SUCCESS(status))\r
277                 goto Cleanup;\r
278 \r
279         //\r
280         // Expose also PCI.SYS interface for MLX4_HCA\r
281         //\r
282         WDF_QUERY_INTERFACE_CONFIG_INIT( &p_pdo->qiPciBus,\r
283                 (PINTERFACE) &p_fdo->pci_dev.bus_pci_ifc,\r
284                 &GUID_BUS_INTERFACE_STANDARD, NULL);\r
285 \r
286         // TODO: Soft Reset - how tobar getting interface during RESET_IN_PROGRESS\r
287         // maybe - using EvtDeviceProcessQueryInterfaceRequest\r
288         status = WdfDeviceAddQueryInterface( hChild, &p_pdo->qiPciBus );\r
289         if (!NT_SUCCESS(status))\r
290                 goto Cleanup;\r
291 \r
292         //\r
293         // Add this device to the FDO's collection of children.\r
294         // After the child device is added to the static collection successfully,\r
295         // driver must call WdfPdoMarkMissing to get the device deleted. It\r
296         // shouldn't delete the child device directly by calling WdfObjectDelete.\r
297         //\r
298         status = WdfFdoAddStaticChild(Device, hChild);\r
299         if (!NT_SUCCESS(status)) {\r
300                 goto Cleanup;\r
301         }\r
302 \r
303         return status;\r
304 \r
305 Cleanup:\r
306         KdPrint(("BusEnum: Bus_CreatePdo failed %x\n", status));\r
307 \r
308         //\r
309         // Call WdfDeviceInitFree if you encounter an error before the\r
310         // device is created. Once the device is created, framework\r
311         // NULLs the pDeviceInit value.\r
312         //\r
313         if (pDeviceInit != NULL) {\r
314                 WdfDeviceInitFree(pDeviceInit);\r
315         }\r
316 \r
317         if(hChild) {\r
318                 WdfObjectDelete(hChild);\r
319         }\r
320 \r
321         return status;\r
322 }\r
323 \r
324 \r