2 #include <initguid.h>
\r
5 #if defined(EVENT_TRACING)
\r
10 #pragma alloc_text(PAGE, create_pdo)
\r
13 #define MAX_ID_LEN 80
\r
17 __in WDFDEVICE Device,
\r
18 __in PWCHAR HardwareIds,
\r
19 __in PWCHAR DeviceDescription,
\r
24 Routine Description:
\r
26 This routine creates and initialize a PDO.
\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
49 MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("Entered CreatePdo\n"));
\r
51 RtlInitUnicodeString(&compatId, HardwareIds);
\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
58 pDeviceInit = WdfPdoInitAllocate(Device);
\r
60 if (pDeviceInit == NULL) {
\r
61 status = STATUS_INSUFFICIENT_RESOURCES;
\r
68 WdfDeviceInitSetDeviceType(pDeviceInit, FILE_DEVICE_BUS_EXTENDER);
\r
71 // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId
\r
73 RtlInitUnicodeString(&deviceId,HardwareIds);
\r
75 status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId);
\r
76 if (!NT_SUCCESS(status)) {
\r
81 // Note same string is used to initialize hardware id too
\r
83 status = WdfPdoInitAddHardwareID(pDeviceInit, &deviceId);
\r
84 if (!NT_SUCCESS(status)) {
\r
88 status = WdfPdoInitAddCompatibleID(pDeviceInit, &compatId);
\r
89 if (!NT_SUCCESS(status)) {
\r
93 status = RtlUnicodeStringPrintf(&buffer, L"%02d", SerialNo);
\r
94 if (!NT_SUCCESS(status)) {
\r
98 status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);
\r
99 if (!NT_SUCCESS(status)) {
\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
112 status = RtlUnicodeStringPrintf(&buffer,DeviceDescription , SerialNo );
\r
114 if (!NT_SUCCESS(status)) {
\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
126 status = WdfPdoInitAddDeviceText(pDeviceInit,
\r
127 &buffer, &deviceLocation, 0x409);
\r
128 if (!NT_SUCCESS(status)) {
\r
132 WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409);
\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
138 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA);
\r
140 status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);
\r
141 if (!NT_SUCCESS(status)) {
\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
150 // Get the device context.
\r
152 p_pdo = PdoGetData(hChild);
\r
153 p_fdo = FdoGetData(Device);
\r
155 p_pdo->p_fdo = p_fdo;
\r
156 p_pdo->SerialNo = SerialNo;
\r
157 p_pdo->PdoDevice = hChild;
\r
160 // Set some properties for the child device.
\r
162 WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
\r
163 pnpCaps.Removable = WdfTrue;
\r
164 pnpCaps.EjectSupported = WdfTrue;
\r
165 pnpCaps.SurpriseRemovalOK = WdfTrue;
\r
167 pnpCaps.Address = SerialNo;
\r
168 pnpCaps.UINumber = SerialNo;
\r
170 WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);
\r
172 WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);
\r
174 powerCaps.DeviceD1 = WdfTrue;
\r
175 powerCaps.WakeFromD1 = WdfTrue;
\r
176 powerCaps.DeviceWake = PowerDeviceD1;
\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
185 WdfDeviceSetPowerCapabilities(hChild, &powerCaps);
\r
187 p_fdo->bus_ib_ifc.port_id = 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
191 // Create a custom interface so that other drivers can
\r
192 // query (IRP_MN_QUERY_INTERFACE) and use our callbacks directly.
\r
194 p_fdo->bus_ib_ifc.i.Context = p_pdo;
\r
196 WDF_QUERY_INTERFACE_CONFIG_INIT( &p_pdo->qiMlx4Bus,
\r
197 (PINTERFACE) &p_fdo->bus_ib_ifc,
\r
198 &MLX4_BUS_IB_INTERFACE_GUID, NULL);
\r
200 status = WdfDeviceAddQueryInterface( hChild, &p_pdo->qiMlx4Bus );
\r
201 if (!NT_SUCCESS(status))
\r
205 // Expose also PCI.SYS interface for MLX4_HCA
\r
207 WDF_QUERY_INTERFACE_CONFIG_INIT( &p_pdo->qiPciBus,
\r
208 (PINTERFACE) &p_fdo->pci_dev.bus_pci_ifc,
\r
209 &GUID_BUS_INTERFACE_STANDARD, NULL);
\r
211 status = WdfDeviceAddQueryInterface( hChild, &p_pdo->qiPciBus );
\r
212 if (!NT_SUCCESS(status))
\r
216 // Add this device to the FDO's collection of children.
\r
217 // After the child device is added to the static collection successfully,
\r
218 // driver must call WdfPdoMarkMissing to get the device deleted. It
\r
219 // shouldn't delete the child device directly by calling WdfObjectDelete.
\r
221 status = WdfFdoAddStaticChild(Device, hChild);
\r
222 if (!NT_SUCCESS(status)) {
\r
229 KdPrint(("BusEnum: Bus_CreatePdo failed %x\n", status));
\r
232 // Call WdfDeviceInitFree if you encounter an error before the
\r
233 // device is created. Once the device is created, framework
\r
234 // NULLs the pDeviceInit value.
\r
236 if (pDeviceInit != NULL) {
\r
237 WdfDeviceInitFree(pDeviceInit);
\r
241 WdfObjectDelete(hChild);
\r