2 * CTU CAN FD PCI device emulation
3 * http://canbus.pages.fel.cvut.cz/
5 * Copyright (c) 2019 Jan Charvat (jancharvat.charvat@gmail.com)
7 * Based on Kvaser PCI CAN device (SJA1000 based) emulation implemented by
8 * Jin Yang and Pavel Pisa
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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
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
29 #include "qemu/osdep.h"
31 #include "chardev/char.h"
33 #include "migration/vmstate.h"
34 #include "net/can_emu.h"
36 #include "ctucan_core.h"
42 #define DPRINTF(fmt, ...) \
45 qemu_log("[ctucan]: " fmt , ## __VA_ARGS__); \
49 static void ctucan_buff2frame(const uint8_t *buff
, qemu_can_frame
*frame
)
59 union ctu_can_fd_frame_form_w frame_form_w
;
60 union ctu_can_fd_identifier_w identifier_w
;
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
);
68 w
= le32_to_cpu(*(uint32_t *)(buff
+ 4));
69 identifier_w
= (union ctu_can_fd_identifier_w
)w
;
71 ide
= frame_form_w
.s
.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
;
77 frame
->can_id
= identifier_w
.s
.identifier_base
;
80 if (frame_form_w
.s
.esi_rsv
) {
81 frame
->flags
|= QEMU_CAN_FRMF_ESI
;
84 if (frame_form_w
.s
.rtr
) {
85 frame
->can_id
|= QEMU_CAN_RTR_FLAG
;
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
;
96 memcpy(frame
->data
, buff
+ 0x10, 0x40);
100 static int ctucan_frame2buff(const qemu_can_frame
*frame
, uint8_t *buff
)
102 unsigned int bytes_cnt
= -1;
103 memset(buff
, 0, CTUCAN_MSG_MAX_LEN
* sizeof(*buff
));
109 union ctu_can_fd_frame_form_w frame_form_w
;
110 union ctu_can_fd_identifier_w identifier_w
;
112 frame_form_w
.u32
= 0;
113 identifier_w
.u32
= 0;
115 bytes_cnt
= frame
->can_dlc
;
116 bytes_cnt
= (bytes_cnt
+ 3) & ~3;
118 frame_form_w
.s
.rwcnt
= (bytes_cnt
>> 2) - 1;
120 frame_form_w
.s
.dlc
= can_len2dlc(frame
->can_dlc
);
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;
128 identifier_w
.s
.identifier_base
= frame
->can_id
& 0x7FF;
131 if (frame
->flags
& QEMU_CAN_FRMF_ESI
) {
132 frame_form_w
.s
.esi_rsv
= 1;
135 if (frame
->can_id
& QEMU_CAN_RTR_FLAG
) {
136 frame_form_w
.s
.rtr
= 1;
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;
145 *(uint32_t *)buff
= cpu_to_le32(frame_form_w
.u32
);
146 *(uint32_t *)(buff
+ 4) = cpu_to_le32(identifier_w
.u32
);
149 memcpy(buff
+ 0x10, frame
->data
, 0x40);
154 static void ctucan_update_irq(CtuCanCoreState
*s
)
156 union ctu_can_fd_int_stat int_rq
;
160 if (s
->rx_status_rx_settings
.s
.rxfrc
) {
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
);
169 qemu_irq_lower(s
->irq
);
173 static void ctucan_update_txnf(CtuCanCoreState
*s
)
177 unsigned int buff_st
;
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
) {
187 s
->status
.s
.txnf
= txnf
;
190 void ctucan_hardware_reset(CtuCanCoreState
*s
)
192 DPRINTF("Hardware reset in progress!!!\n");
194 unsigned int buff_st
;
195 uint32_t buff_st_mask
;
197 s
->tx_status
.u32
= 0;
198 for (i
= 0; i
< CTUCAN_CORE_TXBUF_NUM
; i
++) {
199 buff_st_mask
= 0xf << (i
* 4);
201 s
->tx_status
.u32
= (s
->tx_status
.u32
& ~buff_st_mask
) |
202 (buff_st
<< (i
* 4));
204 s
->status
.s
.idle
= 1;
206 ctucan_update_txnf(s
);
208 s
->rx_status_rx_settings
.u32
= 0;
213 /* Flush RX buffer */
218 /* Set on progdokum reset value */
219 s
->mode_settings
.u32
= 0;
220 s
->mode_settings
.s
.fde
= 1;
226 s
->rx_status_rx_settings
.u32
= 0;
227 s
->rx_status_rx_settings
.s
.rxe
= 0;
229 s
->rx_fr_ctr
.u32
= 0;
230 s
->tx_fr_ctr
.u32
= 0;
232 s
->yolo_reg
.s
.yolo_val
= 3735928559;
234 qemu_irq_lower(s
->irq
);
237 static void ctucan_send_ready_buffers(CtuCanCoreState
*s
)
239 qemu_can_frame frame
;
242 uint32_t tx_prio_max
;
244 if (!s
->mode_settings
.s
.ena
) {
249 union ctu_can_fd_int_stat int_stat
;
254 for (i
= 0; i
< CTUCAN_CORE_TXBUF_NUM
; i
++) {
257 if (extract32(s
->tx_status
.u32
, i
* 4, 4) != TXT_RDY
) {
260 prio
= (s
->tx_priority
.u32
>> (i
* 4)) & 0x7;
261 if (tx_prio_max
< prio
) {
266 if (buff2tx_idx
== -1) {
270 pf
= s
->tx_buffer
[buff2tx_idx
].data
;
271 ctucan_buff2frame(pf
, &frame
);
272 s
->status
.s
.idle
= 0;
274 can_bus_client_send(&s
->bus_client
, &frame
, 1);
275 s
->status
.s
.idle
= 1;
277 s
->tx_fr_ctr
.s
.tx_fr_ctr_val
++;
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
);
286 #define CTUCAN_CORE_TXBUFF_SPAN \
287 (CTU_CAN_FD_TXTB2_DATA_1 - CTU_CAN_FD_TXTB1_DATA_1)
289 void ctucan_mem_write(CtuCanCoreState
*s
, hwaddr addr
, uint64_t val
,
294 DPRINTF("write 0x%02llx addr 0x%02x\n",
295 (unsigned long long)val
, (unsigned int)addr
);
297 if (addr
>= CTUCAN_CORE_MEM_SIZE
) {
301 if (addr
>= CTU_CAN_FD_TXTB1_DATA_1
) {
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
);
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;
319 case CTU_CAN_FD_COMMAND
:
321 union ctu_can_fd_command command
;
322 command
.u32
= (uint32_t)val
;
330 s
->rx_status_rx_settings
.s
.rxfrc
= 0;
332 if (command
.s
.txfcrst
) {
333 s
->tx_fr_ctr
.s
.tx_fr_ctr_val
= 0;
335 if (command
.s
.rxfcrst
) {
336 s
->rx_fr_ctr
.s
.rx_fr_ctr_val
= 0;
340 case CTU_CAN_FD_INT_STAT
:
341 s
->int_stat
.u32
&= ~(uint32_t)val
;
343 case CTU_CAN_FD_INT_ENA_SET
:
344 s
->int_ena
.u32
|= (uint32_t)val
;
346 case CTU_CAN_FD_INT_ENA_CLR
:
347 s
->int_ena
.u32
&= ~(uint32_t)val
;
349 case CTU_CAN_FD_INT_MASK_SET
:
350 s
->int_mask
.u32
|= (uint32_t)val
;
352 case CTU_CAN_FD_INT_MASK_CLR
:
353 s
->int_mask
.u32
&= ~(uint32_t)val
;
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
;
362 tx_command
.u32
= (uint32_t)val
;
366 for (i
= 0; i
< CTUCAN_CORE_TXBUF_NUM
; i
++) {
367 if (!(tx_command
.u32
& (mask
.u32
<< i
))) {
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
) {
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
))
382 if (tx_command
.s
.txce
) {
383 if ((buff_st
== TXT_TOK
) || (buff_st
== TXT_ERR
) ||
384 (buff_st
== TXT_ABT
))
387 s
->tx_status
.u32
= (s
->tx_status
.u32
& ~buff_st_mask
) |
388 (buff_st
<< (i
* 4));
391 ctucan_send_ready_buffers(s
);
392 ctucan_update_txnf(s
);
395 case CTU_CAN_FD_TX_PRIORITY
:
396 s
->tx_priority
.u32
= (uint32_t)val
;
400 ctucan_update_irq(s
);
406 uint64_t ctucan_mem_read(CtuCanCoreState
*s
, hwaddr addr
, unsigned size
)
410 DPRINTF("read addr 0x%02x ...\n", (unsigned int)addr
);
412 if (addr
> CTUCAN_CORE_MEM_SIZE
) {
417 case CTU_CAN_FD_DEVICE_ID
:
419 union ctu_can_fd_device_id_version idver
;
421 idver
.s
.device_id
= CTU_CAN_FD_ID
;
422 idver
.s
.ver_major
= 2;
423 idver
.s
.ver_minor
= 2;
427 case CTU_CAN_FD_MODE
:
428 val
= s
->mode_settings
.u32
;
430 case CTU_CAN_FD_STATUS
:
433 case CTU_CAN_FD_INT_STAT
:
434 val
= s
->int_stat
.u32
;
436 case CTU_CAN_FD_INT_ENA_SET
:
437 case CTU_CAN_FD_INT_ENA_CLR
:
438 val
= s
->int_ena
.u32
;
440 case CTU_CAN_FD_INT_MASK_SET
:
441 case CTU_CAN_FD_INT_MASK_CLR
:
442 val
= s
->int_mask
.u32
;
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
-
449 val
= s
->rx_mem_info
.u32
;
451 case CTU_CAN_FD_RX_POINTERS
:
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
;
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;
465 s
->rx_status_rx_settings
.s
.rxe
= 0;
467 if (((s
->rx_cnt
+ 3) & ~3) == CTUCAN_RCV_BUF_LEN
) {
468 s
->rx_status_rx_settings
.s
.rxf
= 1;
470 s
->rx_status_rx_settings
.s
.rxf
= 0;
472 val
= s
->rx_status_rx_settings
.u32
;
474 case CTU_CAN_FD_RX_DATA
:
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;
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;
493 s
->rx_tail_pos
= (s
->rx_tail_pos
+ 4) % CTUCAN_RCV_BUF_LEN
;
498 case CTU_CAN_FD_TX_STATUS
:
499 val
= s
->tx_status
.u32
;
501 case CTU_CAN_FD_TX_PRIORITY
:
502 val
= s
->tx_priority
.u32
;
504 case CTU_CAN_FD_RX_FR_CTR
:
505 val
= s
->rx_fr_ctr
.s
.rx_fr_ctr_val
;
507 case CTU_CAN_FD_TX_FR_CTR
:
508 val
= s
->tx_fr_ctr
.s
.tx_fr_ctr_val
;
510 case CTU_CAN_FD_YOLO_REG
:
511 val
= s
->yolo_reg
.s
.yolo_val
;
515 val
>>= ((addr
& 3) << 3);
517 val
&= ((uint64_t)1 << (size
<< 3)) - 1;
523 bool ctucan_can_receive(CanBusClientState
*client
)
525 CtuCanCoreState
*s
= container_of(client
, CtuCanCoreState
, bus_client
);
527 if (!s
->mode_settings
.s
.ena
) {
531 return true; /* always return true, when operation mode */
534 ssize_t
ctucan_receive(CanBusClientState
*client
, const qemu_can_frame
*frames
,
537 CtuCanCoreState
*s
= container_of(client
, CtuCanCoreState
, bus_client
);
538 static uint8_t rcv
[CTUCAN_MSG_MAX_LEN
];
541 const qemu_can_frame
*frame
= frames
;
542 union ctu_can_fd_int_stat int_stat
;
545 if (frames_cnt
<= 0) {
549 ret
= ctucan_frame2buff(frame
, rcv
);
551 if (s
->rx_cnt
+ ret
> CTUCAN_RCV_BUF_LEN
) { /* Data overrun. */
554 s
->int_stat
.u32
|= int_stat
.u32
& ~s
->int_mask
.u32
;
555 ctucan_update_irq(s
);
556 DPRINTF("Receive FIFO overrun\n");
559 s
->status
.s
.idle
= 0;
562 if (((s
->rx_cnt
+ 3) & ~3) == CTUCAN_RCV_BUF_LEN
) {
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
];
572 s
->status
.s
.rxne
= 1;
574 ctucan_update_irq(s
);
579 static CanBusClientInfo ctucan_bus_client_info
= {
580 .can_receive
= ctucan_can_receive
,
581 .receive
= ctucan_receive
,
585 int ctucan_connect_to_bus(CtuCanCoreState
*s
, CanBusState
*bus
)
587 s
->bus_client
.info
= &ctucan_bus_client_info
;
593 if (can_bus_insert_client(bus
, &s
->bus_client
) < 0) {
600 void ctucan_disconnect(CtuCanCoreState
*s
)
602 can_bus_remove_client(&s
->bus_client
);
605 int ctucan_init(CtuCanCoreState
*s
, qemu_irq irq
)
609 qemu_irq_lower(s
->irq
);
611 ctucan_hardware_reset(s
);
616 const VMStateDescription vmstate_qemu_ctucan_tx_buffer
= {
617 .name
= "qemu_ctucan_tx_buffer",
619 .minimum_version_id
= 1,
620 .fields
= (VMStateField
[]) {
621 VMSTATE_UINT8_ARRAY(data
, CtuCanCoreMsgBuffer
, CTUCAN_CORE_MSG_MAX_LEN
),
622 VMSTATE_END_OF_LIST()
626 static int ctucan_post_load(void *opaque
, int version_id
)
628 CtuCanCoreState
*s
= opaque
;
629 ctucan_update_irq(s
);
633 /* VMState is needed for live migration of QEMU images */
634 const VMStateDescription vmstate_ctucan
= {
637 .minimum_version_id
= 1,
638 .post_load
= ctucan_post_load
,
639 .fields
= (VMStateField
[]) {
640 VMSTATE_UINT32(mode_settings
.u32
, CtuCanCoreState
),
641 VMSTATE_UINT32(status
.u32
, CtuCanCoreState
),
642 VMSTATE_UINT32(int_stat
.u32
, CtuCanCoreState
),
643 VMSTATE_UINT32(int_ena
.u32
, CtuCanCoreState
),
644 VMSTATE_UINT32(int_mask
.u32
, CtuCanCoreState
),
645 VMSTATE_UINT32(brt
.u32
, CtuCanCoreState
),
646 VMSTATE_UINT32(brt_fd
.u32
, CtuCanCoreState
),
647 VMSTATE_UINT32(ewl_erp_fault_state
.u32
, CtuCanCoreState
),
648 VMSTATE_UINT32(rec_tec
.u32
, CtuCanCoreState
),
649 VMSTATE_UINT32(err_norm_err_fd
.u32
, CtuCanCoreState
),
650 VMSTATE_UINT32(ctr_pres
.u32
, CtuCanCoreState
),
651 VMSTATE_UINT32(filter_a_mask
.u32
, CtuCanCoreState
),
652 VMSTATE_UINT32(filter_a_val
.u32
, CtuCanCoreState
),
653 VMSTATE_UINT32(filter_b_mask
.u32
, CtuCanCoreState
),
654 VMSTATE_UINT32(filter_b_val
.u32
, CtuCanCoreState
),
655 VMSTATE_UINT32(filter_c_mask
.u32
, CtuCanCoreState
),
656 VMSTATE_UINT32(filter_c_val
.u32
, CtuCanCoreState
),
657 VMSTATE_UINT32(filter_ran_low
.u32
, CtuCanCoreState
),
658 VMSTATE_UINT32(filter_ran_high
.u32
, CtuCanCoreState
),
659 VMSTATE_UINT32(filter_control_filter_status
.u32
, CtuCanCoreState
),
660 VMSTATE_UINT32(rx_mem_info
.u32
, CtuCanCoreState
),
661 VMSTATE_UINT32(rx_pointers
.u32
, CtuCanCoreState
),
662 VMSTATE_UINT32(rx_status_rx_settings
.u32
, CtuCanCoreState
),
663 VMSTATE_UINT32(tx_status
.u32
, CtuCanCoreState
),
664 VMSTATE_UINT32(tx_priority
.u32
, CtuCanCoreState
),
665 VMSTATE_UINT32(err_capt_alc
.u32
, CtuCanCoreState
),
666 VMSTATE_UINT32(trv_delay_ssp_cfg
.u32
, CtuCanCoreState
),
667 VMSTATE_UINT32(rx_fr_ctr
.u32
, CtuCanCoreState
),
668 VMSTATE_UINT32(tx_fr_ctr
.u32
, CtuCanCoreState
),
669 VMSTATE_UINT32(debug_register
.u32
, CtuCanCoreState
),
670 VMSTATE_UINT32(yolo_reg
.u32
, CtuCanCoreState
),
671 VMSTATE_UINT32(timestamp_low
.u32
, CtuCanCoreState
),
672 VMSTATE_UINT32(timestamp_high
.u32
, CtuCanCoreState
),
674 VMSTATE_STRUCT_ARRAY(tx_buffer
, CtuCanCoreState
,
675 CTUCAN_CORE_TXBUF_NUM
, 0, vmstate_qemu_ctucan_tx_buffer
,
676 CtuCanCoreMsgBuffer
),
678 VMSTATE_BUFFER(rx_buff
, CtuCanCoreState
),
679 VMSTATE_UINT32(rx_tail_pos
, CtuCanCoreState
),
680 VMSTATE_UINT32(rx_cnt
, CtuCanCoreState
),
681 VMSTATE_UINT32(rx_frame_rem
, CtuCanCoreState
),
683 VMSTATE_END_OF_LIST()