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