2 * Kvaser PCI CAN device (SJA1000 based) emulation
4 * Copyright (c) 2013-2014 Jin Yang
5 * Copyright (c) 2014 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
33 #include "hw/pci/pci.h"
34 #include "qemu/event_notifier.h"
35 #include "qemu/osdep.h"
36 #include "qemu/thread.h"
37 #include "qemu/sockets.h"
38 #include "sysemu/char.h"
39 #include "can/can_emu.h"
41 #include "can_sja1000.h"
43 #define TYPE_CAN_PCI_DEV "kvaser_pci"
45 #define KVASER_PCI_DEV(obj) \
46 OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV)
48 #ifndef KVASER_PCI_VENDOR_ID1
49 #define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */
52 #ifndef KVASER_PCI_DEVICE_ID1
53 #define KVASER_PCI_DEVICE_ID1 0x8406
56 #define KVASER_PCI_S5920_RANGE 0x80
57 #define KVASER_PCI_SJA_RANGE 0x80
58 #define KVASER_PCI_XILINX_RANGE 0x8
60 #define KVASER_PCI_BYTES_PER_SJA 0x20
62 #define S5920_OMB 0x0C
63 #define S5920_IMB 0x1C
64 #define S5920_MBEF 0x34
65 #define S5920_INTCSR 0x38
66 #define S5920_RCR 0x3C
67 #define S5920_PTCR 0x60
69 #define S5920_INTCSR_ADDON_INTENABLE_M 0x2000
70 #define S5920_INTCSR_INTERRUPT_ASSERTED_M 0x800000
72 #define KVASER_PCI_XILINX_VERINT 7 /* Lower nibble simulate interrupts,
73 high nibble version number. */
75 typedef struct KvaserPCIState {
79 MemoryRegion s5920_io;
81 MemoryRegion xilinx_io;
83 CanSJA1000State sja_state;
86 uint32_t s5920_intcsr;
87 uint32_t s5920_irqstate;
89 char *model; /* The model that support, only SJA1000 now. */
94 static void kvaser_pci_irq_raise(void *opaque)
96 KvaserPCIState *d = (KvaserPCIState *)opaque;
97 d->s5920_irqstate = 1;
99 if (d->s5920_intcsr & S5920_INTCSR_ADDON_INTENABLE_M)
100 qemu_irq_raise(d->irq);
103 static void kvaser_pci_irq_lower(void *opaque)
105 KvaserPCIState *d = (KvaserPCIState *)opaque;
106 d->s5920_irqstate = 0;
107 qemu_irq_lower(d->irq);
111 kvaser_pci_reset(void *opaque)
113 KvaserPCIState *d = (KvaserPCIState *)opaque;
114 CanSJA1000State *s = &d->sja_state;
116 can_sja_hardware_reset(s);
119 static uint64_t kvaser_pci_s5920_io_read(void *opaque, hwaddr addr, unsigned size)
121 KvaserPCIState *d = opaque;
126 val = d->s5920_intcsr;
127 val &= ~S5920_INTCSR_INTERRUPT_ASSERTED_M;
128 if (d->s5920_irqstate) {
129 val |= S5920_INTCSR_INTERRUPT_ASSERTED_M;
136 static void kvaser_pci_s5920_io_write(void *opaque, hwaddr addr, uint64_t data,
139 KvaserPCIState *d = opaque;
143 if (~d->s5920_intcsr & data & S5920_INTCSR_ADDON_INTENABLE_M) {
144 if (d->s5920_irqstate) {
145 qemu_irq_raise(d->irq);
148 d->s5920_intcsr = data;
153 static uint64_t kvaser_pci_sja_io_read(void *opaque, hwaddr addr, unsigned size)
155 KvaserPCIState *d = opaque;
156 CanSJA1000State *s = &d->sja_state;
158 if (addr >= KVASER_PCI_BYTES_PER_SJA) {
162 return can_sja_mem_read(s, addr, size);
165 static void kvaser_pci_sja_io_write(void *opaque, hwaddr addr, uint64_t data,
168 KvaserPCIState *d = opaque;
169 CanSJA1000State *s = &d->sja_state;
171 if (addr >= KVASER_PCI_BYTES_PER_SJA) {
175 can_sja_mem_write(s, addr, data, size);
178 static uint64_t kvaser_pci_xilinx_io_read(void *opaque, hwaddr addr, unsigned size)
180 /*KvaserPCIState *d = opaque;*/
183 case KVASER_PCI_XILINX_VERINT:
184 return (13 << 4) | 0;
190 static void kvaser_pci_xilinx_io_write(void *opaque, hwaddr addr, uint64_t data,
193 /*KvaserPCIState *d = opaque;*/
196 static const MemoryRegionOps kvaser_pci_s5920_io_ops = {
197 .read = kvaser_pci_s5920_io_read,
198 .write = kvaser_pci_s5920_io_write,
199 .endianness = DEVICE_LITTLE_ENDIAN,
201 .min_access_size = 4,
202 .max_access_size = 4,
206 static const MemoryRegionOps kvaser_pci_sja_io_ops = {
207 .read = kvaser_pci_sja_io_read,
208 .write = kvaser_pci_sja_io_write,
209 .endianness = DEVICE_LITTLE_ENDIAN,
211 .min_access_size = 1,
212 .max_access_size = 1,
216 static const MemoryRegionOps kvaser_pci_xilinx_io_ops = {
217 .read = kvaser_pci_xilinx_io_read,
218 .write = kvaser_pci_xilinx_io_write,
219 .endianness = DEVICE_LITTLE_ENDIAN,
221 .min_access_size = 1,
222 .max_access_size = 1,
226 static int kvaser_pci_init(PCIDevice *pci_dev)
228 KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
229 CanSJA1000State *s = &d->sja_state;
231 CanBusState *can_bus;
234 if (strncmp(d->model, "pcican-s", 256)) { /* for security reason */
235 qerror_report(ERROR_CLASS_GENERIC_ERROR,
236 "Can't create CAN device, the model %s is not supported now.\n",
242 can_bus = can_bus_find_by_name(d->canbus, true);
243 if (can_bus == NULL) {
244 qerror_report(ERROR_CLASS_GENERIC_ERROR, "Cannot create can find/allocate CAN bus\n");
249 if (d->host != NULL) {
250 if (can_bus_connect_to_host_device(can_bus, d->host) < 0) {
251 qerror_report(ERROR_CLASS_GENERIC_ERROR, "Cannot connect CAN bus to host device \"%s\"\n", d->host);
256 pci_conf = pci_dev->config;
257 pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
259 d->irq = pci_allocate_irq(&d->dev);
261 can_sja_init(s, kvaser_pci_irq_raise, kvaser_pci_irq_lower, d);
263 qemu_register_reset(kvaser_pci_reset, d);
265 if (can_sja_connect_to_bus(s, can_bus) < 0) {
266 qerror_report(ERROR_CLASS_GENERIC_ERROR,
267 "can_sja_connect_to_bus failed\n");
271 memory_region_init_io(&d->s5920_io, OBJECT(d), &kvaser_pci_s5920_io_ops, d,
272 "kvaser_pci-s5920", KVASER_PCI_S5920_RANGE);
273 memory_region_init_io(&d->sja_io, OBJECT(d), &kvaser_pci_sja_io_ops, d,
274 "kvaser_pci-sja", KVASER_PCI_SJA_RANGE);
275 memory_region_init_io(&d->xilinx_io, OBJECT(d), &kvaser_pci_xilinx_io_ops, d,
276 "kvaser_pci-xilinx", KVASER_PCI_XILINX_RANGE);
278 pci_register_bar(&d->dev, /*BAR*/ 0, PCI_BASE_ADDRESS_SPACE_IO, &d->s5920_io);
279 pci_register_bar(&d->dev, /*BAR*/ 1, PCI_BASE_ADDRESS_SPACE_IO, &d->sja_io);
280 pci_register_bar(&d->dev, /*BAR*/ 2, PCI_BASE_ADDRESS_SPACE_IO, &d->xilinx_io);
285 static void kvaser_pci_exit(PCIDevice *pci_dev)
287 KvaserPCIState *d = KVASER_PCI_DEV(pci_dev);
288 CanSJA1000State *s = &d->sja_state;
290 can_sja_disconnect(s);
292 qemu_unregister_reset(kvaser_pci_reset, d);
295 * regions d->s5920_io, d->sja_io and d->xilinx_io
296 * are destroyed by QOM now
298 /* memory_region_destroy(&d->s5920_io); */
299 /* memory_region_destroy(&d->sja_io); */
300 /* memory_region_destroy(&d->xilinx_io); */
304 qemu_free_irq(d->irq);
307 static const VMStateDescription vmstate_kvaser_pci = {
308 .name = "kvaser_pci",
310 .minimum_version_id = 1,
311 .minimum_version_id_old = 1,
312 .fields = (VMStateField[]) {
313 VMSTATE_PCI_DEVICE(dev, KvaserPCIState),
314 VMSTATE_STRUCT(sja_state, KvaserPCIState, 0, vmstate_can_sja, CanSJA1000State),
316 VMSTATE_UINT32(s5920_intcsr, KvaserPCIState),
317 VMSTATE_UINT32(s5920_irqstate, KvaserPCIState),
318 VMSTATE_END_OF_LIST()
322 static void qdev_kvaser_pci_reset(DeviceState *dev)
324 KvaserPCIState *d = KVASER_PCI_DEV(dev);
328 static Property kvaser_pci_properties[] = {
329 DEFINE_PROP_STRING("canbus", KvaserPCIState, canbus),
330 DEFINE_PROP_STRING("host", KvaserPCIState, host),
331 DEFINE_PROP_STRING("model", KvaserPCIState, model),
332 DEFINE_PROP_END_OF_LIST(),
335 static void kvaser_pci_class_init(ObjectClass *klass, void *data)
337 DeviceClass *dc = DEVICE_CLASS(klass);
338 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
340 k->init = kvaser_pci_init;
341 k->exit = kvaser_pci_exit;
342 k->vendor_id = KVASER_PCI_VENDOR_ID1;
343 k->device_id = KVASER_PCI_DEVICE_ID1;
345 k->class_id = 0x00ff00;
346 dc->desc = "Kvaser PCICANx";
347 dc->props = kvaser_pci_properties;
348 dc->vmsd = &vmstate_kvaser_pci;
349 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
350 dc->reset = qdev_kvaser_pci_reset;
353 static const TypeInfo kvaser_pci_info = {
354 .name = TYPE_CAN_PCI_DEV,
355 .parent = TYPE_PCI_DEVICE,
356 .instance_size = sizeof(KvaserPCIState),
357 .class_init = kvaser_pci_class_init,
360 static void kvaser_pci_register_types(void)
362 type_register_static(&kvaser_pci_info);
365 type_init(kvaser_pci_register_types)