198944Sobrien/*- 298944Sobrien * Copyright (c) 2014 Leon Dang <ldang@nahannisys.com> 398944Sobrien * All rights reserved. 498944Sobrien * 598944Sobrien * Redistribution and use in source and binary forms, with or without 698944Sobrien * modification, are permitted provided that the following conditions 798944Sobrien * are met: 898944Sobrien * 1. Redistributions of source code must retain the above copyright 998944Sobrien * notice, this list of conditions and the following disclaimer. 1098944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1198944Sobrien * notice, this list of conditions and the following disclaimer in the 1298944Sobrien * documentation and/or other materials provided with the distribution. 1398944Sobrien * 1498944Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1598944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1698944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1798944Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1898944Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1998944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2098944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2198944Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2298944Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2398944Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2498944Sobrien * SUCH DAMAGE. 2598944Sobrien * 2698944Sobrien * $FreeBSD: releng/11.0/usr.sbin/bhyve/usb_emul.h 302408 2016-07-08 00:04:57Z gjb $ 2798944Sobrien */ 2898944Sobrien 2998944Sobrien#ifndef _USB_EMUL_H_ 3098944Sobrien#define _USB_EMUL_H_ 3198944Sobrien 3298944Sobrien#include <stdlib.h> 3398944Sobrien#include <sys/linker_set.h> 3498944Sobrien#include <pthread.h> 3598944Sobrien 3698944Sobrien#define USB_MAX_XFER_BLOCKS 8 3798944Sobrien 3898944Sobrien#define USB_XFER_OUT 0 3998944Sobrien#define USB_XFER_IN 1 4098944Sobrien 4198944Sobrien 4298944Sobrien 4398944Sobrienstruct usb_hci; 4498944Sobrienstruct usb_device_request; 4598944Sobrienstruct usb_data_xfer; 4698944Sobrien 4798944Sobrien/* Device emulation handlers */ 4898944Sobrienstruct usb_devemu { 4998944Sobrien char *ue_emu; /* name of device emulation */ 5098944Sobrien int ue_usbver; /* usb version: 2 or 3 */ 5198944Sobrien int ue_usbspeed; /* usb device speed */ 5298944Sobrien 5398944Sobrien /* instance creation */ 5498944Sobrien void *(*ue_init)(struct usb_hci *hci, char *opt); 5598944Sobrien 5698944Sobrien /* handlers */ 5798944Sobrien int (*ue_request)(void *sc, struct usb_data_xfer *xfer); 5898944Sobrien int (*ue_data)(void *sc, struct usb_data_xfer *xfer, int dir, 5998944Sobrien int epctx); 6098944Sobrien int (*ue_reset)(void *sc); 6198944Sobrien int (*ue_remove)(void *sc); 6298944Sobrien int (*ue_stop)(void *sc); 6398944Sobrien}; 6498944Sobrien#define USB_EMUL_SET(x) DATA_SET(usb_emu_set, x); 6598944Sobrien 6698944Sobrien/* 6798944Sobrien * USB device events to notify HCI when state changes 6898944Sobrien */ 6998944Sobrienenum hci_usbev { 7098944Sobrien USBDEV_ATTACH, 7198944Sobrien USBDEV_RESET, 7298944Sobrien USBDEV_STOP, 7398944Sobrien USBDEV_REMOVE, 7498944Sobrien}; 7598944Sobrien 7698944Sobrien/* usb controller, ie xhci, ehci */ 7798944Sobrienstruct usb_hci { 7898944Sobrien int (*hci_intr)(struct usb_hci *hci, int epctx); 7998944Sobrien int (*hci_event)(struct usb_hci *hci, enum hci_usbev evid, 8098944Sobrien void *param); 8198944Sobrien void *hci_sc; /* private softc for hci */ 8298944Sobrien 8398944Sobrien /* controller managed fields */ 8498944Sobrien int hci_address; 8598944Sobrien int hci_port; 8698944Sobrien}; 8798944Sobrien 8898944Sobrien/* 8998944Sobrien * Each xfer block is mapped to the hci transfer block. 9098944Sobrien * On input into the device handler, blen is set to the lenght of buf. 9198944Sobrien * The device handler is to update blen to reflect on the residual size 9298944Sobrien * of the buffer, i.e. len(buf) - len(consumed). 9398944Sobrien */ 9498944Sobrienstruct usb_data_xfer_block { 9598944Sobrien void *buf; /* IN or OUT pointer */ 9698944Sobrien int blen; /* in:len(buf), out:len(remaining) */ 9798944Sobrien int bdone; /* bytes transferred */ 9898944Sobrien uint32_t processed; /* device processed this + errcode */ 9998944Sobrien void *hci_data; /* HCI private reference */ 10098944Sobrien int ccs; 10198944Sobrien uint32_t streamid; 10298944Sobrien uint64_t trbnext; /* next TRB guest address */ 10398944Sobrien}; 10498944Sobrien 10598944Sobrienstruct usb_data_xfer { 10698944Sobrien struct usb_data_xfer_block data[USB_MAX_XFER_BLOCKS]; 10798944Sobrien struct usb_device_request *ureq; /* setup ctl request */ 10898944Sobrien int ndata; /* # of data items */ 10998944Sobrien int head; 11098944Sobrien int tail; 11198944Sobrien pthread_mutex_t mtx; 11298944Sobrien}; 11398944Sobrien 11498944Sobrienenum USB_ERRCODE { 11598944Sobrien USB_ACK, 11698944Sobrien USB_NAK, 11798944Sobrien USB_STALL, 11898944Sobrien USB_NYET, 11998944Sobrien USB_ERR, 12098944Sobrien USB_SHORT 12198944Sobrien}; 12298944Sobrien 12398944Sobrien#define USB_DATA_GET_ERRCODE(x) (x)->processed >> 8 12498944Sobrien#define USB_DATA_SET_ERRCODE(x,e) do { \ 12598944Sobrien (x)->processed = ((x)->processed & 0xFF) | (e << 8); \ 12698944Sobrien } while (0) 12798944Sobrien 12898944Sobrien#define USB_DATA_OK(x,i) ((x)->data[(i)].buf != NULL) 12998944Sobrien 13098944Sobrien#define USB_DATA_XFER_INIT(x) do { \ 13198944Sobrien memset((x), 0, sizeof(*(x))); \ 13298944Sobrien pthread_mutex_init(&((x)->mtx), NULL); \ 13398944Sobrien } while (0) 13498944Sobrien 13598944Sobrien#define USB_DATA_XFER_RESET(x) do { \ 13698944Sobrien memset((x)->data, 0, sizeof((x)->data)); \ 13798944Sobrien (x)->ndata = 0; \ 13898944Sobrien (x)->head = (x)->tail = 0; \ 13998944Sobrien } while (0) 14098944Sobrien 14198944Sobrien#define USB_DATA_XFER_LOCK(x) do { \ 14298944Sobrien pthread_mutex_lock(&((x)->mtx)); \ 14398944Sobrien } while (0) 14498944Sobrien 14598944Sobrien#define USB_DATA_XFER_UNLOCK(x) do { \ 14698944Sobrien pthread_mutex_unlock(&((x)->mtx)); \ 14798944Sobrien } while (0) 14898944Sobrien 14998944Sobrien 15098944Sobrienstruct usb_devemu *usb_emu_finddev(char *name); 15198944Sobrien 15298944Sobrienstruct usb_data_xfer_block *usb_data_xfer_append(struct usb_data_xfer *xfer, 15398944Sobrien void *buf, int blen, void *hci_data, int ccs); 15498944Sobrien 15598944Sobrien 15698944Sobrien#endif /* _USB_EMUL_H_ */ 15798944Sobrien