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