win-pvdrivers

view xenusb/xenusb_fdo.c @ 991:e9903455ba9d

Fix low gref resource handling. again.
Tidy up.
author James Harper <james.harper@bendigoit.com.au>
date Fri Sep 21 23:25:36 2012 +1000 (2012-09-21)
parents ea3c61839ff5
children 329b9b9d47ec
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->req_id_ss);
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->req_id_ss, 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 USHORT old_port_status;
246 conn_rsp = RING_GET_RESPONSE(&xudd->conn_ring, cons);
247 KdPrint((__DRIVER_NAME " conn_rsp->portnum = %d\n", conn_rsp->portnum));
248 KdPrint((__DRIVER_NAME " conn_rsp->speed = %d\n", conn_rsp->speed));
250 old_port_status = xudd->ports[conn_rsp->portnum - 1].port_status;
251 xudd->ports[conn_rsp->portnum - 1].port_type = conn_rsp->speed;
252 xudd->ports[conn_rsp->portnum - 1].port_status &= ~((1 << PORT_LOW_SPEED) | (1 << PORT_HIGH_SPEED) | (1 << PORT_CONNECTION));
253 switch (conn_rsp->speed)
254 {
255 case USB_PORT_TYPE_NOT_CONNECTED:
256 xudd->ports[conn_rsp->portnum - 1].port_status &= ~(1 << PORT_ENABLE);
257 break;
258 case USB_PORT_TYPE_LOW_SPEED:
259 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_LOW_SPEED) | (1 << PORT_CONNECTION);
260 break;
261 case USB_PORT_TYPE_FULL_SPEED:
262 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_CONNECTION);
263 break;
264 case USB_PORT_TYPE_HIGH_SPEED:
265 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_HIGH_SPEED) | (1 << PORT_CONNECTION);
266 break;
267 }
268 xudd->ports[conn_rsp->portnum - 1].port_change |= (xudd->ports[conn_rsp->portnum - 1].port_status ^ old_port_status) & ((1 << PORT_ENABLE) | (1 << PORT_CONNECTION));
269 if (xudd->ports[conn_rsp->portnum - 1].port_change)
270 port_changed = TRUE;
271 conn_req = RING_GET_REQUEST(&xudd->conn_ring, xudd->conn_ring.req_prod_pvt);
272 conn_req->id = conn_rsp->id;
273 xudd->conn_ring.req_prod_pvt++;
274 }
276 xudd->conn_ring.rsp_cons = cons;
277 if (cons != xudd->conn_ring.req_prod_pvt)
278 {
279 RING_FINAL_CHECK_FOR_RESPONSES(&xudd->conn_ring, more_to_do);
280 }
281 else
282 {
283 xudd->conn_ring.sring->rsp_event = cons + 1;
284 more_to_do = FALSE;
285 }
286 }
287 KeReleaseSpinLockFromDpcLevel(&xudd->conn_ring_lock);
289 if (port_changed) {
290 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(xudd->root_hub_device);
291 XenUsbHub_ProcessHubInterruptEvent(xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]);
292 }
294 FUNCTION_EXIT();
296 return TRUE;
297 }
299 static NTSTATUS
300 XenUsb_StartXenbusInit(PXENUSB_DEVICE_DATA xudd)
301 {
302 PUCHAR ptr;
303 USHORT type;
304 PCHAR setting, value, value2;
306 xudd->urb_sring = NULL;
307 xudd->event_channel = 0;
309 ptr = xudd->config_page;
310 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END) {
311 switch(type) {
312 case XEN_INIT_TYPE_READ_STRING_BACK:
313 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING_BACK - %s = %s\n", setting, value));
314 break;
315 case XEN_INIT_TYPE_READ_STRING_FRONT:
316 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING_FRONT - %s = %s\n", setting, value));
317 break;
318 case XEN_INIT_TYPE_VECTORS:
319 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
320 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
321 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC) {
322 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
323 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
324 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
325 return STATUS_BAD_INITIAL_PC;
326 }
327 else
328 memcpy(&xudd->vectors, value, sizeof(XENPCI_VECTORS));
329 break;
330 case XEN_INIT_TYPE_STATE_PTR:
331 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
332 xudd->device_state = (PXENPCI_DEVICE_STATE)value;
333 break;
334 default:
335 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
336 break;
337 }
338 }
340 return STATUS_SUCCESS;
341 }
343 static NTSTATUS
344 XenUsb_CompleteXenbusInit(PXENUSB_DEVICE_DATA xudd)
345 {
346 PUCHAR ptr;
347 USHORT type;
348 PCHAR setting, value, value2;
349 ULONG i;
351 ptr = xudd->config_page;
352 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
353 {
354 switch(type)
355 {
356 case XEN_INIT_TYPE_RING: /* frontend ring */
357 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
358 if (strcmp(setting, "urb-ring-ref") == 0)
359 {
360 xudd->urb_sring = (usbif_urb_sring_t *)value;
361 FRONT_RING_INIT(&xudd->urb_ring, xudd->urb_sring, PAGE_SIZE);
362 }
363 if (strcmp(setting, "conn-ring-ref") == 0)
364 {
365 xudd->conn_sring = (usbif_conn_sring_t *)value;
366 FRONT_RING_INIT(&xudd->conn_ring, xudd->conn_sring, PAGE_SIZE);
367 }
368 break;
369 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel */
370 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL_DPC - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF));
371 if (strcmp(setting, "event-channel") == 0)
372 {
373 xudd->event_channel = PtrToUlong(value);
374 }
375 break;
376 case XEN_INIT_TYPE_READ_STRING_BACK:
377 case XEN_INIT_TYPE_READ_STRING_FRONT:
378 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
379 break;
380 default:
381 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
382 break;
383 }
384 }
385 if (xudd->urb_sring == NULL || xudd->conn_sring == NULL || xudd->event_channel == 0)
386 {
387 KdPrint((__DRIVER_NAME " Missing settings\n"));
388 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
389 return STATUS_BAD_INITIAL_PC;
390 }
392 stack_new(&xudd->req_id_ss, REQ_ID_COUNT);
393 for (i = 0; i < REQ_ID_COUNT; i++) {
394 put_id_on_freelist(xudd->req_id_ss, (uint16_t)i);
395 }
397 return STATUS_SUCCESS;
398 }
400 NTSTATUS
401 XenUsb_EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resources_raw, WDFCMRESLIST resources_translated)
402 {
403 NTSTATUS status = STATUS_SUCCESS;
404 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
405 PCM_PARTIAL_RESOURCE_DESCRIPTOR raw_descriptor, translated_descriptor;
406 ULONG i;
407 PUCHAR ptr;
409 FUNCTION_ENTER();
411 ASSERT(WdfCmResourceListGetCount(resources_raw) == WdfCmResourceListGetCount(resources_translated));
413 for (i = 0; i < WdfCmResourceListGetCount(resources_raw); i++)
414 {
415 raw_descriptor = WdfCmResourceListGetDescriptor(resources_raw, i);
416 translated_descriptor = WdfCmResourceListGetDescriptor(resources_translated, i);
417 switch (raw_descriptor->Type) {
418 case CmResourceTypePort:
419 KdPrint((__DRIVER_NAME " IoPort Address(%x) Length: %d\n", translated_descriptor->u.Port.Start.LowPart, translated_descriptor->u.Port.Length));
420 break;
421 case CmResourceTypeMemory:
422 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));
423 KdPrint((__DRIVER_NAME " Memory flags = %04X\n", translated_descriptor->Flags));
424 xudd->config_page = MmMapIoSpace(translated_descriptor->u.Memory.Start, translated_descriptor->u.Memory.Length, MmNonCached);
425 KdPrint((__DRIVER_NAME " Memory mapped to %p\n", xudd->config_page));
426 break;
427 case CmResourceTypeInterrupt:
428 KdPrint((__DRIVER_NAME " irq_number = %03x\n", raw_descriptor->u.Interrupt.Vector));
429 KdPrint((__DRIVER_NAME " irq_vector = %03x\n", translated_descriptor->u.Interrupt.Vector));
430 KdPrint((__DRIVER_NAME " irq_level = %03x\n", translated_descriptor->u.Interrupt.Level));
431 break;
432 case CmResourceTypeDevicePrivate:
433 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]));
434 break;
435 default:
436 KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", translated_descriptor->Type));
437 break;
438 }
439 }
441 status = XenUsb_StartXenbusInit(xudd);
443 ptr = xudd->config_page;
444 //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
445 //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
446 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "urb-ring-ref", NULL, NULL);
447 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "conn-ring-ref", NULL, NULL);
448 #pragma warning(suppress:4054)
449 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_DPC, "event-channel", (PVOID)XenUsb_HandleEvent, xudd);
450 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
451 __ADD_XEN_INIT_UCHAR(&ptr, 0); /* no pre-connect required */
452 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
453 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
454 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
455 __ADD_XEN_INIT_UCHAR(&ptr, 20);
456 __ADD_XEN_INIT_UCHAR(&ptr, 0);
457 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
458 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
459 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
460 __ADD_XEN_INIT_UCHAR(&ptr, 50);
461 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
462 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
463 __ADD_XEN_INIT_UCHAR(&ptr, 50);
464 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
465 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
466 __ADD_XEN_INIT_UCHAR(&ptr, 50);
467 __ADD_XEN_INIT_UCHAR(&ptr, 0);
468 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
469 status = xudd->vectors.XenPci_XenConfigDevice(xudd->vectors.context);
471 status = XenUsb_CompleteXenbusInit(xudd);
473 FUNCTION_EXIT();
475 return status;
476 }
478 NTSTATUS
479 XenUsb_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
480 {
481 NTSTATUS status = STATUS_SUCCESS;
482 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
483 ULONG i;
484 int notify;
485 //PXENUSB_DEVICE_DATA xudd = GetXudd(device);
487 UNREFERENCED_PARAMETER(device);
489 FUNCTION_ENTER();
491 switch (previous_state)
492 {
493 case WdfPowerDeviceD0:
494 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
495 break;
496 case WdfPowerDeviceD1:
497 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
498 break;
499 case WdfPowerDeviceD2:
500 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
501 break;
502 case WdfPowerDeviceD3:
503 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
504 break;
505 case WdfPowerDeviceD3Final:
506 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
507 break;
508 case WdfPowerDevicePrepareForHibernation:
509 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
510 break;
511 default:
512 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", previous_state));
513 break;
514 }
516 /* fill conn ring with requests */
517 for (i = 0; i < USB_CONN_RING_SIZE; i++)
518 {
519 usbif_conn_request_t *req = RING_GET_REQUEST(&xudd->conn_ring, i);
520 req->id = (uint16_t)i;
521 }
522 xudd->conn_ring.req_prod_pvt = i;
524 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xudd->urb_ring, notify);
525 if (notify)
526 {
527 xudd->vectors.EvtChn_Notify(xudd->vectors.context, xudd->event_channel);
528 }
530 FUNCTION_EXIT();
532 return status;
533 }
535 NTSTATUS
536 XenUsb_EvtDeviceD0EntryPostInterruptsEnabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state)
537 {
538 NTSTATUS status = STATUS_SUCCESS;
539 //PXENUSB_DEVICE_DATA xudd = GetXudd(device);
541 UNREFERENCED_PARAMETER(device);
542 UNREFERENCED_PARAMETER(previous_state);
544 FUNCTION_ENTER();
546 FUNCTION_EXIT();
548 return status;
549 }
551 NTSTATUS
552 XenUsb_EvtDeviceD0ExitPreInterruptsDisabled(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
553 {
554 NTSTATUS status = STATUS_SUCCESS;
556 UNREFERENCED_PARAMETER(device);
558 FUNCTION_ENTER();
560 switch (target_state)
561 {
562 case WdfPowerDeviceD0:
563 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
564 break;
565 case WdfPowerDeviceD1:
566 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
567 break;
568 case WdfPowerDeviceD2:
569 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
570 break;
571 case WdfPowerDeviceD3:
572 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
573 break;
574 case WdfPowerDeviceD3Final:
575 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
576 break;
577 case WdfPowerDevicePrepareForHibernation:
578 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
579 break;
580 default:
581 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
582 break;
583 }
585 FUNCTION_EXIT();
587 return status;
588 }
590 NTSTATUS
591 XenUsb_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state)
592 {
593 NTSTATUS status = STATUS_SUCCESS;
594 //PXENUSB_DEVICE_DATA xudd = GetXudd(device);
596 FUNCTION_ENTER();
598 UNREFERENCED_PARAMETER(device);
600 switch (target_state)
601 {
602 case WdfPowerDeviceD0:
603 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
604 break;
605 case WdfPowerDeviceD1:
606 KdPrint((__DRIVER_NAME " WdfPowerDeviceD1\n"));
607 break;
608 case WdfPowerDeviceD2:
609 KdPrint((__DRIVER_NAME " WdfPowerDeviceD2\n"));
610 break;
611 case WdfPowerDeviceD3:
612 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3\n"));
613 break;
614 case WdfPowerDeviceD3Final:
615 KdPrint((__DRIVER_NAME " WdfPowerDeviceD3Final\n"));
616 break;
617 case WdfPowerDevicePrepareForHibernation:
618 KdPrint((__DRIVER_NAME " WdfPowerDevicePrepareForHibernation\n"));
619 break;
620 default:
621 KdPrint((__DRIVER_NAME " Unknown WdfPowerDevice state %d\n", target_state));
622 break;
623 }
625 FUNCTION_EXIT();
627 return status;
628 }
630 NTSTATUS
631 XenUsb_EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resources_translated)
632 {
633 NTSTATUS status = STATUS_SUCCESS;
635 UNREFERENCED_PARAMETER(device);
636 UNREFERENCED_PARAMETER(resources_translated);
638 FUNCTION_ENTER();
639 FUNCTION_EXIT();
641 return status;
642 }
644 VOID
645 XenUsb_EvtChildListScanForChildren(WDFCHILDLIST child_list)
646 {
647 NTSTATUS status;
648 PXENUSB_DEVICE_DATA xudd = GetXudd(WdfChildListGetDevice(child_list));
649 XENUSB_PDO_IDENTIFICATION_DESCRIPTION child_description;
650 CHAR path[128];
651 PCHAR err;
652 PCHAR value;
653 ULONG i;
655 FUNCTION_ENTER();
657 WdfChildListBeginScan(child_list);
659 // hold the queue on each device and set each device to a pending state
660 // read backend/num_ports
661 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/num-ports", xudd->vectors.backend_path);
662 err = xudd->vectors.XenBus_Read(xudd->vectors.context, XBT_NIL, path, &value);
663 if (err)
664 {
665 XenPci_FreeMem(err);
666 WdfChildListEndScan(child_list);
667 KdPrint((__DRIVER_NAME " Failed to read num-ports\n"));
668 return;
669 }
670 xudd->num_ports = (ULONG)parse_numeric_string(value);
671 XenPci_FreeMem(value);
672 KdPrint((__DRIVER_NAME " num-ports = %d\n", xudd->num_ports));
674 for (i = 0; i < 8; i++)
675 {
676 xudd->ports[i].port_number = i + 1;
677 xudd->ports[i].port_type = USB_PORT_TYPE_NOT_CONNECTED;
678 xudd->ports[i].port_status = 0; //1 << PORT_ENABLE;
679 xudd->ports[i].port_change = 0x0000;
680 }
682 /* only a single root hub is enumerated */
683 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description));
685 child_description.device_number = 0; //TODO: get the proper index from parent
687 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(child_list, &child_description.header, NULL);
688 if (!NT_SUCCESS(status))
689 {
690 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status 0x%08x\n", status));
691 }
693 WdfChildListEndScan(child_list);
695 FUNCTION_EXIT();
696 }
698 static VOID
699 XenUsb_EvtIoDeviceControl(
700 WDFQUEUE queue,
701 WDFREQUEST request,
702 size_t output_buffer_length,
703 size_t input_buffer_length,
704 ULONG io_control_code)
705 {
706 NTSTATUS status;
707 WDFDEVICE device = WdfIoQueueGetDevice(queue);
708 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
710 UNREFERENCED_PARAMETER(queue);
711 UNREFERENCED_PARAMETER(input_buffer_length);
712 UNREFERENCED_PARAMETER(output_buffer_length);
714 FUNCTION_ENTER();
716 status = STATUS_BAD_INITIAL_PC;
718 // these are in api\usbioctl.h
719 switch(io_control_code)
720 {
721 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
722 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n"));
723 break;
724 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
725 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n"));
726 break;
727 case IOCTL_USB_GET_NODE_CONNECTION_NAME:
728 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_NAME\n"));
729 break;
730 case IOCTL_USB_DIAG_IGNORE_HUBS_ON:
731 KdPrint((__DRIVER_NAME " IOCTL_USB_DIAG_IGNORE_HUBS_ON\n"));
732 break;
733 case IOCTL_USB_DIAG_IGNORE_HUBS_OFF:
734 KdPrint((__DRIVER_NAME " IOCTL_USB_DIAG_IGNORE_HUBS_OFF\n"));
735 break;
736 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
737 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n"));
738 break;
739 case IOCTL_USB_GET_HUB_CAPABILITIES:
740 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_HUB_CAPABILITIES\n"));
741 break;
742 case IOCTL_USB_HUB_CYCLE_PORT:
743 KdPrint((__DRIVER_NAME " IOCTL_USB_HUB_CYCLE_PORT\n"));
744 break;
745 case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES:
746 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n"));
747 break;
748 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX:
749 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n"));
750 break;
751 case IOCTL_USB_GET_ROOT_HUB_NAME:
752 {
753 PUSB_HCD_DRIVERKEY_NAME uhdn;
754 size_t length;
755 ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
757 KdPrint((__DRIVER_NAME " IOCTL_USB_GET_ROOT_HUB_NAME\n"));
758 KdPrint((__DRIVER_NAME " output_buffer_length = %d\n", output_buffer_length));
760 if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
761 status = STATUS_BUFFER_TOO_SMALL;
762 } else {
763 status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
764 if (NT_SUCCESS(status)) {
765 WDFSTRING symbolic_link_wdfstring;
766 UNICODE_STRING symbolic_link;
768 uhdn->DriverKeyName[0] = 0;
769 status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolic_link_wdfstring);
770 if (NT_SUCCESS(status)) {
771 status = WdfDeviceRetrieveDeviceInterfaceString(xudd->root_hub_device, &GUID_DEVINTERFACE_USB_HUB, NULL, symbolic_link_wdfstring);
772 if (NT_SUCCESS(status)) {
773 WdfStringGetUnicodeString(symbolic_link_wdfstring, &symbolic_link);
774 /* remove leading \??\ from name */
775 symbolic_link.Buffer += 4;
776 symbolic_link.Length -= 4 * sizeof(WCHAR);
777 required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + symbolic_link.Length + sizeof(WCHAR);
778 FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
779 FUNCTION_MSG("required_length = %d\n", required_length);
780 if (output_buffer_length >= required_length) {
781 uhdn->ActualLength = required_length;
782 memcpy(uhdn->DriverKeyName, symbolic_link.Buffer, symbolic_link.Length);
783 uhdn->DriverKeyName[symbolic_link.Length / 2] = 0;
784 WdfRequestSetInformation(request, required_length);
785 } else {
786 uhdn->ActualLength = required_length;
787 uhdn->DriverKeyName[0] = 0;
788 status = STATUS_SUCCESS;
789 WdfRequestSetInformation(request, output_buffer_length);
790 }
791 } else {
792 KdPrint((__DRIVER_NAME " WdfStringCreate = %08x\n", status));
793 }
794 }
795 else
796 {
797 KdPrint((__DRIVER_NAME " WdfDeviceRetrieveDeviceInterfaceString = %08x\n", status));
798 status = STATUS_INVALID_PARAMETER;
799 }
800 }
801 else
802 {
803 KdPrint((__DRIVER_NAME " WdfRequestRetrieveOutputBuffer = %08x\n", status));
804 }
805 KdPrint((__DRIVER_NAME " uhdn->ActualLength = %d\n", uhdn->ActualLength));
806 KdPrint((__DRIVER_NAME " uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName));
807 }
808 break;
809 }
810 case IOCTL_GET_HCD_DRIVERKEY_NAME:
811 {
812 PUSB_HCD_DRIVERKEY_NAME uhdn;
813 size_t length;
814 ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
815 ULONG key_length;
817 KdPrint((__DRIVER_NAME " IOCTL_GET_HCD_DRIVERKEY_NAME\n"));
818 KdPrint((__DRIVER_NAME " output_buffer_length = %d\n", output_buffer_length));
820 if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
821 FUNCTION_MSG("Buffer too small (%d < %d)\n", output_buffer_length, sizeof(USB_HCD_DRIVERKEY_NAME));
822 status = STATUS_BUFFER_TOO_SMALL;
823 break;
824 }
825 status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
826 if (!NT_SUCCESS(status)) {
827 KdPrint((__DRIVER_NAME " WdfRequestRetrieveOutputBuffer = %08x\n", status));
828 break;
829 }
830 status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, 0, NULL, &key_length);
831 if (!NT_SUCCESS(status)) {
832 KdPrint((__DRIVER_NAME " WdfDeviceQueryProperty = %08x\n", status));
833 break;
834 }
835 KdPrint((__DRIVER_NAME " key_length = %d\n", key_length));
836 required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + key_length + 2;
837 uhdn->ActualLength = required_length;
838 FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
839 FUNCTION_MSG("required_length = %d\n", required_length);
840 if (output_buffer_length >= required_length)
841 {
842 status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName,
843 required_length - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName), uhdn->DriverKeyName,
844 &key_length);
845 WdfRequestSetInformation(request, required_length);
846 }
847 else
848 {
849 uhdn->DriverKeyName[0] = 0;
850 status = STATUS_SUCCESS;
851 WdfRequestSetInformation(request, output_buffer_length);
852 }
853 FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength);
854 FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName);
855 break;
856 }
857 #if 0
858 case IOCTL_USB_RESET_HUB:
859 KdPrint((__DRIVER_NAME " IOCTL_USB_RESET_HUB\n"));
860 break;
861 #endif
862 default:
863 KdPrint((__DRIVER_NAME " Unknown IOCTL %08x\n", io_control_code));
864 break;
865 }
866 KdPrint((__DRIVER_NAME " Calling WdfRequestComplete with status = %08x\n", status));
867 WdfRequestComplete(request, status);
869 FUNCTION_EXIT();
870 }
872 VOID
873 XenUsb_EvtRequestCancelPvUrb(WDFREQUEST request) {
874 WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request));
875 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
876 WDF_REQUEST_PARAMETERS wrp;
877 partial_pvurb_t *partial_pvurb;
878 pvurb_t *pvurb;
879 KIRQL old_irql;
881 FUNCTION_ENTER();
882 FUNCTION_MSG("cancelling request %p\n", request);
884 WDF_REQUEST_PARAMETERS_INIT(&wrp);
885 KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);
887 WdfRequestGetParameters(request, &wrp);
888 pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
889 FUNCTION_MSG("pvurb = %p\n", pvurb);
890 ASSERT(pvurb);
892 partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_queue.Flink;
893 while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_queue) {
894 partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
895 ASSERT(!partial_pvurb->on_ring);
896 FUNCTION_MSG("partial_pvurb = %p is not yet on ring\n", partial_pvurb);
897 RemoveEntryList(&partial_pvurb->entry);
898 ExFreePoolWithTag(partial_pvurb, XENUSB_POOL_TAG);
899 pvurb->ref--;
900 partial_pvurb = next_partial_pvurb;
901 }
902 partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_ring.Flink;
903 while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_ring) {
904 partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
905 partial_pvurb_t *partial_pvurb_cancel;
906 FUNCTION_MSG("partial_pvurb = %p is on ring\n", partial_pvurb);
907 ASSERT(partial_pvurb->on_ring);
908 partial_pvurb_cancel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb_cancel), XENUSB_POOL_TAG); /* todo - use lookaside */
909 ASSERT(partial_pvurb_cancel); /* what would we do if this failed? */
910 partial_pvurb_cancel->req = partial_pvurb->req;
911 partial_pvurb_cancel->req.pipe = usbif_setunlink_pipe(partial_pvurb_cancel->req.pipe);
912 partial_pvurb_cancel->req.u.unlink.unlink_id = partial_pvurb->req.id;
913 partial_pvurb_cancel->pvurb = pvurb;
914 partial_pvurb_cancel->mdl = NULL;
915 partial_pvurb_cancel->other_partial_pvurb = partial_pvurb;
916 partial_pvurb->other_partial_pvurb = partial_pvurb_cancel;
917 partial_pvurb_cancel->on_ring = FALSE;
918 pvurb->ref++;
919 InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb_cancel->entry);
920 partial_pvurb = next_partial_pvurb;
921 }
922 if (pvurb->ref) {
923 PutRequestsOnRing(xudd);
924 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
925 } else {
926 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
927 WdfRequestComplete(request, STATUS_CANCELLED);
928 }
929 FUNCTION_EXIT();
930 }
932 static VOID
933 XenUsb_EvtIoInternalDeviceControl_PVURB(
934 WDFQUEUE queue,
935 WDFREQUEST request,
936 size_t output_buffer_length,
937 size_t input_buffer_length,
938 ULONG io_control_code)
939 {
940 NTSTATUS status;
941 WDFDEVICE device = WdfIoQueueGetDevice(queue);
942 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
943 WDF_REQUEST_PARAMETERS wrp;
944 pvurb_t *pvurb;
945 partial_pvurb_t *partial_pvurb;
946 KIRQL old_irql;
948 UNREFERENCED_PARAMETER(input_buffer_length);
949 UNREFERENCED_PARAMETER(output_buffer_length);
950 UNREFERENCED_PARAMETER(io_control_code);
952 FUNCTION_ENTER();
954 ASSERT(io_control_code == IOCTL_INTERNAL_PVUSB_SUBMIT_URB);
956 WDF_REQUEST_PARAMETERS_INIT(&wrp);
957 WdfRequestGetParameters(request, &wrp);
958 pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
959 ASSERT(pvurb);
960 RtlZeroMemory(&pvurb->rsp, sizeof(pvurb->rsp));
961 pvurb->status = STATUS_SUCCESS;
962 pvurb->request = request;
963 pvurb->ref = 1;
964 pvurb->total_length = 0;
965 partial_pvurb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb), XENUSB_POOL_TAG); /* todo - use lookaside */
966 if (!partial_pvurb) {
967 WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
968 FUNCTION_EXIT();
969 return;
970 }
971 KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);
972 status = WdfRequestMarkCancelableEx(request, XenUsb_EvtRequestCancelPvUrb);
973 if (!NT_SUCCESS(status)) {
974 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
975 FUNCTION_MSG("WdfRequestMarkCancelableEx returned %08x\n", status);
976 WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
977 FUNCTION_EXIT();
978 return;
979 }
981 partial_pvurb->req = pvurb->req;
982 partial_pvurb->mdl = pvurb->mdl; /* 1:1 right now, but may need to split up large pvurb into smaller partial_pvurb's */
983 partial_pvurb->pvurb = pvurb;
984 partial_pvurb->other_partial_pvurb = NULL;
985 partial_pvurb->on_ring = FALSE;
986 if (!partial_pvurb->mdl) {
987 partial_pvurb->req.nr_buffer_segs = 0;
988 partial_pvurb->req.buffer_length = 0;
989 } else {
990 ULONG remaining = MmGetMdlByteCount(partial_pvurb->mdl);
991 USHORT offset = (USHORT)MmGetMdlByteOffset(partial_pvurb->mdl);
992 int i;
993 partial_pvurb->req.buffer_length = (USHORT)MmGetMdlByteCount(partial_pvurb->mdl);
994 partial_pvurb->req.nr_buffer_segs = (USHORT)ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(partial_pvurb->mdl), MmGetMdlByteCount(partial_pvurb->mdl));
995 for (i = 0; i < partial_pvurb->req.nr_buffer_segs; i++) {
996 partial_pvurb->req.seg[i].gref = xudd->vectors.GntTbl_GrantAccess(xudd->vectors.context,
997 (ULONG)MmGetMdlPfnArray(partial_pvurb->mdl)[i], FALSE, INVALID_GRANT_REF, (ULONG)'XUSB');
998 partial_pvurb->req.seg[i].offset = (USHORT)offset;
999 partial_pvurb->req.seg[i].length = (USHORT)min((USHORT)remaining, (USHORT)PAGE_SIZE - offset);
1000 offset = 0;
1001 remaining -= partial_pvurb->req.seg[i].length;
1002 KdPrint((__DRIVER_NAME " seg = %d\n", i));
1003 KdPrint((__DRIVER_NAME " gref = %d\n", partial_pvurb->req.seg[i].gref));
1004 KdPrint((__DRIVER_NAME " offset = %d\n", partial_pvurb->req.seg[i].offset));
1005 KdPrint((__DRIVER_NAME " length = %d\n", partial_pvurb->req.seg[i].length));
1007 KdPrint((__DRIVER_NAME " buffer_length = %d\n", partial_pvurb->req.buffer_length));
1008 KdPrint((__DRIVER_NAME " nr_buffer_segs = %d\n", partial_pvurb->req.nr_buffer_segs));
1010 InsertTailList(&xudd->partial_pvurb_queue, &partial_pvurb->entry);
1011 PutRequestsOnRing(xudd);
1012 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
1014 FUNCTION_EXIT();
1017 static VOID
1018 XenUsb_EvtIoInternalDeviceControl(
1019 WDFQUEUE queue,
1020 WDFREQUEST request,
1021 size_t output_buffer_length,
1022 size_t input_buffer_length,
1023 ULONG io_control_code)
1025 WDFDEVICE device = WdfIoQueueGetDevice(queue);
1026 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
1027 //WDF_REQUEST_PARAMETERS wrp;
1028 //pvusb_urb_t *urb;
1030 UNREFERENCED_PARAMETER(input_buffer_length);
1031 UNREFERENCED_PARAMETER(output_buffer_length);
1033 FUNCTION_ENTER();
1035 //WDF_REQUEST_PARAMETERS_INIT(&wrp);
1036 //WdfRequestGetParameters(request, &wrp);
1038 switch(io_control_code)
1040 case IOCTL_INTERNAL_PVUSB_SUBMIT_URB:
1041 FUNCTION_MSG("IOCTL_INTERNAL_PVUSB_SUBMIT_URB\n");
1042 //urb = (pvusb_urb_t *)wrp.Parameters.Others.Arg1;
1043 //FUNCTION_MSG("urb = %p\n", urb);
1044 WdfRequestForwardToIoQueue(request, xudd->pvurb_queue);
1045 break;
1046 default:
1047 KdPrint((__DRIVER_NAME " Unknown IOCTL %08x\n", io_control_code));
1048 WdfRequestComplete(request, WdfRequestGetStatus(request));
1049 break;
1051 FUNCTION_EXIT();
1054 static VOID
1055 XenUsb_EvtIoDefault(
1056 WDFQUEUE queue,
1057 WDFREQUEST request)
1059 NTSTATUS status;
1060 WDF_REQUEST_PARAMETERS parameters;
1062 FUNCTION_ENTER();
1064 UNREFERENCED_PARAMETER(queue);
1066 status = STATUS_BAD_INITIAL_PC;
1068 WDF_REQUEST_PARAMETERS_INIT(&parameters);
1069 WdfRequestGetParameters(request, &parameters);
1071 switch (parameters.Type)
1073 case WdfRequestTypeCreate:
1074 KdPrint((__DRIVER_NAME " WdfRequestTypeCreate\n"));
1075 break;
1076 case WdfRequestTypeClose:
1077 KdPrint((__DRIVER_NAME " WdfRequestTypeClose\n"));
1078 break;
1079 case WdfRequestTypeRead:
1080 KdPrint((__DRIVER_NAME " WdfRequestTypeRead\n"));
1081 break;
1082 case WdfRequestTypeWrite:
1083 KdPrint((__DRIVER_NAME " WdfRequestTypeWrite\n"));
1084 break;
1085 case WdfRequestTypeDeviceControl:
1086 KdPrint((__DRIVER_NAME " WdfRequestTypeDeviceControl\n"));
1087 break;
1088 case WdfRequestTypeDeviceControlInternal:
1089 KdPrint((__DRIVER_NAME " WdfRequestTypeDeviceControlInternal\n"));
1090 break;
1091 default:
1092 KdPrint((__DRIVER_NAME " Unknown type %x\n", parameters.Type));
1093 break;
1095 WdfRequestComplete(request, status);
1097 FUNCTION_EXIT();
1100 NTSTATUS
1101 XenUsb_EvtDriverDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
1103 NTSTATUS status;
1104 WDF_CHILD_LIST_CONFIG child_list_config;
1105 WDFDEVICE device;
1106 PXENUSB_DEVICE_DATA xudd;
1107 //UNICODE_STRING reference;
1108 WDF_OBJECT_ATTRIBUTES device_attributes;
1109 PNP_BUS_INFORMATION pbi;
1110 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
1111 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
1112 WDF_IO_QUEUE_CONFIG queue_config;
1113 UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE };
1114 DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName");
1115 WDFSTRING symbolicname_value_wdfstring;
1116 WDFKEY device_key;
1117 UNICODE_STRING symbolicname_value;
1119 UNREFERENCED_PARAMETER(driver);
1121 FUNCTION_ENTER();
1123 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
1124 pnp_power_callbacks.EvtDeviceD0Entry = XenUsb_EvtDeviceD0Entry;
1125 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenUsb_EvtDeviceD0EntryPostInterruptsEnabled;
1126 pnp_power_callbacks.EvtDeviceD0Exit = XenUsb_EvtDeviceD0Exit;
1127 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenUsb_EvtDeviceD0ExitPreInterruptsDisabled;
1128 pnp_power_callbacks.EvtDevicePrepareHardware = XenUsb_EvtDevicePrepareHardware;
1129 pnp_power_callbacks.EvtDeviceReleaseHardware = XenUsb_EvtDeviceReleaseHardware;
1130 pnp_power_callbacks.EvtDeviceQueryRemove = XenUsb_EvtDeviceQueryRemove;
1131 //pnp_power_callbacks.EvtDeviceUsageNotification = XenUsb_EvtDeviceUsageNotification;
1133 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
1135 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE,
1136 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
1137 if (!NT_SUCCESS(status))
1139 return status;
1142 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
1143 WdfDeviceInitSetExclusive(device_init, FALSE);
1145 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENUSB_PDO_IDENTIFICATION_DESCRIPTION), XenUsb_EvtChildListCreateDevice);
1146 child_list_config.EvtChildListScanForChildren = XenUsb_EvtChildListScanForChildren;
1147 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
1149 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
1151 WdfDeviceInitSetPowerNotPageable(device_init);
1153 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENUSB_DEVICE_DATA);
1154 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
1155 if (!NT_SUCCESS(status))
1157 KdPrint(("Error creating device %08x\n", status));
1158 return status;
1161 xudd = GetXudd(device);
1162 xudd->child_list = WdfFdoGetDefaultChildList(device);
1163 InitializeListHead(&xudd->partial_pvurb_queue);
1164 InitializeListHead(&xudd->partial_pvurb_ring);
1166 KeInitializeSpinLock(&xudd->urb_ring_lock);
1168 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
1169 queue_config.PowerManaged = FALSE; /* ? */
1170 queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
1171 queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl;
1172 queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
1173 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->io_queue);
1174 if (!NT_SUCCESS(status)) {
1175 KdPrint((__DRIVER_NAME " Error creating io_queue 0x%x\n", status));
1176 return status;
1179 WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel);
1180 queue_config.PowerManaged = FALSE; /* ? */
1181 //queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
1182 queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_PVURB;
1183 //queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
1184 queue_config.Settings.Parallel.NumberOfPresentedRequests = USB_URB_RING_SIZE; /* the queue controls if the ring is full */
1185 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->pvurb_queue);
1186 if (!NT_SUCCESS(status)) {
1187 KdPrint((__DRIVER_NAME " Error creating urb_queue 0x%x\n", status));
1188 return status;
1191 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
1192 power_capabilities.DeviceD1 = WdfTrue;
1193 power_capabilities.WakeFromD1 = WdfTrue;
1194 power_capabilities.DeviceWake = PowerDeviceD1;
1195 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
1196 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
1197 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
1198 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
1199 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
1200 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
1201 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
1203 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
1204 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
1205 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
1207 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
1208 pbi.LegacyBusType = PNPBus;
1209 pbi.BusNumber = 0;
1210 WdfDeviceSetBusInformationForChildren(device, &pbi);
1212 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL);
1213 if (!NT_SUCCESS(status)) {
1214 FUNCTION_MSG("WdfDeviceCreateDeviceInterface returned %08x\n");
1215 return status;
1218 /* USB likes to have a registry key with the symbolic link name in it */
1219 status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring);
1220 if (!NT_SUCCESS(status)) {
1221 FUNCTION_MSG("WdfStringCreate returned %08x\n");
1222 return status;
1224 status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, symbolicname_value_wdfstring);
1225 if (!NT_SUCCESS(status)) {
1226 FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString returned %08x\n");
1227 return status;
1229 WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value);
1230 status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key);
1231 if (!NT_SUCCESS(status)) {
1232 FUNCTION_MSG("WdfDeviceOpenRegistryKey returned %08x\n");
1233 return status;
1235 WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value);
1237 FUNCTION_EXIT();
1238 return status;