From nobody Mon Feb 9 18:46:21 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518523469613898.7249908267589; Tue, 13 Feb 2018 04:04:29 -0800 (PST) Received: from localhost ([::1]:50463 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elZJv-0005d5-Jo for importer@patchew.org; Tue, 13 Feb 2018 07:04:23 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41657) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1elZHL-00042Z-7D for qemu-devel@nongnu.org; Tue, 13 Feb 2018 07:01:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1elZHJ-0007Zf-K4 for qemu-devel@nongnu.org; Tue, 13 Feb 2018 07:01:43 -0500 Received: from mail-wm0-x244.google.com ([2a00:1450:400c:c09::244]:36567) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1elZHJ-0007ZQ-AL for qemu-devel@nongnu.org; Tue, 13 Feb 2018 07:01:41 -0500 Received: by mail-wm0-x244.google.com with SMTP id f3so15602470wmc.1 for ; Tue, 13 Feb 2018 04:01:41 -0800 (PST) Received: from 640k.lan ([82.84.102.245]) by smtp.gmail.com with ESMTPSA id f9sm6870298wmf.12.2018.02.13.04.01.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 13 Feb 2018 04:01:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=03WqDr31ewBgCer0qJF8alPS5uxBzQGkLyhfgC+Ukpg=; b=W6KH9ZAufgIphILPjfVmvjn2SUx6MAZgI53QvCAEP1tfEgX/IV2+UXnCLEWJpKH+aE IRmX+FG2g/uXy/si5SFxTmbev4hhVdCu/iG0AI7Ixav+x2lQ+wrj4LRpu4hIAJ1BpYzH NvVFz8qFK4Y/h9cNEI53q2CwtYNv8ytCOKnZVnzJqVrCI6jD8KOhTs/L9rFuVeP/P+DX oTSazZFWNTWh8SPMKc6hlPehYrqpopUA2uSsXSjMfYnhvmc9iJWHN+9MSt5fVaIKer5f oLgRy3RGprpVsYZQdbYs8th4OdLhVnqEPqYSeEthcyN+k+kcy11/v08cdiNKV5e1+ZNc ul6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=03WqDr31ewBgCer0qJF8alPS5uxBzQGkLyhfgC+Ukpg=; b=nPdMU2QW0w2R5nTBsu/G5CFVUZjON4IYJI4fKHX5uLYVIUQN/7CLGN08gT0b/wttqx HBV2euk9K3uH1RoWtcOMt4YG8EmNFRCyrdDAgZG8RyLDrM40615oGAMe1phUFKPV1sSI FLgXWYKCXs8Te64nyfOhSCOS6aWOQKQ2sSfdCy8wbaeI0hPrcS7mkTRxkufqSD2cekyu bJxYZLnQ2ahXYuZO5zVi7DZ6RzRN0bIi/dfM/KcuDW6R1d5mpbERQyDr1Z81pKGKzDKC 4PkBPvGTk2kdOfftPo2ifLENw6iZ0t9wV/Dtm+lQqtwzOUI+fXF+u+l1y+s2VeHOT0c4 UEew== X-Gm-Message-State: APf1xPBKOqFeEHA7IO2SHjSf+lNnHHA5CpsM2BQUaJ4L20GV2HTXHz6B QufdHDUbqLXSULLcQdLme7NwMX2+ X-Google-Smtp-Source: AH8x225vue9bWLMs/UXR+MsEDUVUlpH4MjhC4yL7DrndlHU3BOWQWgX43Ja0Z6u3OHKshQ3faYEEeg== X-Received: by 10.28.14.129 with SMTP id 123mr1070459wmo.111.1518523299726; Tue, 13 Feb 2018 04:01:39 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 13 Feb 2018 13:00:11 +0100 Message-Id: <1518523252-49106-8-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1518523252-49106-1-git-send-email-pbonzini@redhat.com> References: <1518523252-49106-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::244 Subject: [Qemu-devel] [PULL 07/48] hw/net/can: Kvaser PCI CAN-S (single SJA1000 channel) emulation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Pavel Pisa Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Pavel Pisa Signed-off-by: Pavel Pisa Signed-off-by: Paolo Bonzini --- default-configs/pci.mak | 1 + hw/net/can/Makefile.objs | 1 + hw/net/can/can_kvaser_pci.c | 319 ++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 321 insertions(+) create mode 100644 hw/net/can/can_kvaser_pci.c diff --git a/default-configs/pci.mak b/default-configs/pci.mak index 23f91d0..35e7596 100644 --- a/default-configs/pci.mak +++ b/default-configs/pci.mak @@ -33,6 +33,7 @@ CONFIG_SERIAL_ISA=3Dy CONFIG_SERIAL_PCI=3Dy CONFIG_CAN_BUS=3Dy CONFIG_CAN_SJA1000=3Dy +CONFIG_CAN_PCI=3Dy CONFIG_IPACK=3Dy CONFIG_WDT_IB6300ESB=3Dy CONFIG_PCI_TESTDEV=3Dy diff --git a/hw/net/can/Makefile.objs b/hw/net/can/Makefile.objs index c299f83..9d4a515 100644 --- a/hw/net/can/Makefile.objs +++ b/hw/net/can/Makefile.objs @@ -1 +1,2 @@ common-obj-$(CONFIG_CAN_SJA1000) +=3D can_sja1000.o +common-obj-$(CONFIG_CAN_PCI) +=3D can_kvaser_pci.o diff --git a/hw/net/can/can_kvaser_pci.c b/hw/net/can/can_kvaser_pci.c new file mode 100644 index 0000000..2d77ef2 --- /dev/null +++ b/hw/net/can/can_kvaser_pci.c @@ -0,0 +1,319 @@ +/* + * Kvaser PCI CAN device (SJA1000 based) emulation + * + * Copyright (c) 2013-2014 Jin Yang + * Copyright (c) 2014-2018 Pavel Pisa + * + * Partially based on educational PCIexpress APOHW hardware + * emulator used fro class A0B36APO at CTU FEE course by + * Rostislav Lisovy and Pavel Pisa + * + * Initial development supported by Google GSoC 2013 from RTEMS project sl= ot + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/event_notifier.h" +#include "qemu/thread.h" +#include "qemu/sockets.h" +#include "qapi/error.h" +#include "chardev/char.h" +#include "hw/hw.h" +#include "hw/pci/pci.h" +#include "net/can_emu.h" + +#include "can_sja1000.h" + +#define TYPE_CAN_PCI_DEV "kvaser_pci" + +#define KVASER_PCI_DEV(obj) \ + OBJECT_CHECK(KvaserPCIState, (obj), TYPE_CAN_PCI_DEV) + +#ifndef KVASER_PCI_VENDOR_ID1 +#define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor I= Ds */ +#endif + +#ifndef KVASER_PCI_DEVICE_ID1 +#define KVASER_PCI_DEVICE_ID1 0x8406 +#endif + +#define KVASER_PCI_S5920_RANGE 0x80 +#define KVASER_PCI_SJA_RANGE 0x80 +#define KVASER_PCI_XILINX_RANGE 0x8 + +#define KVASER_PCI_BYTES_PER_SJA 0x20 + +#define S5920_OMB 0x0C +#define S5920_IMB 0x1C +#define S5920_MBEF 0x34 +#define S5920_INTCSR 0x38 +#define S5920_RCR 0x3C +#define S5920_PTCR 0x60 + +#define S5920_INTCSR_ADDON_INTENABLE_M 0x2000 +#define S5920_INTCSR_INTERRUPT_ASSERTED_M 0x800000 + +#define KVASER_PCI_XILINX_VERINT 7 /* Lower nibble simulate interrupts, + high nibble version number. */ + +#define KVASER_PCI_XILINX_VERSION_NUMBER 13 + +typedef struct KvaserPCIState { + /*< private >*/ + PCIDevice dev; + /*< public >*/ + MemoryRegion s5920_io; + MemoryRegion sja_io; + MemoryRegion xilinx_io; + + CanSJA1000State sja_state; + qemu_irq irq; + + uint32_t s5920_intcsr; + uint32_t s5920_irqstate; + + CanBusState *canbus; +} KvaserPCIState; + +static void kvaser_pci_irq_handler(void *opaque, int irq_num, int level) +{ + KvaserPCIState *d =3D (KvaserPCIState *)opaque; + + d->s5920_irqstate =3D level; + if (d->s5920_intcsr & S5920_INTCSR_ADDON_INTENABLE_M) { + pci_set_irq(&d->dev, level); + } +} + +static void kvaser_pci_reset(DeviceState *dev) +{ + KvaserPCIState *d =3D KVASER_PCI_DEV(dev); + CanSJA1000State *s =3D &d->sja_state; + + can_sja_hardware_reset(s); +} + +static uint64_t kvaser_pci_s5920_io_read(void *opaque, hwaddr addr, + unsigned size) +{ + KvaserPCIState *d =3D opaque; + uint64_t val; + + switch (addr) { + case S5920_INTCSR: + val =3D d->s5920_intcsr; + val &=3D ~S5920_INTCSR_INTERRUPT_ASSERTED_M; + if (d->s5920_irqstate) { + val |=3D S5920_INTCSR_INTERRUPT_ASSERTED_M; + } + return val; + } + return 0; +} + +static void kvaser_pci_s5920_io_write(void *opaque, hwaddr addr, uint64_t = data, + unsigned size) +{ + KvaserPCIState *d =3D opaque; + + switch (addr) { + case S5920_INTCSR: + if (d->s5920_irqstate && + ((d->s5920_intcsr ^ data) & S5920_INTCSR_ADDON_INTENABLE_M)) { + pci_set_irq(&d->dev, !!(data & S5920_INTCSR_ADDON_INTENABLE_M)= ); + } + d->s5920_intcsr =3D data; + break; + } +} + +static uint64_t kvaser_pci_sja_io_read(void *opaque, hwaddr addr, unsigned= size) +{ + KvaserPCIState *d =3D opaque; + CanSJA1000State *s =3D &d->sja_state; + + if (addr >=3D KVASER_PCI_BYTES_PER_SJA) { + return 0; + } + + return can_sja_mem_read(s, addr, size); +} + +static void kvaser_pci_sja_io_write(void *opaque, hwaddr addr, uint64_t da= ta, + unsigned size) +{ + KvaserPCIState *d =3D opaque; + CanSJA1000State *s =3D &d->sja_state; + + if (addr >=3D KVASER_PCI_BYTES_PER_SJA) { + return; + } + + can_sja_mem_write(s, addr, data, size); +} + +static uint64_t kvaser_pci_xilinx_io_read(void *opaque, hwaddr addr, + unsigned size) +{ + switch (addr) { + case KVASER_PCI_XILINX_VERINT: + return (KVASER_PCI_XILINX_VERSION_NUMBER << 4) | 0; + } + + return 0; +} + +static void kvaser_pci_xilinx_io_write(void *opaque, hwaddr addr, uint64_t= data, + unsigned size) +{ + +} + +static const MemoryRegionOps kvaser_pci_s5920_io_ops =3D { + .read =3D kvaser_pci_s5920_io_read, + .write =3D kvaser_pci_s5920_io_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static const MemoryRegionOps kvaser_pci_sja_io_ops =3D { + .read =3D kvaser_pci_sja_io_read, + .write =3D kvaser_pci_sja_io_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .max_access_size =3D 1, + }, +}; + +static const MemoryRegionOps kvaser_pci_xilinx_io_ops =3D { + .read =3D kvaser_pci_xilinx_io_read, + .write =3D kvaser_pci_xilinx_io_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl =3D { + .max_access_size =3D 1, + }, +}; + +static void kvaser_pci_realize(PCIDevice *pci_dev, Error **errp) +{ + KvaserPCIState *d =3D KVASER_PCI_DEV(pci_dev); + CanSJA1000State *s =3D &d->sja_state; + uint8_t *pci_conf; + + pci_conf =3D pci_dev->config; + pci_conf[PCI_INTERRUPT_PIN] =3D 0x01; /* interrupt pin A */ + + d->irq =3D qemu_allocate_irq(kvaser_pci_irq_handler, d, 0); + + can_sja_init(s, d->irq); + + if (can_sja_connect_to_bus(s, d->canbus) < 0) { + error_setg(errp, "can_sja_connect_to_bus failed"); + return; + } + + memory_region_init_io(&d->s5920_io, OBJECT(d), &kvaser_pci_s5920_io_op= s, + d, "kvaser_pci-s5920", KVASER_PCI_S5920_RANGE); + memory_region_init_io(&d->sja_io, OBJECT(d), &kvaser_pci_sja_io_ops, + d, "kvaser_pci-sja", KVASER_PCI_SJA_RANGE); + memory_region_init_io(&d->xilinx_io, OBJECT(d), &kvaser_pci_xilinx_io_= ops, + d, "kvaser_pci-xilinx", KVASER_PCI_XILINX_RANGE); + + pci_register_bar(&d->dev, /*BAR*/ 0, PCI_BASE_ADDRESS_SPACE_IO, + &d->s5920_io); + pci_register_bar(&d->dev, /*BAR*/ 1, PCI_BASE_ADDRESS_SPACE_IO, + &d->sja_io); + pci_register_bar(&d->dev, /*BAR*/ 2, PCI_BASE_ADDRESS_SPACE_IO, + &d->xilinx_io); +} + +static void kvaser_pci_exit(PCIDevice *pci_dev) +{ + KvaserPCIState *d =3D KVASER_PCI_DEV(pci_dev); + CanSJA1000State *s =3D &d->sja_state; + + can_sja_disconnect(s); + + qemu_free_irq(d->irq); +} + +static const VMStateDescription vmstate_kvaser_pci =3D { + .name =3D "kvaser_pci", + .version_id =3D 1, + .minimum_version_id =3D 1, + .minimum_version_id_old =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, KvaserPCIState), + VMSTATE_STRUCT(sja_state, KvaserPCIState, 0, vmstate_can_sja, + CanSJA1000State), + VMSTATE_UINT32(s5920_intcsr, KvaserPCIState), + VMSTATE_UINT32(s5920_irqstate, KvaserPCIState), + VMSTATE_END_OF_LIST() + } +}; + +static void kvaser_pci_instance_init(Object *obj) +{ + KvaserPCIState *d =3D KVASER_PCI_DEV(obj); + + object_property_add_link(obj, "canbus", TYPE_CAN_BUS, + (Object **)&d->canbus, + qdev_prop_allow_set_link_before_realize, + 0, &error_abort); +} + +static void kvaser_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + PCIDeviceClass *k =3D PCI_DEVICE_CLASS(klass); + + k->realize =3D kvaser_pci_realize; + k->exit =3D kvaser_pci_exit; + k->vendor_id =3D KVASER_PCI_VENDOR_ID1; + k->device_id =3D KVASER_PCI_DEVICE_ID1; + k->revision =3D 0x00; + k->class_id =3D 0x00ff00; + dc->desc =3D "Kvaser PCICANx"; + dc->vmsd =3D &vmstate_kvaser_pci; + dc->reset =3D kvaser_pci_reset; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo kvaser_pci_info =3D { + .name =3D TYPE_CAN_PCI_DEV, + .parent =3D TYPE_PCI_DEVICE, + .instance_size =3D sizeof(KvaserPCIState), + .class_init =3D kvaser_pci_class_init, + .instance_init =3D kvaser_pci_instance_init, + .interfaces =3D (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static void kvaser_pci_register_types(void) +{ + type_register_static(&kvaser_pci_info); +} + +type_init(kvaser_pci_register_types) --=20 1.8.3.1