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