#ifndef _APPLE_BCE_VHCI_H_
#define _APPLE_BCE_VHCI_H_
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sx.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include "apple_bce.h"
struct usb_bus;
struct usb_device;
struct usb_xfer;
#define BCE_VHCI_MAX_PORTS 16
#define BCE_VHCI_MAX_DEVICES 32
#define BCE_VHCI_MAX_ENDPOINTS 32
#define BCE_VHCI_MSG_QUEUE_EL 32
#define BCE_VHCI_EVT_QUEUE_EL 256
#define BCE_VHCI_EVT_PENDING 32
#define BCE_VHCI_TQ_EL 32
#define BCE_VHCI_XFER_BUFSZ 4096
struct bce_vhci_message {
uint16_t cmd;
uint16_t status;
uint32_t param1;
uint64_t param2;
} __packed;
enum bce_vhci_cmd_id {
BCE_VHCI_CMD_CONTROLLER_ENABLE = 0x0001,
BCE_VHCI_CMD_CONTROLLER_DISABLE = 0x0002,
BCE_VHCI_CMD_CONTROLLER_START = 0x0003,
BCE_VHCI_CMD_CONTROLLER_PAUSE = 0x0004,
BCE_VHCI_CMD_PORT_POWER_ON = 0x0010,
BCE_VHCI_CMD_PORT_POWER_OFF = 0x0011,
BCE_VHCI_CMD_PORT_RESUME = 0x0012,
BCE_VHCI_CMD_PORT_SUSPEND = 0x0013,
BCE_VHCI_CMD_PORT_RESET = 0x0014,
BCE_VHCI_CMD_PORT_DISABLE = 0x0015,
BCE_VHCI_CMD_PORT_STATUS = 0x0016,
BCE_VHCI_CMD_PORT_STATUS_CHANGE = 0x0018,
BCE_VHCI_CMD_DEVICE_CREATE = 0x0030,
BCE_VHCI_CMD_DEVICE_DESTROY = 0x0031,
BCE_VHCI_CMD_ENDPOINT_CREATE = 0x0040,
BCE_VHCI_CMD_ENDPOINT_DESTROY = 0x0041,
BCE_VHCI_CMD_ENDPOINT_SET_STATE = 0x0042,
BCE_VHCI_CMD_ENDPOINT_REQ_STATE = 0x0043,
BCE_VHCI_CMD_ENDPOINT_RESET = 0x0044,
BCE_VHCI_CMD_TRANSFER_REQUEST = 0x1000,
BCE_VHCI_CMD_CTRL_TRANSFER_STATUS = 0x1005,
BCE_VHCI_CMD_REPLY_FLAG = 0x8000,
BCE_VHCI_CMD_CANCEL_FLAG = 0x4000,
};
enum bce_vhci_msg_status {
BCE_VHCI_SUCCESS = 1,
BCE_VHCI_ERROR = 2,
BCE_VHCI_PIPE_STALL = 3,
BCE_VHCI_ABORT = 4,
BCE_VHCI_BAD_ARGUMENT = 5,
BCE_VHCI_OVERRUN = 6,
BCE_VHCI_INTERNAL_ERROR = 7,
BCE_VHCI_NO_POWER = 8,
BCE_VHCI_UNSUPPORTED = 9,
};
enum bce_vhci_endpoint_state {
BCE_VHCI_ENDP_ACTIVE = 0,
BCE_VHCI_ENDP_PAUSED = 1,
BCE_VHCI_ENDP_STALLED = 2,
};
enum bce_vhci_ctrl_state {
BCE_VHCI_CTRL_IDLE = 0,
BCE_VHCI_CTRL_SETUP = 1,
BCE_VHCI_CTRL_DATA = 2,
BCE_VHCI_CTRL_STATUS = 3,
};
#define BCE_VHCI_PAUSE_INTERNAL 0x01
#define BCE_VHCI_PAUSE_FIRMWARE 0x02
#define BCE_VHCI_PAUSE_SUSPEND 0x04
#define BCE_VHCI_PAUSE_SHUTDOWN 0x08
#define BCE_VHCI_PORT_CONNECTED 0x0004
#define BCE_VHCI_PORT_ENABLED 0x0010
#define BCE_VHCI_PORT_SUSPENDED 0x0060
#define BCE_VHCI_PORT_OVERCURRENT 0x0002
#define BCE_VHCI_PORT_RESET 0x0008
#define BCE_VHCI_PORT_C_CONNECTION 0x40000
struct bce_vhci_msg_queue {
struct bce_queue_cq *cq;
struct bce_queue_sq *sq;
bus_dma_tag_t dma_tag;
bus_dmamap_t dma_map;
bus_addr_t dma_addr;
struct bce_vhci_message *data;
uint32_t el_count;
};
struct bce_vhci_evt_queue {
struct bce_queue_sq *sq;
bus_dma_tag_t dma_tag;
bus_dmamap_t dma_map;
bus_addr_t dma_addr;
struct bce_vhci_message *data;
uint32_t el_count;
void *userdata;
};
struct bce_vhci_cmd_queue {
struct bce_vhci_msg_queue *msg;
struct sx exec_lock;
struct mtx lock;
struct sema completion;
struct bce_vhci_message response;
volatile int pending;
uint16_t expected_cmd;
};
struct bce_vhci_transfer_queue {
struct bce_vhci_softc *vhci;
uint8_t dev_addr;
uint8_t endp_addr;
struct mtx lock;
struct bce_queue_cq *cq;
struct bce_queue_sq *sq_in;
struct bce_queue_sq *sq_out;
struct usb_xfer *active_xfer;
uint32_t paused_by;
int active;
int stalled;
int dma_inflight;
int create_pending;
struct usb_endpoint_descriptor *create_edesc;
struct usb_xfer *create_xfer;
bus_dma_tag_t dma_tag;
bus_dmamap_t dma_map;
bus_addr_t dma_addr;
void *dma_buf;
enum bce_vhci_ctrl_state ctrl_state;
uint8_t ctrl_dir;
uint32_t ctrl_data_len;
uint32_t ctrl_actual;
int ctrl_data_done;
int ctrl_status_pending;
struct bce_vhci_message ctrl_status_msg;
struct usb_xfer *pending_xfer;
int evt_pending;
struct bce_vhci_message evt_saved;
};
struct bce_vhci_device {
int allocated;
uint8_t fw_dev_id;
uint8_t port;
struct bce_vhci_transfer_queue tq[BCE_VHCI_MAX_ENDPOINTS];
};
struct bce_vhci_softc;
int bce_vhci_attach(struct apple_bce_softc *sc);
int bce_vhci_detach(struct apple_bce_softc *sc);
#endif