1 /*
2 * Copyright (c) 2026 Abdelkader Boudih <freebsd@seuros.com>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Apple T2 Buffer Copy Engine (BCE) driver.
7 * PCI transport layer for T2 coprocessor communication.
8 */
9
10 #ifndef _APPLE_BCE_H_
11 #define _APPLE_BCE_H_
12
13 #include <sys/param.h>
14 #include <sys/bus.h>
15 #include <sys/kernel.h>
16 #include <sys/lock.h>
17 #include <sys/mutex.h>
18 #include <sys/sema.h>
19 #include <sys/callout.h>
20 #include <sys/rman.h>
21 #include <machine/bus.h>
22 #include <machine/resource.h>
23 #include <dev/pci/pcivar.h>
24 #include <dev/pci/pcireg.h>
25
26 #define BCE_PCI_VENDOR_APPLE 0x106b
27 #define BCE_PCI_DEVICE_T2 0x1801
28
29 #define BCE_MAX_QUEUE_COUNT 0x100
30 #define BCE_MAX_CQ_COUNT 64 /* Max completion queues tracked */
31 #define BCE_QUEUE_USER_MIN 2
32 #define BCE_QUEUE_USER_MAX (BCE_MAX_QUEUE_COUNT - 1)
33 #define BCE_CMD_SIZE 0x40
34
35 #define BCE_FW_PROTOCOL_VER 0x20001
36 #define BCE_MBOX_TIMEOUT_MS 1000
37 #define BCE_TIMESTAMP_MS 150 /* Firmware keepalive interval */
38
39 /*
40 * Mailbox register offsets (BAR4).
41 */
42 #define BCE_REG_MBOX_OUT 0x820 /* 4x u32 to-device */
43 #define BCE_REG_MBOX_REPLY 0x810 /* 4x u32 from-device */
44 #define BCE_REG_MBOX_REPLY_CTR 0x108 /* Reply counter (bits 23:20 = count) */
45 #define BCE_REG_TIMESTAMP 0xC000 /* Timestamp sync */
46
47 /*
48 * DMA register offsets (BAR2).
49 */
50 #define BCE_REG_DOORBELL_BASE 0x44000
51
52 /*
53 * Mailbox message format: 6-bit type (63:58) + 58-bit value.
54 */
55 #define BCE_MB_MSG(type, val) (((uint64_t)(type) << 58) | \
56 ((val) & 0x3FFFFFFFFFFFFFFULL))
57 #define BCE_MB_TYPE(v) ((uint32_t)((v) >> 58))
58 #define BCE_MB_VALUE(v) ((v) & 0x3FFFFFFFFFFFFFFULL)
59
60 /*
61 * Mailbox message types.
62 */
63 enum bce_mb_type {
64 BCE_MB_REGISTER_CMD_SQ = 0x07,
65 BCE_MB_REGISTER_CMD_CQ = 0x08,
66 BCE_MB_REGISTER_QUEUE_REPLY = 0x0B,
67 BCE_MB_SET_FW_PROTOCOL_VER = 0x0C,
68 BCE_MB_SLEEP_NO_STATE = 0x14,
69 BCE_MB_RESTORE_NO_STATE = 0x15,
70 BCE_MB_SAVE_AND_SLEEP = 0x17,
71 BCE_MB_RESTORE_AND_WAKE = 0x18,
72 BCE_MB_SAVE_FAILURE = 0x19,
73 BCE_MB_SAVE_RESTORE_COMPLETE = 0x1A,
74 };
75
76 /*
77 * Queue types.
78 */
79 enum bce_queue_type {
80 BCE_QUEUE_CQ = 0,
81 BCE_QUEUE_SQ = 1,
82 };
83
84 /*
85 * Completion queue entry.
86 */
87 struct bce_qe_completion {
88 uint64_t result;
89 uint64_t data_size;
90 uint16_t qid; /* Source SQ */
91 uint16_t completion_index;
92 uint16_t status;
93 uint16_t flags;
94 #define BCE_CQ_FLAG_PENDING 0x8000
95 } __packed;
96
97 /*
98 * Completion status codes.
99 */
100 enum bce_completion_status {
101 BCE_COMP_SUCCESS = 0,
102 BCE_COMP_ERROR = 1,
103 BCE_COMP_ABORTED = 2,
104 BCE_COMP_NO_SPACE = 3,
105 BCE_COMP_OVERRUN = 4,
106 };
107
108 /*
109 * Submission queue entry.
110 */
111 struct bce_qe_submission {
112 uint64_t length;
113 uint64_t addr;
114 uint64_t segl_addr; /* Scatter-gather list */
115 uint64_t segl_length;
116 } __packed;
117
118 /*
119 * Queue memory configuration (for mailbox registration).
120 */
121 struct bce_queue_memcfg {
122 uint16_t qid;
123 uint16_t el_count;
124 uint16_t vector_or_cq;
125 uint16_t _pad;
126 uint64_t addr;
127 uint64_t length;
128 } __packed;
129
130 /*
131 * Completion data cached per SQ slot.
132 */
133 struct bce_sq_completion_data {
134 uint32_t status;
135 uint64_t data_size;
136 uint64_t result;
137 };
138
139 /*
140 * Completion callback.
141 */
142 struct bce_queue_sq;
143 typedef void (*bce_sq_completion_fn)(struct bce_queue_sq *sq);
144
145 /*
146 * Completion queue.
147 */
148 struct bce_queue_cq {
149 int qid;
150 uint32_t el_count;
151 bus_dma_tag_t dma_tag;
152 bus_dmamap_t dma_map;
153 bus_addr_t dma_addr;
154 struct bce_qe_completion *data;
155 uint32_t index; /* Consumer index */
156 };
157
158 /*
159 * Submission queue.
160 */
161 struct bce_queue_sq {
162 int qid;
163 uint32_t el_size;
164 uint32_t el_count;
165 bus_dma_tag_t dma_tag;
166 bus_dmamap_t dma_map;
167 bus_addr_t dma_addr;
168 void *data;
169 void *userdata;
170
171 /* Submission tracking */
172 volatile int available_commands;
173 uint32_t head;
174 uint32_t tail;
175
176 /* Completion tracking */
177 uint32_t completion_cidx;
178 uint32_t completion_tail;
179 struct bce_sq_completion_data *completion_data;
180 int has_pending;
181 bce_sq_completion_fn completion;
182 };
183
184 /*
185 * Command queue (wraps SQ for synchronous ops).
186 */
187 struct bce_queue_cmdq_result {
188 struct sema cmpl;
189 uint32_t status;
190 uint64_t result;
191 };
192
193 struct bce_queue_cmdq {
194 struct bce_queue_sq *sq;
195 struct mtx lck;
196 struct bce_queue_cmdq_result **tres; /* Pending results per slot */
197 };
198
199 /*
200 * Command queue command IDs.
201 */
202 enum bce_cmdq_cmd {
203 BCE_CMD_REGISTER_QUEUE = 0x20,
204 BCE_CMD_UNREGISTER_QUEUE = 0x30,
205 BCE_CMD_FLUSH_QUEUE = 0x40,
206 BCE_CMD_SET_QUEUE_PROPERTY = 0x50,
207 };
208
209 /*
210 * Register queue command payload (fits in BCE_CMD_SIZE).
211 */
212 struct bce_cmdq_reg_cmd {
213 uint16_t cmd;
214 uint16_t flags;
215 #define BCE_CMDQ_FLAG_NAMED 0x02
216 #define BCE_CMDQ_FLAG_OUT 0x01
217 uint16_t qid;
218 uint16_t _pad;
219 uint16_t el_count;
220 uint16_t vector_or_cq;
221 uint16_t _pad2;
222 uint16_t name_len;
223 char name[0x20];
224 uint64_t addr;
225 uint64_t length;
226 } __packed;
227
228 /*
229 * Simple queue command (unregister/flush).
230 */
231 struct bce_cmdq_simple_cmd {
232 uint16_t cmd;
233 uint16_t flags;
234 uint16_t qid;
235 } __packed;
236
237 /*
238 * Mailbox state.
239 */
240 struct bce_mailbox {
241 struct resource *reg; /* BAR4 resource */
242 volatile int status; /* 0=idle, 1=pending, 2=ready */
243 int initialized;
244 struct sema mb_cmpl;
245 uint64_t mb_result;
246 };
247
248 /*
249 * Main device softc.
250 */
251 struct apple_bce_softc {
252 device_t sc_dev;
253
254 /* PCI resources */
255 int sc_bar2_rid;
256 struct resource *sc_bar2; /* DMA registers */
257 int sc_bar4_rid;
258 struct resource *sc_bar4; /* Mailbox registers */
259
260 /* MSI */
261 int sc_msi_count;
262 int sc_irq_rid_mbox;
263 struct resource *sc_irq_mbox;
264 void *sc_irq_mbox_cookie;
265 int sc_irq_rid_dma;
266 struct resource *sc_irq_dma;
267 void *sc_irq_dma_cookie;
268
269 /* DMA */
270 bus_dma_tag_t sc_dma_tag;
271
272 /* Mailbox */
273 struct bce_mailbox sc_mbox;
274
275 /* Timestamp keepalive */
276 struct callout sc_timestamp_co;
277 struct mtx sc_timestamp_lock;
278 int sc_timestamp_stopped;
279
280 /* Command path */
281 struct bce_queue_cq *sc_cmd_cq;
282 struct bce_queue_cmdq *sc_cmd_cmdq;
283
284 /* Queue registry */
285 void *sc_queues[BCE_MAX_QUEUE_COUNT];
286 struct mtx sc_queues_lock;
287 struct bce_queue_cq *sc_cq_list[BCE_MAX_CQ_COUNT];
288 struct bce_queue_sq *sc_int_sq_list[BCE_MAX_QUEUE_COUNT];
289 device_t sc_vhci_dev;
290 };
291
292 /* Inline helpers */
293 static __inline void *
bce_sq_element(struct bce_queue_sq * sq,uint32_t idx)294 bce_sq_element(struct bce_queue_sq *sq, uint32_t idx)
295 {
296 return ((char *)sq->data + (idx * sq->el_size));
297 }
298
299 static __inline struct bce_qe_completion *
bce_cq_element(struct bce_queue_cq * cq,uint32_t idx)300 bce_cq_element(struct bce_queue_cq *cq, uint32_t idx)
301 {
302 return (&cq->data[idx]);
303 }
304
305 #endif /* _APPLE_BCE_H_ */
306