xref: /qemu/hw/net/can/can_sja1000.c (revision 25145a7d)
1733210e7SPavel Pisa /*
2733210e7SPavel Pisa  * CAN device - SJA1000 chip emulation for QEMU
3733210e7SPavel Pisa  *
4733210e7SPavel Pisa  * Copyright (c) 2013-2014 Jin Yang
5733210e7SPavel Pisa  * Copyright (c) 2014-2018 Pavel Pisa
6733210e7SPavel Pisa  *
7733210e7SPavel Pisa  * Initial development supported by Google GSoC 2013 from RTEMS project slot
8733210e7SPavel Pisa  *
9733210e7SPavel Pisa  * Permission is hereby granted, free of charge, to any person obtaining a copy
10733210e7SPavel Pisa  * of this software and associated documentation files (the "Software"), to deal
11733210e7SPavel Pisa  * in the Software without restriction, including without limitation the rights
12733210e7SPavel Pisa  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13733210e7SPavel Pisa  * copies of the Software, and to permit persons to whom the Software is
14733210e7SPavel Pisa  * furnished to do so, subject to the following conditions:
15733210e7SPavel Pisa  *
16733210e7SPavel Pisa  * The above copyright notice and this permission notice shall be included in
17733210e7SPavel Pisa  * all copies or substantial portions of the Software.
18733210e7SPavel Pisa  *
19733210e7SPavel Pisa  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20733210e7SPavel Pisa  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21733210e7SPavel Pisa  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22733210e7SPavel Pisa  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23733210e7SPavel Pisa  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24733210e7SPavel Pisa  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25733210e7SPavel Pisa  * THE SOFTWARE.
26733210e7SPavel Pisa  */
2764552b6bSMarkus Armbruster 
28733210e7SPavel Pisa #include "qemu/osdep.h"
29733210e7SPavel Pisa #include "qemu/log.h"
30733210e7SPavel Pisa #include "chardev/char.h"
3164552b6bSMarkus Armbruster #include "hw/irq.h"
32d6454270SMarkus Armbruster #include "migration/vmstate.h"
33733210e7SPavel Pisa #include "net/can_emu.h"
34733210e7SPavel Pisa 
35733210e7SPavel Pisa #include "can_sja1000.h"
36733210e7SPavel Pisa 
37733210e7SPavel Pisa #ifndef DEBUG_FILTER
38733210e7SPavel Pisa #define DEBUG_FILTER 0
39733210e7SPavel Pisa #endif /*DEBUG_FILTER*/
40733210e7SPavel Pisa 
41733210e7SPavel Pisa #ifndef DEBUG_CAN
42733210e7SPavel Pisa #define DEBUG_CAN 0
43733210e7SPavel Pisa #endif /*DEBUG_CAN*/
44733210e7SPavel Pisa 
45733210e7SPavel Pisa #define DPRINTF(fmt, ...) \
46733210e7SPavel Pisa     do { \
47733210e7SPavel Pisa         if (DEBUG_CAN) { \
48733210e7SPavel Pisa             qemu_log("[cansja]: " fmt , ## __VA_ARGS__); \
49733210e7SPavel Pisa         } \
50733210e7SPavel Pisa     } while (0)
51733210e7SPavel Pisa 
can_sja_software_reset(CanSJA1000State * s)52733210e7SPavel Pisa static void can_sja_software_reset(CanSJA1000State *s)
53733210e7SPavel Pisa {
54733210e7SPavel Pisa     s->mode        &= ~0x31;
55733210e7SPavel Pisa     s->mode        |= 0x01;
56733210e7SPavel Pisa     s->status_pel  &= ~0x37;
57733210e7SPavel Pisa     s->status_pel  |= 0x34;
58733210e7SPavel Pisa 
59733210e7SPavel Pisa     s->rxbuf_start = 0x00;
60733210e7SPavel Pisa     s->rxmsg_cnt   = 0x00;
61733210e7SPavel Pisa     s->rx_cnt      = 0x00;
62733210e7SPavel Pisa }
63733210e7SPavel Pisa 
can_sja_hardware_reset(CanSJA1000State * s)64733210e7SPavel Pisa void can_sja_hardware_reset(CanSJA1000State *s)
65733210e7SPavel Pisa {
66733210e7SPavel Pisa     /* Reset by hardware, p10 */
67733210e7SPavel Pisa     s->mode        = 0x01;
68733210e7SPavel Pisa     s->status_pel  = 0x3c;
69733210e7SPavel Pisa     s->interrupt_pel = 0x00;
70733210e7SPavel Pisa     s->clock       = 0x00;
71733210e7SPavel Pisa     s->rxbuf_start = 0x00;
72733210e7SPavel Pisa     s->rxmsg_cnt   = 0x00;
73733210e7SPavel Pisa     s->rx_cnt      = 0x00;
74733210e7SPavel Pisa 
75733210e7SPavel Pisa     s->control     = 0x01;
76733210e7SPavel Pisa     s->status_bas  = 0x0c;
77733210e7SPavel Pisa     s->interrupt_bas = 0x00;
78733210e7SPavel Pisa 
79733210e7SPavel Pisa     qemu_irq_lower(s->irq);
80733210e7SPavel Pisa }
81733210e7SPavel Pisa 
82733210e7SPavel Pisa static
can_sja_single_filter(struct qemu_can_filter * filter,const uint8_t * acr,const uint8_t * amr,int extended)83733210e7SPavel Pisa void can_sja_single_filter(struct qemu_can_filter *filter,
84733210e7SPavel Pisa             const uint8_t *acr,  const uint8_t *amr, int extended)
85733210e7SPavel Pisa {
86733210e7SPavel Pisa     if (extended) {
87733210e7SPavel Pisa         filter->can_id = (uint32_t)acr[0] << 21;
88733210e7SPavel Pisa         filter->can_id |= (uint32_t)acr[1] << 13;
89733210e7SPavel Pisa         filter->can_id |= (uint32_t)acr[2] << 5;
90733210e7SPavel Pisa         filter->can_id |= (uint32_t)acr[3] >> 3;
91733210e7SPavel Pisa         if (acr[3] & 4) {
92733210e7SPavel Pisa             filter->can_id |= QEMU_CAN_RTR_FLAG;
93733210e7SPavel Pisa         }
94733210e7SPavel Pisa 
95733210e7SPavel Pisa         filter->can_mask = (uint32_t)amr[0] << 21;
96733210e7SPavel Pisa         filter->can_mask |= (uint32_t)amr[1] << 13;
97733210e7SPavel Pisa         filter->can_mask |= (uint32_t)amr[2] << 5;
98733210e7SPavel Pisa         filter->can_mask |= (uint32_t)amr[3] >> 3;
99733210e7SPavel Pisa         filter->can_mask = ~filter->can_mask & QEMU_CAN_EFF_MASK;
100733210e7SPavel Pisa         if (!(amr[3] & 4)) {
101733210e7SPavel Pisa             filter->can_mask |= QEMU_CAN_RTR_FLAG;
102733210e7SPavel Pisa         }
103733210e7SPavel Pisa     } else {
104733210e7SPavel Pisa         filter->can_id = (uint32_t)acr[0] << 3;
105733210e7SPavel Pisa         filter->can_id |= (uint32_t)acr[1] >> 5;
106733210e7SPavel Pisa         if (acr[1] & 0x10) {
107733210e7SPavel Pisa             filter->can_id |= QEMU_CAN_RTR_FLAG;
108733210e7SPavel Pisa         }
109733210e7SPavel Pisa 
110733210e7SPavel Pisa         filter->can_mask = (uint32_t)amr[0] << 3;
111*25145a7dSPavel Pisa         filter->can_mask |= (uint32_t)amr[1] >> 5;
112733210e7SPavel Pisa         filter->can_mask = ~filter->can_mask & QEMU_CAN_SFF_MASK;
113733210e7SPavel Pisa         if (!(amr[1] & 0x10)) {
114733210e7SPavel Pisa             filter->can_mask |= QEMU_CAN_RTR_FLAG;
115733210e7SPavel Pisa         }
116733210e7SPavel Pisa     }
117733210e7SPavel Pisa }
118733210e7SPavel Pisa 
119733210e7SPavel Pisa static
can_sja_dual_filter(struct qemu_can_filter * filter,const uint8_t * acr,const uint8_t * amr,int extended)120733210e7SPavel Pisa void can_sja_dual_filter(struct qemu_can_filter *filter,
121733210e7SPavel Pisa             const uint8_t *acr,  const uint8_t *amr, int extended)
122733210e7SPavel Pisa {
123733210e7SPavel Pisa     if (extended) {
124733210e7SPavel Pisa         filter->can_id = (uint32_t)acr[0] << 21;
125733210e7SPavel Pisa         filter->can_id |= (uint32_t)acr[1] << 13;
126733210e7SPavel Pisa 
127733210e7SPavel Pisa         filter->can_mask = (uint32_t)amr[0] << 21;
128733210e7SPavel Pisa         filter->can_mask |= (uint32_t)amr[1] << 13;
129733210e7SPavel Pisa         filter->can_mask = ~filter->can_mask & QEMU_CAN_EFF_MASK & ~0x1fff;
130733210e7SPavel Pisa     } else {
131733210e7SPavel Pisa         filter->can_id = (uint32_t)acr[0] << 3;
132733210e7SPavel Pisa         filter->can_id |= (uint32_t)acr[1] >> 5;
133733210e7SPavel Pisa         if (acr[1] & 0x10) {
134733210e7SPavel Pisa             filter->can_id |= QEMU_CAN_RTR_FLAG;
135733210e7SPavel Pisa         }
136733210e7SPavel Pisa 
137733210e7SPavel Pisa         filter->can_mask = (uint32_t)amr[0] << 3;
138733210e7SPavel Pisa         filter->can_mask |= (uint32_t)amr[1] >> 5;
139733210e7SPavel Pisa         filter->can_mask = ~filter->can_mask & QEMU_CAN_SFF_MASK;
140733210e7SPavel Pisa         if (!(amr[1] & 0x10)) {
141733210e7SPavel Pisa             filter->can_mask |= QEMU_CAN_RTR_FLAG;
142733210e7SPavel Pisa         }
143733210e7SPavel Pisa     }
144733210e7SPavel Pisa }
145733210e7SPavel Pisa 
146733210e7SPavel Pisa /* Details in DS-p22, what we need to do here is to test the data. */
147733210e7SPavel Pisa static
can_sja_accept_filter(CanSJA1000State * s,const qemu_can_frame * frame)148733210e7SPavel Pisa int can_sja_accept_filter(CanSJA1000State *s,
149733210e7SPavel Pisa                                  const qemu_can_frame *frame)
150733210e7SPavel Pisa {
151733210e7SPavel Pisa 
152733210e7SPavel Pisa     struct qemu_can_filter filter;
153733210e7SPavel Pisa 
154733210e7SPavel Pisa     if (s->clock & 0x80) { /* PeliCAN Mode */
155733210e7SPavel Pisa         if (s->mode & (1 << 3)) { /* Single mode. */
156733210e7SPavel Pisa             if (frame->can_id & QEMU_CAN_EFF_FLAG) { /* EFF */
157733210e7SPavel Pisa                 can_sja_single_filter(&filter,
158733210e7SPavel Pisa                     s->code_mask + 0, s->code_mask + 4, 1);
159733210e7SPavel Pisa 
160733210e7SPavel Pisa                 if (!can_bus_filter_match(&filter, frame->can_id)) {
161733210e7SPavel Pisa                     return 0;
162733210e7SPavel Pisa                 }
163733210e7SPavel Pisa             } else { /* SFF */
164733210e7SPavel Pisa                 can_sja_single_filter(&filter,
165733210e7SPavel Pisa                     s->code_mask + 0, s->code_mask + 4, 0);
166733210e7SPavel Pisa 
167733210e7SPavel Pisa                 if (!can_bus_filter_match(&filter, frame->can_id)) {
168733210e7SPavel Pisa                     return 0;
169733210e7SPavel Pisa                 }
170733210e7SPavel Pisa 
171733210e7SPavel Pisa                 if (frame->can_id & QEMU_CAN_RTR_FLAG) { /* RTR */
172733210e7SPavel Pisa                     return 1;
173733210e7SPavel Pisa                 }
174733210e7SPavel Pisa 
175733210e7SPavel Pisa                 if (frame->can_dlc == 0) {
176733210e7SPavel Pisa                     return 1;
177733210e7SPavel Pisa                 }
178733210e7SPavel Pisa 
179733210e7SPavel Pisa                 if ((frame->data[0] & ~(s->code_mask[6])) !=
180733210e7SPavel Pisa                    (s->code_mask[2] & ~(s->code_mask[6]))) {
181733210e7SPavel Pisa                     return 0;
182733210e7SPavel Pisa                 }
183733210e7SPavel Pisa 
184733210e7SPavel Pisa                 if (frame->can_dlc < 2) {
185733210e7SPavel Pisa                     return 1;
186733210e7SPavel Pisa                 }
187733210e7SPavel Pisa 
188733210e7SPavel Pisa                 if ((frame->data[1] & ~(s->code_mask[7])) ==
189733210e7SPavel Pisa                     (s->code_mask[3] & ~(s->code_mask[7]))) {
190733210e7SPavel Pisa                     return 1;
191733210e7SPavel Pisa                 }
192733210e7SPavel Pisa 
193733210e7SPavel Pisa                 return 0;
194733210e7SPavel Pisa             }
195733210e7SPavel Pisa         } else { /* Dual mode */
196733210e7SPavel Pisa             if (frame->can_id & QEMU_CAN_EFF_FLAG) { /* EFF */
197733210e7SPavel Pisa                 can_sja_dual_filter(&filter,
198733210e7SPavel Pisa                     s->code_mask + 0, s->code_mask + 4, 1);
199733210e7SPavel Pisa 
200733210e7SPavel Pisa                 if (can_bus_filter_match(&filter, frame->can_id)) {
201733210e7SPavel Pisa                     return 1;
202733210e7SPavel Pisa                 }
203733210e7SPavel Pisa 
204733210e7SPavel Pisa                 can_sja_dual_filter(&filter,
205733210e7SPavel Pisa                     s->code_mask + 2, s->code_mask + 6, 1);
206733210e7SPavel Pisa 
207733210e7SPavel Pisa                 if (can_bus_filter_match(&filter, frame->can_id)) {
208733210e7SPavel Pisa                     return 1;
209733210e7SPavel Pisa                 }
210733210e7SPavel Pisa 
211733210e7SPavel Pisa                 return 0;
212733210e7SPavel Pisa             } else {
213733210e7SPavel Pisa                 can_sja_dual_filter(&filter,
214733210e7SPavel Pisa                     s->code_mask + 0, s->code_mask + 4, 0);
215733210e7SPavel Pisa 
216733210e7SPavel Pisa                 if (can_bus_filter_match(&filter, frame->can_id)) {
217733210e7SPavel Pisa                     uint8_t expect;
218733210e7SPavel Pisa                     uint8_t mask;
219733210e7SPavel Pisa                     expect = s->code_mask[1] << 4;
220733210e7SPavel Pisa                     expect |= s->code_mask[3] & 0x0f;
221733210e7SPavel Pisa 
222733210e7SPavel Pisa                     mask = s->code_mask[5] << 4;
223733210e7SPavel Pisa                     mask |= s->code_mask[7] & 0x0f;
224733210e7SPavel Pisa                         mask = ~mask & 0xff;
225733210e7SPavel Pisa 
226733210e7SPavel Pisa                     if ((frame->data[0] & mask) ==
227733210e7SPavel Pisa                         (expect & mask)) {
228733210e7SPavel Pisa                         return 1;
229733210e7SPavel Pisa                     }
230733210e7SPavel Pisa                 }
231733210e7SPavel Pisa 
232733210e7SPavel Pisa                 can_sja_dual_filter(&filter,
233733210e7SPavel Pisa                     s->code_mask + 2, s->code_mask + 6, 0);
234733210e7SPavel Pisa 
235733210e7SPavel Pisa                 if (can_bus_filter_match(&filter, frame->can_id)) {
236733210e7SPavel Pisa                     return 1;
237733210e7SPavel Pisa                 }
238733210e7SPavel Pisa 
239733210e7SPavel Pisa                 return 0;
240733210e7SPavel Pisa             }
241733210e7SPavel Pisa         }
242733210e7SPavel Pisa     }
243733210e7SPavel Pisa 
244733210e7SPavel Pisa     return 1;
245733210e7SPavel Pisa }
246733210e7SPavel Pisa 
can_display_msg(const char * prefix,const qemu_can_frame * msg)247733210e7SPavel Pisa static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
248733210e7SPavel Pisa {
249733210e7SPavel Pisa     int i;
250c60f599bSRichard Henderson     FILE *logfile = qemu_log_trylock();
251733210e7SPavel Pisa 
25278b54858SRichard Henderson     if (logfile) {
25378b54858SRichard Henderson         fprintf(logfile, "%s%03X [%01d] %s %s",
254733210e7SPavel Pisa                 prefix,
255733210e7SPavel Pisa                 msg->can_id & QEMU_CAN_EFF_MASK,
256733210e7SPavel Pisa                 msg->can_dlc,
257733210e7SPavel Pisa                 msg->can_id & QEMU_CAN_EFF_FLAG ? "EFF" : "SFF",
258733210e7SPavel Pisa                 msg->can_id & QEMU_CAN_RTR_FLAG ? "RTR" : "DAT");
259733210e7SPavel Pisa 
260733210e7SPavel Pisa         for (i = 0; i < msg->can_dlc; i++) {
26178b54858SRichard Henderson             fprintf(logfile, " %02X", msg->data[i]);
262733210e7SPavel Pisa         }
26378b54858SRichard Henderson         fprintf(logfile, "\n");
264fc59d2d8SRobert Foley         qemu_log_unlock(logfile);
265733210e7SPavel Pisa     }
26678b54858SRichard Henderson }
267733210e7SPavel Pisa 
buff2frame_pel(const uint8_t * buff,qemu_can_frame * frame)268733210e7SPavel Pisa static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame)
269733210e7SPavel Pisa {
270733210e7SPavel Pisa     uint8_t i;
271733210e7SPavel Pisa 
272d44948ccSJan Charvat     frame->flags = 0;
273733210e7SPavel Pisa     frame->can_id = 0;
274733210e7SPavel Pisa     if (buff[0] & 0x40) { /* RTR */
275733210e7SPavel Pisa         frame->can_id = QEMU_CAN_RTR_FLAG;
276733210e7SPavel Pisa     }
277733210e7SPavel Pisa     frame->can_dlc = buff[0] & 0x0f;
278733210e7SPavel Pisa 
27911744862SPavel Pisa     if (frame->can_dlc > 8) {
28011744862SPavel Pisa         frame->can_dlc = 8;
28111744862SPavel Pisa     }
28211744862SPavel Pisa 
283733210e7SPavel Pisa     if (buff[0] & 0x80) { /* Extended */
284733210e7SPavel Pisa         frame->can_id |= QEMU_CAN_EFF_FLAG;
285733210e7SPavel Pisa         frame->can_id |= buff[1] << 21; /* ID.28~ID.21 */
286733210e7SPavel Pisa         frame->can_id |= buff[2] << 13; /* ID.20~ID.13 */
287733210e7SPavel Pisa         frame->can_id |= buff[3] <<  5;
288733210e7SPavel Pisa         frame->can_id |= buff[4] >>  3;
289733210e7SPavel Pisa         for (i = 0; i < frame->can_dlc; i++) {
290733210e7SPavel Pisa             frame->data[i] = buff[5 + i];
291733210e7SPavel Pisa         }
292733210e7SPavel Pisa         for (; i < 8; i++) {
293733210e7SPavel Pisa             frame->data[i] = 0;
294733210e7SPavel Pisa         }
295733210e7SPavel Pisa     } else {
296733210e7SPavel Pisa         frame->can_id |= buff[1] <<  3;
297733210e7SPavel Pisa         frame->can_id |= buff[2] >>  5;
298733210e7SPavel Pisa         for (i = 0; i < frame->can_dlc; i++) {
299733210e7SPavel Pisa             frame->data[i] = buff[3 + i];
300733210e7SPavel Pisa         }
301733210e7SPavel Pisa         for (; i < 8; i++) {
302733210e7SPavel Pisa             frame->data[i] = 0;
303733210e7SPavel Pisa         }
304733210e7SPavel Pisa     }
305733210e7SPavel Pisa }
306733210e7SPavel Pisa 
307733210e7SPavel Pisa 
buff2frame_bas(const uint8_t * buff,qemu_can_frame * frame)308733210e7SPavel Pisa static void buff2frame_bas(const uint8_t *buff, qemu_can_frame *frame)
309733210e7SPavel Pisa {
310733210e7SPavel Pisa     uint8_t i;
311733210e7SPavel Pisa 
312d44948ccSJan Charvat     frame->flags = 0;
313733210e7SPavel Pisa     frame->can_id = ((buff[0] << 3) & (0xff << 3)) + ((buff[1] >> 5) & 0x07);
314733210e7SPavel Pisa     if (buff[1] & 0x10) { /* RTR */
315733210e7SPavel Pisa         frame->can_id = QEMU_CAN_RTR_FLAG;
316733210e7SPavel Pisa     }
317733210e7SPavel Pisa     frame->can_dlc = buff[1] & 0x0f;
318733210e7SPavel Pisa 
31911744862SPavel Pisa     if (frame->can_dlc > 8) {
32011744862SPavel Pisa         frame->can_dlc = 8;
32111744862SPavel Pisa     }
32211744862SPavel Pisa 
323733210e7SPavel Pisa     for (i = 0; i < frame->can_dlc; i++) {
324733210e7SPavel Pisa         frame->data[i] = buff[2 + i];
325733210e7SPavel Pisa     }
326733210e7SPavel Pisa     for (; i < 8; i++) {
327733210e7SPavel Pisa         frame->data[i] = 0;
328733210e7SPavel Pisa     }
329733210e7SPavel Pisa }
330733210e7SPavel Pisa 
331733210e7SPavel Pisa 
frame2buff_pel(const qemu_can_frame * frame,uint8_t * buff)332733210e7SPavel Pisa static int frame2buff_pel(const qemu_can_frame *frame, uint8_t *buff)
333733210e7SPavel Pisa {
334733210e7SPavel Pisa     int i;
33546b25fe0SJan Charvat     int dlen = frame->can_dlc;
336733210e7SPavel Pisa 
337733210e7SPavel Pisa     if (frame->can_id & QEMU_CAN_ERR_FLAG) { /* error frame, NOT support now. */
338733210e7SPavel Pisa         return -1;
339733210e7SPavel Pisa     }
340733210e7SPavel Pisa 
34146b25fe0SJan Charvat     if (dlen > 8) {
34246b25fe0SJan Charvat         return -1;
34346b25fe0SJan Charvat     }
34446b25fe0SJan Charvat 
345733210e7SPavel Pisa     buff[0] = 0x0f & frame->can_dlc; /* DLC */
346733210e7SPavel Pisa     if (frame->can_id & QEMU_CAN_RTR_FLAG) { /* RTR */
347733210e7SPavel Pisa         buff[0] |= (1 << 6);
348733210e7SPavel Pisa     }
349733210e7SPavel Pisa     if (frame->can_id & QEMU_CAN_EFF_FLAG) { /* EFF */
350733210e7SPavel Pisa         buff[0] |= (1 << 7);
351733210e7SPavel Pisa         buff[1] = extract32(frame->can_id, 21, 8); /* ID.28~ID.21 */
352733210e7SPavel Pisa         buff[2] = extract32(frame->can_id, 13, 8); /* ID.20~ID.13 */
353733210e7SPavel Pisa         buff[3] = extract32(frame->can_id, 5, 8);  /* ID.12~ID.05 */
354733210e7SPavel Pisa         buff[4] = extract32(frame->can_id, 0, 5) << 3; /* ID.04~ID.00,xxx */
35546b25fe0SJan Charvat         for (i = 0; i < dlen; i++) {
356733210e7SPavel Pisa             buff[5 + i] = frame->data[i];
357733210e7SPavel Pisa         }
35846b25fe0SJan Charvat         return dlen + 5;
359733210e7SPavel Pisa     } else { /* SFF */
360733210e7SPavel Pisa         buff[1] = extract32(frame->can_id, 3, 8); /* ID.10~ID.03 */
361733210e7SPavel Pisa         buff[2] = extract32(frame->can_id, 0, 3) << 5; /* ID.02~ID.00,xxxxx */
36246b25fe0SJan Charvat         for (i = 0; i < dlen; i++) {
363733210e7SPavel Pisa             buff[3 + i] = frame->data[i];
364733210e7SPavel Pisa         }
365733210e7SPavel Pisa 
36646b25fe0SJan Charvat         return dlen + 3;
367733210e7SPavel Pisa     }
368733210e7SPavel Pisa 
369733210e7SPavel Pisa     return -1;
370733210e7SPavel Pisa }
371733210e7SPavel Pisa 
frame2buff_bas(const qemu_can_frame * frame,uint8_t * buff)372733210e7SPavel Pisa static int frame2buff_bas(const qemu_can_frame *frame, uint8_t *buff)
373733210e7SPavel Pisa {
374733210e7SPavel Pisa     int i;
37546b25fe0SJan Charvat     int dlen = frame->can_dlc;
376733210e7SPavel Pisa 
377733210e7SPavel Pisa      /*
378733210e7SPavel Pisa       * EFF, no support for BasicMode
379733210e7SPavel Pisa       * No use for Error frames now,
380733210e7SPavel Pisa       * they could be used in future to update SJA1000 error state
381733210e7SPavel Pisa       */
382733210e7SPavel Pisa     if ((frame->can_id & QEMU_CAN_EFF_FLAG) ||
383733210e7SPavel Pisa        (frame->can_id & QEMU_CAN_ERR_FLAG)) {
384733210e7SPavel Pisa         return -1;
385733210e7SPavel Pisa     }
386733210e7SPavel Pisa 
38746b25fe0SJan Charvat     if (dlen > 8) {
38846b25fe0SJan Charvat         return -1;
38946b25fe0SJan Charvat     }
39046b25fe0SJan Charvat 
391733210e7SPavel Pisa     buff[0] = extract32(frame->can_id, 3, 8); /* ID.10~ID.03 */
392733210e7SPavel Pisa     buff[1] = extract32(frame->can_id, 0, 3) << 5; /* ID.02~ID.00,xxxxx */
393733210e7SPavel Pisa     if (frame->can_id & QEMU_CAN_RTR_FLAG) { /* RTR */
394733210e7SPavel Pisa         buff[1] |= (1 << 4);
395733210e7SPavel Pisa     }
396733210e7SPavel Pisa     buff[1] |= frame->can_dlc & 0x0f;
39746b25fe0SJan Charvat     for (i = 0; i < dlen; i++) {
398733210e7SPavel Pisa         buff[2 + i] = frame->data[i];
399733210e7SPavel Pisa     }
400733210e7SPavel Pisa 
40146b25fe0SJan Charvat     return dlen + 2;
402733210e7SPavel Pisa }
403733210e7SPavel Pisa 
can_sja_update_pel_irq(CanSJA1000State * s)404a62ed5d1SPaolo Bonzini static void can_sja_update_pel_irq(CanSJA1000State *s)
405a62ed5d1SPaolo Bonzini {
406a62ed5d1SPaolo Bonzini     if (s->interrupt_en & s->interrupt_pel) {
407a62ed5d1SPaolo Bonzini         qemu_irq_raise(s->irq);
408a62ed5d1SPaolo Bonzini     } else {
409a62ed5d1SPaolo Bonzini         qemu_irq_lower(s->irq);
410a62ed5d1SPaolo Bonzini     }
411a62ed5d1SPaolo Bonzini }
412a62ed5d1SPaolo Bonzini 
can_sja_update_bas_irq(CanSJA1000State * s)413a62ed5d1SPaolo Bonzini static void can_sja_update_bas_irq(CanSJA1000State *s)
414a62ed5d1SPaolo Bonzini {
415a62ed5d1SPaolo Bonzini     if ((s->control >> 1) & s->interrupt_bas) {
416a62ed5d1SPaolo Bonzini         qemu_irq_raise(s->irq);
417a62ed5d1SPaolo Bonzini     } else {
418a62ed5d1SPaolo Bonzini         qemu_irq_lower(s->irq);
419a62ed5d1SPaolo Bonzini     }
420a62ed5d1SPaolo Bonzini }
421a62ed5d1SPaolo Bonzini 
can_sja_mem_write(CanSJA1000State * s,hwaddr addr,uint64_t val,unsigned size)422733210e7SPavel Pisa void can_sja_mem_write(CanSJA1000State *s, hwaddr addr, uint64_t val,
423733210e7SPavel Pisa                        unsigned size)
424733210e7SPavel Pisa {
425733210e7SPavel Pisa     qemu_can_frame   frame;
426733210e7SPavel Pisa     uint32_t         tmp;
427733210e7SPavel Pisa     uint8_t          tmp8, count;
428733210e7SPavel Pisa 
429733210e7SPavel Pisa 
430733210e7SPavel Pisa     DPRINTF("write 0x%02llx addr 0x%02x\n",
431733210e7SPavel Pisa             (unsigned long long)val, (unsigned int)addr);
432733210e7SPavel Pisa 
433733210e7SPavel Pisa     if (addr > CAN_SJA_MEM_SIZE) {
434733210e7SPavel Pisa         return;
435733210e7SPavel Pisa     }
436733210e7SPavel Pisa 
437733210e7SPavel Pisa     if (s->clock & 0x80) { /* PeliCAN Mode */
438733210e7SPavel Pisa         switch (addr) {
439733210e7SPavel Pisa         case SJA_MOD: /* Mode register */
440733210e7SPavel Pisa             s->mode = 0x1f & val;
441733210e7SPavel Pisa             if ((s->mode & 0x01) && ((val & 0x01) == 0)) {
442733210e7SPavel Pisa                 /* Go to operation mode from reset mode. */
443733210e7SPavel Pisa                 if (s->mode & (1 << 3)) { /* Single mode. */
444733210e7SPavel Pisa                     /* For EFF */
445733210e7SPavel Pisa                     can_sja_single_filter(&s->filter[0],
446733210e7SPavel Pisa                         s->code_mask + 0, s->code_mask + 4, 1);
447733210e7SPavel Pisa 
448733210e7SPavel Pisa                     /* For SFF */
449733210e7SPavel Pisa                     can_sja_single_filter(&s->filter[1],
450733210e7SPavel Pisa                         s->code_mask + 0, s->code_mask + 4, 0);
451733210e7SPavel Pisa 
452733210e7SPavel Pisa                     can_bus_client_set_filters(&s->bus_client, s->filter, 2);
453733210e7SPavel Pisa                 } else { /* Dual mode */
454733210e7SPavel Pisa                     /* For EFF */
455733210e7SPavel Pisa                     can_sja_dual_filter(&s->filter[0],
456733210e7SPavel Pisa                         s->code_mask + 0, s->code_mask + 4, 1);
457733210e7SPavel Pisa 
458733210e7SPavel Pisa                     can_sja_dual_filter(&s->filter[1],
459733210e7SPavel Pisa                         s->code_mask + 2, s->code_mask + 6, 1);
460733210e7SPavel Pisa 
461733210e7SPavel Pisa                     /* For SFF */
462733210e7SPavel Pisa                     can_sja_dual_filter(&s->filter[2],
463733210e7SPavel Pisa                         s->code_mask + 0, s->code_mask + 4, 0);
464733210e7SPavel Pisa 
465733210e7SPavel Pisa                     can_sja_dual_filter(&s->filter[3],
466733210e7SPavel Pisa                         s->code_mask + 2, s->code_mask + 6, 0);
467733210e7SPavel Pisa 
468733210e7SPavel Pisa                     can_bus_client_set_filters(&s->bus_client, s->filter, 4);
469733210e7SPavel Pisa                 }
470733210e7SPavel Pisa 
471733210e7SPavel Pisa                 s->rxmsg_cnt = 0;
472733210e7SPavel Pisa                 s->rx_cnt = 0;
473733210e7SPavel Pisa             }
474733210e7SPavel Pisa             break;
475733210e7SPavel Pisa 
476733210e7SPavel Pisa         case SJA_CMR: /* Command register. */
477733210e7SPavel Pisa             if (0x01 & val) { /* Send transmission request. */
478733210e7SPavel Pisa                 buff2frame_pel(s->tx_buff, &frame);
479733210e7SPavel Pisa                 if (DEBUG_FILTER) {
480733210e7SPavel Pisa                     can_display_msg("[cansja]: Tx request " , &frame);
481733210e7SPavel Pisa                 }
482733210e7SPavel Pisa 
483733210e7SPavel Pisa                 /*
484733210e7SPavel Pisa                  * Clear transmission complete status,
485733210e7SPavel Pisa                  * and Transmit Buffer Status.
486733210e7SPavel Pisa                  * write to the backends.
487733210e7SPavel Pisa                  */
488733210e7SPavel Pisa                 s->status_pel &= ~(3 << 2);
489733210e7SPavel Pisa 
490733210e7SPavel Pisa                 can_bus_client_send(&s->bus_client, &frame, 1);
491733210e7SPavel Pisa 
492733210e7SPavel Pisa                 /*
493733210e7SPavel Pisa                  * Set transmission complete status
494733210e7SPavel Pisa                  * and Transmit Buffer Status.
495733210e7SPavel Pisa                  */
496733210e7SPavel Pisa                 s->status_pel |= (3 << 2);
497733210e7SPavel Pisa 
498733210e7SPavel Pisa                 /* Clear transmit status. */
499733210e7SPavel Pisa                 s->status_pel &= ~(1 << 5);
500733210e7SPavel Pisa                 s->interrupt_pel |= 0x02;
501a62ed5d1SPaolo Bonzini                 can_sja_update_pel_irq(s);
502733210e7SPavel Pisa             }
503733210e7SPavel Pisa             if (0x04 & val) { /* Release Receive Buffer */
504733210e7SPavel Pisa                 if (s->rxmsg_cnt <= 0) {
505733210e7SPavel Pisa                     break;
506733210e7SPavel Pisa                 }
507733210e7SPavel Pisa 
508733210e7SPavel Pisa                 tmp8 = s->rx_buff[s->rxbuf_start]; count = 0;
509733210e7SPavel Pisa                 if (tmp8 & (1 << 7)) { /* EFF */
510733210e7SPavel Pisa                     count += 2;
511733210e7SPavel Pisa                 }
512733210e7SPavel Pisa                 count += 3;
513733210e7SPavel Pisa                 if (!(tmp8 & (1 << 6))) { /* DATA */
514733210e7SPavel Pisa                     count += (tmp8 & 0x0f);
515733210e7SPavel Pisa                 }
516733210e7SPavel Pisa 
517733210e7SPavel Pisa                 if (DEBUG_FILTER) {
518733210e7SPavel Pisa                     qemu_log("[cansja]: message released from "
519733210e7SPavel Pisa                              "Rx FIFO cnt=%d, count=%d\n", s->rx_cnt, count);
520733210e7SPavel Pisa                 }
521733210e7SPavel Pisa 
522733210e7SPavel Pisa                 s->rxbuf_start += count;
523733210e7SPavel Pisa                 s->rxbuf_start %= SJA_RCV_BUF_LEN;
524733210e7SPavel Pisa 
525733210e7SPavel Pisa                 s->rx_cnt -= count;
526733210e7SPavel Pisa                 s->rxmsg_cnt--;
527733210e7SPavel Pisa                 if (s->rxmsg_cnt == 0) {
528733210e7SPavel Pisa                     s->status_pel &= ~(1 << 0);
529733210e7SPavel Pisa                     s->interrupt_pel &= ~(1 << 0);
530a62ed5d1SPaolo Bonzini                     can_sja_update_pel_irq(s);
531733210e7SPavel Pisa                 }
532733210e7SPavel Pisa             }
533733210e7SPavel Pisa             if (0x08 & val) { /* Clear data overrun */
534733210e7SPavel Pisa                 s->status_pel &= ~(1 << 1);
535733210e7SPavel Pisa                 s->interrupt_pel &= ~(1 << 3);
536a62ed5d1SPaolo Bonzini                 can_sja_update_pel_irq(s);
537733210e7SPavel Pisa             }
538733210e7SPavel Pisa             break;
539733210e7SPavel Pisa         case SJA_SR: /* Status register */
540733210e7SPavel Pisa         case SJA_IR: /* Interrupt register */
541733210e7SPavel Pisa             break; /* Do nothing */
542733210e7SPavel Pisa         case SJA_IER: /* Interrupt enable register */
543733210e7SPavel Pisa             s->interrupt_en = val;
544733210e7SPavel Pisa             break;
545733210e7SPavel Pisa         case 16: /* RX frame information addr16-28. */
546733210e7SPavel Pisa             s->status_pel |= (1 << 5); /* Set transmit status. */
547bd7b4e1fSThomas Huth             /* fallthrough */
548733210e7SPavel Pisa         case 17 ... 28:
549733210e7SPavel Pisa             if (s->mode & 0x01) { /* Reset mode */
550733210e7SPavel Pisa                 if (addr < 24) {
551733210e7SPavel Pisa                     s->code_mask[addr - 16] = val;
552733210e7SPavel Pisa                 }
553733210e7SPavel Pisa             } else { /* Operation mode */
554733210e7SPavel Pisa                 s->tx_buff[addr - 16] = val; /* Store to TX buffer directly. */
555733210e7SPavel Pisa             }
556733210e7SPavel Pisa             break;
557733210e7SPavel Pisa         case SJA_CDR:
558733210e7SPavel Pisa             s->clock = val;
559733210e7SPavel Pisa             break;
560733210e7SPavel Pisa         }
561733210e7SPavel Pisa     } else { /* Basic Mode */
562733210e7SPavel Pisa         switch (addr) {
563733210e7SPavel Pisa         case SJA_BCAN_CTR: /* Control register, addr 0 */
564733210e7SPavel Pisa             if ((s->control & 0x01) && ((val & 0x01) == 0)) {
565733210e7SPavel Pisa                 /* Go to operation mode from reset mode. */
566733210e7SPavel Pisa                 s->filter[0].can_id = (s->code << 3) & (0xff << 3);
567733210e7SPavel Pisa                 tmp = (~(s->mask << 3)) & (0xff << 3);
568733210e7SPavel Pisa                 tmp |= QEMU_CAN_EFF_FLAG; /* Only Basic CAN Frame. */
569733210e7SPavel Pisa                 s->filter[0].can_mask = tmp;
570733210e7SPavel Pisa                 can_bus_client_set_filters(&s->bus_client, s->filter, 1);
571733210e7SPavel Pisa 
572733210e7SPavel Pisa                 s->rxmsg_cnt = 0;
573733210e7SPavel Pisa                 s->rx_cnt = 0;
574733210e7SPavel Pisa             } else if (!(s->control & 0x01) && !(val & 0x01)) {
575733210e7SPavel Pisa                 can_sja_software_reset(s);
576733210e7SPavel Pisa             }
577733210e7SPavel Pisa 
578733210e7SPavel Pisa             s->control = 0x1f & val;
579733210e7SPavel Pisa             break;
580733210e7SPavel Pisa         case SJA_BCAN_CMR: /* Command register, addr 1 */
581733210e7SPavel Pisa             if (0x01 & val) { /* Send transmission request. */
582733210e7SPavel Pisa                 buff2frame_bas(s->tx_buff, &frame);
583733210e7SPavel Pisa                 if (DEBUG_FILTER) {
584733210e7SPavel Pisa                     can_display_msg("[cansja]: Tx request " , &frame);
585733210e7SPavel Pisa                 }
586733210e7SPavel Pisa 
587733210e7SPavel Pisa                 /*
588733210e7SPavel Pisa                  * Clear transmission complete status,
589733210e7SPavel Pisa                  * and Transmit Buffer Status.
590733210e7SPavel Pisa                  */
591733210e7SPavel Pisa                 s->status_bas &= ~(3 << 2);
592733210e7SPavel Pisa 
593733210e7SPavel Pisa                 /* write to the backends. */
594733210e7SPavel Pisa                 can_bus_client_send(&s->bus_client, &frame, 1);
595733210e7SPavel Pisa 
596733210e7SPavel Pisa                 /*
597733210e7SPavel Pisa                  * Set transmission complete status,
598733210e7SPavel Pisa                  * and Transmit Buffer Status.
599733210e7SPavel Pisa                  */
600733210e7SPavel Pisa                 s->status_bas |= (3 << 2);
601733210e7SPavel Pisa 
602733210e7SPavel Pisa                 /* Clear transmit status. */
603733210e7SPavel Pisa                 s->status_bas &= ~(1 << 5);
604733210e7SPavel Pisa                 s->interrupt_bas |= 0x02;
605a62ed5d1SPaolo Bonzini                 can_sja_update_bas_irq(s);
606733210e7SPavel Pisa             }
607733210e7SPavel Pisa             if (0x04 & val) { /* Release Receive Buffer */
608733210e7SPavel Pisa                 if (s->rxmsg_cnt <= 0) {
609733210e7SPavel Pisa                     break;
610733210e7SPavel Pisa                 }
611733210e7SPavel Pisa 
612733210e7SPavel Pisa                 tmp8 = s->rx_buff[(s->rxbuf_start + 1) % SJA_RCV_BUF_LEN];
613733210e7SPavel Pisa                 count = 2 + (tmp8 & 0x0f);
614733210e7SPavel Pisa 
615733210e7SPavel Pisa                 if (DEBUG_FILTER) {
616733210e7SPavel Pisa                     qemu_log("[cansja]: message released from "
617733210e7SPavel Pisa                              "Rx FIFO cnt=%d, count=%d\n", s->rx_cnt, count);
618733210e7SPavel Pisa                 }
619733210e7SPavel Pisa 
620733210e7SPavel Pisa                 s->rxbuf_start += count;
621733210e7SPavel Pisa                 s->rxbuf_start %= SJA_RCV_BUF_LEN;
622733210e7SPavel Pisa                 s->rx_cnt -= count;
623733210e7SPavel Pisa                 s->rxmsg_cnt--;
624733210e7SPavel Pisa 
625733210e7SPavel Pisa                 if (s->rxmsg_cnt == 0) {
626733210e7SPavel Pisa                     s->status_bas &= ~(1 << 0);
627733210e7SPavel Pisa                     s->interrupt_bas &= ~(1 << 0);
628a62ed5d1SPaolo Bonzini                     can_sja_update_bas_irq(s);
629733210e7SPavel Pisa                 }
630733210e7SPavel Pisa             }
631733210e7SPavel Pisa             if (0x08 & val) { /* Clear data overrun */
632733210e7SPavel Pisa                 s->status_bas &= ~(1 << 1);
633733210e7SPavel Pisa                 s->interrupt_bas &= ~(1 << 3);
634a62ed5d1SPaolo Bonzini                 can_sja_update_bas_irq(s);
635733210e7SPavel Pisa             }
636733210e7SPavel Pisa             break;
637733210e7SPavel Pisa         case 4:
638733210e7SPavel Pisa             s->code = val;
639733210e7SPavel Pisa             break;
640733210e7SPavel Pisa         case 5:
641733210e7SPavel Pisa             s->mask = val;
642733210e7SPavel Pisa             break;
643733210e7SPavel Pisa         case 10:
644733210e7SPavel Pisa             s->status_bas |= (1 << 5); /* Set transmit status. */
645bd7b4e1fSThomas Huth             /* fallthrough */
646733210e7SPavel Pisa         case 11 ... 19:
647733210e7SPavel Pisa             if ((s->control & 0x01) == 0) { /* Operation mode */
648733210e7SPavel Pisa                 s->tx_buff[addr - 10] = val; /* Store to TX buffer directly. */
649733210e7SPavel Pisa             }
650733210e7SPavel Pisa             break;
651733210e7SPavel Pisa         case SJA_CDR:
652733210e7SPavel Pisa             s->clock = val;
653733210e7SPavel Pisa             break;
654733210e7SPavel Pisa         }
655733210e7SPavel Pisa     }
656733210e7SPavel Pisa }
657733210e7SPavel Pisa 
can_sja_mem_read(CanSJA1000State * s,hwaddr addr,unsigned size)658733210e7SPavel Pisa uint64_t can_sja_mem_read(CanSJA1000State *s, hwaddr addr, unsigned size)
659733210e7SPavel Pisa {
660733210e7SPavel Pisa     uint64_t temp = 0;
661733210e7SPavel Pisa 
662733210e7SPavel Pisa     DPRINTF("read addr 0x%02x ...\n", (unsigned int)addr);
663733210e7SPavel Pisa 
664733210e7SPavel Pisa     if (addr > CAN_SJA_MEM_SIZE) {
665733210e7SPavel Pisa         return 0;
666733210e7SPavel Pisa     }
667733210e7SPavel Pisa 
668733210e7SPavel Pisa     if (s->clock & 0x80) { /* PeliCAN Mode */
669733210e7SPavel Pisa         switch (addr) {
670733210e7SPavel Pisa         case SJA_MOD: /* Mode register, addr 0 */
671733210e7SPavel Pisa             temp = s->mode;
672733210e7SPavel Pisa             break;
673733210e7SPavel Pisa         case SJA_CMR: /* Command register, addr 1 */
674733210e7SPavel Pisa             temp = 0x00; /* Command register, cannot be read. */
675733210e7SPavel Pisa             break;
676733210e7SPavel Pisa         case SJA_SR: /* Status register, addr 2 */
677733210e7SPavel Pisa             temp = s->status_pel;
678733210e7SPavel Pisa             break;
679733210e7SPavel Pisa         case SJA_IR: /* Interrupt register, addr 3 */
680733210e7SPavel Pisa             temp = s->interrupt_pel;
681733210e7SPavel Pisa             s->interrupt_pel = 0;
682733210e7SPavel Pisa             if (s->rxmsg_cnt) {
683733210e7SPavel Pisa                 s->interrupt_pel |= (1 << 0); /* Receive interrupt. */
684733210e7SPavel Pisa             }
685a62ed5d1SPaolo Bonzini             can_sja_update_pel_irq(s);
686733210e7SPavel Pisa             break;
687733210e7SPavel Pisa         case SJA_IER: /* Interrupt enable register, addr 4 */
688733210e7SPavel Pisa             temp = s->interrupt_en;
689733210e7SPavel Pisa             break;
690733210e7SPavel Pisa         case 5: /* Reserved */
691733210e7SPavel Pisa         case 6: /* Bus timing 0, hardware related, not support now. */
692733210e7SPavel Pisa         case 7: /* Bus timing 1, hardware related, not support now. */
693733210e7SPavel Pisa         case 8: /*
694733210e7SPavel Pisa                  * Output control register, hardware related,
695733210e7SPavel Pisa                  * not supported for now.
696733210e7SPavel Pisa                  */
697733210e7SPavel Pisa         case 9: /* Test. */
698733210e7SPavel Pisa         case 10 ... 15: /* Reserved */
699733210e7SPavel Pisa             temp = 0x00;
700733210e7SPavel Pisa             break;
701733210e7SPavel Pisa 
702733210e7SPavel Pisa         case 16 ... 28:
703733210e7SPavel Pisa             if (s->mode & 0x01) { /* Reset mode */
704733210e7SPavel Pisa                 if (addr < 24) {
705733210e7SPavel Pisa                     temp = s->code_mask[addr - 16];
706733210e7SPavel Pisa                 } else {
707733210e7SPavel Pisa                     temp = 0x00;
708733210e7SPavel Pisa                 }
709733210e7SPavel Pisa             } else { /* Operation mode */
710733210e7SPavel Pisa                 temp = s->rx_buff[(s->rxbuf_start + addr - 16) %
711733210e7SPavel Pisa                        SJA_RCV_BUF_LEN];
712733210e7SPavel Pisa             }
713733210e7SPavel Pisa             break;
714733210e7SPavel Pisa         case SJA_CDR:
715733210e7SPavel Pisa             temp = s->clock;
716733210e7SPavel Pisa             break;
717733210e7SPavel Pisa         default:
718733210e7SPavel Pisa             temp = 0xff;
719733210e7SPavel Pisa         }
720733210e7SPavel Pisa     } else { /* Basic Mode */
721733210e7SPavel Pisa         switch (addr) {
722733210e7SPavel Pisa         case SJA_BCAN_CTR: /* Control register, addr 0 */
723733210e7SPavel Pisa             temp = s->control;
724733210e7SPavel Pisa             break;
725733210e7SPavel Pisa         case SJA_BCAN_SR: /* Status register, addr 2 */
726733210e7SPavel Pisa             temp = s->status_bas;
727733210e7SPavel Pisa             break;
728733210e7SPavel Pisa         case SJA_BCAN_IR: /* Interrupt register, addr 3 */
729733210e7SPavel Pisa             temp = s->interrupt_bas;
730733210e7SPavel Pisa             s->interrupt_bas = 0;
731733210e7SPavel Pisa             if (s->rxmsg_cnt) {
732733210e7SPavel Pisa                 s->interrupt_bas |= (1 << 0); /* Receive interrupt. */
733733210e7SPavel Pisa             }
734a62ed5d1SPaolo Bonzini             can_sja_update_bas_irq(s);
735733210e7SPavel Pisa             break;
736733210e7SPavel Pisa         case 4:
737733210e7SPavel Pisa             temp = s->code;
738733210e7SPavel Pisa             break;
739733210e7SPavel Pisa         case 5:
740733210e7SPavel Pisa             temp = s->mask;
741733210e7SPavel Pisa             break;
742733210e7SPavel Pisa         case 20 ... 29:
743733210e7SPavel Pisa             temp = s->rx_buff[(s->rxbuf_start + addr - 20) % SJA_RCV_BUF_LEN];
744733210e7SPavel Pisa             break;
745733210e7SPavel Pisa         case 31:
746733210e7SPavel Pisa             temp = s->clock;
747733210e7SPavel Pisa             break;
748733210e7SPavel Pisa         default:
749733210e7SPavel Pisa             temp = 0xff;
750733210e7SPavel Pisa             break;
751733210e7SPavel Pisa         }
752733210e7SPavel Pisa     }
753733210e7SPavel Pisa     DPRINTF("read addr 0x%02x, %d bytes, content 0x%02lx\n",
754733210e7SPavel Pisa             (int)addr, size, (long unsigned int)temp);
755733210e7SPavel Pisa 
756733210e7SPavel Pisa     return temp;
757733210e7SPavel Pisa }
758733210e7SPavel Pisa 
can_sja_can_receive(CanBusClientState * client)759767cc9a9SPhilippe Mathieu-Daudé bool can_sja_can_receive(CanBusClientState *client)
760733210e7SPavel Pisa {
761733210e7SPavel Pisa     CanSJA1000State *s = container_of(client, CanSJA1000State, bus_client);
762733210e7SPavel Pisa 
763733210e7SPavel Pisa     if (s->clock & 0x80) { /* PeliCAN Mode */
764733210e7SPavel Pisa         if (s->mode & 0x01) { /* reset mode. */
765767cc9a9SPhilippe Mathieu-Daudé             return false;
766733210e7SPavel Pisa         }
767733210e7SPavel Pisa     } else { /* BasicCAN mode */
768733210e7SPavel Pisa         if (s->control & 0x01) {
769767cc9a9SPhilippe Mathieu-Daudé             return false;
770733210e7SPavel Pisa         }
771733210e7SPavel Pisa     }
772733210e7SPavel Pisa 
773767cc9a9SPhilippe Mathieu-Daudé     return true; /* always return true, when operation mode */
774733210e7SPavel Pisa }
775733210e7SPavel Pisa 
can_sja_receive(CanBusClientState * client,const qemu_can_frame * frames,size_t frames_cnt)776733210e7SPavel Pisa ssize_t can_sja_receive(CanBusClientState *client, const qemu_can_frame *frames,
777733210e7SPavel Pisa                         size_t frames_cnt)
778733210e7SPavel Pisa {
779733210e7SPavel Pisa     CanSJA1000State *s = container_of(client, CanSJA1000State, bus_client);
780733210e7SPavel Pisa     static uint8_t rcv[SJA_MSG_MAX_LEN];
781733210e7SPavel Pisa     int i;
782733210e7SPavel Pisa     int ret = -1;
783733210e7SPavel Pisa     const qemu_can_frame *frame = frames;
784733210e7SPavel Pisa 
785733210e7SPavel Pisa     if (frames_cnt <= 0) {
786733210e7SPavel Pisa         return 0;
787733210e7SPavel Pisa     }
78846b25fe0SJan Charvat     if (frame->flags & QEMU_CAN_FRMF_TYPE_FD) {
78946b25fe0SJan Charvat         if (DEBUG_FILTER) {
79046b25fe0SJan Charvat             can_display_msg("[cansja]: ignor fd frame ", frame);
79146b25fe0SJan Charvat         }
79246b25fe0SJan Charvat         return 1;
79346b25fe0SJan Charvat     }
79446b25fe0SJan Charvat 
795733210e7SPavel Pisa     if (DEBUG_FILTER) {
796733210e7SPavel Pisa         can_display_msg("[cansja]: receive ", frame);
797733210e7SPavel Pisa     }
798733210e7SPavel Pisa 
799733210e7SPavel Pisa     if (s->clock & 0x80) { /* PeliCAN Mode */
800733210e7SPavel Pisa 
801733210e7SPavel Pisa         /* the CAN controller is receiving a message */
802733210e7SPavel Pisa         s->status_pel |= (1 << 4);
803733210e7SPavel Pisa 
804733210e7SPavel Pisa         if (can_sja_accept_filter(s, frame) == 0) {
805733210e7SPavel Pisa             s->status_pel &= ~(1 << 4);
806733210e7SPavel Pisa             if (DEBUG_FILTER) {
807733210e7SPavel Pisa                 qemu_log("[cansja]: filter rejects message\n");
808733210e7SPavel Pisa             }
809733210e7SPavel Pisa             return ret;
810733210e7SPavel Pisa         }
811733210e7SPavel Pisa 
812733210e7SPavel Pisa         ret = frame2buff_pel(frame, rcv);
813733210e7SPavel Pisa         if (ret < 0) {
814733210e7SPavel Pisa             s->status_pel &= ~(1 << 4);
815733210e7SPavel Pisa             if (DEBUG_FILTER) {
816733210e7SPavel Pisa                 qemu_log("[cansja]: message store failed\n");
817733210e7SPavel Pisa             }
818733210e7SPavel Pisa             return ret; /* maybe not support now. */
819733210e7SPavel Pisa         }
820733210e7SPavel Pisa 
821733210e7SPavel Pisa         if (s->rx_cnt + ret > SJA_RCV_BUF_LEN) { /* Data overrun. */
822733210e7SPavel Pisa             s->status_pel |= (1 << 1); /* Overrun status */
823733210e7SPavel Pisa             s->interrupt_pel |= (1 << 3);
824733210e7SPavel Pisa             s->status_pel &= ~(1 << 4);
825733210e7SPavel Pisa             if (DEBUG_FILTER) {
826733210e7SPavel Pisa                 qemu_log("[cansja]: receive FIFO overrun\n");
827733210e7SPavel Pisa             }
828a62ed5d1SPaolo Bonzini             can_sja_update_pel_irq(s);
829733210e7SPavel Pisa             return ret;
830733210e7SPavel Pisa         }
831733210e7SPavel Pisa         s->rx_cnt += ret;
832733210e7SPavel Pisa         s->rxmsg_cnt++;
833733210e7SPavel Pisa         if (DEBUG_FILTER) {
834733210e7SPavel Pisa             qemu_log("[cansja]: message stored in receive FIFO\n");
835733210e7SPavel Pisa         }
836733210e7SPavel Pisa 
837733210e7SPavel Pisa         for (i = 0; i < ret; i++) {
838733210e7SPavel Pisa             s->rx_buff[(s->rx_ptr++) % SJA_RCV_BUF_LEN] = rcv[i];
839733210e7SPavel Pisa         }
840733210e7SPavel Pisa         s->rx_ptr %= SJA_RCV_BUF_LEN; /* update the pointer. */
841733210e7SPavel Pisa 
842733210e7SPavel Pisa         s->status_pel |= 0x01; /* Set the Receive Buffer Status. DS-p23 */
843733210e7SPavel Pisa         s->interrupt_pel |= 0x01;
844733210e7SPavel Pisa         s->status_pel &= ~(1 << 4);
845733210e7SPavel Pisa         s->status_pel |= (1 << 0);
846a62ed5d1SPaolo Bonzini         can_sja_update_pel_irq(s);
847733210e7SPavel Pisa     } else { /* BasicCAN mode */
848733210e7SPavel Pisa 
849733210e7SPavel Pisa         /* the CAN controller is receiving a message */
850733210e7SPavel Pisa         s->status_bas |= (1 << 4);
851733210e7SPavel Pisa 
852733210e7SPavel Pisa         ret = frame2buff_bas(frame, rcv);
853733210e7SPavel Pisa         if (ret < 0) {
854733210e7SPavel Pisa             s->status_bas &= ~(1 << 4);
855733210e7SPavel Pisa             if (DEBUG_FILTER) {
856733210e7SPavel Pisa                 qemu_log("[cansja]: message store failed\n");
857733210e7SPavel Pisa             }
858733210e7SPavel Pisa             return ret; /* maybe not support now. */
859733210e7SPavel Pisa         }
860733210e7SPavel Pisa 
861733210e7SPavel Pisa         if (s->rx_cnt + ret > SJA_RCV_BUF_LEN) { /* Data overrun. */
862733210e7SPavel Pisa             s->status_bas |= (1 << 1); /* Overrun status */
863733210e7SPavel Pisa             s->status_bas &= ~(1 << 4);
864733210e7SPavel Pisa             s->interrupt_bas |= (1 << 3);
865a62ed5d1SPaolo Bonzini             can_sja_update_bas_irq(s);
866733210e7SPavel Pisa             if (DEBUG_FILTER) {
867733210e7SPavel Pisa                 qemu_log("[cansja]: receive FIFO overrun\n");
868733210e7SPavel Pisa             }
869733210e7SPavel Pisa             return ret;
870733210e7SPavel Pisa         }
871733210e7SPavel Pisa         s->rx_cnt += ret;
872733210e7SPavel Pisa         s->rxmsg_cnt++;
873733210e7SPavel Pisa 
874733210e7SPavel Pisa         if (DEBUG_FILTER) {
875733210e7SPavel Pisa             qemu_log("[cansja]: message stored\n");
876733210e7SPavel Pisa         }
877733210e7SPavel Pisa 
878733210e7SPavel Pisa         for (i = 0; i < ret; i++) {
879733210e7SPavel Pisa             s->rx_buff[(s->rx_ptr++) % SJA_RCV_BUF_LEN] = rcv[i];
880733210e7SPavel Pisa         }
881733210e7SPavel Pisa         s->rx_ptr %= SJA_RCV_BUF_LEN; /* update the pointer. */
882733210e7SPavel Pisa 
883733210e7SPavel Pisa         s->status_bas |= 0x01; /* Set the Receive Buffer Status. DS-p15 */
884733210e7SPavel Pisa         s->status_bas &= ~(1 << 4);
885a62ed5d1SPaolo Bonzini         s->interrupt_bas |= (1 << 0);
886a62ed5d1SPaolo Bonzini         can_sja_update_bas_irq(s);
887733210e7SPavel Pisa     }
888733210e7SPavel Pisa     return 1;
889733210e7SPavel Pisa }
890733210e7SPavel Pisa 
891733210e7SPavel Pisa static CanBusClientInfo can_sja_bus_client_info = {
892733210e7SPavel Pisa     .can_receive = can_sja_can_receive,
893733210e7SPavel Pisa     .receive = can_sja_receive,
894733210e7SPavel Pisa };
895733210e7SPavel Pisa 
896733210e7SPavel Pisa 
can_sja_connect_to_bus(CanSJA1000State * s,CanBusState * bus)897733210e7SPavel Pisa int can_sja_connect_to_bus(CanSJA1000State *s, CanBusState *bus)
898733210e7SPavel Pisa {
899733210e7SPavel Pisa     s->bus_client.info = &can_sja_bus_client_info;
900733210e7SPavel Pisa 
901089eac81SThomas Huth     if (!bus) {
902089eac81SThomas Huth         return -EINVAL;
903089eac81SThomas Huth     }
904089eac81SThomas Huth 
905733210e7SPavel Pisa     if (can_bus_insert_client(bus, &s->bus_client) < 0) {
906733210e7SPavel Pisa         return -1;
907733210e7SPavel Pisa     }
908733210e7SPavel Pisa 
909733210e7SPavel Pisa     return 0;
910733210e7SPavel Pisa }
911733210e7SPavel Pisa 
can_sja_disconnect(CanSJA1000State * s)912733210e7SPavel Pisa void can_sja_disconnect(CanSJA1000State *s)
913733210e7SPavel Pisa {
914733210e7SPavel Pisa     can_bus_remove_client(&s->bus_client);
915733210e7SPavel Pisa }
916733210e7SPavel Pisa 
can_sja_init(CanSJA1000State * s,qemu_irq irq)917733210e7SPavel Pisa int can_sja_init(CanSJA1000State *s, qemu_irq irq)
918733210e7SPavel Pisa {
919733210e7SPavel Pisa     s->irq = irq;
920733210e7SPavel Pisa 
921733210e7SPavel Pisa     qemu_irq_lower(s->irq);
922733210e7SPavel Pisa 
923733210e7SPavel Pisa     can_sja_hardware_reset(s);
924733210e7SPavel Pisa 
925733210e7SPavel Pisa     return 0;
926733210e7SPavel Pisa }
927733210e7SPavel Pisa 
928733210e7SPavel Pisa const VMStateDescription vmstate_qemu_can_filter = {
929733210e7SPavel Pisa     .name = "qemu_can_filter",
930733210e7SPavel Pisa     .version_id = 1,
931733210e7SPavel Pisa     .minimum_version_id = 1,
9321de81b42SRichard Henderson     .fields = (const VMStateField[]) {
933733210e7SPavel Pisa         VMSTATE_UINT32(can_id, qemu_can_filter),
934733210e7SPavel Pisa         VMSTATE_UINT32(can_mask, qemu_can_filter),
935733210e7SPavel Pisa         VMSTATE_END_OF_LIST()
936733210e7SPavel Pisa     }
937733210e7SPavel Pisa };
938733210e7SPavel Pisa 
can_sja_post_load(void * opaque,int version_id)939a62ed5d1SPaolo Bonzini static int can_sja_post_load(void *opaque, int version_id)
940a62ed5d1SPaolo Bonzini {
941a62ed5d1SPaolo Bonzini     CanSJA1000State *s = opaque;
942a62ed5d1SPaolo Bonzini     if (s->clock & 0x80) { /* PeliCAN Mode */
943a62ed5d1SPaolo Bonzini         can_sja_update_pel_irq(s);
944a62ed5d1SPaolo Bonzini     } else {
945a62ed5d1SPaolo Bonzini         can_sja_update_bas_irq(s);
946a62ed5d1SPaolo Bonzini     }
947a62ed5d1SPaolo Bonzini     return 0;
948a62ed5d1SPaolo Bonzini }
949a62ed5d1SPaolo Bonzini 
950733210e7SPavel Pisa /* VMState is needed for live migration of QEMU images */
951733210e7SPavel Pisa const VMStateDescription vmstate_can_sja = {
952733210e7SPavel Pisa     .name = "can_sja",
953733210e7SPavel Pisa     .version_id = 1,
954733210e7SPavel Pisa     .minimum_version_id = 1,
955a62ed5d1SPaolo Bonzini     .post_load = can_sja_post_load,
9561de81b42SRichard Henderson     .fields = (const VMStateField[]) {
957733210e7SPavel Pisa         VMSTATE_UINT8(mode, CanSJA1000State),
958733210e7SPavel Pisa 
959733210e7SPavel Pisa         VMSTATE_UINT8(status_pel, CanSJA1000State),
960733210e7SPavel Pisa         VMSTATE_UINT8(interrupt_pel, CanSJA1000State),
961733210e7SPavel Pisa         VMSTATE_UINT8(interrupt_en, CanSJA1000State),
962733210e7SPavel Pisa         VMSTATE_UINT8(rxmsg_cnt, CanSJA1000State),
963733210e7SPavel Pisa         VMSTATE_UINT8(rxbuf_start, CanSJA1000State),
964733210e7SPavel Pisa         VMSTATE_UINT8(clock, CanSJA1000State),
965733210e7SPavel Pisa 
966733210e7SPavel Pisa         VMSTATE_BUFFER(code_mask, CanSJA1000State),
967733210e7SPavel Pisa         VMSTATE_BUFFER(tx_buff, CanSJA1000State),
968733210e7SPavel Pisa 
969733210e7SPavel Pisa         VMSTATE_BUFFER(rx_buff, CanSJA1000State),
970733210e7SPavel Pisa 
971733210e7SPavel Pisa         VMSTATE_UINT32(rx_ptr, CanSJA1000State),
972733210e7SPavel Pisa         VMSTATE_UINT32(rx_cnt, CanSJA1000State),
973733210e7SPavel Pisa 
974733210e7SPavel Pisa         VMSTATE_UINT8(control, CanSJA1000State),
975733210e7SPavel Pisa 
976733210e7SPavel Pisa         VMSTATE_UINT8(status_bas, CanSJA1000State),
977733210e7SPavel Pisa         VMSTATE_UINT8(interrupt_bas, CanSJA1000State),
978733210e7SPavel Pisa         VMSTATE_UINT8(code, CanSJA1000State),
979733210e7SPavel Pisa         VMSTATE_UINT8(mask, CanSJA1000State),
980733210e7SPavel Pisa 
981733210e7SPavel Pisa         VMSTATE_STRUCT_ARRAY(filter, CanSJA1000State, 4, 0,
982733210e7SPavel Pisa                              vmstate_qemu_can_filter, qemu_can_filter),
983733210e7SPavel Pisa 
984733210e7SPavel Pisa 
985733210e7SPavel Pisa         VMSTATE_END_OF_LIST()
986733210e7SPavel Pisa     }
987733210e7SPavel Pisa };
988