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