ctucan_core.c (20599B)
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 49static 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 100static 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 154static 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 173static 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 190void 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 237static 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 244 if (!s->mode_settings.s.ena) { 245 return; 246 } 247 248 do { 249 union ctu_can_fd_int_stat int_stat; 250 int i; 251 buff2tx_idx = -1; 252 tx_prio_max = 0; 253 254 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { 255 uint32_t prio; 256 257 if (extract32(s->tx_status.u32, i * 4, 4) != TXT_RDY) { 258 continue; 259 } 260 prio = (s->tx_priority.u32 >> (i * 4)) & 0x7; 261 if (tx_prio_max < prio) { 262 tx_prio_max = prio; 263 buff2tx_idx = i; 264 } 265 } 266 if (buff2tx_idx == -1) { 267 break; 268 } 269 int_stat.u32 = 0; 270 pf = s->tx_buffer[buff2tx_idx].data; 271 ctucan_buff2frame(pf, &frame); 272 s->status.s.idle = 0; 273 s->status.s.txs = 1; 274 can_bus_client_send(&s->bus_client, &frame, 1); 275 s->status.s.idle = 1; 276 s->status.s.txs = 0; 277 s->tx_fr_ctr.s.tx_fr_ctr_val++; 278 int_stat.s.txi = 1; 279 int_stat.s.txbhci = 1; 280 s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; 281 s->tx_status.u32 = deposit32(s->tx_status.u32, 282 buff2tx_idx * 4, 4, TXT_TOK); 283 } while (1); 284} 285 286#define CTUCAN_CORE_TXBUFF_SPAN \ 287 (CTU_CAN_FD_TXTB2_DATA_1 - CTU_CAN_FD_TXTB1_DATA_1) 288 289void ctucan_mem_write(CtuCanCoreState *s, hwaddr addr, uint64_t val, 290 unsigned size) 291{ 292 int i; 293 294 DPRINTF("write 0x%02llx addr 0x%02x\n", 295 (unsigned long long)val, (unsigned int)addr); 296 297 if (addr >= CTUCAN_CORE_MEM_SIZE) { 298 return; 299 } 300 301 if (addr >= CTU_CAN_FD_TXTB1_DATA_1) { 302 int buff_num; 303 addr -= CTU_CAN_FD_TXTB1_DATA_1; 304 buff_num = addr / CTUCAN_CORE_TXBUFF_SPAN; 305 addr %= CTUCAN_CORE_TXBUFF_SPAN; 306 if ((buff_num < CTUCAN_CORE_TXBUF_NUM) && 307 ((addr + size) <= sizeof(s->tx_buffer[buff_num].data))) { 308 stn_le_p(s->tx_buffer[buff_num].data + addr, size, val); 309 } 310 } else { 311 switch (addr & ~3) { 312 case CTU_CAN_FD_MODE: 313 s->mode_settings.u32 = (uint32_t)val; 314 if (s->mode_settings.s.rst) { 315 ctucan_hardware_reset(s); 316 s->mode_settings.s.rst = 0; 317 } 318 break; 319 case CTU_CAN_FD_COMMAND: 320 { 321 union ctu_can_fd_command command; 322 command.u32 = (uint32_t)val; 323 if (command.s.cdo) { 324 s->status.s.dor = 0; 325 } 326 if (command.s.rrb) { 327 s->rx_tail_pos = 0; 328 s->rx_cnt = 0; 329 s->rx_frame_rem = 0; 330 s->rx_status_rx_settings.s.rxfrc = 0; 331 } 332 if (command.s.txfcrst) { 333 s->tx_fr_ctr.s.tx_fr_ctr_val = 0; 334 } 335 if (command.s.rxfcrst) { 336 s->rx_fr_ctr.s.rx_fr_ctr_val = 0; 337 } 338 break; 339 } 340 case CTU_CAN_FD_INT_STAT: 341 s->int_stat.u32 &= ~(uint32_t)val; 342 break; 343 case CTU_CAN_FD_INT_ENA_SET: 344 s->int_ena.u32 |= (uint32_t)val; 345 break; 346 case CTU_CAN_FD_INT_ENA_CLR: 347 s->int_ena.u32 &= ~(uint32_t)val; 348 break; 349 case CTU_CAN_FD_INT_MASK_SET: 350 s->int_mask.u32 |= (uint32_t)val; 351 break; 352 case CTU_CAN_FD_INT_MASK_CLR: 353 s->int_mask.u32 &= ~(uint32_t)val; 354 break; 355 case CTU_CAN_FD_TX_COMMAND: 356 if (s->mode_settings.s.ena) { 357 union ctu_can_fd_tx_command tx_command; 358 union ctu_can_fd_tx_command mask; 359 unsigned int buff_st; 360 uint32_t buff_st_mask; 361 362 tx_command.u32 = (uint32_t)val; 363 mask.u32 = 0; 364 mask.s.txb1 = 1; 365 366 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) { 367 if (!(tx_command.u32 & (mask.u32 << i))) { 368 continue; 369 } 370 buff_st_mask = 0xf << (i * 4); 371 buff_st = (s->tx_status.u32 >> (i * 4)) & 0xf; 372 if (tx_command.s.txca) { 373 if (buff_st == TXT_RDY) { 374 buff_st = TXT_ABT; 375 } 376 } 377 if (tx_command.s.txcr) { 378 if ((buff_st == TXT_TOK) || (buff_st == TXT_ERR) || 379 (buff_st == TXT_ABT) || (buff_st == TXT_ETY)) 380 buff_st = TXT_RDY; 381 } 382 if (tx_command.s.txce) { 383 if ((buff_st == TXT_TOK) || (buff_st == TXT_ERR) || 384 (buff_st == TXT_ABT)) 385 buff_st = TXT_ETY; 386 } 387 s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) | 388 (buff_st << (i * 4)); 389 } 390 391 ctucan_send_ready_buffers(s); 392 ctucan_update_txnf(s); 393 } 394 break; 395 case CTU_CAN_FD_TX_PRIORITY: 396 s->tx_priority.u32 = (uint32_t)val; 397 break; 398 } 399 400 ctucan_update_irq(s); 401 } 402 403 return; 404} 405 406uint64_t ctucan_mem_read(CtuCanCoreState *s, hwaddr addr, unsigned size) 407{ 408 uint32_t val = 0; 409 410 DPRINTF("read addr 0x%02x ...\n", (unsigned int)addr); 411 412 if (addr > CTUCAN_CORE_MEM_SIZE) { 413 return 0; 414 } 415 416 switch (addr & ~3) { 417 case CTU_CAN_FD_DEVICE_ID: 418 { 419 union ctu_can_fd_device_id_version idver; 420 idver.u32 = 0; 421 idver.s.device_id = CTU_CAN_FD_ID; 422 idver.s.ver_major = 2; 423 idver.s.ver_minor = 2; 424 val = idver.u32; 425 } 426 break; 427 case CTU_CAN_FD_MODE: 428 val = s->mode_settings.u32; 429 break; 430 case CTU_CAN_FD_STATUS: 431 val = s->status.u32; 432 break; 433 case CTU_CAN_FD_INT_STAT: 434 val = s->int_stat.u32; 435 break; 436 case CTU_CAN_FD_INT_ENA_SET: 437 case CTU_CAN_FD_INT_ENA_CLR: 438 val = s->int_ena.u32; 439 break; 440 case CTU_CAN_FD_INT_MASK_SET: 441 case CTU_CAN_FD_INT_MASK_CLR: 442 val = s->int_mask.u32; 443 break; 444 case CTU_CAN_FD_RX_MEM_INFO: 445 s->rx_mem_info.u32 = 0; 446 s->rx_mem_info.s.rx_buff_size = CTUCAN_RCV_BUF_LEN >> 2; 447 s->rx_mem_info.s.rx_mem_free = (CTUCAN_RCV_BUF_LEN - 448 s->rx_cnt) >> 2; 449 val = s->rx_mem_info.u32; 450 break; 451 case CTU_CAN_FD_RX_POINTERS: 452 { 453 uint32_t rx_head_pos = s->rx_tail_pos + s->rx_cnt; 454 rx_head_pos %= CTUCAN_RCV_BUF_LEN; 455 s->rx_pointers.s.rx_wpp = rx_head_pos; 456 s->rx_pointers.s.rx_rpp = s->rx_tail_pos; 457 val = s->rx_pointers.u32; 458 break; 459 } 460 case CTU_CAN_FD_RX_STATUS: 461 case CTU_CAN_FD_RX_SETTINGS: 462 if (!s->rx_status_rx_settings.s.rxfrc) { 463 s->rx_status_rx_settings.s.rxe = 1; 464 } else { 465 s->rx_status_rx_settings.s.rxe = 0; 466 } 467 if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) { 468 s->rx_status_rx_settings.s.rxf = 1; 469 } else { 470 s->rx_status_rx_settings.s.rxf = 0; 471 } 472 val = s->rx_status_rx_settings.u32; 473 break; 474 case CTU_CAN_FD_RX_DATA: 475 if (s->rx_cnt) { 476 memcpy(&val, s->rx_buff + s->rx_tail_pos, 4); 477 val = le32_to_cpu(val); 478 if (!s->rx_frame_rem) { 479 union ctu_can_fd_frame_form_w frame_form_w; 480 frame_form_w.u32 = val; 481 s->rx_frame_rem = frame_form_w.s.rwcnt * 4 + 4; 482 } 483 s->rx_cnt -= 4; 484 s->rx_frame_rem -= 4; 485 if (!s->rx_frame_rem) { 486 s->rx_status_rx_settings.s.rxfrc--; 487 if (!s->rx_status_rx_settings.s.rxfrc) { 488 s->status.s.rxne = 0; 489 s->status.s.idle = 1; 490 s->status.s.rxs = 0; 491 } 492 } 493 s->rx_tail_pos = (s->rx_tail_pos + 4) % CTUCAN_RCV_BUF_LEN; 494 } else { 495 val = 0; 496 } 497 break; 498 case CTU_CAN_FD_TX_STATUS: 499 val = s->tx_status.u32; 500 break; 501 case CTU_CAN_FD_TX_PRIORITY: 502 val = s->tx_priority.u32; 503 break; 504 case CTU_CAN_FD_RX_FR_CTR: 505 val = s->rx_fr_ctr.s.rx_fr_ctr_val; 506 break; 507 case CTU_CAN_FD_TX_FR_CTR: 508 val = s->tx_fr_ctr.s.tx_fr_ctr_val; 509 break; 510 case CTU_CAN_FD_YOLO_REG: 511 val = s->yolo_reg.s.yolo_val; 512 break; 513 } 514 515 val >>= ((addr & 3) << 3); 516 if (size < 8) { 517 val &= ((uint64_t)1 << (size << 3)) - 1; 518 } 519 520 return val; 521} 522 523bool ctucan_can_receive(CanBusClientState *client) 524{ 525 CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client); 526 527 if (!s->mode_settings.s.ena) { 528 return false; 529 } 530 531 return true; /* always return true, when operation mode */ 532} 533 534ssize_t ctucan_receive(CanBusClientState *client, const qemu_can_frame *frames, 535 size_t frames_cnt) 536{ 537 CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client); 538 static uint8_t rcv[CTUCAN_MSG_MAX_LEN]; 539 int i; 540 int ret = -1; 541 const qemu_can_frame *frame = frames; 542 union ctu_can_fd_int_stat int_stat; 543 int_stat.u32 = 0; 544 545 if (frames_cnt <= 0) { 546 return 0; 547 } 548 549 ret = ctucan_frame2buff(frame, rcv); 550 551 if (s->rx_cnt + ret > CTUCAN_RCV_BUF_LEN) { /* Data overrun. */ 552 s->status.s.dor = 1; 553 int_stat.s.doi = 1; 554 s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; 555 ctucan_update_irq(s); 556 DPRINTF("Receive FIFO overrun\n"); 557 return ret; 558 } 559 s->status.s.idle = 0; 560 s->status.s.rxs = 1; 561 int_stat.s.rxi = 1; 562 if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) { 563 int_stat.s.rxfi = 1; 564 } 565 s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32; 566 s->rx_fr_ctr.s.rx_fr_ctr_val++; 567 s->rx_status_rx_settings.s.rxfrc++; 568 for (i = 0; i < ret; i++) { 569 s->rx_buff[(s->rx_tail_pos + s->rx_cnt) % CTUCAN_RCV_BUF_LEN] = rcv[i]; 570 s->rx_cnt++; 571 } 572 s->status.s.rxne = 1; 573 574 ctucan_update_irq(s); 575 576 return 1; 577} 578 579static CanBusClientInfo ctucan_bus_client_info = { 580 .can_receive = ctucan_can_receive, 581 .receive = ctucan_receive, 582}; 583 584 585int ctucan_connect_to_bus(CtuCanCoreState *s, CanBusState *bus) 586{ 587 s->bus_client.info = &ctucan_bus_client_info; 588 589 if (!bus) { 590 return -EINVAL; 591 } 592 593 if (can_bus_insert_client(bus, &s->bus_client) < 0) { 594 return -1; 595 } 596 597 return 0; 598} 599 600void ctucan_disconnect(CtuCanCoreState *s) 601{ 602 can_bus_remove_client(&s->bus_client); 603} 604 605int ctucan_init(CtuCanCoreState *s, qemu_irq irq) 606{ 607 s->irq = irq; 608 609 qemu_irq_lower(s->irq); 610 611 ctucan_hardware_reset(s); 612 613 return 0; 614} 615 616const VMStateDescription vmstate_qemu_ctucan_tx_buffer = { 617 .name = "qemu_ctucan_tx_buffer", 618 .version_id = 1, 619 .minimum_version_id = 1, 620 .minimum_version_id_old = 1, 621 .fields = (VMStateField[]) { 622 VMSTATE_UINT8_ARRAY(data, CtuCanCoreMsgBuffer, CTUCAN_CORE_MSG_MAX_LEN), 623 VMSTATE_END_OF_LIST() 624 } 625}; 626 627static 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 */ 635const VMStateDescription vmstate_ctucan = { 636 .name = "ctucan", 637 .version_id = 1, 638 .minimum_version_id = 1, 639 .minimum_version_id_old = 1, 640 .post_load = ctucan_post_load, 641 .fields = (VMStateField[]) { 642 VMSTATE_UINT32(mode_settings.u32, CtuCanCoreState), 643 VMSTATE_UINT32(status.u32, CtuCanCoreState), 644 VMSTATE_UINT32(int_stat.u32, CtuCanCoreState), 645 VMSTATE_UINT32(int_ena.u32, CtuCanCoreState), 646 VMSTATE_UINT32(int_mask.u32, CtuCanCoreState), 647 VMSTATE_UINT32(brt.u32, CtuCanCoreState), 648 VMSTATE_UINT32(brt_fd.u32, CtuCanCoreState), 649 VMSTATE_UINT32(ewl_erp_fault_state.u32, CtuCanCoreState), 650 VMSTATE_UINT32(rec_tec.u32, CtuCanCoreState), 651 VMSTATE_UINT32(err_norm_err_fd.u32, CtuCanCoreState), 652 VMSTATE_UINT32(ctr_pres.u32, CtuCanCoreState), 653 VMSTATE_UINT32(filter_a_mask.u32, CtuCanCoreState), 654 VMSTATE_UINT32(filter_a_val.u32, CtuCanCoreState), 655 VMSTATE_UINT32(filter_b_mask.u32, CtuCanCoreState), 656 VMSTATE_UINT32(filter_b_val.u32, CtuCanCoreState), 657 VMSTATE_UINT32(filter_c_mask.u32, CtuCanCoreState), 658 VMSTATE_UINT32(filter_c_val.u32, CtuCanCoreState), 659 VMSTATE_UINT32(filter_ran_low.u32, CtuCanCoreState), 660 VMSTATE_UINT32(filter_ran_high.u32, CtuCanCoreState), 661 VMSTATE_UINT32(filter_control_filter_status.u32, CtuCanCoreState), 662 VMSTATE_UINT32(rx_mem_info.u32, CtuCanCoreState), 663 VMSTATE_UINT32(rx_pointers.u32, CtuCanCoreState), 664 VMSTATE_UINT32(rx_status_rx_settings.u32, CtuCanCoreState), 665 VMSTATE_UINT32(tx_status.u32, CtuCanCoreState), 666 VMSTATE_UINT32(tx_priority.u32, CtuCanCoreState), 667 VMSTATE_UINT32(err_capt_alc.u32, CtuCanCoreState), 668 VMSTATE_UINT32(trv_delay_ssp_cfg.u32, CtuCanCoreState), 669 VMSTATE_UINT32(rx_fr_ctr.u32, CtuCanCoreState), 670 VMSTATE_UINT32(tx_fr_ctr.u32, CtuCanCoreState), 671 VMSTATE_UINT32(debug_register.u32, CtuCanCoreState), 672 VMSTATE_UINT32(yolo_reg.u32, CtuCanCoreState), 673 VMSTATE_UINT32(timestamp_low.u32, CtuCanCoreState), 674 VMSTATE_UINT32(timestamp_high.u32, CtuCanCoreState), 675 676 VMSTATE_STRUCT_ARRAY(tx_buffer, CtuCanCoreState, 677 CTUCAN_CORE_TXBUF_NUM, 0, vmstate_qemu_ctucan_tx_buffer, 678 CtuCanCoreMsgBuffer), 679 680 VMSTATE_BUFFER(rx_buff, CtuCanCoreState), 681 VMSTATE_UINT32(rx_tail_pos, CtuCanCoreState), 682 VMSTATE_UINT32(rx_cnt, CtuCanCoreState), 683 VMSTATE_UINT32(rx_frame_rem, CtuCanCoreState), 684 685 VMSTATE_END_OF_LIST() 686 } 687};