14c87aefeSPatrick Mooney /*- 2*32640292SAndy Fiddaman * SPDX-License-Identifier: BSD-2-Clause 34c87aefeSPatrick Mooney * 44c87aefeSPatrick Mooney * Copyright (c) 2014 Leon Dang <ldang@nahannisys.com> 54c87aefeSPatrick Mooney * Copyright 2018 Joyent, Inc. 64c87aefeSPatrick Mooney * All rights reserved. 74c87aefeSPatrick Mooney * 84c87aefeSPatrick Mooney * Redistribution and use in source and binary forms, with or without 94c87aefeSPatrick Mooney * modification, are permitted provided that the following conditions 104c87aefeSPatrick Mooney * are met: 114c87aefeSPatrick Mooney * 1. Redistributions of source code must retain the above copyright 124c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer. 134c87aefeSPatrick Mooney * 2. Redistributions in binary form must reproduce the above copyright 144c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer in the 154c87aefeSPatrick Mooney * documentation and/or other materials provided with the distribution. 164c87aefeSPatrick Mooney * 174c87aefeSPatrick Mooney * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 184c87aefeSPatrick Mooney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 194c87aefeSPatrick Mooney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 204c87aefeSPatrick Mooney * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 214c87aefeSPatrick Mooney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 224c87aefeSPatrick Mooney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 234c87aefeSPatrick Mooney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 244c87aefeSPatrick Mooney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 254c87aefeSPatrick Mooney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 264c87aefeSPatrick Mooney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 274c87aefeSPatrick Mooney * SUCH DAMAGE. 284c87aefeSPatrick Mooney */ 294c87aefeSPatrick Mooney 304c87aefeSPatrick Mooney #ifndef _USB_EMUL_H_ 314c87aefeSPatrick Mooney #define _USB_EMUL_H_ 324c87aefeSPatrick Mooney 332b948146SAndy Fiddaman #include <sys/nv.h> 344c87aefeSPatrick Mooney #include <stdlib.h> 354c87aefeSPatrick Mooney #include <sys/linker_set.h> 364c87aefeSPatrick Mooney #include <pthread.h> 374c87aefeSPatrick Mooney #ifndef __FreeBSD__ 384c87aefeSPatrick Mooney #include <synch.h> 394c87aefeSPatrick Mooney #endif 404c87aefeSPatrick Mooney 414c87aefeSPatrick Mooney #define USB_MAX_XFER_BLOCKS 8 424c87aefeSPatrick Mooney 434c87aefeSPatrick Mooney #define USB_XFER_OUT 0 444c87aefeSPatrick Mooney #define USB_XFER_IN 1 454c87aefeSPatrick Mooney 464c87aefeSPatrick Mooney 474c87aefeSPatrick Mooney 484c87aefeSPatrick Mooney struct usb_hci; 494c87aefeSPatrick Mooney struct usb_device_request; 504c87aefeSPatrick Mooney struct usb_data_xfer; 514c87aefeSPatrick Mooney 524c87aefeSPatrick Mooney /* Device emulation handlers */ 534c87aefeSPatrick Mooney struct usb_devemu { 5459d65d31SAndy Fiddaman const char *ue_emu; /* name of device emulation */ 554c87aefeSPatrick Mooney int ue_usbver; /* usb version: 2 or 3 */ 564c87aefeSPatrick Mooney int ue_usbspeed; /* usb device speed */ 574c87aefeSPatrick Mooney 584c87aefeSPatrick Mooney /* instance creation */ 592b948146SAndy Fiddaman void *(*ue_init)(struct usb_hci *hci, nvlist_t *nvl); 604c87aefeSPatrick Mooney 614c87aefeSPatrick Mooney /* handlers */ 624c87aefeSPatrick Mooney int (*ue_request)(void *sc, struct usb_data_xfer *xfer); 634c87aefeSPatrick Mooney int (*ue_data)(void *sc, struct usb_data_xfer *xfer, int dir, 644c87aefeSPatrick Mooney int epctx); 654c87aefeSPatrick Mooney int (*ue_reset)(void *sc); 664c87aefeSPatrick Mooney int (*ue_remove)(void *sc); 674c87aefeSPatrick Mooney int (*ue_stop)(void *sc); 684c87aefeSPatrick Mooney }; 69*32640292SAndy Fiddaman #define USB_EMUL_SET(x) DATA_SET(usb_emu_set, x) 704c87aefeSPatrick Mooney 714c87aefeSPatrick Mooney /* 724c87aefeSPatrick Mooney * USB device events to notify HCI when state changes 734c87aefeSPatrick Mooney */ 744c87aefeSPatrick Mooney enum hci_usbev { 754c87aefeSPatrick Mooney USBDEV_ATTACH, 764c87aefeSPatrick Mooney USBDEV_RESET, 774c87aefeSPatrick Mooney USBDEV_STOP, 784c87aefeSPatrick Mooney USBDEV_REMOVE, 794c87aefeSPatrick Mooney }; 804c87aefeSPatrick Mooney 814c87aefeSPatrick Mooney /* usb controller, ie xhci, ehci */ 824c87aefeSPatrick Mooney struct usb_hci { 834c87aefeSPatrick Mooney int (*hci_intr)(struct usb_hci *hci, int epctx); 844c87aefeSPatrick Mooney int (*hci_event)(struct usb_hci *hci, enum hci_usbev evid, 854c87aefeSPatrick Mooney void *param); 864c87aefeSPatrick Mooney void *hci_sc; /* private softc for hci */ 874c87aefeSPatrick Mooney 884c87aefeSPatrick Mooney /* controller managed fields */ 894c87aefeSPatrick Mooney int hci_address; 904c87aefeSPatrick Mooney int hci_port; 914c87aefeSPatrick Mooney }; 924c87aefeSPatrick Mooney 934c87aefeSPatrick Mooney /* 944c87aefeSPatrick Mooney * Each xfer block is mapped to the hci transfer block. 95*32640292SAndy Fiddaman * On input into the device handler, blen is set to the length of buf. 964c87aefeSPatrick Mooney * The device handler is to update blen to reflect on the residual size 974c87aefeSPatrick Mooney * of the buffer, i.e. len(buf) - len(consumed). 984c87aefeSPatrick Mooney */ 994c87aefeSPatrick Mooney struct usb_data_xfer_block { 1004c87aefeSPatrick Mooney void *buf; /* IN or OUT pointer */ 1014c87aefeSPatrick Mooney int blen; /* in:len(buf), out:len(remaining) */ 1024c87aefeSPatrick Mooney int bdone; /* bytes transferred */ 1034c87aefeSPatrick Mooney uint32_t processed; /* device processed this + errcode */ 1044c87aefeSPatrick Mooney void *hci_data; /* HCI private reference */ 1054c87aefeSPatrick Mooney int ccs; 1064c87aefeSPatrick Mooney uint32_t streamid; 1074c87aefeSPatrick Mooney uint64_t trbnext; /* next TRB guest address */ 1084c87aefeSPatrick Mooney }; 1094c87aefeSPatrick Mooney 1104c87aefeSPatrick Mooney struct usb_data_xfer { 1114c87aefeSPatrick Mooney struct usb_data_xfer_block data[USB_MAX_XFER_BLOCKS]; 1124c87aefeSPatrick Mooney struct usb_device_request *ureq; /* setup ctl request */ 1134c87aefeSPatrick Mooney int ndata; /* # of data items */ 1144c87aefeSPatrick Mooney int head; 1154c87aefeSPatrick Mooney int tail; 1164c87aefeSPatrick Mooney pthread_mutex_t mtx; 1174c87aefeSPatrick Mooney }; 1184c87aefeSPatrick Mooney 1194c87aefeSPatrick Mooney enum USB_ERRCODE { 1204c87aefeSPatrick Mooney USB_ACK, 1214c87aefeSPatrick Mooney USB_NAK, 1224c87aefeSPatrick Mooney USB_STALL, 1234c87aefeSPatrick Mooney USB_NYET, 1244c87aefeSPatrick Mooney USB_ERR, 1254c87aefeSPatrick Mooney USB_SHORT 1264c87aefeSPatrick Mooney }; 1274c87aefeSPatrick Mooney 1284c87aefeSPatrick Mooney #define USB_DATA_GET_ERRCODE(x) (x)->processed >> 8 1294c87aefeSPatrick Mooney #define USB_DATA_SET_ERRCODE(x,e) do { \ 1304c87aefeSPatrick Mooney (x)->processed = ((x)->processed & 0xFF) | (e << 8); \ 1314c87aefeSPatrick Mooney } while (0) 1324c87aefeSPatrick Mooney 1334c87aefeSPatrick Mooney #define USB_DATA_OK(x,i) ((x)->data[(i)].buf != NULL) 1344c87aefeSPatrick Mooney 1354c87aefeSPatrick Mooney #define USB_DATA_XFER_INIT(x) do { \ 1364c87aefeSPatrick Mooney memset((x), 0, sizeof(*(x))); \ 1374c87aefeSPatrick Mooney pthread_mutex_init(&((x)->mtx), NULL); \ 1384c87aefeSPatrick Mooney } while (0) 1394c87aefeSPatrick Mooney 1404c87aefeSPatrick Mooney #define USB_DATA_XFER_RESET(x) do { \ 1414c87aefeSPatrick Mooney memset((x)->data, 0, sizeof((x)->data)); \ 1424c87aefeSPatrick Mooney (x)->ndata = 0; \ 1434c87aefeSPatrick Mooney (x)->head = (x)->tail = 0; \ 1444c87aefeSPatrick Mooney } while (0) 1454c87aefeSPatrick Mooney 1464c87aefeSPatrick Mooney #define USB_DATA_XFER_LOCK(x) do { \ 1474c87aefeSPatrick Mooney pthread_mutex_lock(&((x)->mtx)); \ 1484c87aefeSPatrick Mooney } while (0) 1494c87aefeSPatrick Mooney 1504c87aefeSPatrick Mooney #define USB_DATA_XFER_UNLOCK(x) do { \ 1514c87aefeSPatrick Mooney pthread_mutex_unlock(&((x)->mtx)); \ 1524c87aefeSPatrick Mooney } while (0) 1534c87aefeSPatrick Mooney #ifndef __FreeBSD__ 1544c87aefeSPatrick Mooney #define USB_DATA_XFER_LOCK_HELD(x) MUTEX_HELD(&((x)->mtx)) 1554c87aefeSPatrick Mooney #endif 1564c87aefeSPatrick Mooney 1572b948146SAndy Fiddaman struct usb_devemu *usb_emu_finddev(const char *name); 1584c87aefeSPatrick Mooney 1594c87aefeSPatrick Mooney struct usb_data_xfer_block *usb_data_xfer_append(struct usb_data_xfer *xfer, 1604c87aefeSPatrick Mooney void *buf, int blen, void *hci_data, int ccs); 1614c87aefeSPatrick Mooney 1624c87aefeSPatrick Mooney 1634c87aefeSPatrick Mooney #endif /* _USB_EMUL_H_ */ 164