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/thread.h"
35 #include "qemu/sockets.h"
36 #include "qapi/error.h"
37 #include "chardev/char.h"
39 #include "hw/pci/pci.h"
40 #include "net/can_emu.h"
42 #include "can_sja1000.h"
44 #define TYPE_CAN_PCI_DEV "kvaser_pci"
46 #define KVASER_PCI_DEV(obj) \
47 OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV)
49 #ifndef KVASER_PCI_VENDOR_ID1
50 #define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */
53 #ifndef KVASER_PCI_DEVICE_ID1
54 #define KVASER_PCI_DEVICE_ID1 0x8406
57 #define KVASER_PCI_S5920_RANGE 0x80
58 #define KVASER_PCI_SJA_RANGE 0x80
59 #define KVASER_PCI_XILINX_RANGE 0x8
61 #define KVASER_PCI_BYTES_PER_SJA 0x20
63 #define S5920_OMB 0x0C
64 #define S5920_IMB 0x1C
65 #define S5920_MBEF 0x34
66 #define S5920_INTCSR 0x38
67 #define S5920_RCR 0x3C
68 #define S5920_PTCR 0x60
70 #define S5920_INTCSR_ADDON_INTENABLE_M 0x2000
71 #define S5920_INTCSR_INTERRUPT_ASSERTED_M 0x800000
73 #define KVASER_PCI_XILINX_VERINT 7 /* Lower nibble simulate interrupts,
74 high nibble version number. */
76 #define KVASER_PCI_XILINX_VERSION_NUMBER 13
78 typedef struct KvaserPCIState
{
82 MemoryRegion s5920_io
;
84 MemoryRegion xilinx_io
;
86 CanSJA1000State sja_state
;
89 uint32_t s5920_intcsr
;
90 uint32_t s5920_irqstate
;
95 static void kvaser_pci_irq_handler(void *opaque
, int irq_num
, int level
)
97 KvaserPCIState
*d
= (KvaserPCIState
*)opaque
;
99 d
->s5920_irqstate
= level
;
100 if (d
->s5920_intcsr
& S5920_INTCSR_ADDON_INTENABLE_M
) {
101 pci_set_irq(&d
->dev
, level
);
105 static void kvaser_pci_reset(DeviceState
*dev
)
107 KvaserPCIState
*d
= KVASER_PCI_DEV(dev
);
108 CanSJA1000State
*s
= &d
->sja_state
;
110 can_sja_hardware_reset(s
);
113 static uint64_t kvaser_pci_s5920_io_read(void *opaque
, hwaddr addr
,
116 KvaserPCIState
*d
= opaque
;
121 val
= d
->s5920_intcsr
;
122 val
&= ~S5920_INTCSR_INTERRUPT_ASSERTED_M
;
123 if (d
->s5920_irqstate
) {
124 val
|= S5920_INTCSR_INTERRUPT_ASSERTED_M
;
131 static void kvaser_pci_s5920_io_write(void *opaque
, hwaddr addr
, uint64_t data
,
134 KvaserPCIState
*d
= opaque
;
138 if (d
->s5920_irqstate
&&
139 ((d
->s5920_intcsr
^ data
) & S5920_INTCSR_ADDON_INTENABLE_M
)) {
140 pci_set_irq(&d
->dev
, !!(data
& S5920_INTCSR_ADDON_INTENABLE_M
));
142 d
->s5920_intcsr
= data
;
147 static uint64_t kvaser_pci_sja_io_read(void *opaque
, hwaddr addr
, unsigned size
)
149 KvaserPCIState
*d
= opaque
;
150 CanSJA1000State
*s
= &d
->sja_state
;
152 if (addr
>= KVASER_PCI_BYTES_PER_SJA
) {
156 return can_sja_mem_read(s
, addr
, size
);
159 static void kvaser_pci_sja_io_write(void *opaque
, hwaddr addr
, uint64_t data
,
162 KvaserPCIState
*d
= opaque
;
163 CanSJA1000State
*s
= &d
->sja_state
;
165 if (addr
>= KVASER_PCI_BYTES_PER_SJA
) {
169 can_sja_mem_write(s
, addr
, data
, size
);
172 static uint64_t kvaser_pci_xilinx_io_read(void *opaque
, hwaddr addr
,
176 case KVASER_PCI_XILINX_VERINT
:
177 return (KVASER_PCI_XILINX_VERSION_NUMBER
<< 4) | 0;
183 static void kvaser_pci_xilinx_io_write(void *opaque
, hwaddr addr
, uint64_t data
,
189 static const MemoryRegionOps kvaser_pci_s5920_io_ops
= {
190 .read
= kvaser_pci_s5920_io_read
,
191 .write
= kvaser_pci_s5920_io_write
,
192 .endianness
= DEVICE_LITTLE_ENDIAN
,
194 .min_access_size
= 4,
195 .max_access_size
= 4,
199 static const MemoryRegionOps kvaser_pci_sja_io_ops
= {
200 .read
= kvaser_pci_sja_io_read
,
201 .write
= kvaser_pci_sja_io_write
,
202 .endianness
= DEVICE_LITTLE_ENDIAN
,
204 .max_access_size
= 1,
208 static const MemoryRegionOps kvaser_pci_xilinx_io_ops
= {
209 .read
= kvaser_pci_xilinx_io_read
,
210 .write
= kvaser_pci_xilinx_io_write
,
211 .endianness
= DEVICE_LITTLE_ENDIAN
,
213 .max_access_size
= 1,
217 static void kvaser_pci_realize(PCIDevice
*pci_dev
, Error
**errp
)
219 KvaserPCIState
*d
= KVASER_PCI_DEV(pci_dev
);
220 CanSJA1000State
*s
= &d
->sja_state
;
223 pci_conf
= pci_dev
->config
;
224 pci_conf
[PCI_INTERRUPT_PIN
] = 0x01; /* interrupt pin A */
226 d
->irq
= qemu_allocate_irq(kvaser_pci_irq_handler
, d
, 0);
228 can_sja_init(s
, d
->irq
);
230 if (can_sja_connect_to_bus(s
, d
->canbus
) < 0) {
231 error_setg(errp
, "can_sja_connect_to_bus failed");
235 memory_region_init_io(&d
->s5920_io
, OBJECT(d
), &kvaser_pci_s5920_io_ops
,
236 d
, "kvaser_pci-s5920", KVASER_PCI_S5920_RANGE
);
237 memory_region_init_io(&d
->sja_io
, OBJECT(d
), &kvaser_pci_sja_io_ops
,
238 d
, "kvaser_pci-sja", KVASER_PCI_SJA_RANGE
);
239 memory_region_init_io(&d
->xilinx_io
, OBJECT(d
), &kvaser_pci_xilinx_io_ops
,
240 d
, "kvaser_pci-xilinx", KVASER_PCI_XILINX_RANGE
);
242 pci_register_bar(&d
->dev
, /*BAR*/ 0, PCI_BASE_ADDRESS_SPACE_IO
,
244 pci_register_bar(&d
->dev
, /*BAR*/ 1, PCI_BASE_ADDRESS_SPACE_IO
,
246 pci_register_bar(&d
->dev
, /*BAR*/ 2, PCI_BASE_ADDRESS_SPACE_IO
,
250 static void kvaser_pci_exit(PCIDevice
*pci_dev
)
252 KvaserPCIState
*d
= KVASER_PCI_DEV(pci_dev
);
253 CanSJA1000State
*s
= &d
->sja_state
;
255 can_sja_disconnect(s
);
257 qemu_free_irq(d
->irq
);
260 static const VMStateDescription vmstate_kvaser_pci
= {
261 .name
= "kvaser_pci",
263 .minimum_version_id
= 1,
264 .minimum_version_id_old
= 1,
265 .fields
= (VMStateField
[]) {
266 VMSTATE_PCI_DEVICE(dev
, KvaserPCIState
),
267 /* Load this before sja_state. */
268 VMSTATE_UINT32(s5920_intcsr
, KvaserPCIState
),
269 VMSTATE_STRUCT(sja_state
, KvaserPCIState
, 0, vmstate_can_sja
,
271 VMSTATE_END_OF_LIST()
275 static void kvaser_pci_instance_init(Object
*obj
)
277 KvaserPCIState
*d
= KVASER_PCI_DEV(obj
);
279 object_property_add_link(obj
, "canbus", TYPE_CAN_BUS
,
280 (Object
**)&d
->canbus
,
281 qdev_prop_allow_set_link_before_realize
,
285 static void kvaser_pci_class_init(ObjectClass
*klass
, void *data
)
287 DeviceClass
*dc
= DEVICE_CLASS(klass
);
288 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
290 k
->realize
= kvaser_pci_realize
;
291 k
->exit
= kvaser_pci_exit
;
292 k
->vendor_id
= KVASER_PCI_VENDOR_ID1
;
293 k
->device_id
= KVASER_PCI_DEVICE_ID1
;
295 k
->class_id
= 0x00ff00;
296 dc
->desc
= "Kvaser PCICANx";
297 dc
->vmsd
= &vmstate_kvaser_pci
;
298 dc
->reset
= kvaser_pci_reset
;
299 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
302 static const TypeInfo kvaser_pci_info
= {
303 .name
= TYPE_CAN_PCI_DEV
,
304 .parent
= TYPE_PCI_DEVICE
,
305 .instance_size
= sizeof(KvaserPCIState
),
306 .class_init
= kvaser_pci_class_init
,
307 .instance_init
= kvaser_pci_instance_init
,
308 .interfaces
= (InterfaceInfo
[]) {
309 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
314 static void kvaser_pci_register_types(void)
316 type_register_static(&kvaser_pci_info
);
319 type_init(kvaser_pci_register_types
)