-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcoremodel.h
More file actions
401 lines (346 loc) · 15.8 KB
/
coremodel.h
File metadata and controls
401 lines (346 loc) · 15.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
/*
* CoreModel C API
*
* Copyright (c) 2022-2026 Corellium Inc.
* SPDX-License-Identifier: Apache-2.0
*
*/
#ifndef _COREMODEL_H
#define _COREMODEL_H
#include <stdint.h>
#include <sys/select.h>
#define COREMODEL_DFLT_PORT 1900
/* Connect to a VM.
* target string like "10.10.0.3:1900"
* Returns error flag.
*/
int coremodel_connect(void **cm, const char *target);
/* Enumerates devices available in VM.
* Returns invalid-terminated array of device structs. The array, as well as
* names in it, is allocated by malloc(3). */
#define COREMODEL_UART 0
#define COREMODEL_I2C 1
#define COREMODEL_SPI 2
#define COREMODEL_GPIO 3
#define COREMODEL_USBH 4
#define COREMODEL_CAN 5
#define COREMODEL_ETH 6
#define COREMODEL_EVENT 7
#define COREMODEL_INVALID (-1)
typedef struct {
int type; /* one of COREMODEL_* constants */
char *name; /* name used to attach to the device */
unsigned num; /* number of subdevices: chip selects (SPI) or pins (GPIO) */
} coremodel_device_list_t;
coremodel_device_list_t *coremodel_list(void *priv);
/* Enumerates subdevices (SPI chip selects, GPIO pins) of a given device in a VM.
* Returns same format as coremodel_list, except num in the returned structures is the
subdevice index. */
coremodel_device_list_t *coremodel_list_subdevices(void *priv, int type, const char *name);
/* Frees a device list */
void coremodel_free_list(coremodel_device_list_t *list);
/* UART */
typedef struct {
/* Called by CoreModel to transmit bytes. Return a >0 number to accept as
* many bytes, or 0 to stall Tx interface (it will have to be un-stalled
* with coremodel_uart_txrdy). */
int (*tx)(void *priv, unsigned len, uint8_t *data);
/* Called by CoreModel to signal a BREAK condition on UART line. */
void (*brk)(void *priv);
/* Called by CoreModel to unstall Rx interface. */
void (*rxrdy)(void *priv);
} coremodel_uart_func_t;
/* Attach to a virtual UART.
* cm coremodel instance
* name name of the UART interface, depends on the VM
* func set of function callbacks to attach
* priv priv value to pass to each callback
* Returns handle of UART, or NULL on failure. */
void *coremodel_attach_uart(void *cm, const char *name, const coremodel_uart_func_t *func, void *priv);
/* Try to push data into the virtual UART.
* uart handle of UART
* len number of bytes to send to the Rx interface
* data data to send
* Returns a >0 number when this many bytes were accepted, or 0 to signal stall
* of the Rx interface (CoreModel will call func->rxrdy to un-stall it). */
int coremodel_uart_rx(void *uart, unsigned len, uint8_t *data);
/* Unstall a stalled Tx interface (signal that CoreModel can once again call
* func->tx to push data).
* uart handle of UART
*/
void coremodel_uart_txrdy(void *uart);
/* I2C */
typedef struct {
/* Called by CoreModel to notify of a START to a device; return -1 to NAK,
* 0 to stall, 1 to accept. A stalled interface will have to be un-stalled
* with coremodel_i2c_ready. */
int (*start)(void *priv);
/* Called by CoreModel to WRITE bytes. Return a >0 number to accept as
* many bytes, -1 to NAK, or 0 to stall interface (it will have to be
* un-stalled with coremodel_i2c_ready). */
int (*write)(void *priv, unsigned len, uint8_t *data);
/* Called by CoreModel to READ bytes. Return a >0 number to produce as
* many bytes, or 0 to stall interface (it will have to be un-stalled
* with coremodel_i2c_ready). */
int (*read)(void *priv, unsigned len, uint8_t *data);
/* Called by CoreModel to notify of a STOP to a device. */
void (*stop)(void *priv);
} coremodel_i2c_func_t;
/* Attach to a virtual I2C bus.
* cm coremodel instance
* name name of the I2C bus, depends on the VM
* addr 7-bit address to attach
* func set of function callbacks to attach
* priv priv value to pass to each callback
* flags behavior flags of device
* Returns handle of I2C interface, or NULL on failure. */
#define COREMODEL_I2C_START_ACK 0x0001 /* device must ACK all starts */
#define COREMODEL_I2C_WRITE_ACK 0x0002 /* device must ACK all writes */
void *coremodel_attach_i2c(void *cm, const char *name, uint8_t addr, const coremodel_i2c_func_t *func, void *priv, uint16_t flags);
/* Push unsolicited I2C READ data. Used to lower access latency.
* i2c handle of I2C interface
* len number of bytes to send to the Rx interface
* data data to send
* Returns number of bytes accepted. */
int coremodel_i2c_push_read(void *i2c, unsigned len, uint8_t *data);
/* Unstall a stalled interface (signal that CoreModel can once again call
* func->start/write/read).
* i2c handle of I2C interface
*/
void coremodel_i2c_ready(void *i2c);
/* SPI */
typedef struct {
/* Called by CoreModel to notify of a CS pin change. */
void (*cs)(void *priv, unsigned csel);
/* Called by CoreModel to write and read bytes. Return a >0 number to
* accept (and produce) as many bytes, or 0 to stall interface (it will
* have to be un-stalled with coremodel_spi_ready). */
int (*xfr)(void *priv, unsigned len, uint8_t *wrdata, uint8_t *rddata);
} coremodel_spi_func_t;
/* Attach to a virtual SPI bus.
* cm coremodel instance
* name name of the SPI bus, depends on the VM
* csel chip select index
* func set of function callbacks to attach
* priv priv value to pass to each callback
* flags behavior flags of device
* Returns handle of SPI interface, or NULL on failure. */
#define COREMODEL_SPI_BLOCK 0x0001 /* device must handle >1 byte transfers */
void *coremodel_attach_spi(void *cm, const char *name, unsigned csel, const coremodel_spi_func_t *func, void *priv, uint16_t flags);
/* Attach to a virtual SPI bus, selecting chip select by name.
* cm coremodel instance
* name name of the SPI bus, depends on the VM
* cselname chip select name
* func set of function callbacks to attach
* priv priv value to pass to each callback
* flags behavior flags of device
* Returns handle of SPI interface, or NULL on failure. */
void *coremodel_attach_spi_name(void *cm, const char *name, const char *cselname, const coremodel_spi_func_t *func, void *priv, uint16_t flags);
/* Unstall a stalled interface (signal that CoreModel can once again call
* func->xfr).
* spi handle of SPI interface
*/
void coremodel_spi_ready(void *spi);
/* GPIO */
typedef struct {
/* Called by CoreModel to update voltage on a GPIO pin. */
void (*notify)(void *priv, int mvolt);
} coremodel_gpio_func_t;
/* Attach to a virtual GPIO pin.
* cm coremodel instance
* name name of the GPIO bank, depends on the VM
* pin pin index within bank
* func set of function callbacks to attach
* priv priv value to pass to each callback
* Returns handle of GPIO interface, or NULL on failure. */
void *coremodel_attach_gpio(void *cm, const char *name, unsigned pin, const coremodel_gpio_func_t *func, void *priv);
/* Attach to a virtual GPIO pin, selecting pin by name.
* cm coremodel instance
* name name of the GPIO bank, depends on the VM
* pinname pin name
* func set of function callbacks to attach
* priv priv value to pass to each callback
* Returns handle of GPIO interface, or NULL on failure. */
void *coremodel_attach_gpio_name(void *cm, const char *name, const char *pinname, const coremodel_gpio_func_t *func, void *priv);
/* Set a tri-state driver on a GPIO pin.
* pin handle of GPIO interface
* drven driver enable
* mvolt voltage to drive (if enabled) in mV */
void coremodel_gpio_set(void *pin, unsigned drven, int mvolt);
/* USB Host (connect a local USB Device to a Host inside VM) */
#define USB_TKN_OUT 0
#define USB_TKN_IN 1
#define USB_TKN_SETUP 2
#define USB_XFR_NAK (-1)
#define USB_XFR_STALL (-2)
typedef struct {
/* Called by CoreModel on USB bus reset. */
void (*rst)(void *priv);
/* Called by CoreModel to perform a USB transfer. Return a >0 number to
* accept / produce as many bytes, or USB_XFR_NAK to pause interface, or
* USB_XFR_STALL to stall interface (create error condition). A paused
* interface will have to be un-paused with coremodel_usbh_ready. */
int (*xfr)(void *priv, uint8_t dev, uint8_t ep, uint8_t tkn, uint8_t *buf, unsigned size, uint8_t end);
} coremodel_usbh_func_t;
/* Attach to a virtual USB host.
* cm coremodel instance
* name name of the USB host, depends on the VM
* port USB port index
* func set of function callbacks to attach
* priv priv value to pass to each callback
* speed requested connection speed
* Returns handle of USB interface, or NULL on failure. */
#define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1
#define USB_SPEED_HIGH 2
#define USB_SPEED_SUPER 3
void *coremodel_attach_usbh(void *cm, const char *name, unsigned port, const coremodel_usbh_func_t *func, void *priv, unsigned speed);
/* Unstall a stalled interface (signal that CoreModel can once again call
* func->xfr).
* usb handle of USB interface
* ep endpoint to signal as ready
* tkn token to signal as ready
*/
void coremodel_usbh_ready(void *usb, uint8_t ep, uint8_t tkn);
/* CAN node */
#define CAN_CTRL1_SEC (1ul << 59)
#define CAN_CTRL1_SDT_MASK (0xFFul << CAN_CTRL1_SDT_SHIFT)
#define CAN_CTRL1_SDT_SHIFT 51
#define CAN_CTRL1_VCID_MASK (0xFFul << CAN_CTRL1_VCID_SHIFT)
#define CAN_CTRL1_VCID_SHIFT 43
#define CAN_CTRL1_PRIO_MASK (0x7FFul << CAN_CTRL1_PRIO_SHIFT)
#define CAN_CTRL1_PRIO_SHIFT 32
#define CAN_CTRL1_AF_MASK (0xFFFFFFFFul << CAN_CTRL1_AF_SHIFT)
#define CAN_CTRL1_AF_SHIFT 0
#define CAN_CTRL_XLF (1ul << 49)
#define CAN_CTRL_FDF (1ul << 48)
#define CAN_CTRL_ID_MASK (0x7FFul << CAN_CTRL_ID_SHIFT)
#define CAN_CTRL_ID_SHIFT 36
#define CAN_CTRL_RTR (1ul << 35)
#define CAN_CTRL_IDE (1ul << 34)
#define CAN_CTRL_EID_MASK (0x3FFFFul << CAN_CTRL_EID_SHIFT)
#define CAN_CTRL_EID_SHIFT 16
#define CAN_CTRL_ERTR (1ul << 15)
#define CAN_CTRL_EDL (1ul << 14)
#define CAN_CTRL_BRS (1ul << 12)
#define CAN_CTRL_ESI (1ul << 11)
#define CAN_CTRL_DLC_MASK (0x7FFul << CAN_CTRL_DLC_SHIFT)
#define CAN_CTRL_DLC_SHIFT 0
#define CAN_ACK 0
#define CAN_NAK 1
#define CAN_STALL (-1)
typedef struct {
int (*tx)(void *priv, uint64_t *ctrl, uint8_t *data); /* return one of CAN_ACK, CAN_NAK, CAN_STALL */
void (*rxcomplete)(void *priv, int nak);
} coremodel_can_func_t;
/* Attach to a virtual CAN bus.
* cm coremodel instance
* name name of the CAN bus, depends on the VM
* func set of function callbacks to attach
* priv priv value to pass to each callback
* Returns handle of CAN interface, or NULL on failure. */
void *coremodel_attach_can(void *cm, const char *name, const coremodel_can_func_t *func, void *priv);
/*
* Check if a CoreModel CAN endpoint would stall if RX was attempted
* can handle of CAN interface
*/
int coremodel_can_rx_busy(void *can);
/* Send a packet to CAN bus.
* can handle of CAN interface
* ctrl control word
* data optional data (if ctrl.DLC != 0)
* Returns 0 on success, 1 if bus is not available because previous packet hasn't been completed yet. */
int coremodel_can_rx(void *can, uint64_t *ctrl, uint8_t *data);
/* Unstall a stalled interface (signal that CoreModel can once again call func->tx).
* can handle of CAN interface
*/
void coremodel_can_ready(void *can);
/* Ethernet */
typedef struct {
int (*tx)(void *priv, unsigned len, uint8_t *data);
} coremodel_eth_func_t;
/* Attach to a virtual Ethernet.
* cm coremodel instance
* name name of the Ethernet interface, depends on the VM
* func set of function callbacks to attach
* priv priv value to pass to each callback
* Returns handle of ethernet, or NULL on failure */
void *coremodel_attach_eth(void *cm, const char *name, const coremodel_eth_func_t *func, void *priv);
/* Try to push data into the virtual ethernet
* eth handle of Ethernet
* len number of bytes to send to the Rx interface
* data data to send
* Returns 0 on success, 1 if bus is not available because previous packet hasn't been completed yet
*/
int coremodel_eth_rx(void *eth, unsigned len, uint8_t *data);
/* Other functions */
/* Prepare fd_sets for select(2).
* cm coremodel instance
* nfds current index of maximum fd in sets + 1
* readfds readfds to update
* writefds writefds to update
* Returns new nfds.
*/
int coremodel_preparefds(void *cm, int nfds, fd_set *readfds, fd_set *writefds);
/* Process fd_sets after select(2).
* cm coremodel instance
* readfds readfds to process
* writefds writefds to process
* Returns error flag.
*/
int coremodel_processfds(void *cm, fd_set *readfds, fd_set *writefds);
/* Simple implementation of a main loop.
* cm coremodel instance
* usec time to spend in loop, in microseconds; negative means forever
* Returns error flag.
*/
int coremodel_mainloop(void *cm, long long usec);
/* Detach any interface.
* handle handle of UART/I2C/SPI/GPIO interface */
void coremodel_detach(void *handle);
/* Close connection to a VM. */
void coremodel_disconnect(void *cm);
/* Event system */
typedef struct {
/* Called by CoreModel to update event state. */
void (*update)(void *priv, uint64_t data0, uint64_t data1, unsigned initial);
/* Called by CoreModel when atomic with response is requested. */
void (*atresp)(void *priv, uint64_t data0, uint64_t data1);
} coremodel_event_func_t;
/* Attach to an event, selected by name.
* cm coremodel instance
* evtname pin name
* func set of function callbacks to attach
* priv priv value to pass to each callback
* Returns handle of event interface, or NULL on failure. */
void *coremodel_attach_event_name(void *cm, const char *evtname, const coremodel_event_func_t *func, void *priv);
/* Send a signal to an event.
* evt handle of event interface
* data0/1 event data
* chgonly only signal event if data changed */
void coremodel_event_signal(void *evt, uint64_t data0, uint64_t data1, unsigned chgonly);
/* Send a signal to an event.
* evt handle of event interface
* data0/1 event data
* op atomic opcode; if EVENT_OP_RESP is set, atresp will be called later with event data from before the atomic */
#define EVENT_OP_XCHG 0
#define EVENT_OP_ADD 1
#define EVENT_OP_SUB 2
#define EVENT_OP_AND 3
#define EVENT_OP_OR 4
#define EVENT_OP_XOR 5
#define EVENT_OP_MIN 6
#define EVENT_OP_MAX 7
#define EVENT_OP_SUBMIN 8
#define EVENT_OP_RESP 0x40
void coremodel_event_atomic(void *evt, uint64_t data0, uint64_t data1, unsigned op);
/* Set value of a wire-type event.
* evt handle of event interface
* value value to put on the wire: LOW, HIGH, LOW | PULSE (pulsed low then back high), HIGH | PULSE (pulsed high then back low), TOGGLE; also | FORCE to force event update */
#define EVENT_WIRE_VALUE_LOW 0x0000
#define EVENT_WIRE_VALUE_HIGH 0x0001
#define EVENT_WIRE_VALUE_PULSE 0x0002
#define EVENT_WIRE_VALUE_TOGGLE 0x4000
#define EVENT_WIRE_VALUE_FORCE 0x8000
void event_signal_wire(void *evt, unsigned val);
#endif