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