2 * Kvaser PCI CAN device (SJA1000 based) emulation
4 * Copyright (c) 2013-2014 Jin Yang
5 * Copyright (c) 2014-2018 Pavel Pisa
7 * Partially based on educational PCIexpress APOHW hardware
8 * emulator used fro class A0B36APO at CTU FEE course by
9 * Rostislav Lisovy and Pavel Pisa
11 * Initial development supported by Google GSoC 2013 from RTEMS project slot
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this software and associated documentation files (the "Software"), to deal
15 * in the Software without restriction, including without limitation the rights
16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 * copies of the Software, and to permit persons to whom the Software is
18 * furnished to do so, subject to the following conditions:
20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32 #include "qemu/osdep.h"
33 #include "qemu/event_notifier.h"
34 #include "qemu/module.h"
35 #include "qemu/thread.h"
36 #include "qemu/sockets.h"
37 #include "qapi/error.h"
38 #include "chardev/char.h"
40 #include "hw/pci/pci.h"
41 #include "migration/vmstate.h"
42 #include "net/can_emu.h"
44 #include "can_sja1000.h"
46 #define TYPE_CAN_PCI_DEV "kvaser_pci"
48 #define KVASER_PCI_DEV(obj) \
49 OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV)
51 #ifndef KVASER_PCI_VENDOR_ID1
52 #define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */
55 #ifndef KVASER_PCI_DEVICE_ID1
56 #define KVASER_PCI_DEVICE_ID1 0x8406
59 #define KVASER_PCI_S5920_RANGE 0x80
60 #define KVASER_PCI_SJA_RANGE 0x80
61 #define KVASER_PCI_XILINX_RANGE 0x8
63 #define KVASER_PCI_BYTES_PER_SJA 0x20
65 #define S5920_OMB 0x0C
66 #define S5920_IMB 0x1C
67 #define S5920_MBEF 0x34
68 #define S5920_INTCSR 0x38
69 #define S5920_RCR 0x3C
70 #define S5920_PTCR 0x60
72 #define S5920_INTCSR_ADDON_INTENABLE_M 0x2000
73 #define S5920_INTCSR_INTERRUPT_ASSERTED_M 0x800000
75 #define KVASER_PCI_XILINX_VERINT 7 /* Lower nibble simulate interrupts,
76 high nibble version number. */
78 #define KVASER_PCI_XILINX_VERSION_NUMBER 13
80 typedef struct KvaserPCIState
{
84 MemoryRegion s5920_io
;
86 MemoryRegion xilinx_io
;
88 CanSJA1000State sja_state
;
91 uint32_t s5920_intcsr
;
92 uint32_t s5920_irqstate
;
97 static void kvaser_pci_irq_handler(void *opaque
, int irq_num
, int level
)
99 KvaserPCIState
*d
= (KvaserPCIState
*)opaque
;
101 d
->s5920_irqstate
= level
;
102 if (d
->s5920_intcsr
& S5920_INTCSR_ADDON_INTENABLE_M
) {
103 pci_set_irq(&d
->dev
, level
);
107 static void kvaser_pci_reset(DeviceState
*dev
)
109 KvaserPCIState
*d
= KVASER_PCI_DEV(dev
);
110 CanSJA1000State
*s
= &d
->sja_state
;
112 can_sja_hardware_reset(s
);
115 static uint64_t kvaser_pci_s5920_io_read(void *opaque
, hwaddr addr
,
118 KvaserPCIState
*d
= opaque
;
123 val
= d
->s5920_intcsr
;
124 val
&= ~S5920_INTCSR_INTERRUPT_ASSERTED_M
;
125 if (d
->s5920_irqstate
) {
126 val
|= S5920_INTCSR_INTERRUPT_ASSERTED_M
;
133 static void kvaser_pci_s5920_io_write(void *opaque
, hwaddr addr
, uint64_t data
,
136 KvaserPCIState
*d
= opaque
;
140 if (d
->s5920_irqstate
&&
141 ((d
->s5920_intcsr
^ data
) & S5920_INTCSR_ADDON_INTENABLE_M
)) {
142 pci_set_irq(&d
->dev
, !!(data
& S5920_INTCSR_ADDON_INTENABLE_M
));
144 d
->s5920_intcsr
= data
;
149 static uint64_t kvaser_pci_sja_io_read(void *opaque
, hwaddr addr
, unsigned size
)
151 KvaserPCIState
*d
= opaque
;
152 CanSJA1000State
*s
= &d
->sja_state
;
154 if (addr
>= KVASER_PCI_BYTES_PER_SJA
) {
158 return can_sja_mem_read(s
, addr
, size
);
161 static void kvaser_pci_sja_io_write(void *opaque
, hwaddr addr
, uint64_t data
,
164 KvaserPCIState
*d
= opaque
;
165 CanSJA1000State
*s
= &d
->sja_state
;
167 if (addr
>= KVASER_PCI_BYTES_PER_SJA
) {
171 can_sja_mem_write(s
, addr
, data
, size
);
174 static uint64_t kvaser_pci_xilinx_io_read(void *opaque
, hwaddr addr
,
178 case KVASER_PCI_XILINX_VERINT
:
179 return (KVASER_PCI_XILINX_VERSION_NUMBER
<< 4) | 0;
185 static void kvaser_pci_xilinx_io_write(void *opaque
, hwaddr addr
, uint64_t data
,
191 static const MemoryRegionOps kvaser_pci_s5920_io_ops
= {
192 .read
= kvaser_pci_s5920_io_read
,
193 .write
= kvaser_pci_s5920_io_write
,
194 .endianness
= DEVICE_LITTLE_ENDIAN
,
196 .min_access_size
= 4,
197 .max_access_size
= 4,
201 static const MemoryRegionOps kvaser_pci_sja_io_ops
= {
202 .read
= kvaser_pci_sja_io_read
,
203 .write
= kvaser_pci_sja_io_write
,
204 .endianness
= DEVICE_LITTLE_ENDIAN
,
206 .max_access_size
= 1,
210 static const MemoryRegionOps kvaser_pci_xilinx_io_ops
= {
211 .read
= kvaser_pci_xilinx_io_read
,
212 .write
= kvaser_pci_xilinx_io_write
,
213 .endianness
= DEVICE_LITTLE_ENDIAN
,
215 .max_access_size
= 1,
219 static void kvaser_pci_realize(PCIDevice
*pci_dev
, Error
**errp
)
221 KvaserPCIState
*d
= KVASER_PCI_DEV(pci_dev
);
222 CanSJA1000State
*s
= &d
->sja_state
;
225 pci_conf
= pci_dev
->config
;
226 pci_conf
[PCI_INTERRUPT_PIN
] = 0x01; /* interrupt pin A */
228 d
->irq
= qemu_allocate_irq(kvaser_pci_irq_handler
, d
, 0);
230 can_sja_init(s
, d
->irq
);
232 if (can_sja_connect_to_bus(s
, d
->canbus
) < 0) {
233 error_setg(errp
, "can_sja_connect_to_bus failed");
237 memory_region_init_io(&d
->s5920_io
, OBJECT(d
), &kvaser_pci_s5920_io_ops
,
238 d
, "kvaser_pci-s5920", KVASER_PCI_S5920_RANGE
);
239 memory_region_init_io(&d
->sja_io
, OBJECT(d
), &kvaser_pci_sja_io_ops
,
240 d
, "kvaser_pci-sja", KVASER_PCI_SJA_RANGE
);
241 memory_region_init_io(&d
->xilinx_io
, OBJECT(d
), &kvaser_pci_xilinx_io_ops
,
242 d
, "kvaser_pci-xilinx", KVASER_PCI_XILINX_RANGE
);
244 pci_register_bar(&d
->dev
, /*BAR*/ 0, PCI_BASE_ADDRESS_SPACE_IO
,
246 pci_register_bar(&d
->dev
, /*BAR*/ 1, PCI_BASE_ADDRESS_SPACE_IO
,
248 pci_register_bar(&d
->dev
, /*BAR*/ 2, PCI_BASE_ADDRESS_SPACE_IO
,
252 static void kvaser_pci_exit(PCIDevice
*pci_dev
)
254 KvaserPCIState
*d
= KVASER_PCI_DEV(pci_dev
);
255 CanSJA1000State
*s
= &d
->sja_state
;
257 can_sja_disconnect(s
);
259 qemu_free_irq(d
->irq
);
262 static const VMStateDescription vmstate_kvaser_pci
= {
263 .name
= "kvaser_pci",
265 .minimum_version_id
= 1,
266 .minimum_version_id_old
= 1,
267 .fields
= (VMStateField
[]) {
268 VMSTATE_PCI_DEVICE(dev
, KvaserPCIState
),
269 /* Load this before sja_state. */
270 VMSTATE_UINT32(s5920_intcsr
, KvaserPCIState
),
271 VMSTATE_STRUCT(sja_state
, KvaserPCIState
, 0, vmstate_can_sja
,
273 VMSTATE_END_OF_LIST()
277 static void kvaser_pci_instance_init(Object
*obj
)
279 KvaserPCIState
*d
= KVASER_PCI_DEV(obj
);
281 object_property_add_link(obj
, "canbus", TYPE_CAN_BUS
,
282 (Object
**)&d
->canbus
,
283 qdev_prop_allow_set_link_before_realize
,
287 static void kvaser_pci_class_init(ObjectClass
*klass
, void *data
)
289 DeviceClass
*dc
= DEVICE_CLASS(klass
);
290 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
292 k
->realize
= kvaser_pci_realize
;
293 k
->exit
= kvaser_pci_exit
;
294 k
->vendor_id
= KVASER_PCI_VENDOR_ID1
;
295 k
->device_id
= KVASER_PCI_DEVICE_ID1
;
297 k
->class_id
= 0x00ff00;
298 dc
->desc
= "Kvaser PCICANx";
299 dc
->vmsd
= &vmstate_kvaser_pci
;
300 dc
->reset
= kvaser_pci_reset
;
301 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
304 static const TypeInfo kvaser_pci_info
= {
305 .name
= TYPE_CAN_PCI_DEV
,
306 .parent
= TYPE_PCI_DEVICE
,
307 .instance_size
= sizeof(KvaserPCIState
),
308 .class_init
= kvaser_pci_class_init
,
309 .instance_init
= kvaser_pci_instance_init
,
310 .interfaces
= (InterfaceInfo
[]) {
311 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
316 static void kvaser_pci_register_types(void)
318 type_register_static(&kvaser_pci_info
);
321 type_init(kvaser_pci_register_types
)