win-pvdrivers

view xenusb/xenusb_fdo.c @ 1058:8b6500e0ebfc

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