win-pvdrivers

annotate xenusb/xenusb.h @ 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 329b9b9d47ec
children
rev   line source
james@655 1 /*
james@655 2 PV Drivers for Windows Xen HVM Domains
james@655 3 Copyright (C) 2007 James Harper
james@655 4
james@655 5 This program is free software; you can redistribute it and/or
james@655 6 modify it under the terms of the GNU General Public License
james@655 7 as published by the Free Software Foundation; either version 2
james@655 8 of the License, or (at your option) any later version.
james@655 9
james@655 10 This program is distributed in the hope that it will be useful,
james@655 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@655 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@655 13 GNU General Public License for more details.
james@655 14
james@655 15 You should have received a copy of the GNU General Public License
james@655 16 along with this program; if not, write to the Free Software
james@655 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@655 18 */
james@655 19
james@655 20 #pragma warning(disable: 4127)
james@655 21
james@655 22 #pragma warning(disable : 4200) // zero-sized array
james@655 23
james@655 24 #if !defined(_XENUSB_H_)
james@655 25 #define _XENUSB_H_
james@655 26
james@655 27 #define __attribute__(arg) /* empty */
james@969 28
james@969 29 #define ECONNRESET 104
james@969 30 #define ESHUTDOWN 108
james@969 31 #define EINPROGRESS 115
james@969 32 #define EISCONN 127
james@655 33
james@655 34 #include <ntifs.h>
james@655 35 #include <ntddk.h>
james@655 36
james@655 37 #define DDKAPI
james@655 38 //#include <wdm.h>
james@655 39 #include <wdf.h>
james@655 40 #include <initguid.h>
james@655 41 #include <wdmguid.h>
james@655 42 #include <errno.h>
james@655 43 #define NTSTRSAFE_LIB
james@655 44 #include <ntstrsafe.h>
james@973 45 #include <liblfds.h>
james@655 46
james@655 47 #define __DRIVER_NAME "XenUSB"
james@655 48
james@655 49 #include <xen_windows.h>
james@655 50 #include <io/ring.h>
james@655 51 #include <io/usbif.h>
james@803 52 #include <io/xenbus.h>
james@655 53 #include <usb.h>
james@655 54 #include <usbioctl.h>
james@655 55 #include <usbdlib.h>
james@655 56 #include <hubbusif.h>
james@655 57 #include <usbbusif.h>
james@655 58
james@655 59 #define C_HUB_LOCAL_POWER 0
james@655 60 #define C_HUB_OVER_CURRENT 1
james@655 61 #define PORT_CONNECTION 0
james@655 62 #define PORT_ENABLE 1
james@655 63 #define PORT_SUSPEND 2
james@655 64 #define PORT_OVER_CURRENT 3
james@655 65 #define PORT_RESET 4
james@655 66 #define PORT_POWER 8
james@655 67 #define PORT_LOW_SPEED 9
james@930 68 #define PORT_HIGH_SPEED 10
james@655 69 #define C_PORT_CONNECTION 16
james@655 70 #define C_PORT_ENABLE 17
james@655 71 #define C_PORT_SUSPEND 18
james@655 72 #define C_PORT_OVER_CURRENT 19
james@655 73 #define C_PORT_RESET 20
james@655 74 #define PORT_TEST 21
james@655 75 #define PORT_INDICATOR 22
james@655 76
james@655 77 #define XENUSB_POOL_TAG (ULONG)'XenU'
james@655 78
james@655 79 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
james@655 80
james@655 81 #define CHILD_STATE_EMPTY 0
james@655 82 #define CHILD_STATE_DELETED 1
james@655 83 #define CHILD_STATE_ADDED 2
james@655 84
james@655 85 #define LINUX_PIPE_DIRECTION_OUT 0x00000000
james@655 86 #define LINUX_PIPE_DIRECTION_IN 0x00000080
james@655 87
james@655 88 /* these are linux definitions - different to usb standard */
james@655 89 #define LINUX_PIPE_TYPE_ISOC 0x00000000
james@655 90 #define LINUX_PIPE_TYPE_INTR 0x40000000
james@655 91 #define LINUX_PIPE_TYPE_CTRL 0x80000000
james@655 92 #define LINUX_PIPE_TYPE_BULK 0xC0000000
james@655 93
james@655 94 /*
james@655 95 * urb->transfer_flags:
james@655 96 */
james@655 97 #define LINUX_URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
james@655 98 #define LINUX_URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame ignored */
james@655 99 #define LINUX_URB_NO_TRANSFER_DMA_MAP 0x0004 /* urb->transfer_dma valid on submit */
james@655 100 #define LINUX_URB_NO_SETUP_DMA_MAP 0x0008 /* urb->setup_dma valid on submit */
james@655 101 #define LINUX_URB_NO_FSBR 0x0020 /* UHCI-specific */
james@655 102 #define LINUX_URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
james@655 103 #define LINUX_URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
james@655 104
james@973 105 struct _pvurb;
james@973 106 struct _partial_pvurb;
james@973 107 typedef struct _pvurb pvurb_t;
james@973 108 typedef struct _partial_pvurb partial_pvurb_t;
james@969 109
james@969 110 /* needs to be at least USB_URB_RING_SIZE number of requests available */
james@980 111 #define MAX_REQ_ID_COUNT 64
james@980 112 #define REQ_ID_COUNT min(MAX_REQ_ID_COUNT, USB_URB_RING_SIZE)
james@969 113
james@969 114 /*
james@969 115 for IOCTL_PVUSB_SUBMIT_URB, the pvusb_urb_t struct is passed as Parameters.Others.Arg1
james@969 116 req must have pipe, transfer_flags, buffer_length, and u fields filled in
james@969 117 */
james@969 118
james@969 119 #define IOCTL_INTERNAL_PVUSB_SUBMIT_URB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
james@969 120
james@973 121 struct _partial_pvurb {
james@973 122 LIST_ENTRY entry;
james@973 123 pvurb_t *pvurb;
james@973 124 partial_pvurb_t *other_partial_pvurb; /* link to the cancelled or cancelling partial_pvurb */
james@670 125 usbif_urb_request_t req;
james@670 126 usbif_urb_response_t rsp;
james@973 127 PMDL mdl;
james@973 128 BOOLEAN on_ring; /* is (or has been) on the hardware ring */
james@973 129 };
james@973 130
james@973 131 struct _pvurb {
james@973 132 /* set by xenusb_devurb.c */
james@973 133 usbif_urb_request_t req; /* only pipe, transfer_flags, isoc/intr filled out by submitter */
james@973 134 PMDL mdl; /* can be null for requests with no data */
james@973 135 /* set by xenusb_fdo.c */
james@973 136 usbif_urb_response_t rsp; /* only status, actual_length, error_count valid */
james@973 137 NTSTATUS status;
james@973 138 WDFREQUEST request;
james@973 139 ULONG ref; /* reference counting */
james@969 140 ULONG total_length;
james@973 141 pvurb_t *next; /* collect then process responses as they come off the ring */
james@973 142 };
james@655 143
james@655 144 struct _xenusb_endpoint_t;
james@655 145 struct _xenusb_interface_t;
james@655 146 struct _xenusb_config_t;
james@655 147 struct _xenusb_device_t;
james@655 148 typedef struct _xenusb_endpoint_t xenusb_endpoint_t, *pxenusb_endpoint_t;
james@655 149 typedef struct _xenusb_interface_t xenusb_interface_t;
james@655 150 typedef struct _xenusb_config_t xenusb_config_t;
james@655 151 typedef struct _xenusb_device_t xenusb_device_t;
james@655 152
james@655 153 typedef struct _xenusb_endpoint_t {
james@655 154 xenusb_interface_t *interface;
james@655 155 ULONG pipe_value;
james@931 156 WDFQUEUE queue;
james@931 157 WDFSPINLOCK lock;
james@655 158 USB_ENDPOINT_DESCRIPTOR endpoint_descriptor;
james@655 159 };
james@931 160 //WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(pxenusb_endpoint_t, GetEndpoint)
james@655 161
james@655 162 typedef struct _xenusb_interface_t {
james@655 163 xenusb_config_t *config;
james@655 164 USB_INTERFACE_DESCRIPTOR interface_descriptor;
james@655 165 xenusb_endpoint_t *endpoints[0];
james@655 166 } xenusb_interface_t;
james@655 167
james@655 168 typedef struct _xenusb_config_t {
james@655 169 xenusb_device_t *device;
james@655 170 USB_CONFIGURATION_DESCRIPTOR config_descriptor;
james@964 171 PUCHAR config_descriptor_all;
james@655 172 xenusb_interface_t *interfaces[0];
james@655 173 } xenusb_config_t;
james@655 174
james@655 175 typedef struct _xenusb_device_t {
james@655 176 WDFDEVICE pdo_device;
james@655 177 UCHAR address;
james@655 178 USB_DEVICE_DESCRIPTOR device_descriptor;
james@655 179 ULONG port_number;
james@655 180 WDFQUEUE urb_queue;
james@662 181 USB_DEVICE_SPEED device_speed;
james@662 182 USB_DEVICE_TYPE device_type;
james@655 183 xenusb_config_t *active_config;
james@662 184 xenusb_interface_t *active_interface;
james@655 185 xenusb_config_t **configs; /* pointer to an array of configs */
james@655 186 } xenusb_device_t;
james@655 187
james@655 188 #define USB_PORT_TYPE_NOT_CONNECTED 0
james@655 189 #define USB_PORT_TYPE_LOW_SPEED 1
james@655 190 #define USB_PORT_TYPE_FULL_SPEED 2
james@655 191 #define USB_PORT_TYPE_HIGH_SPEED 3
james@655 192
james@655 193 typedef struct
james@655 194 {
james@655 195 ULONG port_number;
james@655 196 ULONG port_type;
james@655 197 USHORT port_status;
james@655 198 USHORT port_change;
james@930 199 ULONG reset_counter;
james@655 200 } xenusb_port_t;
james@655 201
james@1031 202 #define DEVICE_STATE_DISCONNECTED 0 /* -> INITIALISING */
james@1031 203 #define DEVICE_STATE_INITIALISING 1 /* -> ACTIVE or INACTIVE */
james@1031 204 #define DEVICE_STATE_INACTIVE 2
james@1031 205 #define DEVICE_STATE_ACTIVE 3 /* -> DISCONNECTING */
james@1031 206 #define DEVICE_STATE_DISCONNECTING 4 /* -> DISCONNECTED */
james@1031 207
james@964 208 /*
james@964 209 TODO: this driver crashes under checked build of windows (or probably just checked usbhub.sys)
james@964 210 Needs a magic number of (ULONG)'HUBx' at the start of BusContext
james@964 211 Other magic numbers (ULONG)'BStx' at offset 0x4C of some structure
james@964 212 and (ULONG)'HUB ' somewhere in an FDO extension(?)
james@964 213 */
james@964 214
james@964 215 typedef struct {
james@964 216 ULONG magic; /* (ULONG)'HUBx' */
james@964 217 /* other magic numbers are (ULONG)'BStx' at offset 0x4C and (ULONG)'HUB ' somewhere in an FDO extension(?) */
james@655 218 BOOLEAN XenBus_ShuttingDown;
james@655 219 WDFQUEUE io_queue;
james@969 220 WDFQUEUE pvurb_queue;
james@655 221 WDFCHILDLIST child_list;
james@1031 222 PDEVICE_OBJECT pdo;
james@655 223
james@655 224 WDFDEVICE root_hub_device;
james@655 225
james@1031 226 XN_HANDLE handle;
james@1031 227 ULONG device_state;
james@1031 228 ULONG backend_state;
james@1031 229 KEVENT backend_event;
james@1031 230 KDPC event_dpc;
james@1031 231
james@980 232 struct stack_state *req_id_ss;
james@980 233 partial_pvurb_t *partial_pvurbs[MAX_REQ_ID_COUNT];
james@655 234
james@655 235 PUCHAR config_page;
james@670 236
james@670 237 /* protected by conn_ring_lock */
james@655 238 ULONG num_ports;
james@655 239 xenusb_port_t ports[32];
james@655 240
james@670 241 KSPIN_LOCK urb_ring_lock;
james@670 242 usbif_urb_sring_t *urb_sring;
james@670 243 usbif_urb_front_ring_t urb_ring;
james@1031 244 grant_ref_t urb_sring_gref;
james@1031 245
james@973 246 LIST_ENTRY partial_pvurb_queue;
james@973 247 LIST_ENTRY partial_pvurb_ring;
james@670 248
james@670 249 KSPIN_LOCK conn_ring_lock;
james@670 250 usbif_conn_sring_t *conn_sring;
james@670 251 usbif_conn_front_ring_t conn_ring;
james@1031 252 grant_ref_t conn_sring_gref;
james@670 253
james@973 254 domid_t backend_id;
james@655 255 evtchn_port_t event_channel;
james@655 256 } XENUSB_DEVICE_DATA, *PXENUSB_DEVICE_DATA;
james@655 257
james@655 258 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENUSB_DEVICE_DATA, GetXudd)
james@655 259
james@980 260 #define DEV_ID_COUNT 64
james@980 261
james@655 262 typedef struct {
james@655 263 WDFDEVICE wdf_device;
james@655 264 WDFDEVICE wdf_device_bus_fdo;
james@969 265 WDFIOTARGET bus_fdo_target;
james@655 266 WDFQUEUE io_queue;
james@655 267 WDFQUEUE urb_queue;
james@655 268 ULONG device_number;
james@980 269 struct stack_state *dev_id_ss;
james@655 270 xenusb_device_t *usb_device;
james@655 271 PVOID BusCallbackContext;
james@655 272 PRH_INIT_CALLBACK BusCallbackFunction;
james@655 273 } XENUSB_PDO_DEVICE_DATA, *PXENUSB_PDO_DEVICE_DATA;
james@655 274
james@655 275 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(XENUSB_PDO_DEVICE_DATA, GetXupdd)
james@655 276
james@655 277 #if 0
james@655 278 typedef struct {
james@655 279 UCHAR usb_class;
james@655 280 UCHAR usb_subclass;
james@655 281 UCHAR usb_protocol;
james@655 282 } xenusb_compatible_id_details_t;
james@655 283 #endif
james@655 284
james@655 285 typedef struct {
james@655 286 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER header;
james@655 287 ULONG device_number;
james@655 288 //ULONG port_number;
james@655 289 //ULONG port_type;
james@655 290 //USHORT vendor_id;
james@655 291 //USHORT product_id;
james@655 292 //xenusb_compatible_id_details_t xucid[1];
james@655 293 } XENUSB_PDO_IDENTIFICATION_DESCRIPTION, *PXENUSB_PDO_IDENTIFICATION_DESCRIPTION;
james@655 294
james@973 295
james@973 296 static uint16_t
james@980 297 get_id_from_freelist(struct stack_state *ss) {
james@973 298 ULONG_PTR _id;
james@980 299 if (!stack_pop(ss, (VOID *)&_id)) {
james@1031 300 FUNCTION_MSG("No more id's\n");
james@973 301 return (uint16_t)-1;
james@655 302 }
james@973 303 return (uint16_t)_id;
james@655 304 }
james@655 305
james@655 306 static VOID
james@980 307 put_id_on_freelist(struct stack_state *ss, uint16_t id) {
james@973 308 ULONG_PTR _id = id;
james@980 309 stack_push(ss, (VOID *)_id);
james@655 310 }
james@655 311
james@655 312 static
james@1031 313 ULONGLONG parse_numeric_string(PCHAR string) {
james@655 314 ULONGLONG val = 0;
james@1031 315 while (*string != 0) {
james@655 316 val = val * 10 + (*string - '0');
james@655 317 string++;
james@655 318 }
james@655 319 return val;
james@655 320 }
james@655 321
james@716 322 EVT_WDF_DRIVER_DEVICE_ADD XenUsb_EvtDriverDeviceAdd;
james@655 323
james@716 324 EVT_WDF_CHILD_LIST_CREATE_DEVICE XenUsb_EvtChildListCreateDevice;
james@716 325 EVT_WDF_CHILD_LIST_SCAN_FOR_CHILDREN XenUsb_EvtChildListScanForChildren;
james@655 326
james@655 327 VOID
james@655 328 XenUsb_EnumeratePorts(WDFDEVICE device);
james@655 329
james@716 330 EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL XenUsb_EvtIoInternalDeviceControl_DEVICE_SUBMIT_URB;
james@716 331 EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL XenUsb_EvtIoInternalDeviceControl_ROOTHUB_SUBMIT_URB;
james@655 332
james@929 333 #define URB_DECODE_UNKNOWN 0 /* URB is unknown */
james@929 334 #define URB_DECODE_COMPLETE 1 /* URB is decoded and no further work should be required */
james@929 335 #define URB_DECODE_INCOMPLETE 2 /* URB is decoded but further work is required */
james@929 336 #define URB_DECODE_NOT_CONTROL 3 /* URB is known but not a control packet */
james@929 337
james@929 338 typedef struct {
james@964 339 char *urb_function_name;
james@929 340 PULONG length;
james@929 341 PVOID buffer;
james@964 342 PVOID mdl;
james@964 343 ULONG transfer_flags;
james@929 344 union {
james@929 345 USB_DEFAULT_PIPE_SETUP_PACKET default_pipe_setup_packet;
james@929 346 UCHAR raw[8];
james@929 347 } setup_packet;
james@929 348 } urb_decode_t;
james@929 349
james@929 350 ULONG
james@929 351 XenUsb_DecodeControlUrb(PURB urb, urb_decode_t *decode_data);
james@931 352
james@931 353 VOID
james@931 354 XenUsbHub_ProcessHubInterruptEvent(xenusb_endpoint_t *endpoint);
james@929 355
james@655 356 #endif