1 /* 2 * CTU CAN FD PCI device emulation 3 * http://canbus.pages.fel.cvut.cz/ 4 * 5 * Copyright (c) 2019 Jan Charvat (jancharvat.charvat@gmail.com) 6 * 7 * Based on Kvaser PCI CAN device (SJA1000 based) emulation implemented by 8 * Jin Yang and Pavel Pisa 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a copy 11 * of this software and associated documentation files (the "Software"), to deal 12 * in the Software without restriction, including without limitation the rights 13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 * copies of the Software, and to permit persons to whom the Software is 15 * furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be included in 18 * all copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 * THE SOFTWARE. 27 */ 28 29 #include "qemu/osdep.h" 30 #include "qemu/log.h" 31 #include "chardev/char.h" 32 #include "hw/irq.h" 33 #include "migration/vmstate.h" 34 #include "net/can_emu.h" 35 36 #include "ctucan_core.h" 37 38 #ifndef DEBUG_CAN 39 #define DEBUG_CAN 0 40 #endif /*DEBUG_CAN*/ 41 42 #define DPRINTF(fmt, ...) \ 43 do { \ 44 if (DEBUG_CAN) { \ 45 qemu_log("[ctucan]: " fmt , ## __VA_ARGS__); \ 46 } \ 47 } while (0) 48 49 static void ctucan_buff2frame(const uint8_t *buff, qemu_can_frame *frame) 50 { 51 frame->can_id = 0; 52 frame->can_dlc = 0; 53 frame->flags = 0; 54 55 if (buff == NULL) { 56 return; 57 } 58 { 59 union ctu_can_fd_frame_form_w frame_form_w; 60 union ctu_can_fd_identifier_w identifier_w; 61 unsigned int ide; 62 uint32_t w; 63 64 w = le32_to_cpu(*(uint32_t *)buff); 65 frame_form_w = (union ctu_can_fd_frame_form_w)w; 66 frame->can_dlc = can_dlc2len(frame_form_w.s.dlc); 67 68 w = le32_to_cpu(*(uint32_t *)(buff + 4)); 69 identifier_w = (union ctu_can_fd_identifier_w)w; 70 71 ide = frame_form_w.s.ide; 72 if (ide) { 73 frame->can_id = (identifier_w.s.identifier_base << 18) | 74 identifier_w.s.identifier_ext; 75 frame->can_id |= QEMU_CAN_EFF_FLAG; 76 } else { 77 frame->can_id = identifier_w.s.identifier_base; 78 } 79 80 if (frame_form_w.s.esi_rsv) { 81 frame->flags |= QEMU_CAN_FRMF_ESI; 82 } 83 84 if (frame_form_w.s.rtr) { 85 frame->can_id |= QEMU_CAN_RTR_FLAG; 86 } 87 88 if (frame_form_w.s.fdf) { /*CAN FD*/ 89 frame->flags |= QEMU_CAN_FRMF_TYPE_FD; 90 if (frame_form_w.s.brs) { 91 frame->flags |= QEMU_CAN_FRMF_BRS; 92 } 93 } 94 } 95 96 memcpy(frame->data, buff + 0x10, 0x40); 97 } 98 99 100 static int ctucan_frame2buff(const qemu_can_frame *frame, uint8_t *buff) 101 { 102 unsigned int bytes_cnt = -1; 103 memset(buff, 0, CTUCAN_MSG_MAX_LEN * sizeof(*buff)); 104 105 if (frame == NULL) { 106 return bytes_cnt; 107 } 108 { 109 union ctu_can_fd_frame_form_w frame_form_w; 110 union ctu_can_fd_identifier_w identifier_w; 111 112 frame_form_w.u32 = 0; 113 identifier_w.u32 = 0; 114 115 bytes_cnt = frame->can_dlc; 116 bytes_cnt = (bytes_cnt + 3) & ~3; 117 bytes_cnt += 16; 118 frame_form_w.s.rwcnt = (bytes_cnt >> 2) - 1; 119 120 frame_form_w.s.dlc = can_len2dlc(frame->can_dlc); 121 122 if (frame->can_id & QEMU_CAN_EFF_FLAG) { 123 frame_form_w.s.ide = 1; 124 identifier_w.s.identifier_base = 125 (frame->can_id & 0x1FFC0000) >> 18; 126 identifier_w.s.identifier_ext = frame->can_id & 0x3FFFF; 127 } else { 128 identifier_w.s.identifier_base = frame->can_id & 0x7FF; 129 } 130 131 if (frame->flags & QEMU_CAN_FRMF_ESI) { 132 frame_form_w.s.esi_rsv = 1; 133 } 134 135 if (frame->can_id & QEMU_CAN_RTR_FLAG) { 136 frame_form_w.s.rtr = 1; 137 } 138 139 if (frame->flags & QEMU_CAN_FRMF_TYPE_FD) { /*CAN FD*/ 140 frame_form_w.s.fdf = 1; 141 if (frame->flags & QEMU_CAN_FRMF_BRS) { 142 frame_form_w.s.brs = 1; 143 } 144 } 145 *(uint32_t *)buff = cpu_to_le32(frame_form_w.u32); 146 *(uint32_t *)(buff + 4) = cpu_to_le32(identifier_w.u32); 147 } 148 149 memcpy(buff + 0x10, frame->data, 0x40); 150 151 return bytes_cnt; 152 } 153 154 static void ctucan_update_irq(CtuCanCoreState *s) 155 { 156 union ctu_can_fd_int_stat int_rq; 157 158 int_rq.u32 = 0; 159 160 if (s->rx_status_rx_settings.s.rxfrc) { 161 int_rq.s.rbnei = 1; 162 } 163 164 int_rq.u32 &= ~s->int_mask.u32; 165 s->int_stat.u32 |= int_rq.u32; 166 if (s->int_stat.u32 & s->int_ena.u32) { 167 qemu_irq_raise(s->irq); 168 } else { 169 qemu_irq_lower(s->irq); 170 } 171 } 172 173 static void ctucan_update_txnf(CtuCanCoreState *s) 174 { 175 int i; 176 int txnf; 177 unsigned int buff_st; 178 179 txnf = 0; 180 181 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { 182 buff_st = (s->tx_status.u32 >> (i * 4)) & 0xf; 183 if (buff_st == TXT_ETY) { 184 txnf = 1; 185 } 186 } 187 s->status.s.txnf = txnf; 188 } 189 190 void ctucan_hardware_reset(CtuCanCoreState *s) 191 { 192 DPRINTF("Hardware reset in progress!!!\n"); 193 int i; 194 unsigned int buff_st; 195 uint32_t buff_st_mask; 196 197 s->tx_status.u32 = 0; 198 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { 199 buff_st_mask = 0xf << (i * 4); 200 buff_st = TXT_ETY; 201 s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) | 202 (buff_st << (i * 4)); 203 } 204 s->status.s.idle = 1; 205 206 ctucan_update_txnf(s); 207 208 s->rx_status_rx_settings.u32 = 0; 209 s->rx_tail_pos = 0; 210 s->rx_cnt = 0; 211 s->rx_frame_rem = 0; 212 213 /* Flush RX buffer */ 214 s->rx_tail_pos = 0; 215 s->rx_cnt = 0; 216 s->rx_frame_rem = 0; 217 218 /* Set on progdokum reset value */ 219 s->mode_settings.u32 = 0; 220 s->mode_settings.s.fde = 1; 221 222 s->int_stat.u32 = 0; 223 s->int_ena.u32 = 0; 224 s->int_mask.u32 = 0; 225 226 s->rx_status_rx_settings.u32 = 0; 227 s->rx_status_rx_settings.s.rxe = 0; 228 229 s->rx_fr_ctr.u32 = 0; 230 s->tx_fr_ctr.u32 = 0; 231 232 s->yolo_reg.s.yolo_val = 3735928559; 233 234 qemu_irq_lower(s->irq); 235 } 236 237 static void ctucan_send_ready_buffers(CtuCanCoreState *s) 238 { 239 qemu_can_frame frame; 240 uint8_t *pf; 241 int buff2tx_idx; 242 uint32_t tx_prio_max; 243 unsigned int buff_st; 244 uint32_t buff_st_mask; 245 246 if (!s->mode_settings.s.ena) { 247 return; 248 } 249 250 do { 251 union ctu_can_fd_int_stat int_stat; 252 int i; 253 buff2tx_idx = -1; 254 tx_prio_max = 0; 255 256 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { 257 uint32_t prio; 258 259 buff_st_mask = 0xf << (i * 4); 260 buff_st = (s->tx_status.u32 >> (i * 4)) & 0xf; 261 262 if (buff_st != TXT_RDY) { 263 continue; 264 } 265 prio = (s->tx_priority.u32 >> (i * 4)) & 0x7; 266 if (tx_prio_max < prio) { 267 tx_prio_max = prio; 268 buff2tx_idx = i; 269 } 270 } 271 if (buff2tx_idx == -1) { 272 break; 273 } 274 buff_st_mask = 0xf << (buff2tx_idx * 4); 275 buff_st = (s->tx_status.u32 >> (buff2tx_idx * 4)) & 0xf; 276 int_stat.u32 = 0; 277 buff_st = TXT_RDY; 278 pf = s->tx_buffer[buff2tx_idx].data; 279 ctucan_buff2frame(pf, &frame); 280 s->status.s.idle = 0; 281 s->status.s.txs = 1; 282 can_bus_client_send(&s->bus_client, &frame, 1); 283 s->status.s.idle = 1; 284 s->status.s.txs = 0; 285 s->tx_fr_ctr.s.tx_fr_ctr_val++; 286 buff_st = TXT_TOK; 287 int_stat.s.txi = 1; 288 int_stat.s.txbhci = 1; 289 s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; 290 s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) | 291 (buff_st << (buff2tx_idx * 4)); 292 } while (1); 293 } 294 295 #define CTUCAN_CORE_TXBUFF_SPAN \ 296 (CTU_CAN_FD_TXTB2_DATA_1 - CTU_CAN_FD_TXTB1_DATA_1) 297 298 void ctucan_mem_write(CtuCanCoreState *s, hwaddr addr, uint64_t val, 299 unsigned size) 300 { 301 int i; 302 303 DPRINTF("write 0x%02llx addr 0x%02x\n", 304 (unsigned long long)val, (unsigned int)addr); 305 306 if (addr > CTUCAN_CORE_MEM_SIZE) { 307 return; 308 } 309 310 if (addr >= CTU_CAN_FD_TXTB1_DATA_1) { 311 int buff_num; 312 addr -= CTU_CAN_FD_TXTB1_DATA_1; 313 buff_num = addr / CTUCAN_CORE_TXBUFF_SPAN; 314 addr %= CTUCAN_CORE_TXBUFF_SPAN; 315 if (buff_num < CTUCAN_CORE_TXBUF_NUM) { 316 uint32_t *bufp = (uint32_t *)(s->tx_buffer[buff_num].data + addr); 317 *bufp = cpu_to_le32(val); 318 } 319 } else { 320 switch (addr & ~3) { 321 case CTU_CAN_FD_MODE: 322 s->mode_settings.u32 = (uint32_t)val; 323 if (s->mode_settings.s.rst) { 324 ctucan_hardware_reset(s); 325 s->mode_settings.s.rst = 0; 326 } 327 break; 328 case CTU_CAN_FD_COMMAND: 329 { 330 union ctu_can_fd_command command; 331 command.u32 = (uint32_t)val; 332 if (command.s.cdo) { 333 s->status.s.dor = 0; 334 } 335 if (command.s.rrb) { 336 s->rx_tail_pos = 0; 337 s->rx_cnt = 0; 338 s->rx_frame_rem = 0; 339 s->rx_status_rx_settings.s.rxfrc = 0; 340 } 341 if (command.s.txfcrst) { 342 s->tx_fr_ctr.s.tx_fr_ctr_val = 0; 343 } 344 if (command.s.rxfcrst) { 345 s->rx_fr_ctr.s.rx_fr_ctr_val = 0; 346 } 347 break; 348 } 349 case CTU_CAN_FD_INT_STAT: 350 s->int_stat.u32 &= ~(uint32_t)val; 351 break; 352 case CTU_CAN_FD_INT_ENA_SET: 353 s->int_ena.u32 |= (uint32_t)val; 354 break; 355 case CTU_CAN_FD_INT_ENA_CLR: 356 s->int_ena.u32 &= ~(uint32_t)val; 357 break; 358 case CTU_CAN_FD_INT_MASK_SET: 359 s->int_mask.u32 |= (uint32_t)val; 360 break; 361 case CTU_CAN_FD_INT_MASK_CLR: 362 s->int_mask.u32 &= ~(uint32_t)val; 363 break; 364 case CTU_CAN_FD_TX_COMMAND: 365 if (s->mode_settings.s.ena) { 366 union ctu_can_fd_tx_command tx_command; 367 union ctu_can_fd_tx_command mask; 368 unsigned int buff_st; 369 uint32_t buff_st_mask; 370 371 tx_command.u32 = (uint32_t)val; 372 mask.u32 = 0; 373 mask.s.txb1 = 1; 374 375 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { 376 if (!(tx_command.u32 & (mask.u32 << i))) { 377 continue; 378 } 379 buff_st_mask = 0xf << (i * 4); 380 buff_st = (s->tx_status.u32 >> (i * 4)) & 0xf; 381 if (tx_command.s.txca) { 382 if (buff_st == TXT_RDY) { 383 buff_st = TXT_ABT; 384 } 385 } 386 if (tx_command.s.txcr) { 387 if ((buff_st == TXT_TOK) || (buff_st == TXT_ERR) || 388 (buff_st == TXT_ABT) || (buff_st == TXT_ETY)) 389 buff_st = TXT_RDY; 390 } 391 if (tx_command.s.txce) { 392 if ((buff_st == TXT_TOK) || (buff_st == TXT_ERR) || 393 (buff_st == TXT_ABT)) 394 buff_st = TXT_ETY; 395 } 396 s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) | 397 (buff_st << (i * 4)); 398 } 399 400 ctucan_send_ready_buffers(s); 401 ctucan_update_txnf(s); 402 } 403 break; 404 case CTU_CAN_FD_TX_PRIORITY: 405 s->tx_priority.u32 = (uint32_t)val; 406 break; 407 } 408 409 ctucan_update_irq(s); 410 } 411 412 return; 413 } 414 415 uint64_t ctucan_mem_read(CtuCanCoreState *s, hwaddr addr, unsigned size) 416 { 417 uint32_t val = 0; 418 419 DPRINTF("read addr 0x%02x ...\n", (unsigned int)addr); 420 421 if (addr > CTUCAN_CORE_MEM_SIZE) { 422 return 0; 423 } 424 425 switch (addr & ~3) { 426 case CTU_CAN_FD_DEVICE_ID: 427 { 428 union ctu_can_fd_device_id_version idver; 429 idver.u32 = 0; 430 idver.s.device_id = CTU_CAN_FD_ID; 431 idver.s.ver_major = 2; 432 idver.s.ver_minor = 2; 433 val = idver.u32; 434 } 435 break; 436 case CTU_CAN_FD_MODE: 437 val = s->mode_settings.u32; 438 break; 439 case CTU_CAN_FD_STATUS: 440 val = s->status.u32; 441 break; 442 case CTU_CAN_FD_INT_STAT: 443 val = s->int_stat.u32; 444 break; 445 case CTU_CAN_FD_INT_ENA_SET: 446 case CTU_CAN_FD_INT_ENA_CLR: 447 val = s->int_ena.u32; 448 break; 449 case CTU_CAN_FD_INT_MASK_SET: 450 case CTU_CAN_FD_INT_MASK_CLR: 451 val = s->int_mask.u32; 452 break; 453 case CTU_CAN_FD_RX_MEM_INFO: 454 s->rx_mem_info.u32 = 0; 455 s->rx_mem_info.s.rx_buff_size = CTUCAN_RCV_BUF_LEN >> 2; 456 s->rx_mem_info.s.rx_mem_free = (CTUCAN_RCV_BUF_LEN - 457 s->rx_cnt) >> 2; 458 val = s->rx_mem_info.u32; 459 break; 460 case CTU_CAN_FD_RX_POINTERS: 461 { 462 uint32_t rx_head_pos = s->rx_tail_pos + s->rx_cnt; 463 rx_head_pos %= CTUCAN_RCV_BUF_LEN; 464 s->rx_pointers.s.rx_wpp = rx_head_pos; 465 s->rx_pointers.s.rx_rpp = s->rx_tail_pos; 466 val = s->rx_pointers.u32; 467 break; 468 } 469 case CTU_CAN_FD_RX_STATUS: 470 case CTU_CAN_FD_RX_SETTINGS: 471 if (!s->rx_status_rx_settings.s.rxfrc) { 472 s->rx_status_rx_settings.s.rxe = 1; 473 } else { 474 s->rx_status_rx_settings.s.rxe = 0; 475 } 476 if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) { 477 s->rx_status_rx_settings.s.rxf = 1; 478 } else { 479 s->rx_status_rx_settings.s.rxf = 0; 480 } 481 val = s->rx_status_rx_settings.u32; 482 break; 483 case CTU_CAN_FD_RX_DATA: 484 if (s->rx_cnt) { 485 memcpy(&val, s->rx_buff + s->rx_tail_pos, 4); 486 val = le32_to_cpu(val); 487 if (!s->rx_frame_rem) { 488 union ctu_can_fd_frame_form_w frame_form_w; 489 frame_form_w.u32 = val; 490 s->rx_frame_rem = frame_form_w.s.rwcnt * 4 + 4; 491 } 492 s->rx_cnt -= 4; 493 s->rx_frame_rem -= 4; 494 if (!s->rx_frame_rem) { 495 s->rx_status_rx_settings.s.rxfrc--; 496 if (!s->rx_status_rx_settings.s.rxfrc) { 497 s->status.s.rxne = 0; 498 s->status.s.idle = 1; 499 s->status.s.rxs = 0; 500 } 501 } 502 s->rx_tail_pos = (s->rx_tail_pos + 4) % CTUCAN_RCV_BUF_LEN; 503 } else { 504 val = 0; 505 } 506 break; 507 case CTU_CAN_FD_TX_STATUS: 508 val = s->tx_status.u32; 509 break; 510 case CTU_CAN_FD_TX_PRIORITY: 511 val = s->tx_priority.u32; 512 break; 513 case CTU_CAN_FD_RX_FR_CTR: 514 val = s->rx_fr_ctr.s.rx_fr_ctr_val; 515 break; 516 case CTU_CAN_FD_TX_FR_CTR: 517 val = s->tx_fr_ctr.s.tx_fr_ctr_val; 518 break; 519 case CTU_CAN_FD_YOLO_REG: 520 val = s->yolo_reg.s.yolo_val; 521 break; 522 } 523 524 val >>= ((addr & 3) << 3); 525 if (size < 8) { 526 val &= ((uint64_t)1 << (size << 3)) - 1; 527 } 528 529 return val; 530 } 531 532 bool ctucan_can_receive(CanBusClientState *client) 533 { 534 CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client); 535 536 if (!s->mode_settings.s.ena) { 537 return false; 538 } 539 540 return true; /* always return true, when operation mode */ 541 } 542 543 ssize_t ctucan_receive(CanBusClientState *client, const qemu_can_frame *frames, 544 size_t frames_cnt) 545 { 546 CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client); 547 static uint8_t rcv[CTUCAN_MSG_MAX_LEN]; 548 int i; 549 int ret = -1; 550 const qemu_can_frame *frame = frames; 551 union ctu_can_fd_int_stat int_stat; 552 int_stat.u32 = 0; 553 554 if (frames_cnt <= 0) { 555 return 0; 556 } 557 558 ret = ctucan_frame2buff(frame, rcv); 559 560 if (s->rx_cnt + ret > CTUCAN_RCV_BUF_LEN) { /* Data overrun. */ 561 s->status.s.dor = 1; 562 int_stat.s.doi = 1; 563 s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; 564 ctucan_update_irq(s); 565 DPRINTF("Receive FIFO overrun\n"); 566 return ret; 567 } 568 s->status.s.idle = 0; 569 s->status.s.rxs = 1; 570 int_stat.s.rxi = 1; 571 if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) { 572 int_stat.s.rxfi = 1; 573 } 574 s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; 575 s->rx_fr_ctr.s.rx_fr_ctr_val++; 576 s->rx_status_rx_settings.s.rxfrc++; 577 for (i = 0; i < ret; i++) { 578 s->rx_buff[(s->rx_tail_pos + s->rx_cnt) % CTUCAN_RCV_BUF_LEN] = rcv[i]; 579 s->rx_cnt++; 580 } 581 s->status.s.rxne = 1; 582 583 ctucan_update_irq(s); 584 585 return 1; 586 } 587 588 static CanBusClientInfo ctucan_bus_client_info = { 589 .can_receive = ctucan_can_receive, 590 .receive = ctucan_receive, 591 }; 592 593 594 int ctucan_connect_to_bus(CtuCanCoreState *s, CanBusState *bus) 595 { 596 s->bus_client.info = &ctucan_bus_client_info; 597 598 if (!bus) { 599 return -EINVAL; 600 } 601 602 if (can_bus_insert_client(bus, &s->bus_client) < 0) { 603 return -1; 604 } 605 606 return 0; 607 } 608 609 void ctucan_disconnect(CtuCanCoreState *s) 610 { 611 can_bus_remove_client(&s->bus_client); 612 } 613 614 int ctucan_init(CtuCanCoreState *s, qemu_irq irq) 615 { 616 s->irq = irq; 617 618 qemu_irq_lower(s->irq); 619 620 ctucan_hardware_reset(s); 621 622 return 0; 623 } 624 625 const VMStateDescription vmstate_qemu_ctucan_tx_buffer = { 626 .name = "qemu_ctucan_tx_buffer", 627 .version_id = 1, 628 .minimum_version_id = 1, 629 .minimum_version_id_old = 1, 630 .fields = (VMStateField[]) { 631 VMSTATE_UINT8_ARRAY(data, CtuCanCoreMsgBuffer, CTUCAN_CORE_MSG_MAX_LEN), 632 VMSTATE_END_OF_LIST() 633 } 634 }; 635 636 static int ctucan_post_load(void *opaque, int version_id) 637 { 638 CtuCanCoreState *s = opaque; 639 ctucan_update_irq(s); 640 return 0; 641 } 642 643 /* VMState is needed for live migration of QEMU images */ 644 const VMStateDescription vmstate_ctucan = { 645 .name = "ctucan", 646 .version_id = 1, 647 .minimum_version_id = 1, 648 .minimum_version_id_old = 1, 649 .post_load = ctucan_post_load, 650 .fields = (VMStateField[]) { 651 VMSTATE_UINT32(mode_settings.u32, CtuCanCoreState), 652 VMSTATE_UINT32(status.u32, CtuCanCoreState), 653 VMSTATE_UINT32(int_stat.u32, CtuCanCoreState), 654 VMSTATE_UINT32(int_ena.u32, CtuCanCoreState), 655 VMSTATE_UINT32(int_mask.u32, CtuCanCoreState), 656 VMSTATE_UINT32(brt.u32, CtuCanCoreState), 657 VMSTATE_UINT32(brt_fd.u32, CtuCanCoreState), 658 VMSTATE_UINT32(ewl_erp_fault_state.u32, CtuCanCoreState), 659 VMSTATE_UINT32(rec_tec.u32, CtuCanCoreState), 660 VMSTATE_UINT32(err_norm_err_fd.u32, CtuCanCoreState), 661 VMSTATE_UINT32(ctr_pres.u32, CtuCanCoreState), 662 VMSTATE_UINT32(filter_a_mask.u32, CtuCanCoreState), 663 VMSTATE_UINT32(filter_a_val.u32, CtuCanCoreState), 664 VMSTATE_UINT32(filter_b_mask.u32, CtuCanCoreState), 665 VMSTATE_UINT32(filter_b_val.u32, CtuCanCoreState), 666 VMSTATE_UINT32(filter_c_mask.u32, CtuCanCoreState), 667 VMSTATE_UINT32(filter_c_val.u32, CtuCanCoreState), 668 VMSTATE_UINT32(filter_ran_low.u32, CtuCanCoreState), 669 VMSTATE_UINT32(filter_ran_high.u32, CtuCanCoreState), 670 VMSTATE_UINT32(filter_control_filter_status.u32, CtuCanCoreState), 671 VMSTATE_UINT32(rx_mem_info.u32, CtuCanCoreState), 672 VMSTATE_UINT32(rx_pointers.u32, CtuCanCoreState), 673 VMSTATE_UINT32(rx_status_rx_settings.u32, CtuCanCoreState), 674 VMSTATE_UINT32(tx_status.u32, CtuCanCoreState), 675 VMSTATE_UINT32(tx_priority.u32, CtuCanCoreState), 676 VMSTATE_UINT32(err_capt_alc.u32, CtuCanCoreState), 677 VMSTATE_UINT32(trv_delay_ssp_cfg.u32, CtuCanCoreState), 678 VMSTATE_UINT32(rx_fr_ctr.u32, CtuCanCoreState), 679 VMSTATE_UINT32(tx_fr_ctr.u32, CtuCanCoreState), 680 VMSTATE_UINT32(debug_register.u32, CtuCanCoreState), 681 VMSTATE_UINT32(yolo_reg.u32, CtuCanCoreState), 682 VMSTATE_UINT32(timestamp_low.u32, CtuCanCoreState), 683 VMSTATE_UINT32(timestamp_high.u32, CtuCanCoreState), 684 685 VMSTATE_STRUCT_ARRAY(tx_buffer, CtuCanCoreState, 686 CTUCAN_CORE_TXBUF_NUM, 0, vmstate_qemu_ctucan_tx_buffer, 687 CtuCanCoreMsgBuffer), 688 689 VMSTATE_BUFFER(rx_buff, CtuCanCoreState), 690 VMSTATE_UINT32(rx_tail_pos, CtuCanCoreState), 691 VMSTATE_UINT32(rx_cnt, CtuCanCoreState), 692 VMSTATE_UINT32(rx_frame_rem, CtuCanCoreState), 693 694 VMSTATE_END_OF_LIST() 695 } 696 }; 697