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 return; 405 } 406 407 uint64_t ctucan_mem_read(CtuCanCoreState *s, hwaddr addr, unsigned size) 408 { 409 uint32_t val = 0; 410 411 DPRINTF("read addr 0x%02x ...\n", (unsigned int)addr); 412 413 if (addr > CTUCAN_CORE_MEM_SIZE) { 414 return 0; 415 } 416 417 switch (addr & ~3) { 418 case CTU_CAN_FD_DEVICE_ID: 419 { 420 union ctu_can_fd_device_id_version idver; 421 idver.u32 = 0; 422 idver.s.device_id = CTU_CAN_FD_ID; 423 idver.s.ver_major = 2; 424 idver.s.ver_minor = 2; 425 val = idver.u32; 426 } 427 break; 428 case CTU_CAN_FD_MODE: 429 val = s->mode_settings.u32; 430 break; 431 case CTU_CAN_FD_STATUS: 432 val = s->status.u32; 433 break; 434 case CTU_CAN_FD_INT_STAT: 435 val = s->int_stat.u32; 436 break; 437 case CTU_CAN_FD_INT_ENA_SET: 438 case CTU_CAN_FD_INT_ENA_CLR: 439 val = s->int_ena.u32; 440 break; 441 case CTU_CAN_FD_INT_MASK_SET: 442 case CTU_CAN_FD_INT_MASK_CLR: 443 val = s->int_mask.u32; 444 break; 445 case CTU_CAN_FD_RX_MEM_INFO: 446 s->rx_mem_info.u32 = 0; 447 s->rx_mem_info.s.rx_buff_size = CTUCAN_RCV_BUF_LEN >> 2; 448 s->rx_mem_info.s.rx_mem_free = (CTUCAN_RCV_BUF_LEN - 449 s->rx_cnt) >> 2; 450 val = s->rx_mem_info.u32; 451 break; 452 case CTU_CAN_FD_RX_POINTERS: 453 { 454 uint32_t rx_head_pos = s->rx_tail_pos + s->rx_cnt; 455 rx_head_pos %= CTUCAN_RCV_BUF_LEN; 456 s->rx_pointers.s.rx_wpp = rx_head_pos; 457 s->rx_pointers.s.rx_rpp = s->rx_tail_pos; 458 val = s->rx_pointers.u32; 459 break; 460 } 461 case CTU_CAN_FD_RX_STATUS: 462 case CTU_CAN_FD_RX_SETTINGS: 463 if (!s->rx_status_rx_settings.s.rxfrc) { 464 s->rx_status_rx_settings.s.rxe = 1; 465 } else { 466 s->rx_status_rx_settings.s.rxe = 0; 467 } 468 if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) { 469 s->rx_status_rx_settings.s.rxf = 1; 470 } else { 471 s->rx_status_rx_settings.s.rxf = 0; 472 } 473 val = s->rx_status_rx_settings.u32; 474 break; 475 case CTU_CAN_FD_RX_DATA: 476 if (s->rx_cnt) { 477 memcpy(&val, s->rx_buff + s->rx_tail_pos, 4); 478 val = le32_to_cpu(val); 479 if (!s->rx_frame_rem) { 480 union ctu_can_fd_frame_form_w frame_form_w; 481 frame_form_w.u32 = val; 482 s->rx_frame_rem = frame_form_w.s.rwcnt * 4 + 4; 483 } 484 s->rx_cnt -= 4; 485 s->rx_frame_rem -= 4; 486 if (!s->rx_frame_rem) { 487 s->rx_status_rx_settings.s.rxfrc--; 488 if (!s->rx_status_rx_settings.s.rxfrc) { 489 s->status.s.rxne = 0; 490 s->status.s.idle = 1; 491 s->status.s.rxs = 0; 492 } 493 } 494 s->rx_tail_pos = (s->rx_tail_pos + 4) % CTUCAN_RCV_BUF_LEN; 495 } else { 496 val = 0; 497 } 498 break; 499 case CTU_CAN_FD_TX_STATUS: 500 val = s->tx_status.u32; 501 break; 502 case CTU_CAN_FD_TX_PRIORITY: 503 val = s->tx_priority.u32; 504 break; 505 case CTU_CAN_FD_RX_FR_CTR: 506 val = s->rx_fr_ctr.s.rx_fr_ctr_val; 507 break; 508 case CTU_CAN_FD_TX_FR_CTR: 509 val = s->tx_fr_ctr.s.tx_fr_ctr_val; 510 break; 511 case CTU_CAN_FD_YOLO_REG: 512 val = s->yolo_reg.s.yolo_val; 513 break; 514 } 515 516 val >>= ((addr & 3) << 3); 517 if (size < 8) { 518 val &= ((uint64_t)1 << (size << 3)) - 1; 519 } 520 521 return val; 522 } 523 524 bool ctucan_can_receive(CanBusClientState *client) 525 { 526 CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client); 527 528 if (!s->mode_settings.s.ena) { 529 return false; 530 } 531 532 return true; /* always return true, when operation mode */ 533 } 534 535 ssize_t ctucan_receive(CanBusClientState *client, const qemu_can_frame *frames, 536 size_t frames_cnt) 537 { 538 CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client); 539 static uint8_t rcv[CTUCAN_MSG_MAX_LEN]; 540 int i; 541 int ret = -1; 542 const qemu_can_frame *frame = frames; 543 union ctu_can_fd_int_stat int_stat; 544 int_stat.u32 = 0; 545 546 if (frames_cnt <= 0) { 547 return 0; 548 } 549 550 ret = ctucan_frame2buff(frame, rcv); 551 552 if (s->rx_cnt + ret > CTUCAN_RCV_BUF_LEN) { /* Data overrun. */ 553 s->status.s.dor = 1; 554 int_stat.s.doi = 1; 555 s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; 556 ctucan_update_irq(s); 557 DPRINTF("Receive FIFO overrun\n"); 558 return ret; 559 } 560 s->status.s.idle = 0; 561 s->status.s.rxs = 1; 562 int_stat.s.rxi = 1; 563 if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) { 564 int_stat.s.rxfi = 1; 565 } 566 s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; 567 s->rx_fr_ctr.s.rx_fr_ctr_val++; 568 s->rx_status_rx_settings.s.rxfrc++; 569 for (i = 0; i < ret; i++) { 570 s->rx_buff[(s->rx_tail_pos + s->rx_cnt) % CTUCAN_RCV_BUF_LEN] = rcv[i]; 571 s->rx_cnt++; 572 } 573 s->status.s.rxne = 1; 574 575 ctucan_update_irq(s); 576 577 return 1; 578 } 579 580 static CanBusClientInfo ctucan_bus_client_info = { 581 .can_receive = ctucan_can_receive, 582 .receive = ctucan_receive, 583 }; 584 585 586 int ctucan_connect_to_bus(CtuCanCoreState *s, CanBusState *bus) 587 { 588 s->bus_client.info = &ctucan_bus_client_info; 589 590 if (!bus) { 591 return -EINVAL; 592 } 593 594 if (can_bus_insert_client(bus, &s->bus_client) < 0) { 595 return -1; 596 } 597 598 return 0; 599 } 600 601 void ctucan_disconnect(CtuCanCoreState *s) 602 { 603 can_bus_remove_client(&s->bus_client); 604 } 605 606 int ctucan_init(CtuCanCoreState *s, qemu_irq irq) 607 { 608 s->irq = irq; 609 610 qemu_irq_lower(s->irq); 611 612 ctucan_hardware_reset(s); 613 614 return 0; 615 } 616 617 const VMStateDescription vmstate_qemu_ctucan_tx_buffer = { 618 .name = "qemu_ctucan_tx_buffer", 619 .version_id = 1, 620 .minimum_version_id = 1, 621 .fields = (const VMStateField[]) { 622 VMSTATE_UINT8_ARRAY(data, CtuCanCoreMsgBuffer, CTUCAN_CORE_MSG_MAX_LEN), 623 VMSTATE_END_OF_LIST() 624 } 625 }; 626 627 static int ctucan_post_load(void *opaque, int version_id) 628 { 629 CtuCanCoreState *s = opaque; 630 ctucan_update_irq(s); 631 return 0; 632 } 633 634 /* VMState is needed for live migration of QEMU images */ 635 const VMStateDescription vmstate_ctucan = { 636 .name = "ctucan", 637 .version_id = 1, 638 .minimum_version_id = 1, 639 .post_load = ctucan_post_load, 640 .fields = (const VMStateField[]) { 641 VMSTATE_UINT32(mode_settings.u32, CtuCanCoreState), 642 VMSTATE_UINT32(status.u32, CtuCanCoreState), 643 VMSTATE_UINT32(int_stat.u32, CtuCanCoreState), 644 VMSTATE_UINT32(int_ena.u32, CtuCanCoreState), 645 VMSTATE_UINT32(int_mask.u32, CtuCanCoreState), 646 VMSTATE_UINT32(brt.u32, CtuCanCoreState), 647 VMSTATE_UINT32(brt_fd.u32, CtuCanCoreState), 648 VMSTATE_UINT32(ewl_erp_fault_state.u32, CtuCanCoreState), 649 VMSTATE_UINT32(rec_tec.u32, CtuCanCoreState), 650 VMSTATE_UINT32(err_norm_err_fd.u32, CtuCanCoreState), 651 VMSTATE_UINT32(ctr_pres.u32, CtuCanCoreState), 652 VMSTATE_UINT32(filter_a_mask.u32, CtuCanCoreState), 653 VMSTATE_UINT32(filter_a_val.u32, CtuCanCoreState), 654 VMSTATE_UINT32(filter_b_mask.u32, CtuCanCoreState), 655 VMSTATE_UINT32(filter_b_val.u32, CtuCanCoreState), 656 VMSTATE_UINT32(filter_c_mask.u32, CtuCanCoreState), 657 VMSTATE_UINT32(filter_c_val.u32, CtuCanCoreState), 658 VMSTATE_UINT32(filter_ran_low.u32, CtuCanCoreState), 659 VMSTATE_UINT32(filter_ran_high.u32, CtuCanCoreState), 660 VMSTATE_UINT32(filter_control_filter_status.u32, CtuCanCoreState), 661 VMSTATE_UINT32(rx_mem_info.u32, CtuCanCoreState), 662 VMSTATE_UINT32(rx_pointers.u32, CtuCanCoreState), 663 VMSTATE_UINT32(rx_status_rx_settings.u32, CtuCanCoreState), 664 VMSTATE_UINT32(tx_status.u32, CtuCanCoreState), 665 VMSTATE_UINT32(tx_priority.u32, CtuCanCoreState), 666 VMSTATE_UINT32(err_capt_alc.u32, CtuCanCoreState), 667 VMSTATE_UINT32(trv_delay_ssp_cfg.u32, CtuCanCoreState), 668 VMSTATE_UINT32(rx_fr_ctr.u32, CtuCanCoreState), 669 VMSTATE_UINT32(tx_fr_ctr.u32, CtuCanCoreState), 670 VMSTATE_UINT32(debug_register.u32, CtuCanCoreState), 671 VMSTATE_UINT32(yolo_reg.u32, CtuCanCoreState), 672 VMSTATE_UINT32(timestamp_low.u32, CtuCanCoreState), 673 VMSTATE_UINT32(timestamp_high.u32, CtuCanCoreState), 674 675 VMSTATE_STRUCT_ARRAY(tx_buffer, CtuCanCoreState, 676 CTUCAN_CORE_TXBUF_NUM, 0, vmstate_qemu_ctucan_tx_buffer, 677 CtuCanCoreMsgBuffer), 678 679 VMSTATE_BUFFER(rx_buff, CtuCanCoreState), 680 VMSTATE_UINT32(rx_tail_pos, CtuCanCoreState), 681 VMSTATE_UINT32(rx_cnt, CtuCanCoreState), 682 VMSTATE_UINT32(rx_frame_rem, CtuCanCoreState), 683 684 VMSTATE_END_OF_LIST() 685 } 686 }; 687