win-pvdrivers

view xenusb/xenusb_fdo.c @ 1031:329b9b9d47ec

re-enable xenusb. compiles but untested.
author James Harper <james.harper@bendigoit.com.au>
date Thu Feb 21 20:37:38 2013 +1100 (2013-02-21)
parents ea3c61839ff5
children aa7329b5211b
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_EXIT XenUsb_EvtDeviceD0Exit;
27 static EVT_WDFDEVICE_WDM_IRP_PREPROCESS XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE;
28 static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL XenUsb_EvtIoDeviceControl;
29 static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL XenUsb_EvtIoInternalDeviceControl;
30 static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL XenUsb_EvtIoInternalDeviceControl_PVURB;
31 static EVT_WDF_IO_QUEUE_IO_DEFAULT XenUsb_EvtIoDefault;
32 static EVT_WDF_REQUEST_CANCEL XenUsb_EvtRequestCancelPvUrb;
34 static NTSTATUS XenUsb_Connect(PVOID context, BOOLEAN suspend);
35 static NTSTATUS XenUsb_Disconnect(PVOID context, BOOLEAN suspend);
37 static NTSTATUS
38 XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE(WDFDEVICE device, PIRP irp)
39 {
40 PIO_STACK_LOCATION stack;
42 FUNCTION_ENTER();
44 stack = IoGetCurrentIrpStackLocation(irp);
46 if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_GUID, sizeof(GUID)) == 0)
47 FUNCTION_MSG("USB_BUS_INTERFACE_HUB_GUID\n");
48 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID, sizeof(GUID)) == 0)
49 FUNCTION_MSG("USB_BUS_INTERFACE_USBDI_GUID\n");
50 else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &GUID_TRANSLATOR_INTERFACE_STANDARD, sizeof(GUID)) == 0)
51 FUNCTION_MSG("GUID_TRANSLATOR_INTERFACE_STANDARD\n");
52 else
53 FUNCTION_MSG("GUID = %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
54 stack->Parameters.QueryInterface.InterfaceType->Data1,
55 stack->Parameters.QueryInterface.InterfaceType->Data2,
56 stack->Parameters.QueryInterface.InterfaceType->Data3,
57 (stack->Parameters.QueryInterface.InterfaceType->Data4[0] << 8) |
58 stack->Parameters.QueryInterface.InterfaceType->Data4[1],
59 stack->Parameters.QueryInterface.InterfaceType->Data4[2],
60 stack->Parameters.QueryInterface.InterfaceType->Data4[3],
61 stack->Parameters.QueryInterface.InterfaceType->Data4[4],
62 stack->Parameters.QueryInterface.InterfaceType->Data4[5],
63 stack->Parameters.QueryInterface.InterfaceType->Data4[6],
64 stack->Parameters.QueryInterface.InterfaceType->Data4[7]);
66 FUNCTION_MSG("Size = %d\n", stack->Parameters.QueryInterface.Size);
67 FUNCTION_MSG("Version = %d\n", stack->Parameters.QueryInterface.Version);
68 FUNCTION_MSG("Interface = %p\n", stack->Parameters.QueryInterface.Interface);
71 IoSkipCurrentIrpStackLocation(irp);
73 FUNCTION_EXIT();
75 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
76 }
78 /* called with urb ring lock held */
79 static VOID
80 PutRequestsOnRing(PXENUSB_DEVICE_DATA xudd) {
81 partial_pvurb_t *partial_pvurb;
82 uint16_t id;
83 int notify;
85 FUNCTION_ENTER();
86 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
88 while ((partial_pvurb = (partial_pvurb_t *)RemoveHeadList((PLIST_ENTRY)&xudd->partial_pvurb_queue)) != (partial_pvurb_t *)&xudd->partial_pvurb_queue) {
89 FUNCTION_MSG("partial_pvurb = %p\n", partial_pvurb);
90 /* 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 */
91 id = get_id_from_freelist(xudd->req_id_ss);
92 if (id == (uint16_t)-1) {
93 FUNCTION_MSG("no free ring slots\n");
94 InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb->entry);
95 break;
96 }
97 InsertTailList(&xudd->partial_pvurb_ring, &partial_pvurb->entry);
98 xudd->partial_pvurbs[id] = partial_pvurb;
99 partial_pvurb->req.id = id;
100 *RING_GET_REQUEST(&xudd->urb_ring, xudd->urb_ring.req_prod_pvt) = partial_pvurb->req;
101 xudd->urb_ring.req_prod_pvt++;
102 }
103 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xudd->urb_ring, notify);
104 if (notify) {
105 FUNCTION_MSG("Notifying\n");
106 XnNotify(xudd->handle, xudd->event_channel);
107 }
109 FUNCTION_EXIT();
110 }
112 static BOOLEAN
113 XenUsb_HandleEventDpc(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2) {
114 NTSTATUS status;
115 PXENUSB_DEVICE_DATA xudd = context;
116 RING_IDX prod, cons;
117 usbif_urb_response_t *urb_rsp;
118 usbif_conn_response_t *conn_rsp;
119 usbif_conn_request_t *conn_req;
120 int more_to_do;
121 pvurb_t *pvurb, *complete_head = NULL, *complete_tail = NULL;
122 partial_pvurb_t *partial_pvurb;
123 BOOLEAN port_changed = FALSE;
125 UNREFERENCED_PARAMETER(dpc);
126 UNREFERENCED_PARAMETER(arg1);
127 UNREFERENCED_PARAMETER(arg2);
129 FUNCTION_ENTER();
131 more_to_do = TRUE;
132 KeAcquireSpinLockAtDpcLevel(&xudd->urb_ring_lock);
133 while (more_to_do)
134 {
135 prod = xudd->urb_ring.sring->rsp_prod;
136 KeMemoryBarrier();
137 for (cons = xudd->urb_ring.rsp_cons; cons != prod; cons++)
138 {
139 urb_rsp = RING_GET_RESPONSE(&xudd->urb_ring, cons);
140 // FUNCTION_MSG("urb_rsp->id = %d\n", urb_rsp->id);
141 partial_pvurb = xudd->partial_pvurbs[urb_rsp->id];
142 RemoveEntryList(&partial_pvurb->entry);
143 partial_pvurb->rsp = *urb_rsp;
144 // FUNCTION_MSG("shadow = %p\n", shadow);
145 // FUNCTION_MSG("shadow->rsp = %p\n", shadow->rsp);
146 if (usbif_pipeunlink(partial_pvurb->req.pipe)) {
147 FUNCTION_MSG("is a cancel request for request %p\n", partial_pvurb->pvurb->request);
148 FUNCTION_MSG("urb_ring rsp status = %d\n", urb_rsp->status);
149 // status should be 115 == EINPROGRESS
150 } else {
151 partial_pvurb->pvurb->total_length += urb_rsp->actual_length;
152 if (!partial_pvurb->pvurb->rsp.status)
153 partial_pvurb->pvurb->rsp.status = urb_rsp->status;
154 partial_pvurb->pvurb->rsp.error_count += urb_rsp->error_count;;
155 if (partial_pvurb->mdl) {
156 int i;
157 for (i = 0; i < partial_pvurb->req.nr_buffer_segs; i++) {
158 XnEndAccess(xudd->handle, partial_pvurb->req.seg[i].gref, FALSE, (ULONG)'XUSB');
159 }
160 }
162 FUNCTION_MSG("urb_ring rsp id = %d\n", partial_pvurb->rsp.id);
163 FUNCTION_MSG("urb_ring rsp start_frame = %d\n", partial_pvurb->rsp.start_frame);
164 FUNCTION_MSG("urb_ring rsp status = %d\n", partial_pvurb->rsp.status);
165 FUNCTION_MSG("urb_ring rsp actual_length = %d\n", partial_pvurb->rsp.actual_length);
166 FUNCTION_MSG("urb_ring rsp error_count = %d\n", partial_pvurb->rsp.error_count);
167 }
168 if (partial_pvurb->other_partial_pvurb) {
169 if (!partial_pvurb->other_partial_pvurb->on_ring) {
170 /* cancel hasn't been put on the ring yet - remove it */
171 RemoveEntryList(&partial_pvurb->other_partial_pvurb->entry);
172 ASSERT(usbif_pipeunlink(partial_pvurb->other_partial_pvurb->req.pipe));
173 partial_pvurb->pvurb->ref--;
174 ExFreePoolWithTag(partial_pvurb->other_partial_pvurb, XENUSB_POOL_TAG);
175 }
176 }
177 partial_pvurb->pvurb->ref--;
178 switch (partial_pvurb->rsp.status) {
179 case EINPROGRESS: /* unlink request */
180 case ECONNRESET: /* cancelled request */
181 ASSERT(partial_pvurb->pvurb->status == STATUS_CANCELLED);
182 break;
183 default:
184 break;
185 }
186 put_id_on_freelist(xudd->req_id_ss, partial_pvurb->rsp.id);
187 partial_pvurb->pvurb->next = NULL;
188 if (!partial_pvurb->pvurb->ref) {
189 if (complete_tail) {
190 complete_tail->next = partial_pvurb->pvurb;
191 } else {
192 complete_head = partial_pvurb->pvurb;
193 }
194 complete_tail = partial_pvurb->pvurb;
195 }
196 }
198 xudd->urb_ring.rsp_cons = cons;
199 if (cons != xudd->urb_ring.req_prod_pvt) {
200 RING_FINAL_CHECK_FOR_RESPONSES(&xudd->urb_ring, more_to_do);
201 } else {
202 xudd->urb_ring.sring->rsp_event = cons + 1;
203 more_to_do = FALSE;
204 }
205 }
206 PutRequestsOnRing(xudd);
207 KeReleaseSpinLockFromDpcLevel(&xudd->urb_ring_lock);
209 pvurb = complete_head;
210 while (pvurb != NULL) {
211 complete_head = pvurb->next;
212 status = WdfRequestUnmarkCancelable(pvurb->request);
213 if (status == STATUS_CANCELLED) {
214 FUNCTION_MSG("Cancel was called\n");
215 }
217 WdfRequestCompleteWithInformation(pvurb->request, pvurb->status, pvurb->total_length); /* the WDFREQUEST is always successfull here even if the pvurb->rsp has an error */
218 pvurb = complete_head;
219 }
221 more_to_do = TRUE;
222 KeAcquireSpinLockAtDpcLevel(&xudd->conn_ring_lock);
223 while (more_to_do)
224 {
225 prod = xudd->conn_ring.sring->rsp_prod;
226 KeMemoryBarrier();
227 for (cons = xudd->conn_ring.rsp_cons; cons != prod; cons++)
228 {
229 USHORT old_port_status;
230 conn_rsp = RING_GET_RESPONSE(&xudd->conn_ring, cons);
231 FUNCTION_MSG("conn_rsp->portnum = %d\n", conn_rsp->portnum);
232 FUNCTION_MSG("conn_rsp->speed = %d\n", conn_rsp->speed);
234 old_port_status = xudd->ports[conn_rsp->portnum - 1].port_status;
235 xudd->ports[conn_rsp->portnum - 1].port_type = conn_rsp->speed;
236 xudd->ports[conn_rsp->portnum - 1].port_status &= ~((1 << PORT_LOW_SPEED) | (1 << PORT_HIGH_SPEED) | (1 << PORT_CONNECTION));
237 switch (conn_rsp->speed)
238 {
239 case USB_PORT_TYPE_NOT_CONNECTED:
240 xudd->ports[conn_rsp->portnum - 1].port_status &= ~(1 << PORT_ENABLE);
241 break;
242 case USB_PORT_TYPE_LOW_SPEED:
243 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_LOW_SPEED) | (1 << PORT_CONNECTION);
244 break;
245 case USB_PORT_TYPE_FULL_SPEED:
246 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_CONNECTION);
247 break;
248 case USB_PORT_TYPE_HIGH_SPEED:
249 xudd->ports[conn_rsp->portnum - 1].port_status |= (1 << PORT_HIGH_SPEED) | (1 << PORT_CONNECTION);
250 break;
251 }
252 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));
253 if (xudd->ports[conn_rsp->portnum - 1].port_change)
254 port_changed = TRUE;
255 conn_req = RING_GET_REQUEST(&xudd->conn_ring, xudd->conn_ring.req_prod_pvt);
256 conn_req->id = conn_rsp->id;
257 xudd->conn_ring.req_prod_pvt++;
258 }
260 xudd->conn_ring.rsp_cons = cons;
261 if (cons != xudd->conn_ring.req_prod_pvt)
262 {
263 RING_FINAL_CHECK_FOR_RESPONSES(&xudd->conn_ring, more_to_do);
264 }
265 else
266 {
267 xudd->conn_ring.sring->rsp_event = cons + 1;
268 more_to_do = FALSE;
269 }
270 }
271 KeReleaseSpinLockFromDpcLevel(&xudd->conn_ring_lock);
273 if (port_changed) {
274 PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(xudd->root_hub_device);
275 XenUsbHub_ProcessHubInterruptEvent(xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]);
276 }
278 FUNCTION_EXIT();
280 return TRUE;
281 }
283 static BOOLEAN
284 XenUsb_HandleEvent_DIRQL(PVOID context) {
285 PXENUSB_DEVICE_DATA xudd = context;
287 //FUNCTION_ENTER();
288 if (xudd->device_state == DEVICE_STATE_ACTIVE || xudd->device_state == DEVICE_STATE_DISCONNECTING) {
289 KeInsertQueueDpc(&xudd->event_dpc, NULL, NULL);
290 }
291 //FUNCTION_EXIT();
292 return TRUE;
293 }
295 #if 0
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 FUNCTION_MSG("XEN_INIT_TYPE_READ_STRING_BACK - %s = %s\n", setting, value);
311 break;
312 case XEN_INIT_TYPE_READ_STRING_FRONT:
313 FUNCTION_MSG("XEN_INIT_TYPE_READ_STRING_FRONT - %s = %s\n", setting, value);
314 break;
315 case XEN_INIT_TYPE_VECTORS:
316 FUNCTION_MSG("XEN_INIT_TYPE_VECTORS\n");
317 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
318 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC) {
319 FUNCTION_MSG("vectors mismatch (magic = %08x, length = %d)\n",
320 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length);
321 FUNCTION_EXIT();
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 FUNCTION_MSG("XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value));
329 xudd->device_state = (PXENPCI_DEVICE_STATE)value;
330 break;
331 default:
332 FUNCTION_MSG("XEN_INIT_TYPE_%d\n", type);
333 break;
334 }
335 }
336 return STATUS_SUCCESS;
337 }
338 #endif
340 #if 0
341 static NTSTATUS
342 XenUsb_CompleteXenbusInit(PXENUSB_DEVICE_DATA xudd) {
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 switch(type) {
351 case XEN_INIT_TYPE_RING: /* frontend ring */
352 FUNCTION_MSG("XEN_INIT_TYPE_RING - %s = %p\n", setting, value);
353 if (strcmp(setting, "urb-ring-ref") == 0) {
354 xudd->urb_sring = (usbif_urb_sring_t *)value;
355 FRONT_RING_INIT(&xudd->urb_ring, xudd->urb_sring, PAGE_SIZE);
356 }
357 if (strcmp(setting, "conn-ring-ref") == 0) {
358 xudd->conn_sring = (usbif_conn_sring_t *)value;
359 FRONT_RING_INIT(&xudd->conn_ring, xudd->conn_sring, PAGE_SIZE);
360 }
361 break;
362 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel */
363 FUNCTION_MSG("XEN_INIT_TYPE_EVENT_CHANNEL_DPC - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF);
364 if (strcmp(setting, "event-channel") == 0) {
365 xudd->event_channel = PtrToUlong(value);
366 }
367 break;
368 case XEN_INIT_TYPE_READ_STRING_BACK:
369 case XEN_INIT_TYPE_READ_STRING_FRONT:
370 FUNCTION_MSG("XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value);
371 break;
372 default:
373 FUNCTION_MSG("XEN_INIT_TYPE_%d\n", type);
374 break;
375 }
376 }
377 if (xudd->urb_sring == NULL || xudd->conn_sring == NULL || xudd->event_channel == 0) {
378 FUNCTION_MSG("Missing settings\n");
379 FUNCTION_EXIT();
380 return STATUS_BAD_INITIAL_PC;
381 }
383 stack_new(&xudd->req_id_ss, REQ_ID_COUNT);
384 for (i = 0; i < REQ_ID_COUNT; i++) {
385 put_id_on_freelist(xudd->req_id_ss, (uint16_t)i);
386 }
388 return STATUS_SUCCESS;
389 }
390 #endif
392 VOID
393 XenUsb_DeviceCallback(PVOID context, ULONG callback_type, PVOID value) {
394 PXENUSB_DEVICE_DATA xudd = (PXENUSB_DEVICE_DATA)context;
395 ULONG state;
397 FUNCTION_ENTER();
398 switch (callback_type) {
399 case XN_DEVICE_CALLBACK_BACKEND_STATE:
400 state = (ULONG)(ULONG_PTR)value;
401 if (state == xudd->backend_state) {
402 FUNCTION_MSG("same state %d\n", state);
403 FUNCTION_EXIT();
404 }
405 FUNCTION_MSG("XenBusState = %d -> %d\n", xudd->backend_state, state);
406 xudd->backend_state = state;
407 KeSetEvent(&xudd->backend_event, 0, FALSE);
408 break;
409 case XN_DEVICE_CALLBACK_SUSPEND:
410 FUNCTION_MSG("XN_DEVICE_CALLBACK_SUSPEND");
411 XenUsb_Disconnect(xudd, TRUE);
412 break;
413 case XN_DEVICE_CALLBACK_RESUME:
414 FUNCTION_MSG("XN_DEVICE_CALLBACK_RESUME");
415 xudd->device_state = DEVICE_STATE_INITIALISING;
416 XenUsb_Connect(xudd, TRUE);
417 // some sort of notify to kick things off?
418 break;
419 }
420 FUNCTION_EXIT();
421 }
423 NTSTATUS
424 XenUsb_Connect(PVOID context, BOOLEAN suspend) {
425 NTSTATUS status;
426 PXENUSB_DEVICE_DATA xudd = context;
427 PFN_NUMBER pfn;
428 int i;
430 if (!suspend) {
431 xudd->handle = XnOpenDevice(xudd->pdo, XenUsb_DeviceCallback, xudd);
432 }
433 if (!xudd->handle) {
434 FUNCTION_MSG("Cannot open Xen device\n");
435 return STATUS_UNSUCCESSFUL;
436 }
438 if (xudd->device_state != DEVICE_STATE_INACTIVE) {
439 for (i = 0; i <= 5 && xudd->backend_state != XenbusStateInitialising && xudd->backend_state != XenbusStateInitWait && xudd->backend_state != XenbusStateInitialised; i++) {
440 FUNCTION_MSG("Waiting for XenbusStateInitXxx\n");
441 if (xudd->backend_state == XenbusStateClosed) {
442 status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "state", XenbusStateInitialising);
443 }
444 KeWaitForSingleObject(&xudd->backend_event, Executive, KernelMode, FALSE, NULL);
445 }
446 if (xudd->backend_state != XenbusStateInitialising && xudd->backend_state != XenbusStateInitWait && xudd->backend_state != XenbusStateInitialised) {
447 FUNCTION_MSG("Backend state timeout\n");
448 return STATUS_UNSUCCESSFUL;
449 }
450 if (!NT_SUCCESS(status = XnBindEvent(xudd->handle, &xudd->event_channel, XenUsb_HandleEvent_DIRQL, xudd))) {
451 FUNCTION_MSG("Cannot allocate event channel\n");
452 return STATUS_UNSUCCESSFUL;
453 }
454 FUNCTION_MSG("event_channel = %d\n", xudd->event_channel);
455 status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "event-channel", xudd->event_channel);
456 xudd->urb_sring = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENUSB_POOL_TAG);
457 if (!xudd->urb_sring) {
458 FUNCTION_MSG("Cannot allocate urb_sring\n");
459 return STATUS_UNSUCCESSFUL;
460 }
461 SHARED_RING_INIT(xudd->urb_sring);
462 FRONT_RING_INIT(&xudd->urb_ring, xudd->urb_sring, PAGE_SIZE);
463 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(xudd->urb_sring).QuadPart >> PAGE_SHIFT);
464 FUNCTION_MSG("usb sring pfn = %d\n", (ULONG)pfn);
465 xudd->urb_sring_gref = XnGrantAccess(xudd->handle, (ULONG)pfn, FALSE, INVALID_GRANT_REF, XENUSB_POOL_TAG);
466 FUNCTION_MSG("usb sring_gref = %d\n", xudd->urb_sring_gref);
467 status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "urb-ring-ref", xudd->urb_sring_gref);
468 xudd->conn_sring = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENUSB_POOL_TAG);
469 if (!xudd->conn_sring) {
470 FUNCTION_MSG("Cannot allocate conn_sring\n");
471 return STATUS_UNSUCCESSFUL;
472 }
473 SHARED_RING_INIT(xudd->conn_sring);
474 FRONT_RING_INIT(&xudd->conn_ring, xudd->conn_sring, PAGE_SIZE);
475 pfn = (PFN_NUMBER)(MmGetPhysicalAddress(xudd->conn_sring).QuadPart >> PAGE_SHIFT);
476 FUNCTION_MSG("conn sring pfn = %d\n", (ULONG)pfn);
477 xudd->conn_sring_gref = XnGrantAccess(xudd->handle, (ULONG)pfn, FALSE, INVALID_GRANT_REF, XENUSB_POOL_TAG);
478 FUNCTION_MSG("conn sring_gref = %d\n", xudd->conn_sring_gref);
479 status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "conn-ring-ref", xudd->conn_sring_gref);
481 /* fill conn ring with requests */
482 for (i = 0; i < USB_CONN_RING_SIZE; i++) {
483 usbif_conn_request_t *req = RING_GET_REQUEST(&xudd->conn_ring, i);
484 req->id = (uint16_t)i;
485 }
486 xudd->conn_ring.req_prod_pvt = i;
488 status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "state", XenbusStateConnected);
489 for (i = 0; i <= 5 && xudd->backend_state != XenbusStateConnected; i++) {
490 FUNCTION_MSG("Waiting for XenbusStateConnected\n");
491 KeWaitForSingleObject(&xudd->backend_event, Executive, KernelMode, FALSE, NULL);
492 }
493 if (xudd->backend_state != XenbusStateConnected) {
494 FUNCTION_MSG("Backend state timeout\n");
495 return STATUS_UNSUCCESSFUL;
496 }
497 xudd->device_state = DEVICE_STATE_ACTIVE;
498 }
500 return STATUS_SUCCESS;
501 }
503 NTSTATUS
504 XenUsb_Disconnect(PVOID context, BOOLEAN suspend) {
505 PXENUSB_DEVICE_DATA xudd = (PXENUSB_DEVICE_DATA)context;
506 //PFN_NUMBER pfn;
507 NTSTATUS status;
509 if (xudd->device_state != DEVICE_STATE_ACTIVE && xudd->device_state != DEVICE_STATE_INACTIVE) {
510 FUNCTION_MSG("state not DEVICE_STATE_(IN)ACTIVE, is %d instead\n", xudd->device_state);
511 FUNCTION_EXIT();
512 return STATUS_SUCCESS;
513 }
514 if (xudd->device_state != DEVICE_STATE_INACTIVE) {
515 xudd->device_state = DEVICE_STATE_DISCONNECTING;
516 status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosing);
517 while (xudd->backend_state != XenbusStateClosing && xudd->backend_state != XenbusStateClosed) {
518 FUNCTION_MSG("Waiting for XenbusStateClosing/Closed\n");
519 KeWaitForSingleObject(&xudd->backend_event, Executive, KernelMode, FALSE, NULL);
520 }
521 status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosed);
522 while (xudd->backend_state != XenbusStateClosed) {
523 FUNCTION_MSG("Waiting for XenbusStateClosed\n");
524 KeWaitForSingleObject(&xudd->backend_event, Executive, KernelMode, FALSE, NULL);
525 }
526 XnUnbindEvent(xudd->handle, xudd->event_channel);
528 #if NTDDI_VERSION < WINXP
529 KeFlushQueuedDpcs();
530 #endif
531 XnEndAccess(xudd->handle, xudd->conn_sring_gref, FALSE, XENUSB_POOL_TAG);
532 ExFreePoolWithTag(xudd->conn_sring, XENUSB_POOL_TAG);
533 XnEndAccess(xudd->handle, xudd->urb_sring_gref, FALSE, XENUSB_POOL_TAG);
534 ExFreePoolWithTag(xudd->urb_sring, XENUSB_POOL_TAG);
535 }
536 if (!suspend) {
537 XnCloseDevice(xudd->handle);
538 }
539 xudd->device_state = DEVICE_STATE_DISCONNECTED;
540 return STATUS_SUCCESS;
541 }
543 NTSTATUS
544 XenUsb_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state) {
545 NTSTATUS status = STATUS_SUCCESS;
546 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
548 UNREFERENCED_PARAMETER(device);
550 FUNCTION_ENTER();
552 switch (previous_state) {
553 case WdfPowerDeviceD0:
554 FUNCTION_MSG("WdfPowerDeviceD1\n");
555 break;
556 case WdfPowerDeviceD1:
557 FUNCTION_MSG("WdfPowerDeviceD1\n");
558 break;
559 case WdfPowerDeviceD2:
560 FUNCTION_MSG("WdfPowerDeviceD2\n");
561 break;
562 case WdfPowerDeviceD3:
563 FUNCTION_MSG("WdfPowerDeviceD3\n");
564 break;
565 case WdfPowerDeviceD3Final:
566 FUNCTION_MSG("WdfPowerDeviceD3Final\n");
567 break;
568 case WdfPowerDevicePrepareForHibernation:
569 FUNCTION_MSG("WdfPowerDevicePrepareForHibernation\n");
570 break;
571 default:
572 FUNCTION_MSG("Unknown WdfPowerDevice state %d\n", previous_state);
573 break;
574 }
576 XenUsb_Connect(xudd, FALSE);
578 FUNCTION_EXIT();
580 return status;
581 }
583 NTSTATUS
584 XenUsb_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state) {
585 NTSTATUS status = STATUS_SUCCESS;
586 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
588 FUNCTION_ENTER();
590 UNREFERENCED_PARAMETER(device);
592 switch (target_state) {
593 case WdfPowerDeviceD0:
594 FUNCTION_MSG("WdfPowerDeviceD1\n");
595 break;
596 case WdfPowerDeviceD1:
597 FUNCTION_MSG("WdfPowerDeviceD1\n");
598 break;
599 case WdfPowerDeviceD2:
600 FUNCTION_MSG("WdfPowerDeviceD2\n");
601 break;
602 case WdfPowerDeviceD3:
603 FUNCTION_MSG("WdfPowerDeviceD3\n");
604 break;
605 case WdfPowerDeviceD3Final:
606 FUNCTION_MSG("WdfPowerDeviceD3Final\n");
607 break;
608 case WdfPowerDevicePrepareForHibernation:
609 FUNCTION_MSG("WdfPowerDevicePrepareForHibernation\n");
610 break;
611 default:
612 FUNCTION_MSG("Unknown WdfPowerDevice state %d\n", target_state);
613 break;
614 }
616 XenUsb_Disconnect(xudd, FALSE);
618 FUNCTION_EXIT();
620 return status;
621 }
623 VOID
624 XenUsb_EvtChildListScanForChildren(WDFCHILDLIST child_list) {
625 NTSTATUS status;
626 PXENUSB_DEVICE_DATA xudd = GetXudd(WdfChildListGetDevice(child_list));
627 XENUSB_PDO_IDENTIFICATION_DESCRIPTION child_description;
628 CHAR path[128];
629 PCHAR value;
630 ULONG i;
632 FUNCTION_ENTER();
634 WdfChildListBeginScan(child_list);
636 // hold the queue on each device and set each device to a pending state
637 // read backend/num_ports
638 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/num-ports", xudd->vectors.backend_path);
639 status = XnReadString(xudd->handle, XBT_NIL, path, &value);
640 if (status != STATUS_SUCCESS) {
641 WdfChildListEndScan(child_list);
642 FUNCTION_MSG("Failed to read num-ports\n");
643 return;
644 }
645 xudd->num_ports = (ULONG)parse_numeric_string(value);
646 XnFreeMem(xudd->handle, value);
647 FUNCTION_MSG("num-ports = %d\n", xudd->num_ports);
649 for (i = 0; i < 8; i++) {
650 xudd->ports[i].port_number = i + 1;
651 xudd->ports[i].port_type = USB_PORT_TYPE_NOT_CONNECTED;
652 xudd->ports[i].port_status = 0; //1 << PORT_ENABLE;
653 xudd->ports[i].port_change = 0x0000;
654 }
656 /* only a single root hub is enumerated */
657 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description));
659 child_description.device_number = 0; //TODO: get the proper index from parent
661 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(child_list, &child_description.header, NULL);
662 if (!NT_SUCCESS(status)) {
663 FUNCTION_MSG("WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status 0x%08x\n", status);
664 }
666 WdfChildListEndScan(child_list);
668 FUNCTION_EXIT();
669 }
671 static VOID
672 XenUsb_EvtIoDeviceControl(
673 WDFQUEUE queue,
674 WDFREQUEST request,
675 size_t output_buffer_length,
676 size_t input_buffer_length,
677 ULONG io_control_code)
678 {
679 NTSTATUS status;
680 WDFDEVICE device = WdfIoQueueGetDevice(queue);
681 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
683 UNREFERENCED_PARAMETER(queue);
684 UNREFERENCED_PARAMETER(input_buffer_length);
685 UNREFERENCED_PARAMETER(output_buffer_length);
687 FUNCTION_ENTER();
689 status = STATUS_BAD_INITIAL_PC;
691 // these are in api\usbioctl.h
692 switch(io_control_code)
693 {
694 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
695 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
696 break;
697 case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
698 FUNCTION_MSG("IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
699 break;
700 case IOCTL_USB_GET_NODE_CONNECTION_NAME:
701 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
702 break;
703 case IOCTL_USB_DIAG_IGNORE_HUBS_ON:
704 FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_ON\n");
705 break;
706 case IOCTL_USB_DIAG_IGNORE_HUBS_OFF:
707 FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_OFF\n");
708 break;
709 case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
710 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
711 break;
712 case IOCTL_USB_GET_HUB_CAPABILITIES:
713 FUNCTION_MSG("IOCTL_USB_GET_HUB_CAPABILITIES\n");
714 break;
715 case IOCTL_USB_HUB_CYCLE_PORT:
716 FUNCTION_MSG("IOCTL_USB_HUB_CYCLE_PORT\n");
717 break;
718 case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES:
719 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n");
720 break;
721 case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX:
722 FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n");
723 break;
724 case IOCTL_USB_GET_ROOT_HUB_NAME:
725 {
726 PUSB_HCD_DRIVERKEY_NAME uhdn;
727 size_t length;
728 ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
730 FUNCTION_MSG("IOCTL_USB_GET_ROOT_HUB_NAME\n");
731 FUNCTION_MSG(" output_buffer_length = %d\n", output_buffer_length);
733 if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
734 status = STATUS_BUFFER_TOO_SMALL;
735 } else {
736 status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
737 if (NT_SUCCESS(status)) {
738 WDFSTRING symbolic_link_wdfstring;
739 UNICODE_STRING symbolic_link;
741 uhdn->DriverKeyName[0] = 0;
742 status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolic_link_wdfstring);
743 if (NT_SUCCESS(status)) {
744 status = WdfDeviceRetrieveDeviceInterfaceString(xudd->root_hub_device, &GUID_DEVINTERFACE_USB_HUB, NULL, symbolic_link_wdfstring);
745 if (NT_SUCCESS(status)) {
746 WdfStringGetUnicodeString(symbolic_link_wdfstring, &symbolic_link);
747 /* remove leading \??\ from name */
748 symbolic_link.Buffer += 4;
749 symbolic_link.Length -= 4 * sizeof(WCHAR);
750 required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + symbolic_link.Length + sizeof(WCHAR);
751 FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
752 FUNCTION_MSG("required_length = %d\n", required_length);
753 if (output_buffer_length >= required_length) {
754 uhdn->ActualLength = required_length;
755 memcpy(uhdn->DriverKeyName, symbolic_link.Buffer, symbolic_link.Length);
756 uhdn->DriverKeyName[symbolic_link.Length / 2] = 0;
757 WdfRequestSetInformation(request, required_length);
758 } else {
759 uhdn->ActualLength = required_length;
760 uhdn->DriverKeyName[0] = 0;
761 status = STATUS_SUCCESS;
762 WdfRequestSetInformation(request, output_buffer_length);
763 }
764 } else {
765 FUNCTION_MSG("WdfStringCreate = %08x\n", status);
766 }
767 } else {
768 FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString = %08x\n", status);
769 status = STATUS_INVALID_PARAMETER;
770 }
771 } else {
772 FUNCTION_MSG("WdfRequestRetrieveOutputBuffer = %08x\n", status);
773 }
774 FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength);
775 FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName);
776 }
777 break;
778 }
779 case IOCTL_GET_HCD_DRIVERKEY_NAME:
780 {
781 PUSB_HCD_DRIVERKEY_NAME uhdn;
782 size_t length;
783 ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
784 ULONG key_length;
786 FUNCTION_MSG("IOCTL_GET_HCD_DRIVERKEY_NAME\n");
787 FUNCTION_MSG(" output_buffer_length = %d\n", output_buffer_length);
789 if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
790 FUNCTION_MSG("Buffer too small (%d < %d)\n", output_buffer_length, sizeof(USB_HCD_DRIVERKEY_NAME));
791 status = STATUS_BUFFER_TOO_SMALL;
792 break;
793 }
794 status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
795 if (!NT_SUCCESS(status)) {
796 FUNCTION_MSG("WdfRequestRetrieveOutputBuffer = %08x\n", status);
797 break;
798 }
799 status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, 0, NULL, &key_length);
800 if (!NT_SUCCESS(status)) {
801 FUNCTION_MSG("WdfDeviceQueryProperty = %08x\n", status);
802 break;
803 }
804 FUNCTION_MSG(" key_length = %d\n", key_length);
805 required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + key_length + 2;
806 uhdn->ActualLength = required_length;
807 FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
808 FUNCTION_MSG("required_length = %d\n", required_length);
809 if (output_buffer_length >= required_length)
810 {
811 status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName,
812 required_length - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName), uhdn->DriverKeyName,
813 &key_length);
814 WdfRequestSetInformation(request, required_length);
815 }
816 else
817 {
818 uhdn->DriverKeyName[0] = 0;
819 status = STATUS_SUCCESS;
820 WdfRequestSetInformation(request, output_buffer_length);
821 }
822 FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength);
823 FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName);
824 break;
825 }
826 #if 0
827 case IOCTL_USB_RESET_HUB:
828 FUNCTION_MSG("IOCTL_USB_RESET_HUB\n");
829 break;
830 #endif
831 default:
832 FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code);
833 break;
834 }
835 FUNCTION_MSG("Calling WdfRequestComplete with status = %08x\n", status);
836 WdfRequestComplete(request, status);
838 FUNCTION_EXIT();
839 }
841 VOID
842 XenUsb_EvtRequestCancelPvUrb(WDFREQUEST request) {
843 WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request));
844 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
845 WDF_REQUEST_PARAMETERS wrp;
846 partial_pvurb_t *partial_pvurb;
847 pvurb_t *pvurb;
848 KIRQL old_irql;
850 FUNCTION_ENTER();
851 FUNCTION_MSG("cancelling request %p\n", request);
853 WDF_REQUEST_PARAMETERS_INIT(&wrp);
854 KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);
856 WdfRequestGetParameters(request, &wrp);
857 pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
858 FUNCTION_MSG("pvurb = %p\n", pvurb);
859 ASSERT(pvurb);
861 partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_queue.Flink;
862 while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_queue) {
863 partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
864 ASSERT(!partial_pvurb->on_ring);
865 FUNCTION_MSG("partial_pvurb = %p is not yet on ring\n", partial_pvurb);
866 RemoveEntryList(&partial_pvurb->entry);
867 ExFreePoolWithTag(partial_pvurb, XENUSB_POOL_TAG);
868 pvurb->ref--;
869 partial_pvurb = next_partial_pvurb;
870 }
871 partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_ring.Flink;
872 while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_ring) {
873 partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
874 partial_pvurb_t *partial_pvurb_cancel;
875 FUNCTION_MSG("partial_pvurb = %p is on ring\n", partial_pvurb);
876 ASSERT(partial_pvurb->on_ring);
877 partial_pvurb_cancel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb_cancel), XENUSB_POOL_TAG); /* todo - use lookaside */
878 ASSERT(partial_pvurb_cancel); /* what would we do if this failed? */
879 partial_pvurb_cancel->req = partial_pvurb->req;
880 partial_pvurb_cancel->req.pipe = usbif_setunlink_pipe(partial_pvurb_cancel->req.pipe);
881 partial_pvurb_cancel->req.u.unlink.unlink_id = partial_pvurb->req.id;
882 partial_pvurb_cancel->pvurb = pvurb;
883 partial_pvurb_cancel->mdl = NULL;
884 partial_pvurb_cancel->other_partial_pvurb = partial_pvurb;
885 partial_pvurb->other_partial_pvurb = partial_pvurb_cancel;
886 partial_pvurb_cancel->on_ring = FALSE;
887 pvurb->ref++;
888 InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb_cancel->entry);
889 partial_pvurb = next_partial_pvurb;
890 }
891 if (pvurb->ref) {
892 PutRequestsOnRing(xudd);
893 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
894 } else {
895 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
896 WdfRequestComplete(request, STATUS_CANCELLED);
897 }
898 FUNCTION_EXIT();
899 }
901 static VOID
902 XenUsb_EvtIoInternalDeviceControl_PVURB(
903 WDFQUEUE queue,
904 WDFREQUEST request,
905 size_t output_buffer_length,
906 size_t input_buffer_length,
907 ULONG io_control_code)
908 {
909 NTSTATUS status;
910 WDFDEVICE device = WdfIoQueueGetDevice(queue);
911 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
912 WDF_REQUEST_PARAMETERS wrp;
913 pvurb_t *pvurb;
914 partial_pvurb_t *partial_pvurb;
915 KIRQL old_irql;
917 UNREFERENCED_PARAMETER(input_buffer_length);
918 UNREFERENCED_PARAMETER(output_buffer_length);
919 UNREFERENCED_PARAMETER(io_control_code);
921 FUNCTION_ENTER();
923 ASSERT(io_control_code == IOCTL_INTERNAL_PVUSB_SUBMIT_URB);
925 WDF_REQUEST_PARAMETERS_INIT(&wrp);
926 WdfRequestGetParameters(request, &wrp);
927 pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
928 ASSERT(pvurb);
929 RtlZeroMemory(&pvurb->rsp, sizeof(pvurb->rsp));
930 pvurb->status = STATUS_SUCCESS;
931 pvurb->request = request;
932 pvurb->ref = 1;
933 pvurb->total_length = 0;
934 partial_pvurb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb), XENUSB_POOL_TAG); /* todo - use lookaside */
935 if (!partial_pvurb) {
936 WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
937 FUNCTION_EXIT();
938 return;
939 }
940 KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);
941 status = WdfRequestMarkCancelableEx(request, XenUsb_EvtRequestCancelPvUrb);
942 if (!NT_SUCCESS(status)) {
943 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
944 FUNCTION_MSG("WdfRequestMarkCancelableEx returned %08x\n", status);
945 WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
946 FUNCTION_EXIT();
947 return;
948 }
950 partial_pvurb->req = pvurb->req;
951 partial_pvurb->mdl = pvurb->mdl; /* 1:1 right now, but may need to split up large pvurb into smaller partial_pvurb's */
952 partial_pvurb->pvurb = pvurb;
953 partial_pvurb->other_partial_pvurb = NULL;
954 partial_pvurb->on_ring = FALSE;
955 if (!partial_pvurb->mdl) {
956 partial_pvurb->req.nr_buffer_segs = 0;
957 partial_pvurb->req.buffer_length = 0;
958 } else {
959 ULONG remaining = MmGetMdlByteCount(partial_pvurb->mdl);
960 USHORT offset = (USHORT)MmGetMdlByteOffset(partial_pvurb->mdl);
961 int i;
962 partial_pvurb->req.buffer_length = (USHORT)MmGetMdlByteCount(partial_pvurb->mdl);
963 partial_pvurb->req.nr_buffer_segs = (USHORT)ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(partial_pvurb->mdl), MmGetMdlByteCount(partial_pvurb->mdl));
964 for (i = 0; i < partial_pvurb->req.nr_buffer_segs; i++) {
965 partial_pvurb->req.seg[i].gref = XnGrantAccess(xudd->handle, (ULONG)MmGetMdlPfnArray(partial_pvurb->mdl)[i], FALSE, INVALID_GRANT_REF, (ULONG)'XUSB');
966 partial_pvurb->req.seg[i].offset = (USHORT)offset;
967 partial_pvurb->req.seg[i].length = (USHORT)min((USHORT)remaining, (USHORT)PAGE_SIZE - offset);
968 offset = 0;
969 remaining -= partial_pvurb->req.seg[i].length;
970 FUNCTION_MSG("seg = %d\n", i);
971 FUNCTION_MSG(" gref = %d\n", partial_pvurb->req.seg[i].gref);
972 FUNCTION_MSG(" offset = %d\n", partial_pvurb->req.seg[i].offset);
973 FUNCTION_MSG(" length = %d\n", partial_pvurb->req.seg[i].length);
974 }
975 FUNCTION_MSG("buffer_length = %d\n", partial_pvurb->req.buffer_length);
976 FUNCTION_MSG("nr_buffer_segs = %d\n", partial_pvurb->req.nr_buffer_segs);
977 }
978 InsertTailList(&xudd->partial_pvurb_queue, &partial_pvurb->entry);
979 PutRequestsOnRing(xudd);
980 KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
982 FUNCTION_EXIT();
983 }
985 static VOID
986 XenUsb_EvtIoInternalDeviceControl(
987 WDFQUEUE queue,
988 WDFREQUEST request,
989 size_t output_buffer_length,
990 size_t input_buffer_length,
991 ULONG io_control_code)
992 {
993 WDFDEVICE device = WdfIoQueueGetDevice(queue);
994 PXENUSB_DEVICE_DATA xudd = GetXudd(device);
995 //WDF_REQUEST_PARAMETERS wrp;
996 //pvusb_urb_t *urb;
998 UNREFERENCED_PARAMETER(input_buffer_length);
999 UNREFERENCED_PARAMETER(output_buffer_length);
1001 FUNCTION_ENTER();
1003 //WDF_REQUEST_PARAMETERS_INIT(&wrp);
1004 //WdfRequestGetParameters(request, &wrp);
1006 switch(io_control_code)
1008 case IOCTL_INTERNAL_PVUSB_SUBMIT_URB:
1009 FUNCTION_MSG("IOCTL_INTERNAL_PVUSB_SUBMIT_URB\n");
1010 //urb = (pvusb_urb_t *)wrp.Parameters.Others.Arg1;
1011 //FUNCTION_MSG("urb = %p\n", urb);
1012 WdfRequestForwardToIoQueue(request, xudd->pvurb_queue);
1013 break;
1014 default:
1015 FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code);
1016 WdfRequestComplete(request, WdfRequestGetStatus(request));
1017 break;
1019 FUNCTION_EXIT();
1022 static VOID
1023 XenUsb_EvtIoDefault(
1024 WDFQUEUE queue,
1025 WDFREQUEST request)
1027 NTSTATUS status;
1028 WDF_REQUEST_PARAMETERS parameters;
1030 FUNCTION_ENTER();
1032 UNREFERENCED_PARAMETER(queue);
1034 status = STATUS_BAD_INITIAL_PC;
1036 WDF_REQUEST_PARAMETERS_INIT(&parameters);
1037 WdfRequestGetParameters(request, &parameters);
1039 switch (parameters.Type)
1041 case WdfRequestTypeCreate:
1042 FUNCTION_MSG("WdfRequestTypeCreate\n");
1043 break;
1044 case WdfRequestTypeClose:
1045 FUNCTION_MSG("WdfRequestTypeClose\n");
1046 break;
1047 case WdfRequestTypeRead:
1048 FUNCTION_MSG("WdfRequestTypeRead\n");
1049 break;
1050 case WdfRequestTypeWrite:
1051 FUNCTION_MSG("WdfRequestTypeWrite\n");
1052 break;
1053 case WdfRequestTypeDeviceControl:
1054 FUNCTION_MSG("WdfRequestTypeDeviceControl\n");
1055 break;
1056 case WdfRequestTypeDeviceControlInternal:
1057 FUNCTION_MSG("WdfRequestTypeDeviceControlInternal\n");
1058 break;
1059 default:
1060 FUNCTION_MSG("Unknown type %x\n", parameters.Type);
1061 break;
1063 WdfRequestComplete(request, status);
1065 FUNCTION_EXIT();
1068 NTSTATUS
1069 XenUsb_EvtDriverDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
1071 NTSTATUS status;
1072 WDF_CHILD_LIST_CONFIG child_list_config;
1073 WDFDEVICE device;
1074 PXENUSB_DEVICE_DATA xudd;
1075 //UNICODE_STRING reference;
1076 WDF_OBJECT_ATTRIBUTES device_attributes;
1077 PNP_BUS_INFORMATION pbi;
1078 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
1079 WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
1080 WDF_IO_QUEUE_CONFIG queue_config;
1081 UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE };
1082 DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName");
1083 WDFSTRING symbolicname_value_wdfstring;
1084 WDFKEY device_key;
1085 UNICODE_STRING symbolicname_value;
1087 UNREFERENCED_PARAMETER(driver);
1089 FUNCTION_ENTER();
1091 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
1092 pnp_power_callbacks.EvtDeviceD0Entry = XenUsb_EvtDeviceD0Entry;
1093 pnp_power_callbacks.EvtDeviceD0Exit = XenUsb_EvtDeviceD0Exit;
1095 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
1097 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE,
1098 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
1099 if (!NT_SUCCESS(status))
1101 return status;
1104 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
1105 WdfDeviceInitSetExclusive(device_init, FALSE);
1107 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENUSB_PDO_IDENTIFICATION_DESCRIPTION), XenUsb_EvtChildListCreateDevice);
1108 child_list_config.EvtChildListScanForChildren = XenUsb_EvtChildListScanForChildren;
1109 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
1111 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
1113 WdfDeviceInitSetPowerNotPageable(device_init);
1115 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENUSB_DEVICE_DATA);
1116 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
1117 if (!NT_SUCCESS(status))
1119 FUNCTION_MSG("Error creating device %08x\n", status);
1120 return status;
1123 xudd = GetXudd(device);
1124 xudd->pdo = WdfDeviceWdmGetPhysicalDevice(device);
1125 xudd->child_list = WdfFdoGetDefaultChildList(device);
1126 KeInitializeEvent(&xudd->backend_event, SynchronizationEvent, FALSE);
1127 InitializeListHead(&xudd->partial_pvurb_queue);
1128 InitializeListHead(&xudd->partial_pvurb_ring);
1129 KeInitializeDpc(&xudd->event_dpc, XenUsb_HandleEventDpc, xudd);
1131 KeInitializeSpinLock(&xudd->urb_ring_lock);
1133 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
1134 queue_config.PowerManaged = FALSE; /* ? */
1135 queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
1136 queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl;
1137 queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
1138 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->io_queue);
1139 if (!NT_SUCCESS(status)) {
1140 FUNCTION_MSG("Error creating io_queue 0x%x\n", status);
1141 return status;
1144 WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel);
1145 queue_config.PowerManaged = FALSE; /* ? */
1146 //queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
1147 queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_PVURB;
1148 //queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
1149 queue_config.Settings.Parallel.NumberOfPresentedRequests = USB_URB_RING_SIZE; /* the queue controls if the ring is full */
1150 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->pvurb_queue);
1151 if (!NT_SUCCESS(status)) {
1152 FUNCTION_MSG("Error creating urb_queue 0x%x\n", status);
1153 return status;
1156 WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
1157 power_capabilities.DeviceD1 = WdfTrue;
1158 power_capabilities.WakeFromD1 = WdfTrue;
1159 power_capabilities.DeviceWake = PowerDeviceD1;
1160 power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0;
1161 power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
1162 power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
1163 power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
1164 power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
1165 power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
1166 WdfDeviceSetPowerCapabilities(device, &power_capabilities);
1168 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
1169 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
1170 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
1172 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
1173 pbi.LegacyBusType = PNPBus;
1174 pbi.BusNumber = 0;
1175 WdfDeviceSetBusInformationForChildren(device, &pbi);
1177 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL);
1178 if (!NT_SUCCESS(status)) {
1179 FUNCTION_MSG("WdfDeviceCreateDeviceInterface returned %08x\n");
1180 return status;
1183 /* USB likes to have a registry key with the symbolic link name in it */
1184 status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring);
1185 if (!NT_SUCCESS(status)) {
1186 FUNCTION_MSG("WdfStringCreate returned %08x\n");
1187 return status;
1189 status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, symbolicname_value_wdfstring);
1190 if (!NT_SUCCESS(status)) {
1191 FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString returned %08x\n");
1192 return status;
1194 WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value);
1195 status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key);
1196 if (!NT_SUCCESS(status)) {
1197 FUNCTION_MSG("WdfDeviceOpenRegistryKey returned %08x\n");
1198 return status;
1200 WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value);
1202 FUNCTION_EXIT();
1203 return status;