1 /* 2 * Remote I3C Device 3 * 4 * Copyright (c) 2023 Google LLC 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * for more details. 15 */ 16 17 #include "qemu/osdep.h" 18 #include "qemu/bswap.h" 19 #include "qemu/log.h" 20 #include "qemu/fifo8.h" 21 #include "chardev/char-fe.h" 22 #include "trace.h" 23 #include "hw/i3c/i3c.h" 24 #include "hw/i3c/remote-i3c.h" 25 #include "hw/qdev-properties-system.h" 26 27 typedef enum { 28 IBI_RX_STATE_DONE = 0, 29 IBI_RX_STATE_READ_ADDR = 1, 30 IBI_RX_STATE_READ_RNW = 2, 31 IBI_RX_STATE_READ_SIZE = 3, 32 IBI_RX_STATE_READ_DATA = 4, 33 } IBIRXState; 34 35 typedef struct { 36 uint8_t addr; 37 bool is_recv; 38 uint32_t num_bytes; 39 uint8_t *data; 40 } IBIData; 41 42 typedef struct { 43 I3CTarget parent_obj; 44 CharBackend chr; 45 /* For ease of debugging. */ 46 47 struct { 48 char *name; 49 uint32_t buf_size; 50 } cfg; 51 52 /* Intermediate buffer to store IBI data received over socket. */ 53 IBIData ibi_data; 54 Fifo8 tx_fifo; 55 Fifo8 rx_fifo; 56 uint8_t current_cmd; 57 IBIRXState ibi_rx_state; 58 /* 59 * To keep track of where we are in reading in data that's longer than 60 * 1-byte. 61 */ 62 uint32_t ibi_bytes_rxed; 63 } RemoteI3C; 64 remote_i3c_recv(I3CTarget * t,uint8_t * data,uint32_t num_to_read)65 static uint32_t remote_i3c_recv(I3CTarget *t, uint8_t *data, 66 uint32_t num_to_read) 67 { 68 RemoteI3C *i3c = REMOTE_I3C(t); 69 uint8_t type = REMOTE_I3C_RECV; 70 uint32_t num_read; 71 72 qemu_chr_fe_write_all(&i3c->chr, &type, 1); 73 uint32_t num_to_read_le = cpu_to_le32(num_to_read); 74 qemu_chr_fe_write_all(&i3c->chr, (uint8_t *)&num_to_read_le, 75 sizeof(num_to_read_le)); 76 /* 77 * The response will first contain the size of the packet, as a LE uint32. 78 */ 79 qemu_chr_fe_read_all(&i3c->chr, (uint8_t *)&num_read, sizeof(num_read)); 80 81 num_read = le32_to_cpu(num_read); 82 qemu_chr_fe_read_all(&i3c->chr, data, num_read); 83 trace_remote_i3c_recv(i3c->cfg.name, num_read, num_to_read); 84 return num_read; 85 } 86 remote_i3c_tx_in_progress(RemoteI3C * i3c)87 static inline bool remote_i3c_tx_in_progress(RemoteI3C *i3c) 88 { 89 return !fifo8_is_empty(&i3c->tx_fifo); 90 } 91 remote_i3c_chr_send_bytes(RemoteI3C * i3c)92 static int remote_i3c_chr_send_bytes(RemoteI3C *i3c) 93 { 94 uint32_t i; 95 uint32_t num_bytes = fifo8_num_used(&i3c->tx_fifo); 96 g_autofree uint8_t *buf = g_new0(uint8_t, num_bytes); 97 98 qemu_chr_fe_write_all(&i3c->chr, &i3c->current_cmd, 99 sizeof(i3c->current_cmd)); 100 101 /* The FIFO data is stored in a ring buffer, move it into a linear one. */ 102 for (i = 0; i < num_bytes; i++) { 103 buf[i] = fifo8_pop(&i3c->tx_fifo); 104 } 105 106 uint32_t num_bytes_le = cpu_to_le32(num_bytes); 107 qemu_chr_fe_write_all(&i3c->chr, (uint8_t *)&num_bytes_le, 4); 108 qemu_chr_fe_write_all(&i3c->chr, buf, num_bytes); 109 trace_remote_i3c_send(i3c->cfg.name, num_bytes, i3c->current_cmd == 110 REMOTE_I3C_HANDLE_CCC_WRITE); 111 112 return 0; 113 } 114 remote_i3c_tx_fifo_push(RemoteI3C * i3c,const uint8_t * data,uint32_t num_to_send,uint32_t * num_sent)115 static bool remote_i3c_tx_fifo_push(RemoteI3C *i3c, const uint8_t *data, 116 uint32_t num_to_send, uint32_t *num_sent) 117 { 118 uint32_t num_to_push = num_to_send; 119 bool ack = true; 120 121 /* 122 * For performance reasons, we buffer data being sent from the controller to 123 * us. 124 * If this FIFO has data in it, we transmit it when we receive an I3C 125 * STOP or START. 126 */ 127 if (fifo8_num_free(&i3c->tx_fifo) < num_to_send) { 128 qemu_log_mask(LOG_GUEST_ERROR, "%s-%s: TX FIFO buffer full.\n", 129 object_get_canonical_path(OBJECT(i3c)), i3c->cfg.name); 130 num_to_push = fifo8_num_free(&i3c->tx_fifo); 131 ack = false; 132 } 133 134 *num_sent = num_to_push; 135 for (uint32_t i = 0; i < num_to_push; i++) { 136 fifo8_push(&i3c->tx_fifo, data[i]); 137 } 138 139 return ack; 140 } 141 remote_i3c_send(I3CTarget * t,const uint8_t * data,uint32_t num_to_send,uint32_t * num_sent)142 static int remote_i3c_send(I3CTarget *t, const uint8_t *data, 143 uint32_t num_to_send, uint32_t *num_sent) 144 { 145 RemoteI3C *i3c = REMOTE_I3C(t); 146 i3c->current_cmd = REMOTE_I3C_SEND; 147 if (!remote_i3c_tx_fifo_push(i3c, data, num_to_send, num_sent)) { 148 return -1; 149 } 150 151 return 0; 152 } 153 remote_i3c_handle_ccc_read(I3CTarget * t,uint8_t * data,uint32_t num_to_read,uint32_t * num_read)154 static int remote_i3c_handle_ccc_read(I3CTarget *t, uint8_t *data, 155 uint32_t num_to_read, uint32_t *num_read) 156 { 157 RemoteI3C *i3c = REMOTE_I3C(t); 158 uint8_t type = REMOTE_I3C_HANDLE_CCC_READ; 159 160 qemu_chr_fe_write_all(&i3c->chr, &type, 1); 161 /* 162 * The response will first contain the size of the packet, as a LE uint32. 163 */ 164 qemu_chr_fe_read_all(&i3c->chr, (uint8_t *)num_read, 4); 165 *num_read = le32_to_cpu(*num_read); 166 qemu_chr_fe_read_all(&i3c->chr, data, *num_read); 167 trace_remote_i3c_ccc_read(i3c->cfg.name, *num_read, num_to_read); 168 169 return 0; 170 } 171 remote_i3c_handle_ccc_write(I3CTarget * t,const uint8_t * data,uint32_t num_to_send,uint32_t * num_sent)172 static int remote_i3c_handle_ccc_write(I3CTarget *t, const uint8_t *data, 173 uint32_t num_to_send, uint32_t *num_sent) 174 { 175 RemoteI3C *i3c = REMOTE_I3C(t); 176 i3c->current_cmd = REMOTE_I3C_HANDLE_CCC_WRITE; 177 if (!remote_i3c_tx_fifo_push(i3c, data, num_to_send, num_sent)) { 178 return -1; 179 } 180 181 return 0; 182 } 183 remote_i3c_event(I3CTarget * t,enum I3CEvent event)184 static int remote_i3c_event(I3CTarget *t, enum I3CEvent event) 185 { 186 RemoteI3C *i3c = REMOTE_I3C(t); 187 uint8_t type; 188 trace_remote_i3c_event(i3c->cfg.name, event); 189 switch (event) { 190 case I3C_START_RECV: 191 type = REMOTE_I3C_START_RECV; 192 break; 193 case I3C_START_SEND: 194 type = REMOTE_I3C_START_SEND; 195 break; 196 case I3C_STOP: 197 type = REMOTE_I3C_STOP; 198 break; 199 case I3C_NACK: 200 type = REMOTE_I3C_NACK; 201 break; 202 default: 203 qemu_log_mask(LOG_GUEST_ERROR, "%s-%s: Unknown I3C event %d\n", 204 object_get_canonical_path(OBJECT(i3c)), i3c->cfg.name, 205 event); 206 return -1; 207 } 208 209 /* 210 * If we have a transfer buffered, send it out before we tell the remote 211 * target about the next event. 212 */ 213 if (remote_i3c_tx_in_progress(i3c)) { 214 remote_i3c_chr_send_bytes(i3c); 215 } 216 217 qemu_chr_fe_write_all(&i3c->chr, &type, 1); 218 return 0; 219 } 220 remote_i3c_chr_event(void * opaque,QEMUChrEvent evt)221 static void remote_i3c_chr_event(void *opaque, QEMUChrEvent evt) 222 { 223 switch (evt) { 224 case CHR_EVENT_OPENED: 225 case CHR_EVENT_CLOSED: 226 case CHR_EVENT_BREAK: 227 case CHR_EVENT_MUX_IN: 228 case CHR_EVENT_MUX_OUT: 229 /* 230 * Ignore events. 231 * Our behavior stays the same regardless of what happens. 232 */ 233 break; 234 default: 235 g_assert_not_reached(); 236 } 237 } 238 remote_i3c_rx_ibi(RemoteI3C * i3c,const uint8_t * buf,int size)239 static void remote_i3c_rx_ibi(RemoteI3C *i3c, const uint8_t *buf, int size) 240 { 241 uint32_t p_buf = 0; 242 while (p_buf < size) { 243 switch (i3c->ibi_rx_state) { 244 /* This is the start of a new IBI request. */ 245 case IBI_RX_STATE_DONE: 246 i3c->ibi_rx_state = IBI_RX_STATE_READ_ADDR; 247 p_buf++; 248 break; 249 case IBI_RX_STATE_READ_ADDR: 250 i3c->ibi_data.addr = buf[p_buf]; 251 p_buf++; 252 i3c->ibi_rx_state = IBI_RX_STATE_READ_RNW; 253 break; 254 case IBI_RX_STATE_READ_RNW: 255 i3c->ibi_data.is_recv = buf[p_buf]; 256 p_buf++; 257 i3c->ibi_rx_state = IBI_RX_STATE_READ_SIZE; 258 break; 259 case IBI_RX_STATE_READ_SIZE: 260 i3c->ibi_data.num_bytes |= ((uint32_t)buf[p_buf] << 261 (8 * i3c->ibi_bytes_rxed)); 262 i3c->ibi_bytes_rxed++; 263 p_buf++; 264 /* 265 * If we're done reading the num_bytes portion, move on to reading 266 * data. 267 */ 268 if (i3c->ibi_bytes_rxed == sizeof(i3c->ibi_data.num_bytes)) { 269 i3c->ibi_data.num_bytes = le32_to_cpu(i3c->ibi_data.num_bytes); 270 i3c->ibi_bytes_rxed = 0; 271 i3c->ibi_rx_state = IBI_RX_STATE_READ_DATA; 272 /* If there's no data to read, we're done. */ 273 if (i3c->ibi_data.num_bytes == 0) { 274 /* 275 * Sanity check to see if the remote target is doing 276 * something wonky. This would only happen if it sends 277 * another IBI before the first one has been ACKed/NACKed 278 * by the controller. 279 * We'll try to recover by just exiting early and discarding 280 * the leftover bytes. 281 */ 282 if (p_buf < size) { 283 qemu_log_mask(LOG_GUEST_ERROR, "%s-%s: Remote target " 284 "sent trailing bytes at the end of the " 285 "IBI request.", 286 object_get_canonical_path(OBJECT(i3c)), 287 i3c->cfg.name); 288 return; 289 } 290 i3c->ibi_rx_state = IBI_RX_STATE_DONE; 291 } else { 292 /* 293 * We have IBI bytes to read, allocate memory for it. 294 * Freed when we're done sending the IBI to the controller. 295 */ 296 i3c->ibi_data.data = g_new0(uint8_t, 297 i3c->ibi_data.num_bytes); 298 } 299 } 300 break; 301 case IBI_RX_STATE_READ_DATA: 302 i3c->ibi_data.data[i3c->ibi_bytes_rxed] = buf[p_buf]; 303 i3c->ibi_bytes_rxed++; 304 p_buf++; 305 if (i3c->ibi_bytes_rxed == i3c->ibi_data.num_bytes) { 306 /* 307 * Sanity check to see if the remote target is doing something 308 * wonky. This would only happen if it sends another IBI before 309 * the first one has been ACKed/NACKed by the controller. 310 * We'll try to recover by just exiting early and discarding the 311 * leftover bytes. 312 */ 313 if (p_buf < size) { 314 qemu_log_mask(LOG_GUEST_ERROR, "%s-%s: Remote target " 315 "sent trailing bytes at the end of the " 316 "IBI request.", 317 object_get_canonical_path(OBJECT(i3c)), i3c->cfg.name); 318 return; 319 } 320 i3c->ibi_rx_state = IBI_RX_STATE_DONE; 321 } 322 break; 323 default: 324 qemu_log_mask(LOG_GUEST_ERROR, "%s-%s: Remote target IBI state " 325 "machine reached unknown state 0x%x\n", 326 object_get_canonical_path(OBJECT(i3c)), i3c->cfg.name, 327 i3c->ibi_rx_state); 328 g_assert_not_reached(); 329 } 330 } 331 } 332 remote_i3c_ibi_rx_state_reset(RemoteI3C * i3c)333 static void remote_i3c_ibi_rx_state_reset(RemoteI3C *i3c) 334 { 335 if (i3c->ibi_data.num_bytes) { 336 free(i3c->ibi_data.data); 337 } 338 i3c->ibi_data.addr = 0; 339 i3c->ibi_data.is_recv = 0; 340 i3c->ibi_data.num_bytes = 0; 341 i3c->ibi_bytes_rxed = 0; 342 i3c->ibi_rx_state = IBI_RX_STATE_DONE; 343 } 344 remote_i3c_do_ibi(RemoteI3C * i3c)345 static void remote_i3c_do_ibi(RemoteI3C *i3c) 346 { 347 uint32_t i; 348 uint8_t resp = REMOTE_I3C_IBI_ACK; 349 350 trace_remote_i3c_do_ibi(i3c->cfg.name, i3c->ibi_data.addr, 351 i3c->ibi_data.is_recv); 352 if (i3c_target_send_ibi(&i3c->parent_obj, i3c->ibi_data.addr, 353 i3c->ibi_data.is_recv)) { 354 resp = REMOTE_I3C_IBI_NACK; 355 } else { 356 for (i = 0; i < i3c->ibi_data.num_bytes; i++) { 357 if (i3c_target_send_ibi_bytes(&i3c->parent_obj, 358 i3c->ibi_data.data[i])) { 359 resp = REMOTE_I3C_IBI_DATA_NACK; 360 break; 361 } 362 } 363 } 364 365 if (i3c_target_ibi_finish(&i3c->parent_obj, 0x00)) { 366 resp = REMOTE_I3C_IBI_NACK; 367 } 368 qemu_chr_fe_write_all(&i3c->chr, &resp, sizeof(resp)); 369 remote_i3c_ibi_rx_state_reset(i3c); 370 } 371 remote_i3c_chr_can_receive(void * opaque)372 static int remote_i3c_chr_can_receive(void *opaque) 373 { 374 return 1; 375 } 376 remote_i3c_chr_receive(void * opaque,const uint8_t * buf,int size)377 static void remote_i3c_chr_receive(void *opaque, const uint8_t *buf, int size) 378 { 379 RemoteI3C *i3c = REMOTE_I3C(opaque); 380 381 /* 382 * The only things we expect to receive unprompted are: 383 * - An ACK of a previous transfer 384 * - A NACK of a previous transfer 385 * - An IBI requested by the remote target. 386 * - Bytes for an IBI request. 387 */ 388 /* If we're in the middle of handling an IBI request, parse it here. */ 389 if (i3c->ibi_rx_state != IBI_RX_STATE_DONE) { 390 remote_i3c_rx_ibi(i3c, buf, size); 391 /* If we finished reading the IBI, do it. */ 392 if (i3c->ibi_rx_state == IBI_RX_STATE_DONE) { 393 remote_i3c_do_ibi(i3c); 394 } 395 return; 396 } 397 398 switch (buf[0]) { 399 case REMOTE_I3C_RX_ACK: 400 break; 401 case REMOTE_I3C_RX_NACK: 402 qemu_log_mask(LOG_GUEST_ERROR, "%s-%s: Received NACK from remote " 403 "target\n", object_get_canonical_path(OBJECT(i3c)), 404 i3c->cfg.name); 405 break; 406 case REMOTE_I3C_IBI: 407 remote_i3c_rx_ibi(i3c, buf, size); 408 /* If we finished reading the IBI, do it. */ 409 if (i3c->ibi_rx_state == IBI_RX_STATE_DONE) { 410 remote_i3c_do_ibi(i3c); 411 } 412 break; 413 default: 414 qemu_log_mask(LOG_GUEST_ERROR, "%s-%s: Unknown response 0x%x\n", 415 object_get_canonical_path(OBJECT(i3c)), i3c->cfg.name, 416 buf[0]); 417 break; 418 } 419 } 420 remote_i3c_realize(DeviceState * dev,Error ** errp)421 static void remote_i3c_realize(DeviceState *dev, Error **errp) 422 { 423 RemoteI3C *i3c = REMOTE_I3C(dev); 424 425 fifo8_create(&i3c->tx_fifo, i3c->cfg.buf_size); 426 fifo8_create(&i3c->rx_fifo, i3c->cfg.buf_size); 427 i3c->ibi_data.data = g_new0(uint8_t, i3c->cfg.buf_size); 428 remote_i3c_ibi_rx_state_reset(i3c); 429 430 qemu_chr_fe_set_handlers(&i3c->chr, remote_i3c_chr_can_receive, 431 remote_i3c_chr_receive, remote_i3c_chr_event, 432 NULL, OBJECT(i3c), NULL, true); 433 } 434 435 static Property remote_i3c_props[] = { 436 DEFINE_PROP_CHR("chardev", RemoteI3C, chr), 437 DEFINE_PROP_UINT32("buf-size", RemoteI3C, cfg.buf_size, 0x10000), 438 DEFINE_PROP_STRING("device-name", RemoteI3C, cfg.name), 439 DEFINE_PROP_END_OF_LIST(), 440 }; 441 remote_i3c_class_init(ObjectClass * klass,void * data)442 static void remote_i3c_class_init(ObjectClass *klass, void *data) 443 { 444 DeviceClass *dc = DEVICE_CLASS(klass); 445 I3CTargetClass *k = I3C_TARGET_CLASS(klass); 446 447 k->recv = &remote_i3c_recv; 448 k->send = &remote_i3c_send; 449 k->event = &remote_i3c_event; 450 k->handle_ccc_read = &remote_i3c_handle_ccc_read; 451 k->handle_ccc_write = &remote_i3c_handle_ccc_write; 452 device_class_set_props(dc, remote_i3c_props); 453 dc->realize = remote_i3c_realize; 454 } 455 456 static const TypeInfo remote_i3c_type = { 457 .name = TYPE_REMOTE_I3C, 458 .parent = TYPE_I3C_TARGET, 459 .instance_size = sizeof(RemoteI3C), 460 .class_size = sizeof(I3CTargetClass), 461 .class_init = remote_i3c_class_init, 462 }; 463 remote_i3c_register(void)464 static void remote_i3c_register(void) 465 { 466 type_register_static(&remote_i3c_type); 467 } 468 469 type_init(remote_i3c_register) 470