win-pvdrivers

view xenusb/xenusb_fdo.c @ 979:8f483a2b2991

Fix up PREfast warnings
author James Harper <james.harper@bendigoit.com.au>
date Sun Apr 15 19:47:10 2012 +1000 (2012-04-15)
parents 941699790045
children ea3c61839ff5
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 // STATUS_UNSUCCESSFUL -> STATUS_BAD_INITIAL_PC
22 #include "xenusb.h"
24 /* Not really necessary but keeps PREfast happy */
25 static EVT_WDF_DEVICE_D0_ENTRY XenUsb_EvtDeviceD0Entry;
26 static EVT_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED XenUsb_EvtDeviceD0EntryPostInterruptsEnabled;
27 static EVT_WDF_DEVICE_D0_EXIT XenUsb_EvtDeviceD0Exit;
28 static EVT_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED XenUsb_EvtDeviceD0ExitPreInterruptsDisabled;
29 static EVT_WDF_DEVICE_PREPARE_HARDWARE XenUsb_EvtDevicePrepareHardware;
30 static EVT_WDF_DEVICE_RELEASE_HARDWARE XenUsb_EvtDeviceReleaseHardware;
31 static EVT_WDF_DEVICE_QUERY_REMOVE XenUsb_EvtDeviceQueryRemove;
32 static EVT_WDFDEVICE_WDM_IRP_PREPROCESS XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE;
33 static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL XenUsb_EvtIoDeviceControl;
34 static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL XenUsb_EvtIoInternalDeviceControl;
35 static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL XenUsb_EvtIoInternalDeviceControl_PVURB;
36 static EVT_WDF_IO_QUEUE_IO_DEFAULT XenUsb_EvtIoDefault;
37 static EVT_WDF_REQUEST_CANCEL XenUsb_EvtRequestCancelPvUrb;
39 //static EVT_WDF_PROGRAM_DMA XenUsb_ExecuteRequestCallback;
41 NTSTATUS
42 XenUsb_EvtDeviceQueryRemove(WDFDEVICE device)
43 {
44 //PXENUSB_DEVICE_DATA xudd = GetXudd(device);
45 NTSTATUS status = STATUS_SUCCESS;
47 UNREFERENCED_PARAMETER(device);
49 FUNCTION_ENTER();
50 FUNCTION_EXIT();
51 return status;
52 }
54 static NTSTATUS
55 XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE(WDFDEVICE device, PIRP irp)
56 {
57 PIO_STACK_LOCATION stack;
59 FUNCTION_ENTER();
61 stack = IoGetCurrentIrpStackLocation(irp);
63 if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_GUID, sizeof(GUID)) == 0)
64 KdPrint((__DRIVER_NAME " USB_BUS_INTERFACE_HUB_GUID\n"));
65 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID, sizeof(GUID)) == 0)
66 KdPrint((__DRIVER_NAME " USB_BUS_INTERFACE_USBDI_GUID\n"));
67 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &GUID_TRANSLATOR_INTERFACE_STANDARD, sizeof(GUID)) == 0)
68 KdPrint((__DRIVER_NAME " GUID_TRANSLATOR_INTERFACE_STANDARD\n"));
69 else
70 KdPrint((__DRIVER_NAME " GUID = %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
71 stack->Parameters.QueryInterface.InterfaceType->Data1,
72 stack->Parameters.QueryInterface.InterfaceType->Data2,
73 stack->Parameters.QueryInterface.InterfaceType->Data3,
74 (stack->Parameters.QueryInterface.InterfaceType->Data4[0] << 8) |
75 stack->Parameters.QueryInterface.InterfaceType->Data4[1],
76 stack->Parameters.QueryInterface.InterfaceType->Data4[2],
77 stack->Parameters.QueryInterface.InterfaceType->Data4[3],
78 stack->Parameters.QueryInterface.InterfaceType->Data4[4],
79 stack->Parameters.QueryInterface.InterfaceType->Data4[5],
80 stack->Parameters.QueryInterface.InterfaceType->Data4[6],
81 stack->Parameters.QueryInterface.InterfaceType->Data4[7]));
83 KdPrint((__DRIVER_NAME " Size = %d\n", stack->Parameters.QueryInterface.Size));
84 KdPrint((__DRIVER_NAME " Version = %d\n", stack->Parameters.QueryInterface.Version));
85 KdPrint((__DRIVER_NAME " Interface = %p\n", stack->Parameters.QueryInterface.Interface));
88 IoSkipCurrentIrpStackLocation(irp);
90 FUNCTION_EXIT();
92 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
93 }
95 /* called with urb ring lock held */
96 static VOID
97 PutRequestsOnRing(PXENUSB_DEVICE_DATA xudd) {
98 partial_pvurb_t *partial_pvurb;
99 uint16_t id;
100 int notify;
102 FUNCTION_ENTER();
103 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
105 while ((partial_pvurb = (partial_pvurb_t *)RemoveHeadList((PLIST_ENTRY)&xudd->partial_pvurb_queue)) != (partial_pvurb_t *)&xudd->partial_pvurb_queue) {
106 FUNCTION_MSG("partial_pvurb = %p\n", partial_pvurb);
107 /* if this partial_pvurb is cancelling another we don't need to check if the cancelled partial_pvurb is on the ring - that is taken care of in HandleEvent */
108 id = get_id_from_freelist(xudd);
109 if (id == (uint16_t)-1) {
110 FUNCTION_MSG("no free ring slots\n");
111 InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb->entry);
112 break;
113 }
114 InsertTailList(&xudd->partial_pvurb_ring, &partial_pvurb->entry);
115 xudd->partial_pvurbs[id] = partial_pvurb;
116 partial_pvurb->req.id = id;
117 *RING_GET_REQUEST(&xudd->urb_ring, xudd->urb_ring.req_prod_pvt) = partial_pvurb->req;
118 xudd->urb_ring.req_prod_pvt++;
119 }
120 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xudd->urb_ring, notify);
121 if (notify) {
122 FUNCTION_MSG("Notifying\n");
123 xudd->vectors.EvtChn_Notify(xudd->vectors.context, xudd->event_channel);
124 }
126 FUNCTION_EXIT();
127 }
129 /* called at DISPATCH_LEVEL */
130 static BOOLEAN
131 XenUsb_HandleEvent(PVOID context)
132 {
133 NTSTATUS status;
134 PXENUSB_DEVICE_DATA xudd = context;
135 RING_IDX prod, cons;
136 usbif_urb_response_t *urb_rsp;
137 usbif_conn_response_t *conn_rsp;
138 usbif_conn_request_t *conn_req;
139 int more_to_do;
140 pvurb_t *pvurb, *complete_head = NULL, *complete_tail = NULL;
141 partial_pvurb_t *partial_pvurb;
142 BOOLEAN port_changed = FALSE;
144 FUNCTION_ENTER();
146 more_to_do = TRUE;
147 KeAcquireSpinLockAtDpcLevel(&xudd->urb_ring_lock);
148 while (more_to_do)
149 {
150 prod = xudd->urb_ring.sring->rsp_prod;
151 KeMemoryBarrier();
152 for (cons = xudd->urb_ring.rsp_cons; cons != prod; cons++)
153 {
154 urb_rsp = RING_GET_RESPONSE(&xudd->urb_ring, cons);
155 // FUNCTION_MSG("urb_rsp->id = %d\n", urb_rsp->id);
156 partial_pvurb = xudd->partial_pvurbs[urb_rsp->id];
157 RemoveEntryList(&partial_pvurb->entry);
158 partial_pvurb->rsp = *urb_rsp;
159 // FUNCTION_MSG("shadow = %p\n", shadow);
160 // FUNCTION_MSG("shadow->rsp = %p\n", shadow->rsp);
161 if (usbif_pipeunlink(partial_pvurb->req.pipe)) {
162 FUNCTION_MSG("is a cancel request for request %p\n", partial_pvurb->pvurb->request);
163 FUNCTION_MSG("urb_ring rsp status = %d\n", urb_rsp->status);
164 // status should be 115 == EINPROGRESS
165 } else {
166 partial_pvurb->pvurb->total_length += urb_rsp->actual_length;
167 if (!partial_pvurb->pvurb->rsp.status)
168 partial_pvurb->pvurb->rsp.status = urb_rsp->status;
169 partial_pvurb->pvurb->rsp.error_count += urb_rsp->error_count;;
170 if (partial_pvurb->mdl) {
171 int i;
172 for (i = 0; i < partial_pvurb->req.nr_buffer_segs; i++) {
173 xudd->vectors.GntTbl_EndAccess(xudd->vectors.context,
174 partial_pvurb->req.seg[i].gref, FALSE, (ULONG)'XUSB');
175 }
176 }
178 KdPrint((__DRIVER_NAME " urb_ring rsp id = %d\n", partial_pvurb->rsp.id));
179 KdPrint((__DRIVER_NAME " urb_ring rsp start_frame = %d\n", partial_pvurb->rsp.start_frame));
180 KdPrint((__DRIVER_NAME " urb_ring rsp status = %d\n", partial_pvurb->rsp.status));
181 KdPrint((__DRIVER_NAME " urb_ring rsp actual_length = %d\n", partial_pvurb->rsp.actual_length));
182 KdPrint((__DRIVER_NAME " urb_ring rsp error_count = %d\n", partial_pvurb->rsp.error_count));
183 }
184 if (partial_pvurb->other_partial_pvurb) {
185 if (!partial_pvurb->other_partial_pvurb->on_ring) {
186 /* cancel hasn't been put on the ring yet - remove it */
187 RemoveEntryList(&partial_pvurb->other_partial_pvurb->entry);
188 ASSERT(usbif_pipeunlink(partial_pvurb->other_partial_pvurb->req.pipe));
189 partial_pvurb->pvurb->ref--;
190 ExFreePoolWithTag(partial_pvurb->other_partial_pvurb, XENUSB_POOL_TAG);
191 }
192 }
193 partial_pvurb->pvurb->ref--;
194 switch (partial_pvurb->rsp.status) {
195 case EINPROGRESS: /* unlink request */
196 case ECONNRESET: /* cancelled request */
197 ASSERT(partial_pvurb->pvurb->status == STATUS_CANCELLED);
198 break;
199 default:
200 break;
201 }
202 put_id_on_freelist(xudd, partial_pvurb->rsp.id);
203 partial_pvurb->pvurb->next = NULL;
204 if (!partial_pvurb->pvurb->ref) {
205 if (complete_tail) {
206 complete_tail->next = partial_pvurb->pvurb;
207 } else {
208 complete_head = partial_pvurb->pvurb;
209 }
210 complete_tail = partial_pvurb->pvurb;
211 }
212 }
214 xudd->urb_ring.rsp_cons = cons;
215 if (cons != xudd->urb_ring.req_prod_pvt) {
216 RING_FINAL_CHECK_FOR_RESPONSES(&xudd->urb_ring, more_to_do);
217 } else {
218 xudd->urb_ring.sring->rsp_event = cons + 1;
219 more_to_do = FALSE;
220 }
221 }
222 PutRequestsOnRing(xudd);
223 KeReleaseSpinLockFromDpcLevel(&xudd->urb_ring_lock);
225 pvurb = complete_head;
226 while (pvurb != NULL) {
227 complete_head = pvurb->next;
228 status = WdfRequestUnmarkCancelable(pvurb->request);
229 if (status == STATUS_CANCELLED) {
230 FUNCTION_MSG("Cancel was called\n");
231 }
233 WdfRequestCompleteWithInformation(pvurb->request, pvurb->status, pvurb->total_length); /* the WDFREQUEST is always successfull here even if the pvurb->rsp has an error */
234 pvurb = complete_head;
235 }
237 more_to_do = TRUE;
238 KeAcquireSpinLockAtDpcLevel(&xudd->conn_ring_lock);
239 while (more_to_do)
240 {
241 prod = xudd->conn_ring.sring->rsp_prod;
242 KeMemoryBarrier();
243 for (cons = xudd->conn_ring.rsp_cons; cons != prod; cons++)
244 {
245 conn_rsp = RING_GET_RESPONSE(&xudd->conn_ring, cons);
246 KdPrint((__DRIVER_NAME " conn_rsp->portnum = %d\n", conn_rsp->portnum));
247 KdPrint((__DRIVER_NAME " conn_rsp->speed = %d\n", conn_rsp->speed));
249 xudd->ports[conn_rsp->portnum - 1].port_type = conn_rsp->speed;
250 xudd->ports[conn_rsp->portnum - 1].port_status &= ~((1 << PORT_LOW_SPEED) | (1 << PORT_HIGH_SPEED) | (1 << PORT_CONNECTION));
251 switch (conn_rsp->speed)
252 {
253 case USB_PORT_TYPE_NOT_CONNECTED:
254 //xudd->ports[conn_rsp->portnum - 1].port_status |= 0;
255 break;
256 case USB_PORT_TYPE_LOW_SPEED:
257 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_LOW_SPEED) | (1 << PORT_CONNECTION);
258 break;
259 case USB_PORT_TYPE_FULL_SPEED:
260 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_CONNECTION);
261 break;
262 case USB_PORT_TYPE_HIGH_SPEED:
263 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_HIGH_SPEED) | (1 << PORT_CONNECTION);
264 break;
265 }
266 xudd->ports[conn_rsp->portnum - 1].port_change |= (1 << PORT_CONNECTION);
267 port_changed = TRUE;
268 conn_req = RING_GET_REQUEST(&xudd->conn_ring, xudd->conn_ring.req_prod_pvt);
269 conn_req->id = conn_rsp->id;
270 xudd->conn_ring.req_prod_pvt++;
271 }
273 xudd->conn_ring.rsp_cons = cons;
274 if (cons != xudd->conn_ring.req_prod_pvt)
275 {
276 RING_FINAL_CHECK_FOR_RESPONSES(&xudd->conn_ring, more_to_do);
277 }
278 else
279 {
280 xudd->conn_ring.sring->rsp_event = cons + 1;
281 more_to_do = FALSE;
282 }
283 }
284 KeReleaseSpinLockFromDpcLevel(&xudd->conn_ring_lock);
286 if (port_changed) {
287 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(xudd->root_hub_device);
288 XenUsbHub_ProcessHubInterruptEvent(xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]);
289 }
291 FUNCTION_EXIT();
293 return TRUE;
294 }
296 static NTSTATUS
297 XenUsb_StartXenbusInit(PXENUSB_DEVICE_DATA xudd)
298 {
299 PUCHAR ptr;
300 USHORT type;
301 PCHAR setting, value, value2;
303 xudd->urb_sring = NULL;
304 xudd->event_channel = 0;
306 ptr = xudd->config_page;
307 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END) {
308 switch(type) {
309 case XEN_INIT_TYPE_READ_STRING_BACK:
310 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING_BACK - %s = %s\n", setting, value));
311 break;
312 case XEN_INIT_TYPE_READ_STRING_FRONT:
313 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING_FRONT - %s = %s\n", setting, value));
314 break;
315 case XEN_INIT_TYPE_VECTORS:
316 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
317 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
318 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC) {
319 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
320 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
321 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
322 return STATUS_BAD_INITIAL_PC;
323 }
324 else
325 memcpy(&xudd->vectors, value, sizeof(XENPCI_VECTORS));
326 break;
327 case XEN_INIT_TYPE_STATE_PTR:
328 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
329 xudd->device_state = (PXENPCI_DEVICE_STATE)value;
330 break;
331 default:
332 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
333 break;
334 }
335 }
337 return STATUS_SUCCESS;
338 }
340 static NTSTATUS
341 XenUsb_CompleteXenbusInit(PXENUSB_DEVICE_DATA xudd)
342 {
343 PUCHAR ptr;
344 USHORT type;
345 PCHAR setting, value, value2;
346 ULONG i;
348 ptr = xudd->config_page;
349 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
350 {
351 switch(type)
352 {
353 case XEN_INIT_TYPE_RING: /* frontend ring */
354 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
355 if (strcmp(setting, "urb-ring-ref") == 0)
356 {
357 xudd->urb_sring = (usbif_urb_sring_t *)value;
358 FRONT_RING_INIT(&xudd->urb_ring, xudd->urb_sring, PAGE_SIZE);
359 }
360 if (strcmp(setting, "conn-ring-ref") == 0)
361 {
362 xudd->conn_sring = (usbif_conn_sring_t *)value;
363 FRONT_RING_INIT(&xudd->conn_ring, xudd->conn_sring, PAGE_SIZE);
364 }
365 break;
366 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel */
367 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL_DPC - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF));
368 if (strcmp(setting, "event-channel") == 0)
369 {
370 xudd->event_channel = PtrToUlong(value);
371 }
372 break;
373 case XEN_INIT_TYPE_READ_STRING_BACK:
374 case XEN_INIT_TYPE_READ_STRING_FRONT:
375 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
376 break;
377 default:
378 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
379 break;
380 }
381 }
382 if (xudd->urb_sring == NULL || xudd->conn_sring == NULL || xudd->event_channel == 0)
383 {
384 KdPrint((__DRIVER_NAME " Missing settings\n"));
385 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
386 return STATUS_BAD_INITIAL_PC;
387 }
389 stack_new(&xudd->id_ss, ID_COUNT);
390 for (i = 0; i < ID_COUNT; i++) {
391 put_id_on_freelist(xudd, (uint16_t)i);
392 }
394 return STATUS_SUCCESS;
395 }
397 NTSTATUS
398 XenUsb_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
399 {
400 NTSTATUS status = STATUS_SUCCESS;
401 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
402 PCM_PARTIAL_RESOURCE_DESCRIPTOR raw_descriptor, translated_descriptor;
403 ULONG i;
404 PUCHAR ptr;
406 FUNCTION_ENTER();
408 ASSERT(WdfCmResourceListGetCount(resources_raw) == WdfCmResourceListGetCount(resources_translated));
410 for (i = 0; i < WdfCmResourceListGetCount(resources_raw); i++)
411 {
412 raw_descriptor = WdfCmResourceListGetDescriptor(resources_raw, i);
413 translated_descriptor = WdfCmResourceListGetDescriptor(resources_translated, i);
414 switch (raw_descriptor->Type) {
415 case CmResourceTypePort:
416 KdPrint((__DRIVER_NAME " IoPort Address(%x) Length: %d\n", translated_descriptor->u.Port.Start.LowPart, translated_descriptor->u.Port.Length));
417 break;
418 case CmResourceTypeMemory:
419 KdPrint((__DRIVER_NAME " Memory (%x:%x) Length:(%d)\n", translated_descriptor->u.Memory.Start.LowPart, translated_descriptor->u.Memory.Start.HighPart, translated_descriptor->u.Memory.Length));
420 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", translated_descriptor->Flags));
421 xudd->config_page = MmMapIoSpace(translated_descriptor->u.Memory.Start, translated_descriptor->u.Memory.Length, MmNonCached);
422 KdPrint((__DRIVER_NAME " Memory mapped to %p\n", xudd->config_page));
423 break;
424 case CmResourceTypeInterrupt:
425 KdPrint((__DRIVER_NAME " irq_number = %03x\n", raw_descriptor->u.Interrupt.Vector));
426 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", translated_descriptor->u.Interrupt.Vector));
427 KdPrint((__DRIVER_NAME " irq_level = %03x\n", translated_descriptor->u.Interrupt.Level));
428 break;
429 case CmResourceTypeDevicePrivate:
430 KdPrint((__DRIVER_NAME " Private Data: 0x%02x 0x%02x 0x%02x\n", translated_descriptor->u.DevicePrivate.Data[0], translated_descriptor->u.DevicePrivate.Data[1], translated_descriptor->u.DevicePrivate.Data[2]));
431 break;
432 default:
433 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", translated_descriptor->Type));
434 break;
435 }
436 }
438 status = XenUsb_StartXenbusInit(xudd);
440 ptr = xudd->config_page;
441 //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
442 //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
443 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "urb-ring-ref", NULL, NULL);
444 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "conn-ring-ref", NULL, NULL);
445 #pragma warning(suppress:4054)
446 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_DPC, "event-channel", (PVOID)XenUsb_HandleEvent, xudd);
447 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
448 __ADD_XEN_INIT_UCHAR(&ptr, 0); /* no pre-connect required */
449 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
450 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
451 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
452 __ADD_XEN_INIT_UCHAR(&ptr, 20);
453 __ADD_XEN_INIT_UCHAR(&ptr, 0);
454 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
455 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
456 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
457 __ADD_XEN_INIT_UCHAR(&ptr, 50);
458 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
459 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
460 __ADD_XEN_INIT_UCHAR(&ptr, 50);
461 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
462 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
463 __ADD_XEN_INIT_UCHAR(&ptr, 50);
464 __ADD_XEN_INIT_UCHAR(&ptr, 0);
465 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
466 status = xudd->vectors.XenPci_XenConfigDevice(xudd->vectors.context);
468 status = XenUsb_CompleteXenbusInit(xudd);
470 FUNCTION_EXIT();
472 return status;
473 }
475 NTSTATUS
476 XenUsb_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
477 {
478 NTSTATUS status = STATUS_SUCCESS;
479 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
480 ULONG i;
481 int notify;
482 //PXENUSB_DEVICE_DATA xudd = GetXudd(device);
484 UNREFERENCED_PARAMETER(device);
486 FUNCTION_ENTER();
488 switch (previous_state)
489 {
490 case WdfPowerDeviceD0:
491 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
492 break;
493 case WdfPowerDeviceD1:
494 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
495 break;
496 case WdfPowerDeviceD2:
497 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
498 break;
499 case WdfPowerDeviceD3:
500 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
501 break;
502 case WdfPowerDeviceD3Final:
503 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
504 break;
505 case WdfPowerDevicePrepareForHibernation:
506 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
507 break;
508 default:
509 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
510 break;
511 }
513 /* fill conn ring with requests */
514 for (i = 0; i < USB_CONN_RING_SIZE; i++)
515 {
516 usbif_conn_request_t *req = RING_GET_REQUEST(&xudd->conn_ring, i);
517 req->id = (uint16_t)i;
518 }
519 xudd->conn_ring.req_prod_pvt = i;
521 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xudd->urb_ring, notify);
522 if (notify)
523 {
524 xudd->vectors.EvtChn_Notify(xudd->vectors.context, xudd->event_channel);
525 }
527 FUNCTION_EXIT();
529 return status;
530 }
532 NTSTATUS
533 XenUsb_EvtDeviceD0EntryPostInterruptsEnabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
534 {
535 NTSTATUS status = STATUS_SUCCESS;
536 //PXENUSB_DEVICE_DATA xudd = GetXudd(device);
538 UNREFERENCED_PARAMETER(device);
539 UNREFERENCED_PARAMETER(previous_state);
541 FUNCTION_ENTER();
543 FUNCTION_EXIT();
545 return status;
546 }
548 NTSTATUS
549 XenUsb_EvtDeviceD0ExitPreInterruptsDisabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
550 {
551 NTSTATUS status = STATUS_SUCCESS;
553 UNREFERENCED_PARAMETER(device);
555 FUNCTION_ENTER();
557 switch (target_state)
558 {
559 case WdfPowerDeviceD0:
560 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
561 break;
562 case WdfPowerDeviceD1:
563 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
564 break;
565 case WdfPowerDeviceD2:
566 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
567 break;
568 case WdfPowerDeviceD3:
569 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
570 break;
571 case WdfPowerDeviceD3Final:
572 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
573 break;
574 case WdfPowerDevicePrepareForHibernation:
575 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
576 break;
577 default:
578 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
579 break;
580 }
582 FUNCTION_EXIT();
584 return status;
585 }
587 NTSTATUS
588 XenUsb_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
589 {
590 NTSTATUS status = STATUS_SUCCESS;
591 //PXENUSB_DEVICE_DATA xudd = GetXudd(device);
593 FUNCTION_ENTER();
595 UNREFERENCED_PARAMETER(device);
597 switch (target_state)
598 {
599 case WdfPowerDeviceD0:
600 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
601 break;
602 case WdfPowerDeviceD1:
603 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
604 break;
605 case WdfPowerDeviceD2:
606 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
607 break;
608 case WdfPowerDeviceD3:
609 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
610 break;
611 case WdfPowerDeviceD3Final:
612 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
613 break;
614 case WdfPowerDevicePrepareForHibernation:
615 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
616 break;
617 default:
618 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
619 break;
620 }
622 FUNCTION_EXIT();
624 return status;
625 }
627 NTSTATUS
628 XenUsb_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
629 {
630 NTSTATUS status = STATUS_SUCCESS;
632 UNREFERENCED_PARAMETER(device);
633 UNREFERENCED_PARAMETER(resources_translated);
635 FUNCTION_ENTER();
636 FUNCTION_EXIT();
638 return status;
639 }
641 VOID
642 XenUsb_EvtChildListScanForChildren(WDFCHILDLIST child_list)
643 {
644 NTSTATUS status;
645 PXENUSB_DEVICE_DATA xudd = GetXudd(WdfChildListGetDevice(child_list));
646 XENUSB_PDO_IDENTIFICATION_DESCRIPTION child_description;
647 CHAR path[128];
648 PCHAR err;
649 PCHAR value;
650 ULONG i;
652 FUNCTION_ENTER();
654 WdfChildListBeginScan(child_list);
656 // hold the queue on each device and set each device to a pending state
657 // read backend/num_ports
658 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/num-ports", xudd->vectors.backend_path);
659 err = xudd->vectors.XenBus_Read(xudd->vectors.context, XBT_NIL, path, &value);
660 if (err)
661 {
662 XenPci_FreeMem(err);
663 WdfChildListEndScan(child_list);
664 KdPrint((__DRIVER_NAME " Failed to read num-ports\n"));
665 return;
666 }
667 xudd->num_ports = (ULONG)parse_numeric_string(value);
668 XenPci_FreeMem(value);
669 KdPrint((__DRIVER_NAME " num-ports = %d\n", xudd->num_ports));
671 for (i = 0; i < 8; i++)
672 {
673 xudd->ports[i].port_number = i + 1;
674 xudd->ports[i].port_type = USB_PORT_TYPE_NOT_CONNECTED;
675 xudd->ports[i].port_status = 0; //1 << PORT_ENABLE;
676 xudd->ports[i].port_change = 0x0000;
677 }
679 /* only a single root hub is enumerated */
680 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description));
682 child_description.device_number = 0; //TODO: get the proper index from parent
684 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(child_list, &child_description.header, NULL);
685 if (!NT_SUCCESS(status))
686 {
687 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status 0x%08x\n", status));
688 }
690 WdfChildListEndScan(child_list);
692 FUNCTION_EXIT();
693 }
695 static VOID
696 XenUsb_EvtIoDeviceControl(
697 WDFQUEUE queue,
698 WDFREQUEST request,
699 size_t output_buffer_length,
700 size_t input_buffer_length,
701 ULONG io_control_code)
702 {
703 NTSTATUS status;
704 WDFDEVICE device = WdfIoQueueGetDevice(queue);
705 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
707 UNREFERENCED_PARAMETER(queue);
708 UNREFERENCED_PARAMETER(input_buffer_length);
709 UNREFERENCED_PARAMETER(output_buffer_length);
711 FUNCTION_ENTER();
713 status = STATUS_BAD_INITIAL_PC;
715 // these are in api\usbioctl.h
716 switch(io_control_code)
717 {
718 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
719 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n"));
720 break;
721 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
722 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n"));
723 break;
724 case IOCTL_USB_GET_NODE_CONNECTION_NAME:
725 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_NAME\n"));
726 break;
727 case IOCTL_USB_DIAG_IGNORE_HUBS_ON:
728 KdPrint((__DRIVER_NAME " IOCTL_USB_DIAG_IGNORE_HUBS_ON\n"));
729 break;
730 case IOCTL_USB_DIAG_IGNORE_HUBS_OFF:
731 KdPrint((__DRIVER_NAME " IOCTL_USB_DIAG_IGNORE_HUBS_OFF\n"));
732 break;
733 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
734 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n"));
735 break;
736 case IOCTL_USB_GET_HUB_CAPABILITIES:
737 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_HUB_CAPABILITIES\n"));
738 break;
739 case IOCTL_USB_HUB_CYCLE_PORT:
740 KdPrint((__DRIVER_NAME " IOCTL_USB_HUB_CYCLE_PORT\n"));
741 break;
742 case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES:
743 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n"));
744 break;
745 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX:
746 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n"));
747 break;
748 case IOCTL_USB_GET_ROOT_HUB_NAME:
749 {
750 PUSB_HCD_DRIVERKEY_NAME uhdn;
751 size_t length;
752 ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
754 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_ROOT_HUB_NAME\n"));
755 KdPrint((__DRIVER_NAME " output_buffer_length = %d\n", output_buffer_length));
757 if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
758 status = STATUS_BUFFER_TOO_SMALL;
759 } else {
760 status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
761 if (NT_SUCCESS(status)) {
762 WDFSTRING symbolic_link_wdfstring;
763 UNICODE_STRING symbolic_link;
765 uhdn->DriverKeyName[0] = 0;
766 status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolic_link_wdfstring);
767 if (NT_SUCCESS(status)) {
768 status = WdfDeviceRetrieveDeviceInterfaceString(xudd->root_hub_device, &GUID_DEVINTERFACE_USB_HUB, NULL, symbolic_link_wdfstring);
769 if (NT_SUCCESS(status)) {
770 WdfStringGetUnicodeString(symbolic_link_wdfstring, &symbolic_link);
771 /* remove leading \??\ from name */
772 symbolic_link.Buffer += 4;
773 symbolic_link.Length -= 4 * sizeof(WCHAR);
774 required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + symbolic_link.Length + sizeof(WCHAR);
775 FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
776 FUNCTION_MSG("required_length = %d\n", required_length);
777 if (output_buffer_length >= required_length) {
778 uhdn->ActualLength = required_length;
779 memcpy(uhdn->DriverKeyName, symbolic_link.Buffer, symbolic_link.Length);
780 uhdn->DriverKeyName[symbolic_link.Length / 2] = 0;
781 WdfRequestSetInformation(request, required_length);
782 } else {
783 uhdn->ActualLength = required_length;
784 uhdn->DriverKeyName[0] = 0;
785 status = STATUS_SUCCESS;
786 WdfRequestSetInformation(request, output_buffer_length);
787 }
788 } else {
789 KdPrint((__DRIVER_NAME " WdfStringCreate = %08x\n", status));
790 }
791 }
792 else
793 {
794 KdPrint((__DRIVER_NAME " WdfDeviceRetrieveDeviceInterfaceString = %08x\n", status));
795 status = STATUS_INVALID_PARAMETER;
796 }
797 }
798 else
799 {
800 KdPrint((__DRIVER_NAME " WdfRequestRetrieveOutputBuffer = %08x\n", status));
801 }
802 KdPrint((__DRIVER_NAME " uhdn->ActualLength = %d\n", uhdn->ActualLength));
803 KdPrint((__DRIVER_NAME " uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName));
804 }
805 break;
806 }
807 case IOCTL_GET_HCD_DRIVERKEY_NAME:
808 {
809 PUSB_HCD_DRIVERKEY_NAME uhdn;
810 size_t length;
811 ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
812 ULONG key_length;
814 KdPrint((__DRIVER_NAME " IOCTL_GET_HCD_DRIVERKEY_NAME\n"));
815 KdPrint((__DRIVER_NAME " output_buffer_length = %d\n", output_buffer_length));
817 if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
818 FUNCTION_MSG("Buffer too small (%d < %d)\n", output_buffer_length, sizeof(USB_HCD_DRIVERKEY_NAME));
819 status = STATUS_BUFFER_TOO_SMALL;
820 break;
821 }
822 status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
823 if (!NT_SUCCESS(status)) {
824 KdPrint((__DRIVER_NAME " WdfRequestRetrieveOutputBuffer = %08x\n", status));
825 break;
826 }
827 status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, 0, NULL, &key_length);
828 if (!NT_SUCCESS(status)) {
829 KdPrint((__DRIVER_NAME " WdfDeviceQueryProperty = %08x\n", status));
830 break;
831 }
832 KdPrint((__DRIVER_NAME " key_length = %d\n", key_length));
833 required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + key_length + 2;
834 uhdn->ActualLength = required_length;
835 FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
836 FUNCTION_MSG("required_length = %d\n", required_length);
837 if (output_buffer_length >= required_length)
838 {
839 status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName,
840 required_length - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName), uhdn->DriverKeyName,
841 &key_length);
842 WdfRequestSetInformation(request, required_length);
843 }
844 else
845 {
846 uhdn->DriverKeyName[0] = 0;
847 status = STATUS_SUCCESS;
848 WdfRequestSetInformation(request, output_buffer_length);
849 }
850 FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength);
851 FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName);
852 break;
853 }
854 #if 0
855 case IOCTL_USB_RESET_HUB:
856 KdPrint((__DRIVER_NAME " IOCTL_USB_RESET_HUB\n"));
857 break;
858 #endif
859 default:
860 KdPrint((__DRIVER_NAME " Unknown IOCTL %08x\n", io_control_code));
861 break;
862 }
863 KdPrint((__DRIVER_NAME " Calling WdfRequestComplete with status = %08x\n", status));
864 WdfRequestComplete(request, status);
866 FUNCTION_EXIT();
867 }
869 VOID
870 XenUsb_EvtRequestCancelPvUrb(WDFREQUEST request) {
871 WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request));
872 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
873 WDF_REQUEST_PARAMETERS wrp;
874 partial_pvurb_t *partial_pvurb;
875 pvurb_t *pvurb;
876 KIRQL old_irql;
878 FUNCTION_ENTER();
879 FUNCTION_MSG("cancelling request %p\n", request);
881 WDF_REQUEST_PARAMETERS_INIT(&wrp);
882 KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);
884 WdfRequestGetParameters(request, &wrp);
885 pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
886 FUNCTION_MSG("pvurb = %p\n", pvurb);
887 ASSERT(pvurb);
889 partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_queue.Flink;
890 while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_queue) {
891 partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
892 ASSERT(!partial_pvurb->on_ring);
893 FUNCTION_MSG("partial_pvurb = %p is not yet on ring\n", partial_pvurb);
894 RemoveEntryList(&partial_pvurb->entry);
895 ExFreePoolWithTag(partial_pvurb, XENUSB_POOL_TAG);
896 pvurb->ref--;
897 partial_pvurb = next_partial_pvurb;
898 }
899 partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_ring.Flink;
900 while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_ring) {
901 partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
902 partial_pvurb_t *partial_pvurb_cancel;
903 FUNCTION_MSG("partial_pvurb = %p is on ring\n", partial_pvurb);
904 ASSERT(partial_pvurb->on_ring);
905 partial_pvurb_cancel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb_cancel), XENUSB_POOL_TAG); /* todo - use lookaside */
906 ASSERT(partial_pvurb_cancel); /* what would we do if this failed? */
907 partial_pvurb_cancel->req = partial_pvurb->req;
908 partial_pvurb_cancel->req.pipe = usbif_setunlink_pipe(partial_pvurb_cancel->req.pipe);
909 partial_pvurb_cancel->req.u.unlink.unlink_id = partial_pvurb->req.id;
910 partial_pvurb_cancel->pvurb = pvurb;
911 partial_pvurb_cancel->mdl = NULL;
912 partial_pvurb_cancel->other_partial_pvurb = partial_pvurb;
913 partial_pvurb->other_partial_pvurb = partial_pvurb_cancel;
914 partial_pvurb_cancel->on_ring = FALSE;
915 pvurb->ref++;
916 InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb_cancel->entry);
917 partial_pvurb = next_partial_pvurb;
918 }
919 if (pvurb->ref) {
920 PutRequestsOnRing(xudd);
921 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
922 } else {
923 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
924 WdfRequestComplete(request, STATUS_CANCELLED);
925 }
926 FUNCTION_EXIT();
927 }
929 static VOID
930 XenUsb_EvtIoInternalDeviceControl_PVURB(
931 WDFQUEUE queue,
932 WDFREQUEST request,
933 size_t output_buffer_length,
934 size_t input_buffer_length,
935 ULONG io_control_code)
936 {
937 NTSTATUS status;
938 WDFDEVICE device = WdfIoQueueGetDevice(queue);
939 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
940 WDF_REQUEST_PARAMETERS wrp;
941 pvurb_t *pvurb;
942 partial_pvurb_t *partial_pvurb;
943 KIRQL old_irql;
945 UNREFERENCED_PARAMETER(input_buffer_length);
946 UNREFERENCED_PARAMETER(output_buffer_length);
947 UNREFERENCED_PARAMETER(io_control_code);
949 FUNCTION_ENTER();
951 ASSERT(io_control_code == IOCTL_INTERNAL_PVUSB_SUBMIT_URB);
953 WDF_REQUEST_PARAMETERS_INIT(&wrp);
954 WdfRequestGetParameters(request, &wrp);
955 pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
956 ASSERT(pvurb);
957 RtlZeroMemory(&pvurb->rsp, sizeof(pvurb->rsp));
958 pvurb->status = STATUS_SUCCESS;
959 pvurb->request = request;
960 pvurb->ref = 1;
961 pvurb->total_length = 0;
962 partial_pvurb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb), XENUSB_POOL_TAG); /* todo - use lookaside */
963 if (!partial_pvurb) {
964 WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
965 FUNCTION_EXIT();
966 return;
967 }
968 KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);
969 status = WdfRequestMarkCancelableEx(request, XenUsb_EvtRequestCancelPvUrb);
970 if (!NT_SUCCESS(status)) {
971 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
972 FUNCTION_MSG("WdfRequestMarkCancelableEx returned %08x\n", status);
973 WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
974 FUNCTION_EXIT();
975 return;
976 }
978 partial_pvurb->req = pvurb->req;
979 partial_pvurb->mdl = pvurb->mdl; /* 1:1 right now, but may need to split up large pvurb into smaller partial_pvurb's */
980 partial_pvurb->pvurb = pvurb;
981 partial_pvurb->other_partial_pvurb = NULL;
982 partial_pvurb->on_ring = FALSE;
983 if (!partial_pvurb->mdl) {
984 partial_pvurb->req.nr_buffer_segs = 0;
985 partial_pvurb->req.buffer_length = 0;
986 } else {
987 ULONG remaining = MmGetMdlByteCount(partial_pvurb->mdl);
988 USHORT offset = (USHORT)MmGetMdlByteOffset(partial_pvurb->mdl);
989 int i;
990 partial_pvurb->req.buffer_length = (USHORT)MmGetMdlByteCount(partial_pvurb->mdl);
991 partial_pvurb->req.nr_buffer_segs = (USHORT)ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(partial_pvurb->mdl), MmGetMdlByteCount(partial_pvurb->mdl));
992 for (i = 0; i < partial_pvurb->req.nr_buffer_segs; i++) {
993 partial_pvurb->req.seg[i].gref = xudd->vectors.GntTbl_GrantAccess(xudd->vectors.context,
994 (ULONG)MmGetMdlPfnArray(partial_pvurb->mdl)[i], FALSE, INVALID_GRANT_REF, (ULONG)'XUSB');
995 partial_pvurb->req.seg[i].offset = (USHORT)offset;
996 partial_pvurb->req.seg[i].length = (USHORT)min((USHORT)remaining, (USHORT)PAGE_SIZE - offset);
997 offset = 0;
998 remaining -= partial_pvurb->req.seg[i].length;
999 KdPrint((__DRIVER_NAME " seg = %d\n", i));
1000 KdPrint((__DRIVER_NAME " gref = %d\n", partial_pvurb->req.seg[i].gref));
1001 KdPrint((__DRIVER_NAME " offset = %d\n", partial_pvurb->req.seg[i].offset));
1002 KdPrint((__DRIVER_NAME " length = %d\n", partial_pvurb->req.seg[i].length));
1004 KdPrint((__DRIVER_NAME " buffer_length = %d\n", partial_pvurb->req.buffer_length));
1005 KdPrint((__DRIVER_NAME " nr_buffer_segs = %d\n", partial_pvurb->req.nr_buffer_segs));
1007 InsertTailList(&xudd->partial_pvurb_queue, &partial_pvurb->entry);
1008 PutRequestsOnRing(xudd);
1009 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
1011 FUNCTION_EXIT();
1014 static VOID
1015 XenUsb_EvtIoInternalDeviceControl(
1016 WDFQUEUE queue,
1017 WDFREQUEST request,
1018 size_t output_buffer_length,
1019 size_t input_buffer_length,
1020 ULONG io_control_code)
1022 WDFDEVICE device = WdfIoQueueGetDevice(queue);
1023 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
1024 //WDF_REQUEST_PARAMETERS wrp;
1025 //pvusb_urb_t *urb;
1027 UNREFERENCED_PARAMETER(input_buffer_length);
1028 UNREFERENCED_PARAMETER(output_buffer_length);
1030 FUNCTION_ENTER();
1032 //WDF_REQUEST_PARAMETERS_INIT(&wrp);
1033 //WdfRequestGetParameters(request, &wrp);
1035 switch(io_control_code)
1037 case IOCTL_INTERNAL_PVUSB_SUBMIT_URB:
1038 FUNCTION_MSG("IOCTL_INTERNAL_PVUSB_SUBMIT_URB\n");
1039 //urb = (pvusb_urb_t *)wrp.Parameters.Others.Arg1;
1040 //FUNCTION_MSG("urb = %p\n", urb);
1041 WdfRequestForwardToIoQueue(request, xudd->pvurb_queue);
1042 break;
1043 default:
1044 KdPrint((__DRIVER_NAME " Unknown IOCTL %08x\n", io_control_code));
1045 WdfRequestComplete(request, WdfRequestGetStatus(request));
1046 break;
1048 FUNCTION_EXIT();
1051 static VOID
1052 XenUsb_EvtIoDefault(
1053 WDFQUEUE queue,
1054 WDFREQUEST request)
1056 NTSTATUS status;
1057 WDF_REQUEST_PARAMETERS parameters;
1059 FUNCTION_ENTER();
1061 UNREFERENCED_PARAMETER(queue);
1063 status = STATUS_BAD_INITIAL_PC;
1065 WDF_REQUEST_PARAMETERS_INIT(&parameters);
1066 WdfRequestGetParameters(request, &parameters);
1068 switch (parameters.Type)
1070 case WdfRequestTypeCreate:
1071 KdPrint((__DRIVER_NAME " WdfRequestTypeCreate\n"));
1072 break;
1073 case WdfRequestTypeClose:
1074 KdPrint((__DRIVER_NAME " WdfRequestTypeClose\n"));
1075 break;
1076 case WdfRequestTypeRead:
1077 KdPrint((__DRIVER_NAME " WdfRequestTypeRead\n"));
1078 break;
1079 case WdfRequestTypeWrite:
1080 KdPrint((__DRIVER_NAME " WdfRequestTypeWrite\n"));
1081 break;
1082 case WdfRequestTypeDeviceControl:
1083 KdPrint((__DRIVER_NAME " WdfRequestTypeDeviceControl\n"));
1084 break;
1085 case WdfRequestTypeDeviceControlInternal:
1086 KdPrint((__DRIVER_NAME " WdfRequestTypeDeviceControlInternal\n"));
1087 break;
1088 default:
1089 KdPrint((__DRIVER_NAME " Unknown type %x\n", parameters.Type));
1090 break;
1092 WdfRequestComplete(request, status);
1094 FUNCTION_EXIT();
1097 NTSTATUS
1098 XenUsb_EvtDriverDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
1100 NTSTATUS status;
1101 WDF_CHILD_LIST_CONFIG child_list_config;
1102 WDFDEVICE device;
1103 PXENUSB_DEVICE_DATA xudd;
1104 //UNICODE_STRING reference;
1105 WDF_OBJECT_ATTRIBUTES device_attributes;
1106 PNP_BUS_INFORMATION pbi;
1107 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
1108 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
1109 WDF_IO_QUEUE_CONFIG queue_config;
1110 UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE };
1111 DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName");
1112 WDFSTRING symbolicname_value_wdfstring;
1113 WDFKEY device_key;
1114 UNICODE_STRING symbolicname_value;
1116 UNREFERENCED_PARAMETER(driver);
1118 FUNCTION_ENTER();
1120 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
1121 pnp_power_callbacks.EvtDeviceD0Entry = XenUsb_EvtDeviceD0Entry;
1122 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenUsb_EvtDeviceD0EntryPostInterruptsEnabled;
1123 pnp_power_callbacks.EvtDeviceD0Exit = XenUsb_EvtDeviceD0Exit;
1124 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenUsb_EvtDeviceD0ExitPreInterruptsDisabled;
1125 pnp_power_callbacks.EvtDevicePrepareHardware = XenUsb_EvtDevicePrepareHardware;
1126 pnp_power_callbacks.EvtDeviceReleaseHardware = XenUsb_EvtDeviceReleaseHardware;
1127 pnp_power_callbacks.EvtDeviceQueryRemove = XenUsb_EvtDeviceQueryRemove;
1128 //pnp_power_callbacks.EvtDeviceUsageNotification = XenUsb_EvtDeviceUsageNotification;
1130 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
1132 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE,
1133 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
1134 if (!NT_SUCCESS(status))
1136 return status;
1139 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
1140 WdfDeviceInitSetExclusive(device_init, FALSE);
1142 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENUSB_PDO_IDENTIFICATION_DESCRIPTION), XenUsb_EvtChildListCreateDevice);
1143 child_list_config.EvtChildListScanForChildren = XenUsb_EvtChildListScanForChildren;
1144 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
1146 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
1148 WdfDeviceInitSetPowerNotPageable(device_init);
1150 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENUSB_DEVICE_DATA);
1151 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
1152 if (!NT_SUCCESS(status))
1154 KdPrint(("Error creating device %08x\n", status));
1155 return status;
1158 xudd = GetXudd(device);
1159 xudd->child_list = WdfFdoGetDefaultChildList(device);
1160 InitializeListHead(&xudd->partial_pvurb_queue);
1161 InitializeListHead(&xudd->partial_pvurb_ring);
1163 KeInitializeSpinLock(&xudd->urb_ring_lock);
1165 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
1166 queue_config.PowerManaged = FALSE; /* ? */
1167 queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
1168 queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl;
1169 queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
1170 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->io_queue);
1171 if (!NT_SUCCESS(status)) {
1172 KdPrint((__DRIVER_NAME " Error creating io_queue 0x%x\n", status));
1173 return status;
1176 WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel);
1177 queue_config.PowerManaged = FALSE; /* ? */
1178 //queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
1179 queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_PVURB;
1180 //queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
1181 queue_config.Settings.Parallel.NumberOfPresentedRequests = USB_URB_RING_SIZE; /* the queue controls if the ring is full */
1182 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->pvurb_queue);
1183 if (!NT_SUCCESS(status)) {
1184 KdPrint((__DRIVER_NAME " Error creating urb_queue 0x%x\n", status));
1185 return status;
1188 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
1189 power_capabilities.DeviceD1 = WdfTrue;
1190 power_capabilities.WakeFromD1 = WdfTrue;
1191 power_capabilities.DeviceWake = PowerDeviceD1;
1192 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
1193 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
1194 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
1195 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
1196 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
1197 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
1198 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
1200 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
1201 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
1202 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
1204 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
1205 pbi.LegacyBusType = PNPBus;
1206 pbi.BusNumber = 0;
1207 WdfDeviceSetBusInformationForChildren(device, &pbi);
1209 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL);
1210 if (!NT_SUCCESS(status)) {
1211 FUNCTION_MSG("WdfDeviceCreateDeviceInterface returned %08x\n");
1212 return status;
1215 /* USB likes to have a registry key with the symbolic link name in it */
1216 status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring);
1217 if (!NT_SUCCESS(status)) {
1218 FUNCTION_MSG("WdfStringCreate returned %08x\n");
1219 return status;
1221 status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, symbolicname_value_wdfstring);
1222 if (!NT_SUCCESS(status)) {
1223 FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString returned %08x\n");
1224 return status;
1226 WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value);
1227 status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key);
1228 if (!NT_SUCCESS(status)) {
1229 FUNCTION_MSG("WdfDeviceOpenRegistryKey returned %08x\n");
1230 return status;
1232 WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value);
1234 FUNCTION_EXIT();
1235 return status;