xref: /freebsd/sys/dev/apple_bce/apple_bce_vhci.h (revision 9f90536c74b8172fc67cd977e5451f37a12462d5)
1 /*-
2  * Copyright (c) 2026 Abdelkader Boudih <freebsd@seuros.com>
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Apple T2 BCE Virtual USB Host Controller Interface (VHCI).
7  * Translates USB operations into BCE firmware messages over DMA queues.
8  */
9 
10 #ifndef _APPLE_BCE_VHCI_H_
11 #define _APPLE_BCE_VHCI_H_
12 
13 #include <sys/param.h>
14 #include <sys/bus.h>
15 #include <sys/lock.h>
16 #include <sys/mutex.h>
17 #include <sys/sx.h>
18 #include <sys/sema.h>
19 #include <sys/taskqueue.h>
20 
21 #include "apple_bce.h"
22 
23 /* Forward declaration  -- full USB headers included only in .c file */
24 struct usb_bus;
25 struct usb_device;
26 struct usb_xfer;
27 
28 /*
29  * VHCI limits.
30  */
31 #define BCE_VHCI_MAX_PORTS	16
32 #define BCE_VHCI_MAX_DEVICES	32
33 #define BCE_VHCI_MAX_ENDPOINTS	32
34 
35 /* Queue element counts */
36 #define BCE_VHCI_MSG_QUEUE_EL	32
37 #define BCE_VHCI_EVT_QUEUE_EL	256
38 #define BCE_VHCI_EVT_PENDING	32
39 #define BCE_VHCI_TQ_EL		32	/* Transfer queue elements */
40 #define BCE_VHCI_XFER_BUFSZ	4096	/* DMA buffer per transfer queue */
41 
42 /*
43  * VHCI message format (16 bytes, matches firmware protocol).
44  */
45 struct bce_vhci_message {
46 	uint16_t	cmd;
47 	uint16_t	status;
48 	uint32_t	param1;
49 	uint64_t	param2;
50 } __packed;
51 
52 /*
53  * VHCI command IDs.
54  */
55 enum bce_vhci_cmd_id {
56 	/* Controller commands */
57 	BCE_VHCI_CMD_CONTROLLER_ENABLE	= 0x0001,
58 	BCE_VHCI_CMD_CONTROLLER_DISABLE	= 0x0002,
59 	BCE_VHCI_CMD_CONTROLLER_START	= 0x0003,
60 	BCE_VHCI_CMD_CONTROLLER_PAUSE	= 0x0004,
61 
62 	/* Port commands */
63 	BCE_VHCI_CMD_PORT_POWER_ON	= 0x0010,
64 	BCE_VHCI_CMD_PORT_POWER_OFF	= 0x0011,
65 	BCE_VHCI_CMD_PORT_RESUME	= 0x0012,
66 	BCE_VHCI_CMD_PORT_SUSPEND	= 0x0013,
67 	BCE_VHCI_CMD_PORT_RESET	= 0x0014,
68 	BCE_VHCI_CMD_PORT_DISABLE	= 0x0015,
69 	BCE_VHCI_CMD_PORT_STATUS	= 0x0016,
70 	BCE_VHCI_CMD_PORT_STATUS_CHANGE	= 0x0018,
71 
72 	/* Device commands */
73 	BCE_VHCI_CMD_DEVICE_CREATE	= 0x0030,
74 	BCE_VHCI_CMD_DEVICE_DESTROY	= 0x0031,
75 
76 	/* Endpoint commands */
77 	BCE_VHCI_CMD_ENDPOINT_CREATE	= 0x0040,
78 	BCE_VHCI_CMD_ENDPOINT_DESTROY	= 0x0041,
79 	BCE_VHCI_CMD_ENDPOINT_SET_STATE	= 0x0042,
80 	BCE_VHCI_CMD_ENDPOINT_REQ_STATE	= 0x0043,
81 	BCE_VHCI_CMD_ENDPOINT_RESET	= 0x0044,
82 
83 	/* Transfer commands */
84 	BCE_VHCI_CMD_TRANSFER_REQUEST	= 0x1000,
85 	BCE_VHCI_CMD_CTRL_TRANSFER_STATUS = 0x1005,
86 
87 	/* Reply flag  -- firmware replies have cmd | 0x8000 */
88 	BCE_VHCI_CMD_REPLY_FLAG		= 0x8000,
89 
90 	/* Cancel flag  -- timeout sends cmd | 0x4000 */
91 	BCE_VHCI_CMD_CANCEL_FLAG	= 0x4000,
92 };
93 
94 /*
95  * VHCI message status codes.
96  */
97 enum bce_vhci_msg_status {
98 	BCE_VHCI_SUCCESS	= 1,
99 	BCE_VHCI_ERROR		= 2,
100 	BCE_VHCI_PIPE_STALL	= 3,
101 	BCE_VHCI_ABORT		= 4,
102 	BCE_VHCI_BAD_ARGUMENT	= 5,
103 	BCE_VHCI_OVERRUN	= 6,
104 	BCE_VHCI_INTERNAL_ERROR	= 7,
105 	BCE_VHCI_NO_POWER	= 8,
106 	BCE_VHCI_UNSUPPORTED	= 9,
107 };
108 
109 /*
110  * Endpoint states.
111  */
112 enum bce_vhci_endpoint_state {
113 	BCE_VHCI_ENDP_ACTIVE	= 0,
114 	BCE_VHCI_ENDP_PAUSED	= 1,
115 	BCE_VHCI_ENDP_STALLED	= 2,
116 };
117 
118 /*
119  * Control transfer state machine.
120  */
121 enum bce_vhci_ctrl_state {
122 	BCE_VHCI_CTRL_IDLE	= 0,
123 	BCE_VHCI_CTRL_SETUP	= 1,	/* Awaiting setup XFER_REQ */
124 	BCE_VHCI_CTRL_DATA	= 2,	/* Awaiting data XFER_REQ */
125 	BCE_VHCI_CTRL_STATUS	= 3,	/* Awaiting CTRL_XFER_STATUS */
126 };
127 
128 /*
129  * Pause sources (bitmask).
130  */
131 #define BCE_VHCI_PAUSE_INTERNAL		0x01
132 #define BCE_VHCI_PAUSE_FIRMWARE		0x02
133 #define BCE_VHCI_PAUSE_SUSPEND		0x04
134 #define BCE_VHCI_PAUSE_SHUTDOWN		0x08
135 
136 /*
137  * Port status bit mapping (firmware -> USB).
138  * Firmware uses its own bit encoding; we translate in roothub_exec.
139  */
140 #define BCE_VHCI_PORT_CONNECTED		0x0004
141 #define BCE_VHCI_PORT_ENABLED		0x0010
142 #define BCE_VHCI_PORT_SUSPENDED		0x0060
143 #define BCE_VHCI_PORT_OVERCURRENT	0x0002
144 #define BCE_VHCI_PORT_RESET		0x0008
145 #define BCE_VHCI_PORT_C_CONNECTION	0x40000
146 
147 /*
148  * VHCI message queue (host -> device).
149  */
150 struct bce_vhci_msg_queue {
151 	struct bce_queue_cq	*cq;
152 	struct bce_queue_sq	*sq;
153 	bus_dma_tag_t		dma_tag;
154 	bus_dmamap_t		dma_map;
155 	bus_addr_t		dma_addr;
156 	struct bce_vhci_message	*data;
157 	uint32_t		el_count;
158 };
159 
160 /*
161  * VHCI event queue (device -> host).
162  * Single contiguous DMA buffer for all receive slots.
163  */
164 struct bce_vhci_evt_queue {
165 	struct bce_queue_sq	*sq;
166 	bus_dma_tag_t		dma_tag;
167 	bus_dmamap_t		dma_map;
168 	bus_addr_t		dma_addr;
169 	struct bce_vhci_message	*data;
170 	uint32_t		el_count;
171 	void			*userdata;
172 };
173 
174 /*
175  * VHCI command queue (synchronous command execution).
176  */
177 struct bce_vhci_cmd_queue {
178 	struct bce_vhci_msg_queue *msg;
179 	struct sx		exec_lock;	/* Serialize callers */
180 	struct mtx		lock;
181 	struct sema		completion;
182 	struct bce_vhci_message	response;
183 	volatile int		pending;
184 	uint16_t		expected_cmd;	/* Filter late replies */
185 };
186 
187 /*
188  * VHCI transfer queue (per endpoint).
189  *
190  * Each endpoint gets a CQ + IN SQ + OUT SQ triplet registered with
191  * firmware as named DMA queues.  The DMA buffer is used to shuttle
192  * USB payloads between the USB stack's frame buffers and firmware.
193  */
194 struct bce_vhci_transfer_queue {
195 	struct bce_vhci_softc	*vhci;
196 	uint8_t			dev_addr;	/* firmware device id */
197 	uint8_t			endp_addr;	/* USB endpoint address */
198 	struct mtx		lock;		/* Protects SQ submission */
199 	struct bce_queue_cq	*cq;
200 	struct bce_queue_sq	*sq_in;		/* Device -> host */
201 	struct bce_queue_sq	*sq_out;	/* Host -> device */
202 	struct usb_xfer		*active_xfer;
203 	uint32_t		paused_by;
204 	int			active;		/* Queues created with FW */
205 	int			stalled;
206 	int			dma_inflight;	/* DMA pending */
207 	int			create_pending;	/* Deferred ep create */
208 	struct usb_endpoint_descriptor *create_edesc;
209 	struct usb_xfer		*create_xfer;	/* Deferred xfer */
210 
211 	/* DMA buffer for data transfer */
212 	bus_dma_tag_t		dma_tag;
213 	bus_dmamap_t		dma_map;
214 	bus_addr_t		dma_addr;
215 	void			*dma_buf;
216 
217 	/* Control transfer state machine */
218 	enum bce_vhci_ctrl_state ctrl_state;
219 	uint8_t			ctrl_dir;	/* UE_DIR_IN or UE_DIR_OUT */
220 	uint32_t		ctrl_data_len;	/* Expected data phase length */
221 	uint32_t		ctrl_actual;	/* Actual bytes transferred */
222 	int			ctrl_data_done;	/* IN DMA completion seen */
223 	int			ctrl_status_pending; /* Deferred STATUS msg */
224 	struct bce_vhci_message	ctrl_status_msg; /* Saved STATUS for defer */
225 
226 	/* Queued transfer waiting for active_xfer to finish */
227 	struct usb_xfer		*pending_xfer;
228 
229 	/* Deferred firmware event (TRANSFER_REQUEST arrives before xfer) */
230 	int			evt_pending;
231 	struct bce_vhci_message	evt_saved;
232 };
233 
234 /*
235  * VHCI per-device state.
236  */
237 struct bce_vhci_device {
238 	int			allocated;	/* Device created with FW */
239 	uint8_t			fw_dev_id;	/* Firmware device ID */
240 	uint8_t			port;		/* Port number */
241 	struct bce_vhci_transfer_queue tq[BCE_VHCI_MAX_ENDPOINTS];
242 };
243 
244 /* VHCI softc is defined in apple_bce_vhci.c (depends on USB headers) */
245 struct bce_vhci_softc;
246 
247 /* VHCI driver interface */
248 int	bce_vhci_attach(struct apple_bce_softc *sc);
249 int	bce_vhci_detach(struct apple_bce_softc *sc);
250 
251 #endif /* _APPLE_BCE_VHCI_H_ */
252